From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- chart2/AllLangMoTarget_chart.mk | 13 + chart2/CppunitTest_chart2_common_functors.mk | 43 + chart2/CppunitTest_chart2_dialogs_test.mk | 76 + chart2/CppunitTest_chart2_dump.mk | 128 + chart2/CppunitTest_chart2_export.mk | 139 + chart2/CppunitTest_chart2_geometry.mk | 139 + chart2/CppunitTest_chart2_import.mk | 132 + chart2/CppunitTest_chart2_pivot_chart_test.mk | 131 + chart2/CppunitTest_chart2_trendcalculators.mk | 131 + chart2/CppunitTest_chart2_xshape.mk | 128 + chart2/IwyuFilter_chart2.yaml | 840 ++++++ chart2/JunitTest_chart2_unoapi.mk | 14 + chart2/Library_chartcontroller.mk | 205 ++ chart2/Library_chartcore.mk | 242 ++ chart2/Makefile | 14 + chart2/Module_chart2.mk | 54 + chart2/README | 9 + chart2/UIConfig_chart2.mk | 81 + chart2/inc/ChartModel.hxx | 475 +++ chart2/inc/ChartView.hxx | 255 ++ chart2/inc/SpecialCharacters.hxx | 17 + chart2/inc/bitmaps.hlst | 138 + chart2/inc/chart.hrc | 25 + chart2/inc/pch/precompiled_chartcontroller.cxx | 12 + chart2/inc/pch/precompiled_chartcontroller.hxx | 465 +++ chart2/inc/pch/precompiled_chartcore.cxx | 12 + chart2/inc/pch/precompiled_chartcore.hxx | 277 ++ chart2/inc/strings.hrc | 197 ++ chart2/inc/unonames.hxx | 36 + chart2/qa/TestCaseOldAPI.java | 957 ++++++ chart2/qa/data.chd | 14 + chart2/qa/extras/PivotChartTest.cxx | 986 +++++++ chart2/qa/extras/chart2_trendcalculators.cxx | 209 ++ chart2/qa/extras/chart2dump/chart2dump.cxx | 1147 ++++++++ .../chart2dump/data/axis_special_positioning.odp | Bin 0 -> 25153 bytes .../data/chartwall_auto_adjust_with_titles.ods | Bin 0 -> 24943 bytes .../data/chartwall_auto_adjust_without_titles.ods | Bin 0 -> 25090 bytes .../data/chartwall_custom_positioning.ods | Bin 0 -> 29351 bytes .../chart2dump/data/column_chart_small_spacing.ods | Bin 0 -> 29333 bytes .../chart2dump/data/custom_legend_position.odp | Bin 0 -> 16422 bytes .../chart2dump/data/default_formated_axis.odp | Bin 0 -> 26218 bytes chart2/qa/extras/chart2dump/data/donut_chart.ods | Bin 0 -> 24630 bytes .../extras/chart2dump/data/exploded_pie_chart.ods | Bin 0 -> 26180 bytes .../chart2dump/data/formated_axis_labels.odp | Bin 0 -> 15328 bytes .../extras/chart2dump/data/formated_axis_lines.odp | Bin 0 -> 24305 bytes .../extras/chart2dump/data/formated_grid_line.ods | Bin 0 -> 30275 bytes .../qa/extras/chart2dump/data/horizontal_grid.ods | Bin 0 -> 30942 bytes .../qa/extras/chart2dump/data/legend_on_bottom.odp | Bin 0 -> 16526 bytes .../extras/chart2dump/data/legend_on_left_side.odp | Bin 0 -> 16235 bytes .../chart2dump/data/legend_on_right_side.odp | Bin 0 -> 14176 bytes chart2/qa/extras/chart2dump/data/legend_on_top.odp | Bin 0 -> 16410 bytes .../extras/chart2dump/data/many_legend_entries.odp | Bin 0 -> 20961 bytes .../extras/chart2dump/data/minimal_legend_test.odp | Bin 0 -> 18253 bytes chart2/qa/extras/chart2dump/data/minor_grid.ods | Bin 0 -> 30004 bytes .../extras/chart2dump/data/multiple_categories.odp | Bin 0 -> 21476 bytes .../extras/chart2dump/data/multiple_categories.ods | Bin 0 -> 35766 bytes .../extras/chart2dump/data/normal_area_chart.ods | Bin 0 -> 29023 bytes .../qa/extras/chart2dump/data/normal_bar_chart.ods | Bin 0 -> 31385 bytes .../extras/chart2dump/data/normal_column_chart.ods | Bin 0 -> 29326 bytes .../data/normal_line_chart_lines_and_points.ods | Bin 0 -> 29690 bytes .../data/normal_line_chart_lines_only.ods | Bin 0 -> 29596 bytes .../data/normal_line_chart_points_only.ods | Bin 0 -> 29686 bytes .../qa/extras/chart2dump/data/normal_pie_chart.ods | Bin 0 -> 26374 bytes .../chart2dump/data/percent_stacked_area_chart.ods | Bin 0 -> 31559 bytes .../chart2dump/data/percent_stacked_bar_chart.ods | Bin 0 -> 29672 bytes .../data/percent_stacked_column_chart.odp | Bin 0 -> 23155 bytes .../data/percent_stacked_column_chart.ods | Bin 0 -> 31177 bytes ...percent_stacked_line_chart_lines_and_points.ods | Bin 0 -> 23971 bytes .../data/percent_stacked_line_chart_lines_only.ods | Bin 0 -> 23869 bytes .../percent_stacked_line_chart_points_only.ods | Bin 0 -> 23751 bytes .../chart2dump/data/pie_chart_many_slices.ods | Bin 0 -> 16351 bytes .../chart2dump/data/pivotchart_data_button.ods | Bin 0 -> 18366 bytes .../extras/chart2dump/data/rotated_axis_labels.odp | Bin 0 -> 24098 bytes .../extras/chart2dump/data/rotated_pie_chart.ods | Bin 0 -> 26286 bytes .../data/scatter_chart_lines_and_points.ods | Bin 0 -> 23728 bytes .../chart2dump/data/scatter_chart_lines_only.ods | Bin 0 -> 23540 bytes .../chart2dump/data/scatter_chart_points_only.ods | Bin 0 -> 23520 bytes chart2/qa/extras/chart2dump/data/simple_chart.ods | Bin 0 -> 29601 bytes .../extras/chart2dump/data/stacked_area_chart.ods | Bin 0 -> 30199 bytes .../extras/chart2dump/data/stacked_bar_chart.ods | Bin 0 -> 29285 bytes .../chart2dump/data/stacked_column_chart.ods | Bin 0 -> 29893 bytes .../data/stacked_line_chart_lines_and_points.ods | Bin 0 -> 23638 bytes .../data/stacked_line_chart_lines_only.ods | Bin 0 -> 23312 bytes .../data/stacked_line_chart_points_only.ods | Bin 0 -> 23484 bytes chart2/qa/extras/chart2dump/data/tdf118150.xlsx | Bin 0 -> 14212 bytes chart2/qa/extras/chart2dump/data/vertical_grid.ods | Bin 0 -> 31470 bytes .../reference/areacharttest/normal_area_chart.txt | 62 + .../areacharttest/percent_stacked_area_chart.txt | 62 + .../reference/areacharttest/stacked_area_chart.txt | 62 + .../axisgeometrytest/axis_special_positioning.txt | 38 + .../axisgeometrytest/default_formated_axis.txt | 38 + .../axisgeometrytest/formated_axis_lines.txt | 38 + .../axisgeometrytest/rotated_axis_labels.txt | 38 + .../axislabeltest/default_formated_axis.txt | 96 + .../axislabeltest/formated_axis_labels.txt | 96 + .../axislabeltest/percent_stacked_column_chart.txt | 96 + .../axislabeltest/rotated_axis_labels.txt | 60 + .../reference/axislabeltest/tdf118150.txt | 216 ++ .../chartdatatest/multiple_categories.txt | 70 + .../reference/chartdatatest/simple_chart.txt | 50 + .../chartwall_auto_adjust_with_titles.txt | 10 + .../chartwall_auto_adjust_without_titles.txt | 10 + .../chartwalltest/chartwall_custom_positioning.txt | 10 + .../reference/chartwalltest/formated_chartwall.txt | 10 + .../column_chart_small_spacing.txt | 162 + .../columnbarcharttest/normal_bar_chart.txt | 162 + .../columnbarcharttest/normal_column_chart.txt | 162 + .../percent_stacked_bar_chart.txt | 162 + .../percent_stacked_column_chart.txt | 162 + .../columnbarcharttest/stacked_bar_chart.txt | 162 + .../columnbarcharttest/stacked_column_chart.txt | 162 + .../reference/gridtest/formated_grid_line.txt | 17 + .../reference/gridtest/horizontal_grid.txt | 17 + .../chart2dump/reference/gridtest/minor_grid.txt | 68 + .../reference/gridtest/vertical_grid.txt | 17 + .../legendtest/custom_legend_position.txt | 50 + .../reference/legendtest/legend_on_bottom.txt | 50 + .../reference/legendtest/legend_on_left_side.txt | 50 + .../reference/legendtest/legend_on_right_side.txt | 18 + .../reference/legendtest/legend_on_top.txt | 50 + .../reference/legendtest/many_legend_entries.txt | 182 ++ .../reference/legendtest/minimal_legend_test.txt | 14 + .../reference/legendtest/multiple_categories.txt | 66 + .../reference/piecharttest/donut_chart.txt | 194 ++ .../reference/piecharttest/exploded_pie_chart.txt | 50 + .../reference/piecharttest/normal_pie_chart.txt | 50 + .../piecharttest/pie_chart_many_slices.txt | 275 ++ .../reference/piecharttest/rotated_pie_chart.txt | 50 + .../pivotchart_data_button.txt | 2 + .../normal_line_chart_lines_and_points.txt | 250 ++ .../normal_line_chart_lines_only.txt | 58 + .../normal_line_chart_points_only.txt | 198 ++ ...percent_stacked_line_chart_lines_and_points.txt | 310 ++ .../percent_stacked_line_chart_lines_only.txt | 58 + .../percent_stacked_line_chart_points_only.txt | 258 ++ .../scatter_chart_lines_and_points.txt | 310 ++ .../scatter_chart_lines_only.txt | 58 + .../scatter_chart_points_only.txt | 258 ++ .../stacked_line_chart_lines_and_points.txt | 310 ++ .../stacked_line_chart_lines_only.txt | 58 + .../stacked_line_chart_points_only.txt | 258 ++ chart2/qa/extras/chart2export.cxx | 2834 ++++++++++++++++++ chart2/qa/extras/chart2geometry.cxx | 242 ++ chart2/qa/extras/chart2import.cxx | 2603 ++++++++++++++++ chart2/qa/extras/charttest.hxx | 614 ++++ chart2/qa/extras/data/doc/chart.doc | Bin 0 -> 15872 bytes chart2/qa/extras/data/docx/3d-bar-label.docx | Bin 0 -> 24163 bytes .../qa/extras/data/docx/Bar_horizontal_cone.docx | Bin 0 -> 18237 bytes chart2/qa/extras/data/docx/DisplayUnits.docx | Bin 0 -> 18137 bytes chart2/qa/extras/data/docx/FDO74430.docx | Bin 0 -> 19199 bytes chart2/qa/extras/data/docx/FDO75975.docx | Bin 0 -> 18257 bytes chart2/qa/extras/data/docx/MSO_axis_position.docx | Bin 0 -> 41444 bytes chart2/qa/extras/data/docx/PieChartDataLabels.docx | Bin 0 -> 120403 bytes chart2/qa/extras/data/docx/UpDownBars.docx | Bin 0 -> 24198 bytes chart2/qa/extras/data/docx/area-chart-labels.docx | Bin 0 -> 24123 bytes chart2/qa/extras/data/docx/bar-chart-labels.docx | Bin 0 -> 24357 bytes chart2/qa/extras/data/docx/barChartRotation.docx | Bin 0 -> 24220 bytes chart2/qa/extras/data/docx/bubblechart.docx | Bin 0 -> 17740 bytes chart2/qa/extras/data/docx/chart.docx | Bin 0 -> 17749 bytes .../data/docx/clustered-bar-chart-labels.docx | Bin 0 -> 22977 bytes chart2/qa/extras/data/docx/data-label-borders.docx | Bin 0 -> 34843 bytes .../data/docx/data_point_inherited_color.docx | Bin 0 -> 5426 bytes .../qa/extras/data/docx/doughnut-chart-labels.docx | Bin 0 -> 23902 bytes chart2/qa/extras/data/docx/doughnutChart.docx | Bin 0 -> 17486 bytes .../extras/data/docx/fdo74115_WallBitmapFill.docx | Bin 0 -> 34418 bytes .../data/docx/fdo74115_WallGradientFill.docx | Bin 0 -> 17942 bytes .../docx/fdo78290_Combination_Chart_Marker_x.docx | Bin 0 -> 24245 bytes .../data/docx/fdo78290_Line_Chart_Marker_x.docx | Bin 0 -> 24041 bytes .../data/docx/fdo78290_Scatter_Chart_Marker_x.docx | Bin 0 -> 23747 bytes chart2/qa/extras/data/docx/fdo83058_dlblPos.docx | Bin 0 -> 35931 bytes .../docx/line-chart-label-default-placement.docx | Bin 0 -> 17824 bytes chart2/qa/extras/data/docx/pieChartRotation.docx | Bin 0 -> 23528 bytes .../data/docx/piechart_deleted_legend_entry.docx | Bin 0 -> 27165 bytes chart2/qa/extras/data/docx/radar-chart-labels.docx | Bin 0 -> 24223 bytes .../data/docx/scatter-chart-text-x-values.docx | Bin 0 -> 23974 bytes chart2/qa/extras/data/docx/tdf121744.docx | Bin 0 -> 25221 bytes chart2/qa/extras/data/docx/tdf123206.docx | Bin 0 -> 24223 bytes chart2/qa/extras/data/docx/tdf124083.docx | Bin 0 -> 25793 bytes chart2/qa/extras/data/docx/tdf124243.docx | Bin 0 -> 25872 bytes chart2/qa/extras/data/docx/tdf125337.docx | Bin 0 -> 25063 bytes chart2/qa/extras/data/docx/tdf128794.docx | Bin 0 -> 31616 bytes chart2/qa/extras/data/docx/tdf132174.docx | Bin 0 -> 13865 bytes chart2/qa/extras/data/docx/tdf133632.docx | Bin 0 -> 26280 bytes chart2/qa/extras/data/docx/tdf136650.docx | Bin 0 -> 25543 bytes chart2/qa/extras/data/docx/tdf91250.docx | Bin 0 -> 25895 bytes chart2/qa/extras/data/docx/testAreaChartLoad.docx | Bin 0 -> 23962 bytes .../qa/extras/data/docx/testAxisTitlePosition.docx | Bin 0 -> 26274 bytes chart2/qa/extras/data/docx/testBarChart.docx | Bin 0 -> 23955 bytes .../data/docx/testBarChartDataPointPropDOCX.docx | Bin 0 -> 25590 bytes chart2/qa/extras/data/docx/testChartDataTable.docx | Bin 0 -> 18084 bytes .../docx/testChartTitlePropertiesBitmapFill.docx | Bin 0 -> 47851 bytes .../docx/testChartTitlePropertiesColorFill.docx | Bin 0 -> 5549 bytes .../docx/testChartTitlePropertiesGradientFill.docx | Bin 0 -> 5595 bytes .../docx/testColorGradientWithTransparancy.docx | Bin 0 -> 25872 bytes .../qa/extras/data/docx/testCustomlabeltext.docx | Bin 0 -> 26031 bytes chart2/qa/extras/data/docx/testLabelSeparator.docx | Bin 0 -> 25333 bytes .../data/docx/testMultilevelCategoryAxis.docx | Bin 0 -> 5890 bytes chart2/qa/extras/data/docx/testMultipleChart.docx | Bin 0 -> 47534 bytes .../data/docx/testMultiplechartembeddings.docx | Bin 0 -> 47534 bytes chart2/qa/extras/data/docx/testSeriesIdxOrder.docx | Bin 0 -> 25941 bytes .../extras/data/docx/testSimpleCategoryAxis.docx | Bin 0 -> 31629 bytes chart2/qa/extras/data/docx/testStockChart.docx | Bin 0 -> 19894 bytes chart2/qa/extras/data/docx/testTdf108110.docx | Bin 0 -> 25892 bytes chart2/qa/extras/data/docx/testTdf114179.docx | Bin 0 -> 5839 bytes chart2/qa/extras/data/docx/testTdf122226.docx | Bin 0 -> 19648 bytes .../data/docx/testchartoleobjectembeddings.docx | Bin 0 -> 2041727 bytes .../qa/extras/data/fods/stacked-column-chart.fods | 861 ++++++ chart2/qa/extras/data/odp/chart.odp | Bin 0 -> 14747 bytes .../qa/extras/data/odp/ellipticalGradientFill.odp | Bin 0 -> 17071 bytes chart2/qa/extras/data/odp/tdf119029.odp | Bin 0 -> 13643 bytes chart2/qa/extras/data/odp/tdf121189.odp | Bin 0 -> 16945 bytes chart2/qa/extras/data/odp/tdf123206.odp | Bin 0 -> 19589 bytes chart2/qa/extras/data/ods/ErrorBarRange.ods | Bin 0 -> 17937 bytes chart2/qa/extras/data/ods/PivotChartRoundTrip.ods | Bin 0 -> 21988 bytes chart2/qa/extras/data/ods/PivotTableExample.ods | Bin 0 -> 17183 bytes .../qa/extras/data/ods/axis-numformats-linked.ods | Bin 0 -> 26944 bytes chart2/qa/extras/data/ods/axis_number_format.ods | Bin 0 -> 12662 bytes chart2/qa/extras/data/ods/chart.ods | Bin 0 -> 12599 bytes .../data/ods/combined_chart_secondary_axis.ods | Bin 0 -> 16334 bytes chart2/qa/extras/data/ods/error_bar.ods | Bin 0 -> 13724 bytes chart2/qa/extras/data/ods/error_bar_properties.ods | Bin 0 -> 17387 bytes chart2/qa/extras/data/ods/error_bar_range.ods | Bin 0 -> 13490 bytes chart2/qa/extras/data/ods/fdo60083.ods | Bin 0 -> 14538 bytes chart2/qa/extras/data/ods/labelString.ods | Bin 0 -> 17401 bytes chart2/qa/extras/data/ods/legend_overlay.ods | Bin 0 -> 12314 bytes chart2/qa/extras/data/ods/multilevelcat.ods | Bin 0 -> 13559 bytes chart2/qa/extras/data/ods/multiple_axis.ods | Bin 0 -> 12864 bytes chart2/qa/extras/data/ods/pie_chart_100_and_0.ods | Bin 0 -> 11354 bytes chart2/qa/extras/data/ods/secondary_axis.ods | Bin 0 -> 16783 bytes chart2/qa/extras/data/ods/smoothedLines.ods | Bin 0 -> 16115 bytes chart2/qa/extras/data/ods/stepped_lines.ods | Bin 0 -> 76168 bytes chart2/qa/extras/data/ods/tdf108021.ods | Bin 0 -> 16728 bytes chart2/qa/extras/data/ods/tdf123774.ods | Bin 0 -> 16140 bytes chart2/qa/extras/data/ods/tdf128432.ods | Bin 0 -> 13755 bytes chart2/qa/extras/data/ods/tdf131115.ods | Bin 0 -> 13814 bytes chart2/qa/extras/data/ods/tdf131979.ods | Bin 0 -> 11510 bytes chart2/qa/extras/data/ods/tdf132076.ods | Bin 0 -> 16138 bytes chart2/qa/extras/data/ods/tdf59857.ods | Bin 0 -> 33209 bytes chart2/qa/extras/data/ods/tdf64224.ods | Bin 0 -> 33209 bytes chart2/qa/extras/data/ods/tdf86624.ods | Bin 0 -> 14461 bytes .../extras/data/ods/testChartMainWithSubTitle.ods | Bin 0 -> 12317 bytes chart2/qa/extras/data/ods/testChartSubTitle.ods | Bin 0 -> 12598 bytes .../data/ods/testColorGradientWithTransparancy.ods | Bin 0 -> 17224 bytes chart2/qa/extras/data/ods/test_CrossBetween.ods | Bin 0 -> 12365 bytes chart2/qa/extras/data/ods/trend_calculators.ods | Bin 0 -> 45107 bytes chart2/qa/extras/data/ods/trendline.ods | Bin 0 -> 17563 bytes chart2/qa/extras/data/odt/axis-position.odt | Bin 0 -> 21224 bytes chart2/qa/extras/data/odt/chart.odt | Bin 0 -> 13470 bytes chart2/qa/extras/data/odt/multilevelcat.odt | Bin 0 -> 13942 bytes chart2/qa/extras/data/odt/scatter-plot-labels.odt | Bin 0 -> 13454 bytes chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt | Bin 0 -> 16810 bytes chart2/qa/extras/data/odt/tdf108022.odt | Bin 0 -> 23191 bytes chart2/qa/extras/data/odt/tdf114657.odt | Bin 0 -> 12890 bytes chart2/qa/extras/data/odt/tdf128733.odt | Bin 0 -> 13708 bytes chart2/qa/extras/data/odt/tdf131143.odt | Bin 0 -> 13970 bytes .../extras/data/odt/testPieChartWallLineStyle.odt | Bin 0 -> 16427 bytes chart2/qa/extras/data/ppt/chart.ppt | Bin 0 -> 76800 bytes chart2/qa/extras/data/pptx/bnc864396.pptx | Bin 0 -> 41580 bytes chart2/qa/extras/data/pptx/bnc882383.pptx | Bin 0 -> 43962 bytes chart2/qa/extras/data/pptx/bnc889755.pptx | Bin 0 -> 34771 bytes chart2/qa/extras/data/pptx/chart.pptx | Bin 0 -> 33393 bytes .../data/pptx/percentage-number-formats.pptx | Bin 0 -> 58872 bytes chart2/qa/extras/data/pptx/sparse-chart.pptx | Bin 0 -> 57398 bytes .../data/pptx/stacked-bar-chart-hidden-series.pptx | Bin 0 -> 54370 bytes .../data/pptx/stacked-non-stacked-mix-y-axis.pptx | Bin 0 -> 86216 bytes chart2/qa/extras/data/pptx/tdf105517.pptx | Bin 0 -> 37194 bytes chart2/qa/extras/data/pptx/tdf106217.pptx | Bin 0 -> 47976 bytes chart2/qa/extras/data/pptx/tdf115107-2.pptx | Bin 0 -> 50519 bytes chart2/qa/extras/data/pptx/tdf115107.pptx | Bin 0 -> 50726 bytes chart2/qa/extras/data/pptx/tdf115859.pptx | Bin 0 -> 49120 bytes chart2/qa/extras/data/pptx/tdf116163.pptx | Bin 0 -> 47591 bytes chart2/qa/extras/data/pptx/tdf121205.pptx | Bin 0 -> 42922 bytes chart2/qa/extras/data/pptx/tdf122765.pptx | Bin 0 -> 47625 bytes chart2/qa/extras/data/pptx/tdf125444.pptx | Bin 0 -> 34078 bytes chart2/qa/extras/data/pptx/tdf127393.pptx | Bin 0 -> 64536 bytes chart2/qa/extras/data/pptx/tdf48041.pptx | Bin 0 -> 23937 bytes .../pptx/testChartTitlePropertiesBitmapFill.pptx | Bin 0 -> 50865 bytes .../pptx/testChartTitlePropertiesColorFill.pptx | Bin 0 -> 47424 bytes .../pptx/testChartTitlePropertiesGradientFill.pptx | Bin 0 -> 47473 bytes .../qa/extras/data/xls/axis_sourceformatting.xls | Bin 0 -> 7168 bytes chart2/qa/extras/data/xls/chart.xls | Bin 0 -> 7168 bytes chart2/qa/extras/data/xls/piechart_outside.xls | Bin 0 -> 60928 bytes .../extras/data/xls/source_number_format_axis.xls | Bin 0 -> 7168 bytes .../data/xlsx/add_series_secondary_axis.xlsx | Bin 0 -> 20217 bytes .../qa/extras/data/xlsx/auto_marker_excel10.xlsx | Bin 0 -> 16250 bytes chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx | Bin 0 -> 10455 bytes chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx | Bin 0 -> 13222 bytes .../qa/extras/data/xlsx/axis-label-rotation.xlsx | Bin 0 -> 13698 bytes .../data/xlsx/axis_character_properties.xlsx | Bin 0 -> 10381 bytes .../data/xlsx/axis_title_default_rotation.xlsx | Bin 0 -> 11868 bytes chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx | Bin 0 -> 11579 bytes .../qa/extras/data/xlsx/axis_title_rotation.xlsx | Bin 0 -> 13057 bytes chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx | Bin 0 -> 12966 bytes chart2/qa/extras/data/xlsx/barchart_outend.xlsx | Bin 0 -> 15277 bytes .../qa/extras/data/xlsx/bubble_chart_simple.xlsx | Bin 0 -> 13010 bytes .../data/xlsx/chart-area-style-background.xlsx | Bin 0 -> 13796 bytes .../extras/data/xlsx/chart-area-style-border.xlsx | Bin 0 -> 12006 bytes .../qa/extras/data/xlsx/chart-auto-background.xlsx | Bin 0 -> 11310 bytes chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx | Bin 0 -> 11579 bytes .../extras/data/xlsx/chart-text-can-overlap.xlsx | Bin 0 -> 13368 bytes chart2/qa/extras/data/xlsx/chart.xlsx | Bin 0 -> 7055 bytes .../extras/data/xlsx/chart_label_text_break.xlsx | Bin 0 -> 13940 bytes chart2/qa/extras/data/xlsx/chart_pie2007.xlsx | Bin 0 -> 11299 bytes chart2/qa/extras/data/xlsx/chart_title.xlsx | Bin 0 -> 13085 bytes .../data/xlsx/combined_chart_secondary_axis.xlsx | Bin 0 -> 15304 bytes chart2/qa/extras/data/xlsx/data_label.xlsx | Bin 0 -> 13057 bytes .../qa/extras/data/xlsx/deleted_data_labels.xlsx | Bin 0 -> 7536 bytes .../qa/extras/data/xlsx/deleted_legend_entry.xlsx | Bin 0 -> 14346 bytes .../qa/extras/data/xlsx/deleted_legend_entry2.xlsx | Bin 0 -> 20060 bytes chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx | Bin 0 -> 10520 bytes chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx | Bin 0 -> 13430 bytes chart2/qa/extras/data/xlsx/external_str_ref.xlsx | Bin 0 -> 23847 bytes chart2/qa/extras/data/xlsx/fdo54361-1.xlsx | Bin 0 -> 11106 bytes chart2/qa/extras/data/xlsx/fdo54361.xlsx | Bin 0 -> 10273 bytes chart2/qa/extras/data/xlsx/fdo70609.xlsx | Bin 0 -> 13654 bytes chart2/qa/extras/data/xlsx/fdo78080.xlsx | Bin 0 -> 7020 bytes chart2/qa/extras/data/xlsx/gapWidth.xlsx | Bin 0 -> 18668 bytes chart2/qa/extras/data/xlsx/hidden_cells.xlsx | Bin 0 -> 11215 bytes .../qa/extras/data/xlsx/legend_manual_layout.xlsx | Bin 0 -> 13145 bytes chart2/qa/extras/data/xlsx/majorTickMark.xlsx | Bin 0 -> 11223 bytes chart2/qa/extras/data/xlsx/markerColor.xlsx | Bin 0 -> 12999 bytes chart2/qa/extras/data/xlsx/minorTickMark.xlsx | Bin 0 -> 11256 bytes chart2/qa/extras/data/xlsx/no_marker.xlsx | Bin 0 -> 13006 bytes chart2/qa/extras/data/xlsx/number-formats.xlsx | Bin 0 -> 12638 bytes .../data/xlsx/pie_chart_datapoint_explosion.xlsx | Bin 0 -> 19237 bytes chart2/qa/extras/data/xlsx/piechart_outside.xlsx | Bin 0 -> 15473 bytes chart2/qa/extras/data/xlsx/plotVisOnly.xlsx | Bin 0 -> 11206 bytes .../extras/data/xlsx/plot_area_manual_layout.xlsx | Bin 0 -> 13142 bytes chart2/qa/extras/data/xlsx/rAngAx.xlsx | Bin 0 -> 11364 bytes .../secondary_axis_title_default_rotation.xlsx | Bin 0 -> 11529 bytes chart2/qa/extras/data/xlsx/smoothed_series.xlsx | Bin 0 -> 12836 bytes .../qa/extras/data/xlsx/smoothed_series2007.xlsx | Bin 0 -> 12351 bytes chart2/qa/extras/data/xlsx/strict_chart.xlsx | Bin 0 -> 12779 bytes chart2/qa/extras/data/xlsx/tdf100084.xlsx | Bin 0 -> 10070 bytes chart2/qa/extras/data/xlsx/tdf108107.xlsx | Bin 0 -> 14277 bytes chart2/qa/extras/data/xlsx/tdf111173.xlsx | Bin 0 -> 16013 bytes chart2/qa/extras/data/xlsx/tdf111824.xlsx | Bin 0 -> 15235 bytes chart2/qa/extras/data/xlsx/tdf114139.xlsx | Bin 0 -> 18794 bytes chart2/qa/extras/data/xlsx/tdf115012.xlsx | Bin 0 -> 13729 bytes .../xlsx/tdf119138-missing-autotitledeleted.xlsx | Bin 0 -> 8424 bytes chart2/qa/extras/data/xlsx/tdf122031.xlsx | Bin 0 -> 13229 bytes chart2/qa/extras/data/xlsx/tdf122915.xlsx | Bin 0 -> 14310 bytes chart2/qa/extras/data/xlsx/tdf124817.xlsx | Bin 0 -> 20868 bytes chart2/qa/extras/data/xlsx/tdf126033.xlsx | Bin 0 -> 20012 bytes chart2/qa/extras/data/xlsx/tdf126115.xlsx | Bin 0 -> 20173 bytes chart2/qa/extras/data/xlsx/tdf127777.xlsx | Bin 0 -> 14421 bytes chart2/qa/extras/data/xlsx/tdf128619.xlsx | Bin 0 -> 13658 bytes chart2/qa/extras/data/xlsx/tdf128627.xlsx | Bin 0 -> 14307 bytes chart2/qa/extras/data/xlsx/tdf128633.xlsx | Bin 0 -> 15018 bytes chart2/qa/extras/data/xlsx/tdf128634.xlsx | Bin 0 -> 14185 bytes chart2/qa/extras/data/xlsx/tdf128732.xlsx | Bin 0 -> 7511 bytes chart2/qa/extras/data/xlsx/tdf130657.xlsx | Bin 0 -> 7468 bytes chart2/qa/extras/data/xlsx/tdf130986.xlsx | Bin 0 -> 15393 bytes chart2/qa/extras/data/xlsx/tdf132076.xlsx | Bin 0 -> 14632 bytes .../qa/extras/data/xlsx/tdf133190_tdf133191.xlsx | Bin 0 -> 12142 bytes chart2/qa/extras/data/xlsx/tdf133376.xlsx | Bin 0 -> 12736 bytes chart2/qa/extras/data/xlsx/tdf134225.xlsx | Bin 0 -> 13956 bytes .../qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx | Bin 0 -> 25538 bytes .../extras/data/xlsx/tdf135184RoundLineCap2.xlsx | Bin 0 -> 21937 bytes chart2/qa/extras/data/xlsx/tdf136267.xlsx | Bin 0 -> 31986 bytes chart2/qa/extras/data/xlsx/tdf90876.xlsx | Bin 0 -> 12736 bytes chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx | Bin 0 -> 13917 bytes .../qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx | Bin 0 -> 15501 bytes .../qa/extras/data/xlsx/testAutoTitleDeleted.xlsx | Bin 0 -> 15097 bytes .../data/xlsx/testBarChartDataPointPropXLSX.xlsx | Bin 0 -> 14007 bytes .../xlsx/testChartTitlePropertiesBitmapFill.xlsx | Bin 0 -> 49790 bytes .../xlsx/testChartTitlePropertiesColorFill.xlsx | Bin 0 -> 11515 bytes .../xlsx/testChartTitlePropertiesGradientFill.xlsx | Bin 0 -> 7542 bytes .../qa/extras/data/xlsx/testCombinedChartAxis.xlsx | Bin 0 -> 20857 bytes .../extras/data/xlsx/testCustomPosDataLabels.xlsx | Bin 0 -> 14332 bytes .../data/xlsx/testDataPointLabelCustomPos.xlsx | Bin 0 -> 15069 bytes .../xlsx/testDataseriesOverlapStackedChart.xlsx | Bin 0 -> 11007 bytes chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx | Bin 0 -> 14559 bytes chart2/qa/extras/data/xlsx/testTdf130032.xlsx | Bin 0 -> 14208 bytes chart2/qa/extras/data/xlsx/testTdf90749.xlsx | Bin 0 -> 14505 bytes .../data/xlsx/title_character_properties.xlsx | Bin 0 -> 10355 bytes .../qa/extras/data/xlsx/title_manual_layout.xlsx | Bin 0 -> 13160 bytes chart2/qa/extras/data/xlsx/trendline.xlsx | Bin 0 -> 13397 bytes chart2/qa/extras/data/xlsx/trendline2007.xlsx | Bin 0 -> 12514 bytes chart2/qa/extras/data/xlsx/vary_color.xlsx | Bin 0 -> 13935 bytes chart2/qa/extras/data/xlsx/vary_color2007.xlsx | Bin 0 -> 13142 bytes .../qa/extras/data/xlsx/xAxisLabelsRotation.xlsx | Bin 0 -> 13601 bytes chart2/qa/extras/xshape/chart2xshape.cxx | 253 ++ chart2/qa/extras/xshape/data/ods/fdo75075.ods | Bin 0 -> 15763 bytes .../xshape/data/ods/property-mapping-bar.ods | Bin 0 -> 15481 bytes .../xshape/data/ods/tdf76649_TrendLineBug.ods | Bin 0 -> 12060 bytes chart2/qa/extras/xshape/data/ods/tdf90839-4.ods | Bin 0 -> 19789 bytes .../data/pptx/tdf88154_LabelRotatedLayout.pptx | Bin 0 -> 34771 bytes .../qa/extras/xshape/data/reference/fdo75075.xml | 1692 +++++++++++ .../xshape/data/reference/property-mapping-bar.xml | 1164 ++++++++ .../qa/extras/xshape/data/reference/tdf90839-1.xml | 336 +++ .../qa/extras/xshape/data/reference/tdf90839-2.xml | 336 +++ .../qa/extras/xshape/data/reference/tdf90839-3.xml | 336 +++ .../qa/extras/xshape/data/reference/tdf90839-4.xml | 336 +++ chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx | Bin 0 -> 13209 bytes chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx | Bin 0 -> 12601 bytes chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx | Bin 0 -> 13312 bytes chart2/qa/unit/chart2-dialogs-test.cxx | 61 + chart2/qa/unit/common_functor_test.cxx | 90 + chart2/qa/unit/data/chart2-dialogs-test.txt | 69 + chart2/qa/unit/data/ods/testChart.ods | Bin 0 -> 11156 bytes chart2/qa/unit/data/reference/testChart.xml | 1216 ++++++++ chart2/qa/unit/data/tolerance.xml | 7 + chart2/qa/unoapi/knownissues.xcl | 58 + chart2/qa/unoapi/sch.sce | 42 + .../qa/unoapi/testdocuments/TransparencyChart.sxs | Bin 0 -> 10810 bytes chart2/qa/unoapi/testdocuments/emptyChart.sds | Bin 0 -> 44544 bytes chart2/qa/unoapi/testdocuments/space-metal.jpg | Bin 0 -> 4313 bytes chart2/source/chartcore.component | 259 ++ .../controller/accessibility/AccessibleBase.cxx | 865 ++++++ .../accessibility/AccessibleChartElement.cxx | 244 ++ .../accessibility/AccessibleChartElement.hxx | 107 + .../accessibility/AccessibleChartShape.cxx | 251 ++ .../accessibility/AccessibleChartShape.hxx | 86 + .../accessibility/AccessibleChartView.cxx | 358 +++ .../accessibility/AccessibleTextHelper.cxx | 167 ++ .../accessibility/AccessibleViewForwarder.cxx | 79 + .../accessibility/AccessibleViewForwarder.hxx | 57 + .../accessibility/ChartElementFactory.cxx | 71 + .../accessibility/ChartElementFactory.hxx | 41 + .../controller/chartapiwrapper/AreaWrapper.cxx | 177 ++ .../controller/chartapiwrapper/AreaWrapper.hxx | 88 + .../controller/chartapiwrapper/AxisWrapper.cxx | 674 +++++ .../controller/chartapiwrapper/AxisWrapper.hxx | 130 + .../chartapiwrapper/Chart2ModelContact.cxx | 295 ++ .../chartapiwrapper/Chart2ModelContact.hxx | 155 + .../chartapiwrapper/ChartDataWrapper.cxx | 695 +++++ .../chartapiwrapper/ChartDataWrapper.hxx | 125 + .../chartapiwrapper/ChartDocumentWrapper.cxx | 1454 +++++++++ .../chartapiwrapper/DataSeriesPointWrapper.cxx | 885 ++++++ .../chartapiwrapper/DataSeriesPointWrapper.hxx | 131 + .../controller/chartapiwrapper/DiagramWrapper.cxx | 1930 ++++++++++++ .../controller/chartapiwrapper/DiagramWrapper.hxx | 224 ++ .../controller/chartapiwrapper/GridWrapper.cxx | 187 ++ .../controller/chartapiwrapper/GridWrapper.hxx | 88 + .../controller/chartapiwrapper/LegendWrapper.cxx | 423 +++ .../controller/chartapiwrapper/LegendWrapper.hxx | 95 + .../chartapiwrapper/MinMaxLineWrapper.cxx | 393 +++ .../chartapiwrapper/MinMaxLineWrapper.hxx | 112 + .../ReferenceSizePropertyProvider.hxx | 45 + .../controller/chartapiwrapper/TitleWrapper.cxx | 512 ++++ .../controller/chartapiwrapper/TitleWrapper.hxx | 117 + .../chartapiwrapper/UpDownBarWrapper.cxx | 361 +++ .../chartapiwrapper/UpDownBarWrapper.hxx | 113 + .../chartapiwrapper/WallFloorWrapper.cxx | 169 ++ .../chartapiwrapper/WallFloorWrapper.hxx | 77 + .../chartapiwrapper/WrappedAddInProperty.cxx | 121 + .../chartapiwrapper/WrappedAddInProperty.hxx | 94 + .../WrappedAutomaticPositionProperties.cxx | 123 + .../WrappedAutomaticPositionProperties.hxx | 46 + .../WrappedAxisAndGridExistenceProperties.cxx | 403 +++ .../WrappedAxisAndGridExistenceProperties.hxx | 60 + .../WrappedCharacterHeightProperty.cxx | 138 + .../WrappedCharacterHeightProperty.hxx | 84 + .../WrappedDataCaptionProperties.cxx | 150 + .../WrappedDataCaptionProperties.hxx | 51 + .../chartapiwrapper/WrappedGapwidthProperty.cxx | 171 ++ .../chartapiwrapper/WrappedGapwidthProperty.hxx | 80 + .../WrappedNumberFormatProperty.cxx | 121 + .../WrappedNumberFormatProperty.hxx | 71 + .../chartapiwrapper/WrappedScaleProperty.cxx | 584 ++++ .../chartapiwrapper/WrappedScaleProperty.hxx | 90 + .../chartapiwrapper/WrappedScaleTextProperties.cxx | 138 + .../chartapiwrapper/WrappedScaleTextProperties.hxx | 46 + .../chartapiwrapper/WrappedSceneProperty.cxx | 101 + .../chartapiwrapper/WrappedSceneProperty.hxx | 62 + .../WrappedSeriesAreaOrLineProperty.cxx | 51 + .../WrappedSeriesAreaOrLineProperty.hxx | 52 + .../WrappedSeriesOrDiagramProperty.hxx | 173 ++ .../chartapiwrapper/WrappedSplineProperties.cxx | 291 ++ .../chartapiwrapper/WrappedSplineProperties.hxx | 49 + .../chartapiwrapper/WrappedStatisticProperties.cxx | 1072 +++++++ .../chartapiwrapper/WrappedStatisticProperties.hxx | 51 + .../chartapiwrapper/WrappedStockProperties.cxx | 281 ++ .../chartapiwrapper/WrappedStockProperties.hxx | 49 + .../chartapiwrapper/WrappedSymbolProperties.cxx | 530 ++++ .../chartapiwrapper/WrappedSymbolProperties.hxx | 51 + .../WrappedTextRotationProperty.cxx | 71 + .../WrappedTextRotationProperty.hxx | 47 + chart2/source/controller/chartcontroller.component | 58 + .../source/controller/dialogs/ChangingResource.cxx | 43 + .../controller/dialogs/ChartResourceGroupDlgs.cxx | 131 + .../controller/dialogs/ChartResourceGroups.cxx | 359 +++ .../dialogs/ChartTypeDialogController.cxx | 1253 ++++++++ chart2/source/controller/dialogs/DataBrowser.cxx | 1389 +++++++++ chart2/source/controller/dialogs/DataBrowser.hxx | 191 ++ .../source/controller/dialogs/DataBrowserModel.cxx | 963 ++++++ .../source/controller/dialogs/DataBrowserModel.hxx | 167 ++ chart2/source/controller/dialogs/DialogModel.cxx | 860 ++++++ chart2/source/controller/dialogs/DialogModel.hxx | 183 ++ .../controller/dialogs/ObjectNameProvider.cxx | 865 ++++++ .../controller/dialogs/RangeSelectionHelper.cxx | 177 ++ .../controller/dialogs/RangeSelectionListener.cxx | 61 + .../controller/dialogs/TextDirectionListBox.cxx | 36 + .../dialogs/TimerTriggeredControllerLock.cxx | 55 + .../source/controller/dialogs/TitleDialogData.cxx | 115 + chart2/source/controller/dialogs/dlg_ChartType.cxx | 51 + .../controller/dialogs/dlg_ChartType_UNO.cxx | 106 + .../controller/dialogs/dlg_CreationWizard.cxx | 199 ++ .../controller/dialogs/dlg_CreationWizard_UNO.cxx | 349 +++ .../source/controller/dialogs/dlg_DataEditor.cxx | 149 + .../source/controller/dialogs/dlg_DataSource.cxx | 182 ++ .../controller/dialogs/dlg_InsertAxis_Grid.cxx | 92 + .../controller/dialogs/dlg_InsertDataLabel.cxx | 43 + .../controller/dialogs/dlg_InsertErrorBars.cxx | 101 + .../source/controller/dialogs/dlg_InsertLegend.cxx | 46 + .../source/controller/dialogs/dlg_InsertTitle.cxx | 42 + .../source/controller/dialogs/dlg_NumberFormat.cxx | 60 + .../source/controller/dialogs/dlg_NumberFormat.hxx | 43 + .../controller/dialogs/dlg_ObjectProperties.cxx | 624 ++++ chart2/source/controller/dialogs/dlg_ShapeFont.cxx | 61 + .../controller/dialogs/dlg_ShapeParagraph.cxx | 66 + chart2/source/controller/dialogs/dlg_View3D.cxx | 82 + .../source/controller/dialogs/res_BarGeometry.cxx | 66 + chart2/source/controller/dialogs/res_DataLabel.cxx | 359 +++ chart2/source/controller/dialogs/res_DataLabel.hxx | 96 + chart2/source/controller/dialogs/res_ErrorBar.cxx | 718 +++++ .../controller/dialogs/res_LegendPosition.cxx | 237 ++ chart2/source/controller/dialogs/res_Titles.cxx | 134 + chart2/source/controller/dialogs/res_Trendline.cxx | 392 +++ chart2/source/controller/dialogs/res_Trendline.hxx | 100 + .../controller/dialogs/tp_3D_SceneAppearance.cxx | 320 ++ .../controller/dialogs/tp_3D_SceneAppearance.hxx | 71 + .../controller/dialogs/tp_3D_SceneGeometry.cxx | 253 ++ .../controller/dialogs/tp_3D_SceneGeometry.hxx | 88 + .../controller/dialogs/tp_3D_SceneIllumination.cxx | 529 ++++ .../controller/dialogs/tp_3D_SceneIllumination.hxx | 97 + chart2/source/controller/dialogs/tp_AxisLabel.cxx | 303 ++ chart2/source/controller/dialogs/tp_AxisLabel.hxx | 86 + .../source/controller/dialogs/tp_AxisPositions.cxx | 314 ++ .../source/controller/dialogs/tp_AxisPositions.hxx | 87 + chart2/source/controller/dialogs/tp_ChartType.cxx | 374 +++ chart2/source/controller/dialogs/tp_ChartType.hxx | 96 + chart2/source/controller/dialogs/tp_DataLabel.cxx | 54 + chart2/source/controller/dialogs/tp_DataLabel.hxx | 49 + .../controller/dialogs/tp_DataPointOption.cxx | 68 + .../controller/dialogs/tp_DataPointOption.hxx | 51 + chart2/source/controller/dialogs/tp_DataSource.cxx | 928 ++++++ chart2/source/controller/dialogs/tp_DataSource.hxx | 149 + chart2/source/controller/dialogs/tp_ErrorBars.cxx | 67 + chart2/source/controller/dialogs/tp_ErrorBars.hxx | 51 + .../controller/dialogs/tp_LegendPosition.cxx | 78 + .../controller/dialogs/tp_LegendPosition.hxx | 52 + .../source/controller/dialogs/tp_PointGeometry.cxx | 80 + .../source/controller/dialogs/tp_PointGeometry.hxx | 46 + .../source/controller/dialogs/tp_PolarOptions.cxx | 105 + .../source/controller/dialogs/tp_PolarOptions.hxx | 60 + .../source/controller/dialogs/tp_RangeChooser.cxx | 382 +++ .../source/controller/dialogs/tp_RangeChooser.hxx | 102 + chart2/source/controller/dialogs/tp_Scale.cxx | 604 ++++ chart2/source/controller/dialogs/tp_Scale.hxx | 111 + .../source/controller/dialogs/tp_SeriesToAxis.cxx | 248 ++ .../source/controller/dialogs/tp_SeriesToAxis.hxx | 80 + .../source/controller/dialogs/tp_TitleRotation.cxx | 123 + .../source/controller/dialogs/tp_TitleRotation.hxx | 65 + chart2/source/controller/dialogs/tp_Trendline.cxx | 59 + chart2/source/controller/dialogs/tp_Trendline.hxx | 49 + .../dialogs/tp_Wizard_TitlesAndObjects.cxx | 158 + .../dialogs/tp_Wizard_TitlesAndObjects.hxx | 72 + .../controller/drawinglayer/DrawViewWrapper.cxx | 387 +++ .../drawinglayer/ViewElementListProvider.cxx | 200 ++ chart2/source/controller/inc/AccessibleBase.hxx | 331 +++ .../source/controller/inc/AccessibleChartView.hxx | 120 + .../source/controller/inc/AccessibleTextHelper.hxx | 94 + chart2/source/controller/inc/AxisItemConverter.hxx | 76 + .../inc/CharacterPropertyItemConverter.hxx | 62 + chart2/source/controller/inc/ChartController.hxx | 559 ++++ .../source/controller/inc/ChartDocumentWrapper.hxx | 176 ++ .../controller/inc/ChartToolbarController.hxx | 84 + chart2/source/controller/inc/ChartWindow.hxx | 94 + .../controller/inc/CommandDispatchContainer.hxx | 140 + .../source/controller/inc/ConfigurationAccess.hxx | 44 + .../controller/inc/DataPointItemConverter.hxx | 91 + chart2/source/controller/inc/DrawViewWrapper.hxx | 102 + .../controller/inc/ErrorBarItemConverter.hxx | 66 + .../inc/GraphicPropertyItemConverter.hxx | 71 + chart2/source/controller/inc/ItemConverter.hxx | 198 ++ chart2/source/controller/inc/ItemPropertyMap.hxx | 37 + .../source/controller/inc/LegendItemConverter.hxx | 68 + .../controller/inc/MultipleChartConverters.hxx | 106 + .../controller/inc/MultipleItemConverter.hxx | 49 + chart2/source/controller/inc/ObjectHierarchy.hxx | 108 + .../source/controller/inc/ObjectNameProvider.hxx | 72 + .../controller/inc/PositionAndSizeHelper.hxx | 50 + .../source/controller/inc/RangeSelectionHelper.hxx | 75 + .../controller/inc/RangeSelectionListener.hxx | 71 + .../inc/RegressionCurveItemConverter.hxx | 66 + .../inc/RegressionEquationItemConverter.hxx | 64 + chart2/source/controller/inc/SelectionHelper.hxx | 117 + .../controller/inc/SeriesOptionsItemConverter.hxx | 87 + chart2/source/controller/inc/ShapeController.h | 38 + .../controller/inc/StatisticsItemConverter.hxx | 57 + chart2/source/controller/inc/TabPageNotifiable.hxx | 47 + .../source/controller/inc/TextDirectionListBox.hxx | 39 + .../controller/inc/TextLabelItemConverter.hxx | 73 + .../inc/TimerTriggeredControllerLock.hxx | 51 + chart2/source/controller/inc/TitleDialogData.hxx | 53 + .../source/controller/inc/TitleItemConverter.hxx | 62 + .../controller/inc/ViewElementListProvider.hxx | 63 + chart2/source/controller/inc/dlg_ChartType.hxx | 47 + chart2/source/controller/inc/dlg_ChartType_UNO.hxx | 67 + .../source/controller/inc/dlg_CreationWizard.hxx | 80 + .../controller/inc/dlg_CreationWizard_UNO.hxx | 118 + chart2/source/controller/inc/dlg_DataEditor.hxx | 75 + chart2/source/controller/inc/dlg_DataSource.hxx | 83 + .../source/controller/inc/dlg_InsertAxis_Grid.hxx | 71 + .../source/controller/inc/dlg_InsertDataLabel.hxx | 49 + .../source/controller/inc/dlg_InsertErrorBars.hxx | 57 + chart2/source/controller/inc/dlg_InsertLegend.hxx | 50 + chart2/source/controller/inc/dlg_InsertTitle.hxx | 43 + .../source/controller/inc/dlg_ObjectProperties.hxx | 148 + chart2/source/controller/inc/dlg_ShapeFont.hxx | 47 + .../source/controller/inc/dlg_ShapeParagraph.hxx | 42 + chart2/source/controller/inc/dlg_View3D.hxx | 58 + chart2/source/controller/inc/helpids.h | 34 + chart2/source/controller/inc/res_ErrorBar.hxx | 144 + .../source/controller/inc/res_LegendPosition.hxx | 75 + chart2/source/controller/inc/res_Titles.hxx | 68 + chart2/source/controller/inc/uiobject.hxx | 68 + .../itemsetwrapper/AxisItemConverter.cxx | 989 +++++++ .../CharacterPropertyItemConverter.cxx | 556 ++++ .../itemsetwrapper/DataPointItemConverter.cxx | 782 +++++ .../itemsetwrapper/ErrorBarItemConverter.cxx | 433 +++ .../GraphicPropertyItemConverter.cxx | 752 +++++ .../controller/itemsetwrapper/ItemConverter.cxx | 223 ++ .../itemsetwrapper/LegendItemConverter.cxx | 208 ++ .../itemsetwrapper/MultipleChartConverters.cxx | 194 ++ .../itemsetwrapper/MultipleItemConverter.cxx | 72 + .../RegressionCurveItemConverter.cxx | 335 +++ .../RegressionEquationItemConverter.cxx | 149 + .../controller/itemsetwrapper/SchWhichPairs.hxx | 244 ++ .../itemsetwrapper/SeriesOptionsItemConverter.cxx | 438 +++ .../itemsetwrapper/StatisticsItemConverter.cxx | 849 ++++++ .../itemsetwrapper/TextLabelItemConverter.cxx | 680 +++++ .../itemsetwrapper/TitleItemConverter.cxx | 210 ++ chart2/source/controller/main/ChartController.cxx | 1659 +++++++++++ .../controller/main/ChartController_EditData.cxx | 55 + .../controller/main/ChartController_Insert.cxx | 877 ++++++ .../controller/main/ChartController_Position.cxx | 210 ++ .../controller/main/ChartController_Properties.cxx | 829 ++++++ .../controller/main/ChartController_TextEdit.cxx | 220 ++ .../controller/main/ChartController_Tools.cxx | 990 +++++++ .../controller/main/ChartController_Window.cxx | 2121 +++++++++++++ .../controller/main/ChartDropTargetHelper.cxx | 176 ++ .../controller/main/ChartDropTargetHelper.hxx | 58 + chart2/source/controller/main/ChartFrameloader.cxx | 201 ++ chart2/source/controller/main/ChartFrameloader.hxx | 70 + chart2/source/controller/main/ChartModelClone.cxx | 249 ++ chart2/source/controller/main/ChartModelClone.hxx | 76 + .../source/controller/main/ChartTransferable.cxx | 164 ++ .../source/controller/main/ChartTransferable.hxx | 64 + chart2/source/controller/main/ChartWindow.cxx | 392 +++ chart2/source/controller/main/CommandDispatch.cxx | 170 ++ chart2/source/controller/main/CommandDispatch.hxx | 136 + .../controller/main/CommandDispatchContainer.cxx | 198 ++ .../source/controller/main/ConfigurationAccess.cxx | 99 + .../controller/main/ControllerCommandDispatch.cxx | 837 ++++++ .../controller/main/ControllerCommandDispatch.hxx | 123 + chart2/source/controller/main/DragMethod_Base.cxx | 77 + chart2/source/controller/main/DragMethod_Base.hxx | 62 + .../controller/main/DragMethod_PieSegment.cxx | 152 + .../controller/main/DragMethod_PieSegment.hxx | 58 + .../controller/main/DragMethod_RotateDiagram.cxx | 229 ++ .../controller/main/DragMethod_RotateDiagram.hxx | 90 + .../source/controller/main/DrawCommandDispatch.cxx | 619 ++++ .../source/controller/main/DrawCommandDispatch.h | 42 + .../source/controller/main/DrawCommandDispatch.hxx | 76 + chart2/source/controller/main/ElementSelector.cxx | 328 +++ chart2/source/controller/main/ElementSelector.hxx | 104 + .../controller/main/FeatureCommandDispatchBase.cxx | 94 + .../controller/main/FeatureCommandDispatchBase.hxx | 101 + chart2/source/controller/main/ObjectHierarchy.cxx | 845 ++++++ .../controller/main/PositionAndSizeHelper.cxx | 180 ++ chart2/source/controller/main/SelectionHelper.cxx | 650 ++++ chart2/source/controller/main/ShapeController.cxx | 676 +++++ chart2/source/controller/main/ShapeController.hxx | 85 + .../controller/main/StatusBarCommandDispatch.cxx | 128 + .../controller/main/StatusBarCommandDispatch.hxx | 97 + .../source/controller/main/ToolbarController.cxx | 124 + chart2/source/controller/main/UndoActions.cxx | 123 + chart2/source/controller/main/UndoActions.hxx | 115 + .../source/controller/main/UndoCommandDispatch.cxx | 147 + .../source/controller/main/UndoCommandDispatch.hxx | 71 + chart2/source/controller/main/UndoGuard.cxx | 151 + chart2/source/controller/main/UndoGuard.hxx | 118 + .../controller/sidebar/Chart2PanelFactory.cxx | 154 + .../controller/sidebar/Chart2PanelFactory.hxx | 61 + .../source/controller/sidebar/ChartAreaPanel.cxx | 536 ++++ .../source/controller/sidebar/ChartAreaPanel.hxx | 89 + .../source/controller/sidebar/ChartAxisPanel.cxx | 390 +++ .../source/controller/sidebar/ChartAxisPanel.hxx | 103 + .../controller/sidebar/ChartColorWrapper.cxx | 213 ++ .../controller/sidebar/ChartColorWrapper.hxx | 68 + .../controller/sidebar/ChartElementsPanel.cxx | 634 ++++ .../controller/sidebar/ChartElementsPanel.hxx | 119 + .../controller/sidebar/ChartErrorBarPanel.cxx | 434 +++ .../controller/sidebar/ChartErrorBarPanel.hxx | 96 + .../source/controller/sidebar/ChartLinePanel.cxx | 280 ++ .../source/controller/sidebar/ChartLinePanel.hxx | 89 + .../source/controller/sidebar/ChartSeriesPanel.cxx | 488 +++ .../source/controller/sidebar/ChartSeriesPanel.hxx | 115 + .../sidebar/ChartSidebarModifyListener.cxx | 44 + .../sidebar/ChartSidebarModifyListener.hxx | 48 + .../sidebar/ChartSidebarSelectionListener.cxx | 84 + .../sidebar/ChartSidebarSelectionListener.hxx | 57 + .../source/controller/sidebar/ChartTypePanel.cxx | 438 +++ .../source/controller/sidebar/ChartTypePanel.hxx | 137 + chart2/source/controller/uitest/uiobject.cxx | 201 ++ chart2/source/inc/AxisHelper.hxx | 208 ++ chart2/source/inc/AxisIndexDefines.hxx | 33 + chart2/source/inc/BaseGFXHelper.hxx | 89 + chart2/source/inc/CachedDataSequence.hxx | 168 ++ chart2/source/inc/ChangingResource.hxx | 48 + chart2/source/inc/CharacterProperties.hxx | 140 + chart2/source/inc/ChartModelHelper.hxx | 89 + chart2/source/inc/ChartResourceGroupDlgs.hxx | 65 + chart2/source/inc/ChartResourceGroups.hxx | 149 + chart2/source/inc/ChartTypeDialogController.hxx | 363 +++ chart2/source/inc/ChartTypeHelper.hxx | 88 + chart2/source/inc/ChartTypeTemplateProvider.hxx | 51 + chart2/source/inc/ChartViewHelper.hxx | 39 + chart2/source/inc/CloneHelper.hxx | 78 + chart2/source/inc/ColorPerPointHelper.hxx | 50 + chart2/source/inc/CommonConverters.hxx | 214 ++ chart2/source/inc/CommonFunctors.hxx | 133 + chart2/source/inc/ConfigColorScheme.hxx | 79 + chart2/source/inc/ControllerLockGuard.hxx | 95 + chart2/source/inc/DataSeriesHelper.hxx | 184 ++ chart2/source/inc/DataSource.hxx | 66 + chart2/source/inc/DataSourceHelper.hxx | 134 + chart2/source/inc/DiagramHelper.hxx | 298 ++ chart2/source/inc/DisposeHelper.hxx | 58 + chart2/source/inc/ErrorBar.hxx | 144 + chart2/source/inc/EventListenerHelper.hxx | 124 + chart2/source/inc/ExplicitCategoriesProvider.hxx | 117 + .../inc/ExponentialRegressionCurveCalculator.hxx | 66 + chart2/source/inc/FastPropertyIdRanges.hxx | 51 + chart2/source/inc/FillProperties.hxx | 78 + chart2/source/inc/FormattedStringHelper.hxx | 46 + chart2/source/inc/InternalData.hxx | 99 + chart2/source/inc/InternalDataProvider.hxx | 219 ++ chart2/source/inc/LabeledDataSequence.hxx | 92 + chart2/source/inc/LegendHelper.hxx | 57 + chart2/source/inc/LifeTime.hxx | 215 ++ chart2/source/inc/LinePropertiesHelper.hxx | 72 + .../source/inc/LinearRegressionCurveCalculator.hxx | 54 + .../inc/LogarithmicRegressionCurveCalculator.hxx | 64 + .../inc/MeanValueRegressionCurveCalculator.hxx | 63 + chart2/source/inc/MediaDescriptorHelper.hxx | 93 + chart2/source/inc/ModifyListenerHelper.hxx | 266 ++ .../inc/MovingAverageRegressionCurveCalculator.hxx | 63 + chart2/source/inc/MutexContainer.hxx | 41 + chart2/source/inc/NameContainer.hxx | 91 + chart2/source/inc/NumberFormatterWrapper.hxx | 71 + chart2/source/inc/OPropertySet.hxx | 208 ++ chart2/source/inc/ObjectIdentifier.hxx | 254 ++ .../inc/PolynomialRegressionCurveCalculator.hxx | 64 + chart2/source/inc/PopupRequest.hxx | 57 + .../inc/PotentialRegressionCurveCalculator.hxx | 65 + chart2/source/inc/PropertyHelper.hxx | 152 + chart2/source/inc/RangeHighlighter.hxx | 106 + chart2/source/inc/ReferenceSizeProvider.hxx | 132 + chart2/source/inc/RegressionCalculationHelper.hxx | 142 + chart2/source/inc/RegressionCurveCalculator.hxx | 105 + chart2/source/inc/RegressionCurveHelper.hxx | 184 ++ chart2/source/inc/RelativePositionHelper.hxx | 105 + chart2/source/inc/RelativeSizeHelper.hxx | 54 + chart2/source/inc/ResId.hxx | 35 + chart2/source/inc/Scaling.hxx | 161 + chart2/source/inc/SceneProperties.hxx | 85 + chart2/source/inc/StackMode.hxx | 39 + chart2/source/inc/StatisticsHelper.hxx | 107 + chart2/source/inc/ThreeDHelper.hxx | 132 + chart2/source/inc/TitleHelper.hxx | 102 + chart2/source/inc/TrueGuard.hxx | 39 + chart2/source/inc/UncachedDataSequence.hxx | 175 ++ chart2/source/inc/UserDefinedProperties.hxx | 58 + chart2/source/inc/WeakListenerAdapter.hxx | 107 + chart2/source/inc/WrappedDefaultProperty.hxx | 53 + chart2/source/inc/WrappedDirectStateProperty.hxx | 45 + chart2/source/inc/WrappedIgnoreProperty.hxx | 66 + chart2/source/inc/WrappedProperty.hxx | 90 + chart2/source/inc/WrappedPropertySet.hxx | 126 + chart2/source/inc/XMLRangeHelper.hxx | 67 + chart2/source/inc/charttoolsdllapi.hxx | 35 + chart2/source/inc/chartview/ChartSfxItemIds.hxx | 228 ++ .../inc/chartview/DataPointSymbolSupplier.hxx | 45 + chart2/source/inc/chartview/DrawModelWrapper.hxx | 93 + .../source/inc/chartview/ExplicitScaleValues.hxx | 154 + .../source/inc/chartview/ExplicitValueProvider.hxx | 98 + chart2/source/inc/chartview/chartviewdllapi.hxx | 35 + chart2/source/inc/defines.hxx | 27 + chart2/source/inc/res_BarGeometry.hxx | 48 + chart2/source/inc/servicenames.hxx | 55 + chart2/source/inc/servicenames_charttypes.hxx | 39 + chart2/source/inc/servicenames_coosystems.hxx | 31 + chart2/source/model/filter/XMLFilter.cxx | 786 +++++ chart2/source/model/inc/BaseCoordinateSystem.hxx | 129 + .../source/model/inc/CartesianCoordinateSystem.hxx | 76 + chart2/source/model/inc/ChartTypeManager.hxx | 74 + chart2/source/model/inc/DataSeries.hxx | 172 ++ chart2/source/model/inc/Diagram.hxx | 186 ++ chart2/source/model/inc/PolarCoordinateSystem.hxx | 76 + chart2/source/model/inc/StockBar.hxx | 96 + chart2/source/model/inc/XMLFilter.hxx | 171 ++ chart2/source/model/main/Axis.cxx | 632 ++++ chart2/source/model/main/Axis.hxx | 138 + chart2/source/model/main/BaseCoordinateSystem.cxx | 361 +++ .../model/main/CartesianCoordinateSystem.cxx | 160 + chart2/source/model/main/ChartModel.cxx | 1301 ++++++++ .../source/model/main/ChartModel_Persistence.cxx | 809 +++++ chart2/source/model/main/DataPoint.cxx | 293 ++ chart2/source/model/main/DataPoint.hxx | 116 + chart2/source/model/main/DataPointProperties.cxx | 540 ++++ chart2/source/model/main/DataPointProperties.hxx | 107 + chart2/source/model/main/DataSeries.cxx | 565 ++++ chart2/source/model/main/DataSeriesProperties.cxx | 92 + chart2/source/model/main/DataSeriesProperties.hxx | 55 + chart2/source/model/main/Diagram.cxx | 704 +++++ chart2/source/model/main/FormattedString.cxx | 284 ++ chart2/source/model/main/FormattedString.hxx | 140 + chart2/source/model/main/GridProperties.cxx | 249 ++ chart2/source/model/main/GridProperties.hxx | 105 + chart2/source/model/main/Legend.cxx | 315 ++ chart2/source/model/main/Legend.hxx | 107 + chart2/source/model/main/PageBackground.cxx | 230 ++ chart2/source/model/main/PageBackground.hxx | 104 + chart2/source/model/main/PolarCoordinateSystem.cxx | 157 + chart2/source/model/main/StockBar.cxx | 213 ++ chart2/source/model/main/Title.cxx | 390 +++ chart2/source/model/main/Title.hxx | 115 + chart2/source/model/main/UndoManager.cxx | 350 +++ chart2/source/model/main/UndoManager.hxx | 94 + chart2/source/model/main/Wall.cxx | 201 ++ chart2/source/model/main/Wall.hxx | 99 + chart2/source/model/template/AreaChartType.cxx | 79 + chart2/source/model/template/AreaChartType.hxx | 55 + .../model/template/AreaChartTypeTemplate.cxx | 237 ++ .../model/template/AreaChartTypeTemplate.hxx | 86 + chart2/source/model/template/BarChartType.cxx | 89 + chart2/source/model/template/BarChartType.hxx | 57 + .../source/model/template/BarChartTypeTemplate.cxx | 311 ++ .../source/model/template/BarChartTypeTemplate.hxx | 102 + chart2/source/model/template/BubbleChartType.cxx | 220 ++ chart2/source/model/template/BubbleChartType.hxx | 72 + .../model/template/BubbleChartTypeTemplate.cxx | 211 ++ .../model/template/BubbleChartTypeTemplate.hxx | 78 + .../model/template/BubbleDataInterpreter.cxx | 290 ++ .../model/template/BubbleDataInterpreter.hxx | 50 + .../source/model/template/CandleStickChartType.cxx | 342 +++ .../source/model/template/CandleStickChartType.hxx | 75 + chart2/source/model/template/ChartType.cxx | 308 ++ chart2/source/model/template/ChartType.hxx | 141 + chart2/source/model/template/ChartTypeManager.cxx | 606 ++++ chart2/source/model/template/ChartTypeTemplate.cxx | 877 ++++++ chart2/source/model/template/ChartTypeTemplate.hxx | 256 ++ chart2/source/model/template/ColumnChartType.cxx | 206 ++ chart2/source/model/template/ColumnChartType.hxx | 65 + .../model/template/ColumnLineChartTypeTemplate.cxx | 410 +++ .../model/template/ColumnLineChartTypeTemplate.hxx | 101 + .../model/template/ColumnLineDataInterpreter.cxx | 80 + .../model/template/ColumnLineDataInterpreter.hxx | 50 + chart2/source/model/template/DataInterpreter.cxx | 441 +++ chart2/source/model/template/DataInterpreter.hxx | 79 + .../source/model/template/FilledNetChartType.cxx | 84 + .../source/model/template/FilledNetChartType.hxx | 55 + chart2/source/model/template/LineChartType.cxx | 208 ++ chart2/source/model/template/LineChartType.hxx | 63 + .../model/template/LineChartTypeTemplate.cxx | 374 +++ .../model/template/LineChartTypeTemplate.hxx | 90 + chart2/source/model/template/NetChartType.cxx | 183 ++ chart2/source/model/template/NetChartType.hxx | 78 + .../source/model/template/NetChartTypeTemplate.cxx | 194 ++ .../source/model/template/NetChartTypeTemplate.hxx | 71 + chart2/source/model/template/PieChartType.cxx | 241 ++ chart2/source/model/template/PieChartType.hxx | 69 + .../source/model/template/PieChartTypeTemplate.cxx | 608 ++++ .../source/model/template/PieChartTypeTemplate.hxx | 112 + chart2/source/model/template/ScatterChartType.cxx | 251 ++ chart2/source/model/template/ScatterChartType.hxx | 69 + .../model/template/ScatterChartTypeTemplate.cxx | 391 +++ .../model/template/ScatterChartTypeTemplate.hxx | 90 + .../model/template/StockChartTypeTemplate.cxx | 499 ++++ .../model/template/StockChartTypeTemplate.hxx | 120 + .../source/model/template/StockDataInterpreter.cxx | 319 ++ .../source/model/template/StockDataInterpreter.hxx | 58 + chart2/source/model/template/XYDataInterpreter.cxx | 252 ++ chart2/source/model/template/XYDataInterpreter.hxx | 50 + chart2/source/tools/AxisHelper.cxx | 1158 ++++++++ chart2/source/tools/BaseGFXHelper.cxx | 198 ++ chart2/source/tools/CachedDataSequence.cxx | 373 +++ chart2/source/tools/CharacterProperties.cxx | 459 +++ chart2/source/tools/ChartModelHelper.cxx | 286 ++ chart2/source/tools/ChartTypeHelper.cxx | 709 +++++ chart2/source/tools/ChartViewHelper.cxx | 57 + chart2/source/tools/ColorPerPointHelper.cxx | 78 + chart2/source/tools/CommonConverters.cxx | 522 ++++ chart2/source/tools/ConfigColorScheme.cxx | 190 ++ chart2/source/tools/ControllerLockGuard.cxx | 84 + chart2/source/tools/DataSeriesHelper.cxx | 849 ++++++ chart2/source/tools/DataSource.cxx | 81 + chart2/source/tools/DataSourceHelper.cxx | 532 ++++ chart2/source/tools/DiagramHelper.cxx | 1685 +++++++++++ chart2/source/tools/ErrorBar.cxx | 485 +++ chart2/source/tools/ExplicitCategoriesProvider.cxx | 561 ++++ .../tools/ExponentialRegressionCurveCalculator.cxx | 224 ++ chart2/source/tools/FillProperties.cxx | 200 ++ chart2/source/tools/FormattedStringHelper.cxx | 63 + chart2/source/tools/ImplOPropertySet.cxx | 178 ++ chart2/source/tools/ImplOPropertySet.hxx | 89 + chart2/source/tools/InternalData.cxx | 565 ++++ chart2/source/tools/InternalDataProvider.cxx | 1530 ++++++++++ chart2/source/tools/LabeledDataSequence.cxx | 171 ++ chart2/source/tools/LegendHelper.cxx | 123 + chart2/source/tools/LifeTime.cxx | 444 +++ chart2/source/tools/LinePropertiesHelper.cxx | 192 ++ .../tools/LinearRegressionCurveCalculator.cxx | 71 + .../tools/LogarithmicRegressionCurveCalculator.cxx | 194 ++ .../tools/MeanValueRegressionCurveCalculator.cxx | 128 + chart2/source/tools/MediaDescriptorHelper.cxx | 223 ++ chart2/source/tools/ModifyListenerHelper.cxx | 183 ++ .../MovingAverageRegressionCurveCalculator.cxx | 104 + chart2/source/tools/NameContainer.cxx | 146 + chart2/source/tools/NumberFormatterWrapper.cxx | 130 + chart2/source/tools/OPropertySet.cxx | 372 +++ chart2/source/tools/ObjectIdentifier.cxx | 1502 ++++++++++ .../tools/PolynomialRegressionCurveCalculator.cxx | 396 +++ chart2/source/tools/PopupRequest.cxx | 42 + .../tools/PotentialRegressionCurveCalculator.cxx | 195 ++ chart2/source/tools/PropertyHelper.cxx | 297 ++ chart2/source/tools/RangeHighlighter.cxx | 398 +++ chart2/source/tools/ReferenceSizeProvider.cxx | 351 +++ chart2/source/tools/RegressionCurveCalculator.cxx | 220 ++ chart2/source/tools/RegressionCurveHelper.cxx | 764 +++++ chart2/source/tools/RegressionCurveModel.cxx | 570 ++++ chart2/source/tools/RegressionCurveModel.hxx | 245 ++ chart2/source/tools/RegressionEquation.cxx | 336 +++ chart2/source/tools/RegressionEquation.hxx | 123 + chart2/source/tools/RelativePositionHelper.cxx | 381 +++ chart2/source/tools/RelativeSizeHelper.cxx | 90 + chart2/source/tools/ResId.cxx | 31 + chart2/source/tools/Scaling.cxx | 277 ++ chart2/source/tools/SceneProperties.cxx | 332 +++ chart2/source/tools/StatisticsHelper.cxx | 375 +++ chart2/source/tools/ThreeDHelper.cxx | 1460 +++++++++ chart2/source/tools/TitleHelper.cxx | 452 +++ chart2/source/tools/TrueGuard.cxx | 38 + chart2/source/tools/UncachedDataSequence.cxx | 336 +++ chart2/source/tools/UserDefinedProperties.cxx | 61 + chart2/source/tools/WeakListenerAdapter.cxx | 61 + chart2/source/tools/WrappedDefaultProperty.cxx | 77 + chart2/source/tools/WrappedDirectStateProperty.cxx | 45 + chart2/source/tools/WrappedIgnoreProperty.cxx | 113 + chart2/source/tools/WrappedProperty.cxx | 125 + chart2/source/tools/WrappedPropertySet.cxx | 442 +++ chart2/source/tools/XMLRangeHelper.cxx | 392 +++ chart2/source/view/axes/DateHelper.cxx | 93 + chart2/source/view/axes/DateScaling.cxx | 203 ++ chart2/source/view/axes/DateScaling.hxx | 97 + .../source/view/axes/MinimumAndMaximumSupplier.cxx | 208 ++ chart2/source/view/axes/ScaleAutomatism.cxx | 990 +++++++ chart2/source/view/axes/TickmarkProperties.hxx | 39 + chart2/source/view/axes/Tickmarks.cxx | 325 ++ chart2/source/view/axes/Tickmarks.hxx | 158 + chart2/source/view/axes/Tickmarks_Dates.cxx | 150 + chart2/source/view/axes/Tickmarks_Dates.hxx | 51 + chart2/source/view/axes/Tickmarks_Equidistant.cxx | 621 ++++ chart2/source/view/axes/Tickmarks_Equidistant.hxx | 148 + chart2/source/view/axes/VAxisBase.cxx | 247 ++ chart2/source/view/axes/VAxisBase.hxx | 105 + chart2/source/view/axes/VAxisOrGridBase.cxx | 70 + chart2/source/view/axes/VAxisOrGridBase.hxx | 65 + chart2/source/view/axes/VAxisProperties.cxx | 400 +++ chart2/source/view/axes/VAxisProperties.hxx | 164 ++ chart2/source/view/axes/VCartesianAxis.cxx | 1980 +++++++++++++ chart2/source/view/axes/VCartesianAxis.hxx | 162 + .../view/axes/VCartesianCoordinateSystem.cxx | 219 ++ .../view/axes/VCartesianCoordinateSystem.hxx | 49 + chart2/source/view/axes/VCartesianGrid.cxx | 317 ++ chart2/source/view/axes/VCartesianGrid.hxx | 54 + chart2/source/view/axes/VCoordinateSystem.cxx | 560 ++++ chart2/source/view/axes/VPolarAngleAxis.cxx | 208 ++ chart2/source/view/axes/VPolarAngleAxis.hxx | 53 + chart2/source/view/axes/VPolarAxis.cxx | 65 + chart2/source/view/axes/VPolarAxis.hxx | 56 + chart2/source/view/axes/VPolarCoordinateSystem.cxx | 188 ++ chart2/source/view/axes/VPolarCoordinateSystem.hxx | 53 + chart2/source/view/axes/VPolarGrid.cxx | 245 ++ chart2/source/view/axes/VPolarGrid.hxx | 73 + chart2/source/view/axes/VPolarRadiusAxis.cxx | 166 ++ chart2/source/view/axes/VPolarRadiusAxis.hxx | 75 + chart2/source/view/charttypes/AreaChart.cxx | 994 +++++++ chart2/source/view/charttypes/AreaChart.hxx | 88 + chart2/source/view/charttypes/BarChart.cxx | 985 +++++++ chart2/source/view/charttypes/BarChart.hxx | 73 + .../source/view/charttypes/BarPositionHelper.cxx | 73 + .../source/view/charttypes/BarPositionHelper.hxx | 47 + chart2/source/view/charttypes/BubbleChart.cxx | 368 +++ chart2/source/view/charttypes/BubbleChart.hxx | 62 + chart2/source/view/charttypes/CandleStickChart.cxx | 326 ++ chart2/source/view/charttypes/CandleStickChart.hxx | 56 + .../view/charttypes/CategoryPositionHelper.cxx | 82 + .../view/charttypes/CategoryPositionHelper.hxx | 59 + chart2/source/view/charttypes/ConfigAccess.cxx | 82 + chart2/source/view/charttypes/NetChart.cxx | 643 ++++ chart2/source/view/charttypes/NetChart.hxx | 76 + chart2/source/view/charttypes/PieChart.cxx | 1621 ++++++++++ chart2/source/view/charttypes/PieChart.hxx | 144 + chart2/source/view/charttypes/Splines.cxx | 931 ++++++ chart2/source/view/charttypes/Splines.hxx | 48 + chart2/source/view/charttypes/VSeriesPlotter.cxx | 2865 ++++++++++++++++++ chart2/source/view/diagram/VDiagram.cxx | 739 +++++ chart2/source/view/inc/Clipping.hxx | 57 + chart2/source/view/inc/ConfigAccess.hxx | 40 + chart2/source/view/inc/DateHelper.hxx | 44 + chart2/source/view/inc/LabelAlignment.hxx | 41 + chart2/source/view/inc/LabelPositionHelper.hxx | 70 + chart2/source/view/inc/LegendEntryProvider.hxx | 92 + chart2/source/view/inc/Linear3DTransformation.hxx | 56 + .../source/view/inc/MinimumAndMaximumSupplier.hxx | 93 + chart2/source/view/inc/PlotterBase.hxx | 85 + chart2/source/view/inc/PlottingPositionHelper.hxx | 424 +++ .../source/view/inc/PolarLabelPositionHelper.hxx | 73 + chart2/source/view/inc/PropertyMapper.hxx | 129 + chart2/source/view/inc/ScaleAutomatism.hxx | 146 + chart2/source/view/inc/ShapeFactory.hxx | 332 +++ chart2/source/view/inc/Stripe.hxx | 73 + chart2/source/view/inc/VCoordinateSystem.hxx | 208 ++ chart2/source/view/inc/VDataSeries.hxx | 265 ++ chart2/source/view/inc/VDiagram.hxx | 121 + chart2/source/view/inc/VLegendSymbolFactory.hxx | 60 + chart2/source/view/inc/VLineProperties.hxx | 49 + chart2/source/view/inc/VPolarTransformation.hxx | 56 + chart2/source/view/inc/VSeriesPlotter.hxx | 440 +++ chart2/source/view/inc/ViewDefines.hxx | 38 + chart2/source/view/main/ChartItemPool.cxx | 214 ++ chart2/source/view/main/ChartItemPool.hxx | 52 + chart2/source/view/main/ChartView.cxx | 3101 ++++++++++++++++++++ chart2/source/view/main/Clipping.cxx | 300 ++ .../source/view/main/DataPointSymbolSupplier.cxx | 47 + chart2/source/view/main/DrawModelWrapper.cxx | 329 +++ chart2/source/view/main/LabelPositionHelper.cxx | 468 +++ chart2/source/view/main/Linear3DTransformation.cxx | 92 + chart2/source/view/main/PlotterBase.cxx | 115 + chart2/source/view/main/PlottingPositionHelper.cxx | 692 +++++ .../source/view/main/PolarLabelPositionHelper.cxx | 174 ++ chart2/source/view/main/PropertyMapper.cxx | 511 ++++ chart2/source/view/main/ShapeFactory.cxx | 2764 +++++++++++++++++ chart2/source/view/main/Stripe.cxx | 347 +++ chart2/source/view/main/VButton.cxx | 154 + chart2/source/view/main/VButton.hxx | 88 + chart2/source/view/main/VDataSeries.cxx | 1150 ++++++++ chart2/source/view/main/VLegend.cxx | 1122 +++++++ chart2/source/view/main/VLegend.hxx | 91 + chart2/source/view/main/VLegendSymbolFactory.cxx | 201 ++ chart2/source/view/main/VLineProperties.cxx | 84 + chart2/source/view/main/VPolarTransformation.cxx | 76 + chart2/source/view/main/VTitle.cxx | 142 + chart2/source/view/main/VTitle.hxx | 70 + chart2/uiconfig/accelerator/en-US/default.xml | 46 + chart2/uiconfig/menubar/menubar.xml | 177 ++ chart2/uiconfig/popupmenu/draw.xml | 31 + chart2/uiconfig/popupmenu/drawtext.xml | 29 + chart2/uiconfig/statusbar/statusbar.xml | 23 + chart2/uiconfig/toolbar/arrowshapes.xml | 51 + chart2/uiconfig/toolbar/basicshapes.xml | 48 + chart2/uiconfig/toolbar/calloutshapes.xml | 29 + chart2/uiconfig/toolbar/drawbar.xml | 37 + chart2/uiconfig/toolbar/flowchartshapes.xml | 53 + chart2/uiconfig/toolbar/standardbar.xml | 37 + chart2/uiconfig/toolbar/starshapes.xml | 34 + chart2/uiconfig/toolbar/symbolshapes.xml | 41 + chart2/uiconfig/toolbar/toolbar.xml | 47 + chart2/uiconfig/ui/3dviewdialog.ui | 101 + chart2/uiconfig/ui/attributedialog.ui | 115 + chart2/uiconfig/ui/chardialog.ui | 250 ++ chart2/uiconfig/ui/chartdatadialog.ui | 319 ++ chart2/uiconfig/ui/charttypedialog.ui | 89 + chart2/uiconfig/ui/columnfragment.ui | 34 + chart2/uiconfig/ui/combobox.ui | 38 + chart2/uiconfig/ui/datarangedialog.ui | 192 ++ chart2/uiconfig/ui/dlg_DataLabel.ui | 515 ++++ chart2/uiconfig/ui/dlg_InsertErrorBars.ui | 633 ++++ chart2/uiconfig/ui/dlg_InsertLegend.ui | 234 ++ chart2/uiconfig/ui/imagefragment.ui | 22 + chart2/uiconfig/ui/insertaxisdlg.ui | 283 ++ chart2/uiconfig/ui/insertgriddlg.ui | 283 ++ chart2/uiconfig/ui/inserttitledlg.ui | 372 +++ chart2/uiconfig/ui/paradialog.ui | 298 ++ chart2/uiconfig/ui/sidebaraxis.ui | 129 + chart2/uiconfig/ui/sidebarelements.ui | 557 ++++ chart2/uiconfig/ui/sidebarerrorbar.ui | 237 ++ chart2/uiconfig/ui/sidebarseries.ui | 313 ++ chart2/uiconfig/ui/sidebartype.ui | 418 +++ chart2/uiconfig/ui/smoothlinesdlg.ui | 231 ++ chart2/uiconfig/ui/steppedlinesdlg.ui | 236 ++ chart2/uiconfig/ui/titlerotationtabpage.ui | 168 ++ chart2/uiconfig/ui/tp_3D_SceneAppearance.ui | 127 + chart2/uiconfig/ui/tp_3D_SceneGeometry.ui | 168 ++ chart2/uiconfig/ui/tp_3D_SceneIllumination.ui | 434 +++ chart2/uiconfig/ui/tp_AxisPositions.ui | 660 +++++ chart2/uiconfig/ui/tp_ChartType.ui | 467 +++ chart2/uiconfig/ui/tp_DataLabel.ui | 430 +++ chart2/uiconfig/ui/tp_DataPointOption.ui | 76 + chart2/uiconfig/ui/tp_DataSource.ui | 438 +++ chart2/uiconfig/ui/tp_ErrorBars.ui | 553 ++++ chart2/uiconfig/ui/tp_LegendPosition.ui | 233 ++ chart2/uiconfig/ui/tp_PolarOptions.ui | 185 ++ chart2/uiconfig/ui/tp_RangeChooser.ui | 258 ++ chart2/uiconfig/ui/tp_Scale.ui | 603 ++++ chart2/uiconfig/ui/tp_SeriesToAxis.ui | 420 +++ chart2/uiconfig/ui/tp_Trendline.ui | 575 ++++ chart2/uiconfig/ui/tp_axisLabel.ui | 397 +++ chart2/uiconfig/ui/wizelementspage.ui | 441 +++ chart2/workbench/addin/exports.dxp | 2 + chart2/workbench/addin/makefile.mk | 76 + chart2/workbench/addin/sampleaddin.cxx | 652 ++++ chart2/workbench/addin/sampleaddin.def | 6 + chart2/workbench/addin/sampleaddin.hxx | 155 + 1119 files changed, 198594 insertions(+) create mode 100644 chart2/AllLangMoTarget_chart.mk create mode 100644 chart2/CppunitTest_chart2_common_functors.mk create mode 100644 chart2/CppunitTest_chart2_dialogs_test.mk create mode 100644 chart2/CppunitTest_chart2_dump.mk create mode 100644 chart2/CppunitTest_chart2_export.mk create mode 100644 chart2/CppunitTest_chart2_geometry.mk create mode 100644 chart2/CppunitTest_chart2_import.mk create mode 100644 chart2/CppunitTest_chart2_pivot_chart_test.mk create mode 100644 chart2/CppunitTest_chart2_trendcalculators.mk create mode 100644 chart2/CppunitTest_chart2_xshape.mk create mode 100644 chart2/IwyuFilter_chart2.yaml create mode 100644 chart2/JunitTest_chart2_unoapi.mk create mode 100644 chart2/Library_chartcontroller.mk create mode 100644 chart2/Library_chartcore.mk create mode 100644 chart2/Makefile create mode 100644 chart2/Module_chart2.mk create mode 100644 chart2/README create mode 100644 chart2/UIConfig_chart2.mk create mode 100644 chart2/inc/ChartModel.hxx create mode 100644 chart2/inc/ChartView.hxx create mode 100644 chart2/inc/SpecialCharacters.hxx create mode 100644 chart2/inc/bitmaps.hlst create mode 100644 chart2/inc/chart.hrc create mode 100644 chart2/inc/pch/precompiled_chartcontroller.cxx create mode 100644 chart2/inc/pch/precompiled_chartcontroller.hxx create mode 100644 chart2/inc/pch/precompiled_chartcore.cxx create mode 100644 chart2/inc/pch/precompiled_chartcore.hxx create mode 100644 chart2/inc/strings.hrc create mode 100644 chart2/inc/unonames.hxx create mode 100644 chart2/qa/TestCaseOldAPI.java create mode 100644 chart2/qa/data.chd create mode 100644 chart2/qa/extras/PivotChartTest.cxx create mode 100644 chart2/qa/extras/chart2_trendcalculators.cxx create mode 100644 chart2/qa/extras/chart2dump/chart2dump.cxx create mode 100644 chart2/qa/extras/chart2dump/data/axis_special_positioning.odp create mode 100644 chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.ods create mode 100644 chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.ods create mode 100644 chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.ods create mode 100644 chart2/qa/extras/chart2dump/data/column_chart_small_spacing.ods create mode 100644 chart2/qa/extras/chart2dump/data/custom_legend_position.odp create mode 100644 chart2/qa/extras/chart2dump/data/default_formated_axis.odp create mode 100644 chart2/qa/extras/chart2dump/data/donut_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/exploded_pie_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/formated_axis_labels.odp create mode 100644 chart2/qa/extras/chart2dump/data/formated_axis_lines.odp create mode 100644 chart2/qa/extras/chart2dump/data/formated_grid_line.ods create mode 100644 chart2/qa/extras/chart2dump/data/horizontal_grid.ods create mode 100644 chart2/qa/extras/chart2dump/data/legend_on_bottom.odp create mode 100644 chart2/qa/extras/chart2dump/data/legend_on_left_side.odp create mode 100644 chart2/qa/extras/chart2dump/data/legend_on_right_side.odp create mode 100644 chart2/qa/extras/chart2dump/data/legend_on_top.odp create mode 100644 chart2/qa/extras/chart2dump/data/many_legend_entries.odp create mode 100644 chart2/qa/extras/chart2dump/data/minimal_legend_test.odp create mode 100644 chart2/qa/extras/chart2dump/data/minor_grid.ods create mode 100644 chart2/qa/extras/chart2dump/data/multiple_categories.odp create mode 100644 chart2/qa/extras/chart2dump/data/multiple_categories.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_area_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_bar_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_column_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/normal_pie_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odp create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/pie_chart_many_slices.ods create mode 100644 chart2/qa/extras/chart2dump/data/pivotchart_data_button.ods create mode 100644 chart2/qa/extras/chart2dump/data/rotated_axis_labels.odp create mode 100644 chart2/qa/extras/chart2dump/data/rotated_pie_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.ods create mode 100644 chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/scatter_chart_points_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/simple_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_area_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_bar_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_column_chart.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.ods create mode 100644 chart2/qa/extras/chart2dump/data/tdf118150.xlsx create mode 100644 chart2/qa/extras/chart2dump/data/vertical_grid.ods create mode 100644 chart2/qa/extras/chart2dump/reference/areacharttest/normal_area_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/areacharttest/percent_stacked_area_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/areacharttest/stacked_area_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axisgeometrytest/axis_special_positioning.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axisgeometrytest/default_formated_axis.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axisgeometrytest/formated_axis_lines.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axisgeometrytest/rotated_axis_labels.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axislabeltest/default_formated_axis.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axislabeltest/formated_axis_labels.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axislabeltest/percent_stacked_column_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axislabeltest/rotated_axis_labels.txt create mode 100644 chart2/qa/extras/chart2dump/reference/axislabeltest/tdf118150.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartdatatest/multiple_categories.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartdatatest/simple_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt create mode 100644 chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/column_chart_small_spacing.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_bar_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_column_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_bar_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_column_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_bar_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_column_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/gridtest/formated_grid_line.txt create mode 100644 chart2/qa/extras/chart2dump/reference/gridtest/horizontal_grid.txt create mode 100644 chart2/qa/extras/chart2dump/reference/gridtest/minor_grid.txt create mode 100644 chart2/qa/extras/chart2dump/reference/gridtest/vertical_grid.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/custom_legend_position.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/legend_on_bottom.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/legend_on_left_side.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/legend_on_right_side.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/legend_on_top.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/many_legend_entries.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/minimal_legend_test.txt create mode 100644 chart2/qa/extras/chart2dump/reference/legendtest/multiple_categories.txt create mode 100644 chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/piecharttest/exploded_pie_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/piecharttest/normal_pie_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/piecharttest/pie_chart_many_slices.txt create mode 100644 chart2/qa/extras/chart2dump/reference/piecharttest/rotated_pie_chart.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_and_points.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_points_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_and_points.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_points_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_and_points.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_points_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_and_points.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_only.txt create mode 100644 chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_points_only.txt create mode 100644 chart2/qa/extras/chart2export.cxx create mode 100644 chart2/qa/extras/chart2geometry.cxx create mode 100644 chart2/qa/extras/chart2import.cxx create mode 100644 chart2/qa/extras/charttest.hxx create mode 100644 chart2/qa/extras/data/doc/chart.doc create mode 100644 chart2/qa/extras/data/docx/3d-bar-label.docx create mode 100644 chart2/qa/extras/data/docx/Bar_horizontal_cone.docx create mode 100644 chart2/qa/extras/data/docx/DisplayUnits.docx create mode 100644 chart2/qa/extras/data/docx/FDO74430.docx create mode 100644 chart2/qa/extras/data/docx/FDO75975.docx create mode 100644 chart2/qa/extras/data/docx/MSO_axis_position.docx create mode 100644 chart2/qa/extras/data/docx/PieChartDataLabels.docx create mode 100644 chart2/qa/extras/data/docx/UpDownBars.docx create mode 100644 chart2/qa/extras/data/docx/area-chart-labels.docx create mode 100644 chart2/qa/extras/data/docx/bar-chart-labels.docx create mode 100644 chart2/qa/extras/data/docx/barChartRotation.docx create mode 100644 chart2/qa/extras/data/docx/bubblechart.docx create mode 100644 chart2/qa/extras/data/docx/chart.docx create mode 100644 chart2/qa/extras/data/docx/clustered-bar-chart-labels.docx create mode 100644 chart2/qa/extras/data/docx/data-label-borders.docx create mode 100644 chart2/qa/extras/data/docx/data_point_inherited_color.docx create mode 100644 chart2/qa/extras/data/docx/doughnut-chart-labels.docx create mode 100644 chart2/qa/extras/data/docx/doughnutChart.docx create mode 100644 chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docx create mode 100644 chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docx create mode 100644 chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docx create mode 100644 chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docx create mode 100644 chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docx create mode 100644 chart2/qa/extras/data/docx/fdo83058_dlblPos.docx create mode 100644 chart2/qa/extras/data/docx/line-chart-label-default-placement.docx create mode 100644 chart2/qa/extras/data/docx/pieChartRotation.docx create mode 100644 chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docx create mode 100644 chart2/qa/extras/data/docx/radar-chart-labels.docx create mode 100644 chart2/qa/extras/data/docx/scatter-chart-text-x-values.docx create mode 100644 chart2/qa/extras/data/docx/tdf121744.docx create mode 100644 chart2/qa/extras/data/docx/tdf123206.docx create mode 100644 chart2/qa/extras/data/docx/tdf124083.docx create mode 100644 chart2/qa/extras/data/docx/tdf124243.docx create mode 100644 chart2/qa/extras/data/docx/tdf125337.docx create mode 100644 chart2/qa/extras/data/docx/tdf128794.docx create mode 100644 chart2/qa/extras/data/docx/tdf132174.docx create mode 100644 chart2/qa/extras/data/docx/tdf133632.docx create mode 100644 chart2/qa/extras/data/docx/tdf136650.docx create mode 100644 chart2/qa/extras/data/docx/tdf91250.docx create mode 100644 chart2/qa/extras/data/docx/testAreaChartLoad.docx create mode 100644 chart2/qa/extras/data/docx/testAxisTitlePosition.docx create mode 100644 chart2/qa/extras/data/docx/testBarChart.docx create mode 100644 chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx create mode 100644 chart2/qa/extras/data/docx/testChartDataTable.docx create mode 100644 chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx create mode 100644 chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx create mode 100644 chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx create mode 100644 chart2/qa/extras/data/docx/testColorGradientWithTransparancy.docx create mode 100644 chart2/qa/extras/data/docx/testCustomlabeltext.docx create mode 100644 chart2/qa/extras/data/docx/testLabelSeparator.docx create mode 100644 chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx create mode 100644 chart2/qa/extras/data/docx/testMultipleChart.docx create mode 100644 chart2/qa/extras/data/docx/testMultiplechartembeddings.docx create mode 100644 chart2/qa/extras/data/docx/testSeriesIdxOrder.docx create mode 100644 chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx create mode 100644 chart2/qa/extras/data/docx/testStockChart.docx create mode 100644 chart2/qa/extras/data/docx/testTdf108110.docx create mode 100644 chart2/qa/extras/data/docx/testTdf114179.docx create mode 100644 chart2/qa/extras/data/docx/testTdf122226.docx create mode 100644 chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx create mode 100644 chart2/qa/extras/data/fods/stacked-column-chart.fods create mode 100644 chart2/qa/extras/data/odp/chart.odp create mode 100644 chart2/qa/extras/data/odp/ellipticalGradientFill.odp create mode 100644 chart2/qa/extras/data/odp/tdf119029.odp create mode 100644 chart2/qa/extras/data/odp/tdf121189.odp create mode 100644 chart2/qa/extras/data/odp/tdf123206.odp create mode 100644 chart2/qa/extras/data/ods/ErrorBarRange.ods create mode 100644 chart2/qa/extras/data/ods/PivotChartRoundTrip.ods create mode 100644 chart2/qa/extras/data/ods/PivotTableExample.ods create mode 100644 chart2/qa/extras/data/ods/axis-numformats-linked.ods create mode 100644 chart2/qa/extras/data/ods/axis_number_format.ods create mode 100644 chart2/qa/extras/data/ods/chart.ods create mode 100644 chart2/qa/extras/data/ods/combined_chart_secondary_axis.ods create mode 100644 chart2/qa/extras/data/ods/error_bar.ods create mode 100644 chart2/qa/extras/data/ods/error_bar_properties.ods create mode 100644 chart2/qa/extras/data/ods/error_bar_range.ods create mode 100644 chart2/qa/extras/data/ods/fdo60083.ods create mode 100644 chart2/qa/extras/data/ods/labelString.ods create mode 100644 chart2/qa/extras/data/ods/legend_overlay.ods create mode 100644 chart2/qa/extras/data/ods/multilevelcat.ods create mode 100644 chart2/qa/extras/data/ods/multiple_axis.ods create mode 100644 chart2/qa/extras/data/ods/pie_chart_100_and_0.ods create mode 100644 chart2/qa/extras/data/ods/secondary_axis.ods create mode 100644 chart2/qa/extras/data/ods/smoothedLines.ods create mode 100644 chart2/qa/extras/data/ods/stepped_lines.ods create mode 100644 chart2/qa/extras/data/ods/tdf108021.ods create mode 100644 chart2/qa/extras/data/ods/tdf123774.ods create mode 100644 chart2/qa/extras/data/ods/tdf128432.ods create mode 100644 chart2/qa/extras/data/ods/tdf131115.ods create mode 100644 chart2/qa/extras/data/ods/tdf131979.ods create mode 100644 chart2/qa/extras/data/ods/tdf132076.ods create mode 100644 chart2/qa/extras/data/ods/tdf59857.ods create mode 100644 chart2/qa/extras/data/ods/tdf64224.ods create mode 100644 chart2/qa/extras/data/ods/tdf86624.ods create mode 100644 chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods create mode 100644 chart2/qa/extras/data/ods/testChartSubTitle.ods create mode 100644 chart2/qa/extras/data/ods/testColorGradientWithTransparancy.ods create mode 100644 chart2/qa/extras/data/ods/test_CrossBetween.ods create mode 100644 chart2/qa/extras/data/ods/trend_calculators.ods create mode 100644 chart2/qa/extras/data/ods/trendline.ods create mode 100644 chart2/qa/extras/data/odt/axis-position.odt create mode 100644 chart2/qa/extras/data/odt/chart.odt create mode 100644 chart2/qa/extras/data/odt/multilevelcat.odt create mode 100644 chart2/qa/extras/data/odt/scatter-plot-labels.odt create mode 100644 chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt create mode 100644 chart2/qa/extras/data/odt/tdf108022.odt create mode 100644 chart2/qa/extras/data/odt/tdf114657.odt create mode 100644 chart2/qa/extras/data/odt/tdf128733.odt create mode 100644 chart2/qa/extras/data/odt/tdf131143.odt create mode 100644 chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt create mode 100644 chart2/qa/extras/data/ppt/chart.ppt create mode 100644 chart2/qa/extras/data/pptx/bnc864396.pptx create mode 100644 chart2/qa/extras/data/pptx/bnc882383.pptx create mode 100644 chart2/qa/extras/data/pptx/bnc889755.pptx create mode 100644 chart2/qa/extras/data/pptx/chart.pptx create mode 100644 chart2/qa/extras/data/pptx/percentage-number-formats.pptx create mode 100644 chart2/qa/extras/data/pptx/sparse-chart.pptx create mode 100644 chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptx create mode 100644 chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf105517.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf106217.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf115107-2.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf115107.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf115859.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf116163.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf121205.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf122765.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf125444.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf127393.pptx create mode 100644 chart2/qa/extras/data/pptx/tdf48041.pptx create mode 100644 chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx create mode 100644 chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx create mode 100644 chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx create mode 100644 chart2/qa/extras/data/xls/axis_sourceformatting.xls create mode 100644 chart2/qa/extras/data/xls/chart.xls create mode 100644 chart2/qa/extras/data/xls/piechart_outside.xls create mode 100644 chart2/qa/extras/data/xls/source_number_format_axis.xls create mode 100644 chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsx create mode 100644 chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsx create mode 100644 chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx create mode 100644 chart2/qa/extras/data/xlsx/axis-label-rotation.xlsx create mode 100644 chart2/qa/extras/data/xlsx/axis_character_properties.xlsx create mode 100644 chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsx create mode 100644 chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx create mode 100644 chart2/qa/extras/data/xlsx/axis_title_rotation.xlsx create mode 100644 chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx create mode 100644 chart2/qa/extras/data/xlsx/barchart_outend.xlsx create mode 100644 chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart-area-style-background.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart-area-style-border.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart-auto-background.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart_label_text_break.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart_pie2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/chart_title.xlsx create mode 100644 chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsx create mode 100644 chart2/qa/extras/data/xlsx/data_label.xlsx create mode 100644 chart2/qa/extras/data/xlsx/deleted_data_labels.xlsx create mode 100644 chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsx create mode 100644 chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsx create mode 100644 chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx create mode 100644 chart2/qa/extras/data/xlsx/external_str_ref.xlsx create mode 100644 chart2/qa/extras/data/xlsx/fdo54361-1.xlsx create mode 100644 chart2/qa/extras/data/xlsx/fdo54361.xlsx create mode 100644 chart2/qa/extras/data/xlsx/fdo70609.xlsx create mode 100644 chart2/qa/extras/data/xlsx/fdo78080.xlsx create mode 100644 chart2/qa/extras/data/xlsx/gapWidth.xlsx create mode 100644 chart2/qa/extras/data/xlsx/hidden_cells.xlsx create mode 100644 chart2/qa/extras/data/xlsx/legend_manual_layout.xlsx create mode 100644 chart2/qa/extras/data/xlsx/majorTickMark.xlsx create mode 100644 chart2/qa/extras/data/xlsx/markerColor.xlsx create mode 100644 chart2/qa/extras/data/xlsx/minorTickMark.xlsx create mode 100644 chart2/qa/extras/data/xlsx/no_marker.xlsx create mode 100644 chart2/qa/extras/data/xlsx/number-formats.xlsx create mode 100644 chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsx create mode 100644 chart2/qa/extras/data/xlsx/piechart_outside.xlsx create mode 100644 chart2/qa/extras/data/xlsx/plotVisOnly.xlsx create mode 100644 chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsx create mode 100644 chart2/qa/extras/data/xlsx/rAngAx.xlsx create mode 100644 chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsx create mode 100644 chart2/qa/extras/data/xlsx/smoothed_series.xlsx create mode 100644 chart2/qa/extras/data/xlsx/smoothed_series2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/strict_chart.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf100084.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf108107.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf111173.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf111824.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf114139.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf115012.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf122031.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf122915.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf124817.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf126033.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf126115.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf127777.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf128619.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf128627.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf128633.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf128634.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf128732.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf130657.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf130986.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf132076.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf133376.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf134225.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf136267.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdf90876.xlsx create mode 100644 chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx create mode 100644 chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testTdf130032.xlsx create mode 100644 chart2/qa/extras/data/xlsx/testTdf90749.xlsx create mode 100644 chart2/qa/extras/data/xlsx/title_character_properties.xlsx create mode 100644 chart2/qa/extras/data/xlsx/title_manual_layout.xlsx create mode 100644 chart2/qa/extras/data/xlsx/trendline.xlsx create mode 100644 chart2/qa/extras/data/xlsx/trendline2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/vary_color.xlsx create mode 100644 chart2/qa/extras/data/xlsx/vary_color2007.xlsx create mode 100644 chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx create mode 100644 chart2/qa/extras/xshape/chart2xshape.cxx create mode 100644 chart2/qa/extras/xshape/data/ods/fdo75075.ods create mode 100644 chart2/qa/extras/xshape/data/ods/property-mapping-bar.ods create mode 100644 chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.ods create mode 100644 chart2/qa/extras/xshape/data/ods/tdf90839-4.ods create mode 100644 chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptx create mode 100644 chart2/qa/extras/xshape/data/reference/fdo75075.xml create mode 100644 chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml create mode 100644 chart2/qa/extras/xshape/data/reference/tdf90839-1.xml create mode 100644 chart2/qa/extras/xshape/data/reference/tdf90839-2.xml create mode 100644 chart2/qa/extras/xshape/data/reference/tdf90839-3.xml create mode 100644 chart2/qa/extras/xshape/data/reference/tdf90839-4.xml create mode 100644 chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx create mode 100644 chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx create mode 100644 chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx create mode 100644 chart2/qa/unit/chart2-dialogs-test.cxx create mode 100644 chart2/qa/unit/common_functor_test.cxx create mode 100644 chart2/qa/unit/data/chart2-dialogs-test.txt create mode 100644 chart2/qa/unit/data/ods/testChart.ods create mode 100644 chart2/qa/unit/data/reference/testChart.xml create mode 100644 chart2/qa/unit/data/tolerance.xml create mode 100644 chart2/qa/unoapi/knownissues.xcl create mode 100644 chart2/qa/unoapi/sch.sce create mode 100644 chart2/qa/unoapi/testdocuments/TransparencyChart.sxs create mode 100644 chart2/qa/unoapi/testdocuments/emptyChart.sds create mode 100644 chart2/qa/unoapi/testdocuments/space-metal.jpg create mode 100644 chart2/source/chartcore.component create mode 100644 chart2/source/controller/accessibility/AccessibleBase.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleChartElement.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleChartElement.hxx create mode 100644 chart2/source/controller/accessibility/AccessibleChartShape.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleChartShape.hxx create mode 100644 chart2/source/controller/accessibility/AccessibleChartView.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleTextHelper.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleViewForwarder.cxx create mode 100644 chart2/source/controller/accessibility/AccessibleViewForwarder.hxx create mode 100644 chart2/source/controller/accessibility/ChartElementFactory.cxx create mode 100644 chart2/source/controller/accessibility/ChartElementFactory.hxx create mode 100644 chart2/source/controller/chartapiwrapper/AreaWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/AreaWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/AxisWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/AxisWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx create mode 100644 chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx create mode 100644 chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/GridWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/GridWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/LegendWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/LegendWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.hxx create mode 100644 chart2/source/controller/chartapiwrapper/TitleWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/TitleWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/UpDownBarWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WallFloorWrapper.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAddInProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedScaleProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSceneProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.cxx create mode 100644 chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx create mode 100644 chart2/source/controller/chartcontroller.component create mode 100644 chart2/source/controller/dialogs/ChangingResource.cxx create mode 100644 chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx create mode 100644 chart2/source/controller/dialogs/ChartResourceGroups.cxx create mode 100644 chart2/source/controller/dialogs/ChartTypeDialogController.cxx create mode 100644 chart2/source/controller/dialogs/DataBrowser.cxx create mode 100644 chart2/source/controller/dialogs/DataBrowser.hxx create mode 100644 chart2/source/controller/dialogs/DataBrowserModel.cxx create mode 100644 chart2/source/controller/dialogs/DataBrowserModel.hxx create mode 100644 chart2/source/controller/dialogs/DialogModel.cxx create mode 100644 chart2/source/controller/dialogs/DialogModel.hxx create mode 100644 chart2/source/controller/dialogs/ObjectNameProvider.cxx create mode 100644 chart2/source/controller/dialogs/RangeSelectionHelper.cxx create mode 100644 chart2/source/controller/dialogs/RangeSelectionListener.cxx create mode 100644 chart2/source/controller/dialogs/TextDirectionListBox.cxx create mode 100644 chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx create mode 100644 chart2/source/controller/dialogs/TitleDialogData.cxx create mode 100644 chart2/source/controller/dialogs/dlg_ChartType.cxx create mode 100644 chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx create mode 100644 chart2/source/controller/dialogs/dlg_CreationWizard.cxx create mode 100644 chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx create mode 100644 chart2/source/controller/dialogs/dlg_DataEditor.cxx create mode 100644 chart2/source/controller/dialogs/dlg_DataSource.cxx create mode 100644 chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx create mode 100644 chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx create mode 100644 chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx create mode 100644 chart2/source/controller/dialogs/dlg_InsertLegend.cxx create mode 100644 chart2/source/controller/dialogs/dlg_InsertTitle.cxx create mode 100644 chart2/source/controller/dialogs/dlg_NumberFormat.cxx create mode 100644 chart2/source/controller/dialogs/dlg_NumberFormat.hxx create mode 100644 chart2/source/controller/dialogs/dlg_ObjectProperties.cxx create mode 100644 chart2/source/controller/dialogs/dlg_ShapeFont.cxx create mode 100644 chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx create mode 100644 chart2/source/controller/dialogs/dlg_View3D.cxx create mode 100644 chart2/source/controller/dialogs/res_BarGeometry.cxx create mode 100644 chart2/source/controller/dialogs/res_DataLabel.cxx create mode 100644 chart2/source/controller/dialogs/res_DataLabel.hxx create mode 100644 chart2/source/controller/dialogs/res_ErrorBar.cxx create mode 100644 chart2/source/controller/dialogs/res_LegendPosition.cxx create mode 100644 chart2/source/controller/dialogs/res_Titles.cxx create mode 100644 chart2/source/controller/dialogs/res_Trendline.cxx create mode 100644 chart2/source/controller/dialogs/res_Trendline.hxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx create mode 100644 chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx create mode 100644 chart2/source/controller/dialogs/tp_AxisLabel.cxx create mode 100644 chart2/source/controller/dialogs/tp_AxisLabel.hxx create mode 100644 chart2/source/controller/dialogs/tp_AxisPositions.cxx create mode 100644 chart2/source/controller/dialogs/tp_AxisPositions.hxx create mode 100644 chart2/source/controller/dialogs/tp_ChartType.cxx create mode 100644 chart2/source/controller/dialogs/tp_ChartType.hxx create mode 100644 chart2/source/controller/dialogs/tp_DataLabel.cxx create mode 100644 chart2/source/controller/dialogs/tp_DataLabel.hxx create mode 100644 chart2/source/controller/dialogs/tp_DataPointOption.cxx create mode 100644 chart2/source/controller/dialogs/tp_DataPointOption.hxx create mode 100644 chart2/source/controller/dialogs/tp_DataSource.cxx create mode 100644 chart2/source/controller/dialogs/tp_DataSource.hxx create mode 100644 chart2/source/controller/dialogs/tp_ErrorBars.cxx create mode 100644 chart2/source/controller/dialogs/tp_ErrorBars.hxx create mode 100644 chart2/source/controller/dialogs/tp_LegendPosition.cxx create mode 100644 chart2/source/controller/dialogs/tp_LegendPosition.hxx create mode 100644 chart2/source/controller/dialogs/tp_PointGeometry.cxx create mode 100644 chart2/source/controller/dialogs/tp_PointGeometry.hxx create mode 100644 chart2/source/controller/dialogs/tp_PolarOptions.cxx create mode 100644 chart2/source/controller/dialogs/tp_PolarOptions.hxx create mode 100644 chart2/source/controller/dialogs/tp_RangeChooser.cxx create mode 100644 chart2/source/controller/dialogs/tp_RangeChooser.hxx create mode 100644 chart2/source/controller/dialogs/tp_Scale.cxx create mode 100644 chart2/source/controller/dialogs/tp_Scale.hxx create mode 100644 chart2/source/controller/dialogs/tp_SeriesToAxis.cxx create mode 100644 chart2/source/controller/dialogs/tp_SeriesToAxis.hxx create mode 100644 chart2/source/controller/dialogs/tp_TitleRotation.cxx create mode 100644 chart2/source/controller/dialogs/tp_TitleRotation.hxx create mode 100644 chart2/source/controller/dialogs/tp_Trendline.cxx create mode 100644 chart2/source/controller/dialogs/tp_Trendline.hxx create mode 100644 chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx create mode 100644 chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx create mode 100644 chart2/source/controller/drawinglayer/DrawViewWrapper.cxx create mode 100644 chart2/source/controller/drawinglayer/ViewElementListProvider.cxx create mode 100644 chart2/source/controller/inc/AccessibleBase.hxx create mode 100644 chart2/source/controller/inc/AccessibleChartView.hxx create mode 100644 chart2/source/controller/inc/AccessibleTextHelper.hxx create mode 100644 chart2/source/controller/inc/AxisItemConverter.hxx create mode 100644 chart2/source/controller/inc/CharacterPropertyItemConverter.hxx create mode 100644 chart2/source/controller/inc/ChartController.hxx create mode 100644 chart2/source/controller/inc/ChartDocumentWrapper.hxx create mode 100644 chart2/source/controller/inc/ChartToolbarController.hxx create mode 100644 chart2/source/controller/inc/ChartWindow.hxx create mode 100644 chart2/source/controller/inc/CommandDispatchContainer.hxx create mode 100644 chart2/source/controller/inc/ConfigurationAccess.hxx create mode 100644 chart2/source/controller/inc/DataPointItemConverter.hxx create mode 100644 chart2/source/controller/inc/DrawViewWrapper.hxx create mode 100644 chart2/source/controller/inc/ErrorBarItemConverter.hxx create mode 100644 chart2/source/controller/inc/GraphicPropertyItemConverter.hxx create mode 100644 chart2/source/controller/inc/ItemConverter.hxx create mode 100644 chart2/source/controller/inc/ItemPropertyMap.hxx create mode 100644 chart2/source/controller/inc/LegendItemConverter.hxx create mode 100644 chart2/source/controller/inc/MultipleChartConverters.hxx create mode 100644 chart2/source/controller/inc/MultipleItemConverter.hxx create mode 100644 chart2/source/controller/inc/ObjectHierarchy.hxx create mode 100644 chart2/source/controller/inc/ObjectNameProvider.hxx create mode 100644 chart2/source/controller/inc/PositionAndSizeHelper.hxx create mode 100644 chart2/source/controller/inc/RangeSelectionHelper.hxx create mode 100644 chart2/source/controller/inc/RangeSelectionListener.hxx create mode 100644 chart2/source/controller/inc/RegressionCurveItemConverter.hxx create mode 100644 chart2/source/controller/inc/RegressionEquationItemConverter.hxx create mode 100644 chart2/source/controller/inc/SelectionHelper.hxx create mode 100644 chart2/source/controller/inc/SeriesOptionsItemConverter.hxx create mode 100644 chart2/source/controller/inc/ShapeController.h create mode 100644 chart2/source/controller/inc/StatisticsItemConverter.hxx create mode 100644 chart2/source/controller/inc/TabPageNotifiable.hxx create mode 100644 chart2/source/controller/inc/TextDirectionListBox.hxx create mode 100644 chart2/source/controller/inc/TextLabelItemConverter.hxx create mode 100644 chart2/source/controller/inc/TimerTriggeredControllerLock.hxx create mode 100644 chart2/source/controller/inc/TitleDialogData.hxx create mode 100644 chart2/source/controller/inc/TitleItemConverter.hxx create mode 100644 chart2/source/controller/inc/ViewElementListProvider.hxx create mode 100644 chart2/source/controller/inc/dlg_ChartType.hxx create mode 100644 chart2/source/controller/inc/dlg_ChartType_UNO.hxx create mode 100644 chart2/source/controller/inc/dlg_CreationWizard.hxx create mode 100644 chart2/source/controller/inc/dlg_CreationWizard_UNO.hxx create mode 100644 chart2/source/controller/inc/dlg_DataEditor.hxx create mode 100644 chart2/source/controller/inc/dlg_DataSource.hxx create mode 100644 chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx create mode 100644 chart2/source/controller/inc/dlg_InsertDataLabel.hxx create mode 100644 chart2/source/controller/inc/dlg_InsertErrorBars.hxx create mode 100644 chart2/source/controller/inc/dlg_InsertLegend.hxx create mode 100644 chart2/source/controller/inc/dlg_InsertTitle.hxx create mode 100644 chart2/source/controller/inc/dlg_ObjectProperties.hxx create mode 100644 chart2/source/controller/inc/dlg_ShapeFont.hxx create mode 100644 chart2/source/controller/inc/dlg_ShapeParagraph.hxx create mode 100644 chart2/source/controller/inc/dlg_View3D.hxx create mode 100644 chart2/source/controller/inc/helpids.h create mode 100644 chart2/source/controller/inc/res_ErrorBar.hxx create mode 100644 chart2/source/controller/inc/res_LegendPosition.hxx create mode 100644 chart2/source/controller/inc/res_Titles.hxx create mode 100644 chart2/source/controller/inc/uiobject.hxx create mode 100644 chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/ItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx create mode 100644 chart2/source/controller/itemsetwrapper/MultipleItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx create mode 100644 chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx create mode 100644 chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx create mode 100644 chart2/source/controller/main/ChartController.cxx create mode 100644 chart2/source/controller/main/ChartController_EditData.cxx create mode 100644 chart2/source/controller/main/ChartController_Insert.cxx create mode 100644 chart2/source/controller/main/ChartController_Position.cxx create mode 100644 chart2/source/controller/main/ChartController_Properties.cxx create mode 100644 chart2/source/controller/main/ChartController_TextEdit.cxx create mode 100644 chart2/source/controller/main/ChartController_Tools.cxx create mode 100644 chart2/source/controller/main/ChartController_Window.cxx create mode 100644 chart2/source/controller/main/ChartDropTargetHelper.cxx create mode 100644 chart2/source/controller/main/ChartDropTargetHelper.hxx create mode 100644 chart2/source/controller/main/ChartFrameloader.cxx create mode 100644 chart2/source/controller/main/ChartFrameloader.hxx create mode 100644 chart2/source/controller/main/ChartModelClone.cxx create mode 100644 chart2/source/controller/main/ChartModelClone.hxx create mode 100644 chart2/source/controller/main/ChartTransferable.cxx create mode 100644 chart2/source/controller/main/ChartTransferable.hxx create mode 100644 chart2/source/controller/main/ChartWindow.cxx create mode 100644 chart2/source/controller/main/CommandDispatch.cxx create mode 100644 chart2/source/controller/main/CommandDispatch.hxx create mode 100644 chart2/source/controller/main/CommandDispatchContainer.cxx create mode 100644 chart2/source/controller/main/ConfigurationAccess.cxx create mode 100644 chart2/source/controller/main/ControllerCommandDispatch.cxx create mode 100644 chart2/source/controller/main/ControllerCommandDispatch.hxx create mode 100644 chart2/source/controller/main/DragMethod_Base.cxx create mode 100644 chart2/source/controller/main/DragMethod_Base.hxx create mode 100644 chart2/source/controller/main/DragMethod_PieSegment.cxx create mode 100644 chart2/source/controller/main/DragMethod_PieSegment.hxx create mode 100644 chart2/source/controller/main/DragMethod_RotateDiagram.cxx create mode 100644 chart2/source/controller/main/DragMethod_RotateDiagram.hxx create mode 100644 chart2/source/controller/main/DrawCommandDispatch.cxx create mode 100644 chart2/source/controller/main/DrawCommandDispatch.h create mode 100644 chart2/source/controller/main/DrawCommandDispatch.hxx create mode 100644 chart2/source/controller/main/ElementSelector.cxx create mode 100644 chart2/source/controller/main/ElementSelector.hxx create mode 100644 chart2/source/controller/main/FeatureCommandDispatchBase.cxx create mode 100644 chart2/source/controller/main/FeatureCommandDispatchBase.hxx create mode 100644 chart2/source/controller/main/ObjectHierarchy.cxx create mode 100644 chart2/source/controller/main/PositionAndSizeHelper.cxx create mode 100644 chart2/source/controller/main/SelectionHelper.cxx create mode 100644 chart2/source/controller/main/ShapeController.cxx create mode 100644 chart2/source/controller/main/ShapeController.hxx create mode 100644 chart2/source/controller/main/StatusBarCommandDispatch.cxx create mode 100644 chart2/source/controller/main/StatusBarCommandDispatch.hxx create mode 100644 chart2/source/controller/main/ToolbarController.cxx create mode 100644 chart2/source/controller/main/UndoActions.cxx create mode 100644 chart2/source/controller/main/UndoActions.hxx create mode 100644 chart2/source/controller/main/UndoCommandDispatch.cxx create mode 100644 chart2/source/controller/main/UndoCommandDispatch.hxx create mode 100644 chart2/source/controller/main/UndoGuard.cxx create mode 100644 chart2/source/controller/main/UndoGuard.hxx create mode 100644 chart2/source/controller/sidebar/Chart2PanelFactory.cxx create mode 100644 chart2/source/controller/sidebar/Chart2PanelFactory.hxx create mode 100644 chart2/source/controller/sidebar/ChartAreaPanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartAreaPanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartAxisPanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartAxisPanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartColorWrapper.cxx create mode 100644 chart2/source/controller/sidebar/ChartColorWrapper.hxx create mode 100644 chart2/source/controller/sidebar/ChartElementsPanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartElementsPanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartErrorBarPanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartErrorBarPanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartLinePanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartLinePanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartSeriesPanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartSeriesPanel.hxx create mode 100644 chart2/source/controller/sidebar/ChartSidebarModifyListener.cxx create mode 100644 chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx create mode 100644 chart2/source/controller/sidebar/ChartSidebarSelectionListener.cxx create mode 100644 chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx create mode 100644 chart2/source/controller/sidebar/ChartTypePanel.cxx create mode 100644 chart2/source/controller/sidebar/ChartTypePanel.hxx create mode 100644 chart2/source/controller/uitest/uiobject.cxx create mode 100644 chart2/source/inc/AxisHelper.hxx create mode 100644 chart2/source/inc/AxisIndexDefines.hxx create mode 100644 chart2/source/inc/BaseGFXHelper.hxx create mode 100644 chart2/source/inc/CachedDataSequence.hxx create mode 100644 chart2/source/inc/ChangingResource.hxx create mode 100644 chart2/source/inc/CharacterProperties.hxx create mode 100644 chart2/source/inc/ChartModelHelper.hxx create mode 100644 chart2/source/inc/ChartResourceGroupDlgs.hxx create mode 100644 chart2/source/inc/ChartResourceGroups.hxx create mode 100644 chart2/source/inc/ChartTypeDialogController.hxx create mode 100644 chart2/source/inc/ChartTypeHelper.hxx create mode 100644 chart2/source/inc/ChartTypeTemplateProvider.hxx create mode 100644 chart2/source/inc/ChartViewHelper.hxx create mode 100644 chart2/source/inc/CloneHelper.hxx create mode 100644 chart2/source/inc/ColorPerPointHelper.hxx create mode 100644 chart2/source/inc/CommonConverters.hxx create mode 100644 chart2/source/inc/CommonFunctors.hxx create mode 100644 chart2/source/inc/ConfigColorScheme.hxx create mode 100644 chart2/source/inc/ControllerLockGuard.hxx create mode 100644 chart2/source/inc/DataSeriesHelper.hxx create mode 100644 chart2/source/inc/DataSource.hxx create mode 100644 chart2/source/inc/DataSourceHelper.hxx create mode 100644 chart2/source/inc/DiagramHelper.hxx create mode 100644 chart2/source/inc/DisposeHelper.hxx create mode 100644 chart2/source/inc/ErrorBar.hxx create mode 100644 chart2/source/inc/EventListenerHelper.hxx create mode 100644 chart2/source/inc/ExplicitCategoriesProvider.hxx create mode 100644 chart2/source/inc/ExponentialRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/FastPropertyIdRanges.hxx create mode 100644 chart2/source/inc/FillProperties.hxx create mode 100644 chart2/source/inc/FormattedStringHelper.hxx create mode 100644 chart2/source/inc/InternalData.hxx create mode 100644 chart2/source/inc/InternalDataProvider.hxx create mode 100644 chart2/source/inc/LabeledDataSequence.hxx create mode 100644 chart2/source/inc/LegendHelper.hxx create mode 100644 chart2/source/inc/LifeTime.hxx create mode 100644 chart2/source/inc/LinePropertiesHelper.hxx create mode 100644 chart2/source/inc/LinearRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/LogarithmicRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/MeanValueRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/MediaDescriptorHelper.hxx create mode 100644 chart2/source/inc/ModifyListenerHelper.hxx create mode 100644 chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/MutexContainer.hxx create mode 100644 chart2/source/inc/NameContainer.hxx create mode 100644 chart2/source/inc/NumberFormatterWrapper.hxx create mode 100644 chart2/source/inc/OPropertySet.hxx create mode 100644 chart2/source/inc/ObjectIdentifier.hxx create mode 100644 chart2/source/inc/PolynomialRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/PopupRequest.hxx create mode 100644 chart2/source/inc/PotentialRegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/PropertyHelper.hxx create mode 100644 chart2/source/inc/RangeHighlighter.hxx create mode 100644 chart2/source/inc/ReferenceSizeProvider.hxx create mode 100644 chart2/source/inc/RegressionCalculationHelper.hxx create mode 100644 chart2/source/inc/RegressionCurveCalculator.hxx create mode 100644 chart2/source/inc/RegressionCurveHelper.hxx create mode 100644 chart2/source/inc/RelativePositionHelper.hxx create mode 100644 chart2/source/inc/RelativeSizeHelper.hxx create mode 100644 chart2/source/inc/ResId.hxx create mode 100644 chart2/source/inc/Scaling.hxx create mode 100644 chart2/source/inc/SceneProperties.hxx create mode 100644 chart2/source/inc/StackMode.hxx create mode 100644 chart2/source/inc/StatisticsHelper.hxx create mode 100644 chart2/source/inc/ThreeDHelper.hxx create mode 100644 chart2/source/inc/TitleHelper.hxx create mode 100644 chart2/source/inc/TrueGuard.hxx create mode 100644 chart2/source/inc/UncachedDataSequence.hxx create mode 100644 chart2/source/inc/UserDefinedProperties.hxx create mode 100644 chart2/source/inc/WeakListenerAdapter.hxx create mode 100644 chart2/source/inc/WrappedDefaultProperty.hxx create mode 100644 chart2/source/inc/WrappedDirectStateProperty.hxx create mode 100644 chart2/source/inc/WrappedIgnoreProperty.hxx create mode 100644 chart2/source/inc/WrappedProperty.hxx create mode 100644 chart2/source/inc/WrappedPropertySet.hxx create mode 100644 chart2/source/inc/XMLRangeHelper.hxx create mode 100644 chart2/source/inc/charttoolsdllapi.hxx create mode 100644 chart2/source/inc/chartview/ChartSfxItemIds.hxx create mode 100644 chart2/source/inc/chartview/DataPointSymbolSupplier.hxx create mode 100644 chart2/source/inc/chartview/DrawModelWrapper.hxx create mode 100644 chart2/source/inc/chartview/ExplicitScaleValues.hxx create mode 100644 chart2/source/inc/chartview/ExplicitValueProvider.hxx create mode 100644 chart2/source/inc/chartview/chartviewdllapi.hxx create mode 100644 chart2/source/inc/defines.hxx create mode 100644 chart2/source/inc/res_BarGeometry.hxx create mode 100644 chart2/source/inc/servicenames.hxx create mode 100644 chart2/source/inc/servicenames_charttypes.hxx create mode 100644 chart2/source/inc/servicenames_coosystems.hxx create mode 100644 chart2/source/model/filter/XMLFilter.cxx create mode 100644 chart2/source/model/inc/BaseCoordinateSystem.hxx create mode 100644 chart2/source/model/inc/CartesianCoordinateSystem.hxx create mode 100644 chart2/source/model/inc/ChartTypeManager.hxx create mode 100644 chart2/source/model/inc/DataSeries.hxx create mode 100644 chart2/source/model/inc/Diagram.hxx create mode 100644 chart2/source/model/inc/PolarCoordinateSystem.hxx create mode 100644 chart2/source/model/inc/StockBar.hxx create mode 100644 chart2/source/model/inc/XMLFilter.hxx create mode 100644 chart2/source/model/main/Axis.cxx create mode 100644 chart2/source/model/main/Axis.hxx create mode 100644 chart2/source/model/main/BaseCoordinateSystem.cxx create mode 100644 chart2/source/model/main/CartesianCoordinateSystem.cxx create mode 100644 chart2/source/model/main/ChartModel.cxx create mode 100644 chart2/source/model/main/ChartModel_Persistence.cxx create mode 100644 chart2/source/model/main/DataPoint.cxx create mode 100644 chart2/source/model/main/DataPoint.hxx create mode 100644 chart2/source/model/main/DataPointProperties.cxx create mode 100644 chart2/source/model/main/DataPointProperties.hxx create mode 100644 chart2/source/model/main/DataSeries.cxx create mode 100644 chart2/source/model/main/DataSeriesProperties.cxx create mode 100644 chart2/source/model/main/DataSeriesProperties.hxx create mode 100644 chart2/source/model/main/Diagram.cxx create mode 100644 chart2/source/model/main/FormattedString.cxx create mode 100644 chart2/source/model/main/FormattedString.hxx create mode 100644 chart2/source/model/main/GridProperties.cxx create mode 100644 chart2/source/model/main/GridProperties.hxx create mode 100644 chart2/source/model/main/Legend.cxx create mode 100644 chart2/source/model/main/Legend.hxx create mode 100644 chart2/source/model/main/PageBackground.cxx create mode 100644 chart2/source/model/main/PageBackground.hxx create mode 100644 chart2/source/model/main/PolarCoordinateSystem.cxx create mode 100644 chart2/source/model/main/StockBar.cxx create mode 100644 chart2/source/model/main/Title.cxx create mode 100644 chart2/source/model/main/Title.hxx create mode 100644 chart2/source/model/main/UndoManager.cxx create mode 100644 chart2/source/model/main/UndoManager.hxx create mode 100644 chart2/source/model/main/Wall.cxx create mode 100644 chart2/source/model/main/Wall.hxx create mode 100644 chart2/source/model/template/AreaChartType.cxx create mode 100644 chart2/source/model/template/AreaChartType.hxx create mode 100644 chart2/source/model/template/AreaChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/AreaChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/BarChartType.cxx create mode 100644 chart2/source/model/template/BarChartType.hxx create mode 100644 chart2/source/model/template/BarChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/BarChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/BubbleChartType.cxx create mode 100644 chart2/source/model/template/BubbleChartType.hxx create mode 100644 chart2/source/model/template/BubbleChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/BubbleChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/BubbleDataInterpreter.cxx create mode 100644 chart2/source/model/template/BubbleDataInterpreter.hxx create mode 100644 chart2/source/model/template/CandleStickChartType.cxx create mode 100644 chart2/source/model/template/CandleStickChartType.hxx create mode 100644 chart2/source/model/template/ChartType.cxx create mode 100644 chart2/source/model/template/ChartType.hxx create mode 100644 chart2/source/model/template/ChartTypeManager.cxx create mode 100644 chart2/source/model/template/ChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/ChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/ColumnChartType.cxx create mode 100644 chart2/source/model/template/ColumnChartType.hxx create mode 100644 chart2/source/model/template/ColumnLineChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/ColumnLineChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/ColumnLineDataInterpreter.cxx create mode 100644 chart2/source/model/template/ColumnLineDataInterpreter.hxx create mode 100644 chart2/source/model/template/DataInterpreter.cxx create mode 100644 chart2/source/model/template/DataInterpreter.hxx create mode 100644 chart2/source/model/template/FilledNetChartType.cxx create mode 100644 chart2/source/model/template/FilledNetChartType.hxx create mode 100644 chart2/source/model/template/LineChartType.cxx create mode 100644 chart2/source/model/template/LineChartType.hxx create mode 100644 chart2/source/model/template/LineChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/LineChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/NetChartType.cxx create mode 100644 chart2/source/model/template/NetChartType.hxx create mode 100644 chart2/source/model/template/NetChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/NetChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/PieChartType.cxx create mode 100644 chart2/source/model/template/PieChartType.hxx create mode 100644 chart2/source/model/template/PieChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/PieChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/ScatterChartType.cxx create mode 100644 chart2/source/model/template/ScatterChartType.hxx create mode 100644 chart2/source/model/template/ScatterChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/ScatterChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/StockChartTypeTemplate.cxx create mode 100644 chart2/source/model/template/StockChartTypeTemplate.hxx create mode 100644 chart2/source/model/template/StockDataInterpreter.cxx create mode 100644 chart2/source/model/template/StockDataInterpreter.hxx create mode 100644 chart2/source/model/template/XYDataInterpreter.cxx create mode 100644 chart2/source/model/template/XYDataInterpreter.hxx create mode 100644 chart2/source/tools/AxisHelper.cxx create mode 100644 chart2/source/tools/BaseGFXHelper.cxx create mode 100644 chart2/source/tools/CachedDataSequence.cxx create mode 100644 chart2/source/tools/CharacterProperties.cxx create mode 100644 chart2/source/tools/ChartModelHelper.cxx create mode 100644 chart2/source/tools/ChartTypeHelper.cxx create mode 100644 chart2/source/tools/ChartViewHelper.cxx create mode 100644 chart2/source/tools/ColorPerPointHelper.cxx create mode 100644 chart2/source/tools/CommonConverters.cxx create mode 100644 chart2/source/tools/ConfigColorScheme.cxx create mode 100644 chart2/source/tools/ControllerLockGuard.cxx create mode 100644 chart2/source/tools/DataSeriesHelper.cxx create mode 100644 chart2/source/tools/DataSource.cxx create mode 100644 chart2/source/tools/DataSourceHelper.cxx create mode 100644 chart2/source/tools/DiagramHelper.cxx create mode 100644 chart2/source/tools/ErrorBar.cxx create mode 100644 chart2/source/tools/ExplicitCategoriesProvider.cxx create mode 100644 chart2/source/tools/ExponentialRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/FillProperties.cxx create mode 100644 chart2/source/tools/FormattedStringHelper.cxx create mode 100644 chart2/source/tools/ImplOPropertySet.cxx create mode 100644 chart2/source/tools/ImplOPropertySet.hxx create mode 100644 chart2/source/tools/InternalData.cxx create mode 100644 chart2/source/tools/InternalDataProvider.cxx create mode 100644 chart2/source/tools/LabeledDataSequence.cxx create mode 100644 chart2/source/tools/LegendHelper.cxx create mode 100644 chart2/source/tools/LifeTime.cxx create mode 100644 chart2/source/tools/LinePropertiesHelper.cxx create mode 100644 chart2/source/tools/LinearRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/MeanValueRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/MediaDescriptorHelper.cxx create mode 100644 chart2/source/tools/ModifyListenerHelper.cxx create mode 100644 chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/NameContainer.cxx create mode 100644 chart2/source/tools/NumberFormatterWrapper.cxx create mode 100644 chart2/source/tools/OPropertySet.cxx create mode 100644 chart2/source/tools/ObjectIdentifier.cxx create mode 100644 chart2/source/tools/PolynomialRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/PopupRequest.cxx create mode 100644 chart2/source/tools/PotentialRegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/PropertyHelper.cxx create mode 100644 chart2/source/tools/RangeHighlighter.cxx create mode 100644 chart2/source/tools/ReferenceSizeProvider.cxx create mode 100644 chart2/source/tools/RegressionCurveCalculator.cxx create mode 100644 chart2/source/tools/RegressionCurveHelper.cxx create mode 100644 chart2/source/tools/RegressionCurveModel.cxx create mode 100644 chart2/source/tools/RegressionCurveModel.hxx create mode 100644 chart2/source/tools/RegressionEquation.cxx create mode 100644 chart2/source/tools/RegressionEquation.hxx create mode 100644 chart2/source/tools/RelativePositionHelper.cxx create mode 100644 chart2/source/tools/RelativeSizeHelper.cxx create mode 100644 chart2/source/tools/ResId.cxx create mode 100644 chart2/source/tools/Scaling.cxx create mode 100644 chart2/source/tools/SceneProperties.cxx create mode 100644 chart2/source/tools/StatisticsHelper.cxx create mode 100644 chart2/source/tools/ThreeDHelper.cxx create mode 100644 chart2/source/tools/TitleHelper.cxx create mode 100644 chart2/source/tools/TrueGuard.cxx create mode 100644 chart2/source/tools/UncachedDataSequence.cxx create mode 100644 chart2/source/tools/UserDefinedProperties.cxx create mode 100644 chart2/source/tools/WeakListenerAdapter.cxx create mode 100644 chart2/source/tools/WrappedDefaultProperty.cxx create mode 100644 chart2/source/tools/WrappedDirectStateProperty.cxx create mode 100644 chart2/source/tools/WrappedIgnoreProperty.cxx create mode 100644 chart2/source/tools/WrappedProperty.cxx create mode 100644 chart2/source/tools/WrappedPropertySet.cxx create mode 100644 chart2/source/tools/XMLRangeHelper.cxx create mode 100644 chart2/source/view/axes/DateHelper.cxx create mode 100644 chart2/source/view/axes/DateScaling.cxx create mode 100644 chart2/source/view/axes/DateScaling.hxx create mode 100644 chart2/source/view/axes/MinimumAndMaximumSupplier.cxx create mode 100644 chart2/source/view/axes/ScaleAutomatism.cxx create mode 100644 chart2/source/view/axes/TickmarkProperties.hxx create mode 100644 chart2/source/view/axes/Tickmarks.cxx create mode 100644 chart2/source/view/axes/Tickmarks.hxx create mode 100644 chart2/source/view/axes/Tickmarks_Dates.cxx create mode 100644 chart2/source/view/axes/Tickmarks_Dates.hxx create mode 100644 chart2/source/view/axes/Tickmarks_Equidistant.cxx create mode 100644 chart2/source/view/axes/Tickmarks_Equidistant.hxx create mode 100644 chart2/source/view/axes/VAxisBase.cxx create mode 100644 chart2/source/view/axes/VAxisBase.hxx create mode 100644 chart2/source/view/axes/VAxisOrGridBase.cxx create mode 100644 chart2/source/view/axes/VAxisOrGridBase.hxx create mode 100644 chart2/source/view/axes/VAxisProperties.cxx create mode 100644 chart2/source/view/axes/VAxisProperties.hxx create mode 100644 chart2/source/view/axes/VCartesianAxis.cxx create mode 100644 chart2/source/view/axes/VCartesianAxis.hxx create mode 100644 chart2/source/view/axes/VCartesianCoordinateSystem.cxx create mode 100644 chart2/source/view/axes/VCartesianCoordinateSystem.hxx create mode 100644 chart2/source/view/axes/VCartesianGrid.cxx create mode 100644 chart2/source/view/axes/VCartesianGrid.hxx create mode 100644 chart2/source/view/axes/VCoordinateSystem.cxx create mode 100644 chart2/source/view/axes/VPolarAngleAxis.cxx create mode 100644 chart2/source/view/axes/VPolarAngleAxis.hxx create mode 100644 chart2/source/view/axes/VPolarAxis.cxx create mode 100644 chart2/source/view/axes/VPolarAxis.hxx create mode 100644 chart2/source/view/axes/VPolarCoordinateSystem.cxx create mode 100644 chart2/source/view/axes/VPolarCoordinateSystem.hxx create mode 100644 chart2/source/view/axes/VPolarGrid.cxx create mode 100644 chart2/source/view/axes/VPolarGrid.hxx create mode 100644 chart2/source/view/axes/VPolarRadiusAxis.cxx create mode 100644 chart2/source/view/axes/VPolarRadiusAxis.hxx create mode 100644 chart2/source/view/charttypes/AreaChart.cxx create mode 100644 chart2/source/view/charttypes/AreaChart.hxx create mode 100644 chart2/source/view/charttypes/BarChart.cxx create mode 100644 chart2/source/view/charttypes/BarChart.hxx create mode 100644 chart2/source/view/charttypes/BarPositionHelper.cxx create mode 100644 chart2/source/view/charttypes/BarPositionHelper.hxx create mode 100644 chart2/source/view/charttypes/BubbleChart.cxx create mode 100644 chart2/source/view/charttypes/BubbleChart.hxx create mode 100644 chart2/source/view/charttypes/CandleStickChart.cxx create mode 100644 chart2/source/view/charttypes/CandleStickChart.hxx create mode 100644 chart2/source/view/charttypes/CategoryPositionHelper.cxx create mode 100644 chart2/source/view/charttypes/CategoryPositionHelper.hxx create mode 100644 chart2/source/view/charttypes/ConfigAccess.cxx create mode 100644 chart2/source/view/charttypes/NetChart.cxx create mode 100644 chart2/source/view/charttypes/NetChart.hxx create mode 100644 chart2/source/view/charttypes/PieChart.cxx create mode 100644 chart2/source/view/charttypes/PieChart.hxx create mode 100644 chart2/source/view/charttypes/Splines.cxx create mode 100644 chart2/source/view/charttypes/Splines.hxx create mode 100644 chart2/source/view/charttypes/VSeriesPlotter.cxx create mode 100644 chart2/source/view/diagram/VDiagram.cxx create mode 100644 chart2/source/view/inc/Clipping.hxx create mode 100644 chart2/source/view/inc/ConfigAccess.hxx create mode 100644 chart2/source/view/inc/DateHelper.hxx create mode 100644 chart2/source/view/inc/LabelAlignment.hxx create mode 100644 chart2/source/view/inc/LabelPositionHelper.hxx create mode 100644 chart2/source/view/inc/LegendEntryProvider.hxx create mode 100644 chart2/source/view/inc/Linear3DTransformation.hxx create mode 100644 chart2/source/view/inc/MinimumAndMaximumSupplier.hxx create mode 100644 chart2/source/view/inc/PlotterBase.hxx create mode 100644 chart2/source/view/inc/PlottingPositionHelper.hxx create mode 100644 chart2/source/view/inc/PolarLabelPositionHelper.hxx create mode 100644 chart2/source/view/inc/PropertyMapper.hxx create mode 100644 chart2/source/view/inc/ScaleAutomatism.hxx create mode 100644 chart2/source/view/inc/ShapeFactory.hxx create mode 100644 chart2/source/view/inc/Stripe.hxx create mode 100644 chart2/source/view/inc/VCoordinateSystem.hxx create mode 100644 chart2/source/view/inc/VDataSeries.hxx create mode 100644 chart2/source/view/inc/VDiagram.hxx create mode 100644 chart2/source/view/inc/VLegendSymbolFactory.hxx create mode 100644 chart2/source/view/inc/VLineProperties.hxx create mode 100644 chart2/source/view/inc/VPolarTransformation.hxx create mode 100644 chart2/source/view/inc/VSeriesPlotter.hxx create mode 100644 chart2/source/view/inc/ViewDefines.hxx create mode 100644 chart2/source/view/main/ChartItemPool.cxx create mode 100644 chart2/source/view/main/ChartItemPool.hxx create mode 100644 chart2/source/view/main/ChartView.cxx create mode 100644 chart2/source/view/main/Clipping.cxx create mode 100644 chart2/source/view/main/DataPointSymbolSupplier.cxx create mode 100644 chart2/source/view/main/DrawModelWrapper.cxx create mode 100644 chart2/source/view/main/LabelPositionHelper.cxx create mode 100644 chart2/source/view/main/Linear3DTransformation.cxx create mode 100644 chart2/source/view/main/PlotterBase.cxx create mode 100644 chart2/source/view/main/PlottingPositionHelper.cxx create mode 100644 chart2/source/view/main/PolarLabelPositionHelper.cxx create mode 100644 chart2/source/view/main/PropertyMapper.cxx create mode 100644 chart2/source/view/main/ShapeFactory.cxx create mode 100644 chart2/source/view/main/Stripe.cxx create mode 100644 chart2/source/view/main/VButton.cxx create mode 100644 chart2/source/view/main/VButton.hxx create mode 100644 chart2/source/view/main/VDataSeries.cxx create mode 100644 chart2/source/view/main/VLegend.cxx create mode 100644 chart2/source/view/main/VLegend.hxx create mode 100644 chart2/source/view/main/VLegendSymbolFactory.cxx create mode 100644 chart2/source/view/main/VLineProperties.cxx create mode 100644 chart2/source/view/main/VPolarTransformation.cxx create mode 100644 chart2/source/view/main/VTitle.cxx create mode 100644 chart2/source/view/main/VTitle.hxx create mode 100644 chart2/uiconfig/accelerator/en-US/default.xml create mode 100644 chart2/uiconfig/menubar/menubar.xml create mode 100644 chart2/uiconfig/popupmenu/draw.xml create mode 100644 chart2/uiconfig/popupmenu/drawtext.xml create mode 100644 chart2/uiconfig/statusbar/statusbar.xml create mode 100644 chart2/uiconfig/toolbar/arrowshapes.xml create mode 100644 chart2/uiconfig/toolbar/basicshapes.xml create mode 100644 chart2/uiconfig/toolbar/calloutshapes.xml create mode 100644 chart2/uiconfig/toolbar/drawbar.xml create mode 100644 chart2/uiconfig/toolbar/flowchartshapes.xml create mode 100644 chart2/uiconfig/toolbar/standardbar.xml create mode 100644 chart2/uiconfig/toolbar/starshapes.xml create mode 100644 chart2/uiconfig/toolbar/symbolshapes.xml create mode 100644 chart2/uiconfig/toolbar/toolbar.xml create mode 100644 chart2/uiconfig/ui/3dviewdialog.ui create mode 100644 chart2/uiconfig/ui/attributedialog.ui create mode 100644 chart2/uiconfig/ui/chardialog.ui create mode 100644 chart2/uiconfig/ui/chartdatadialog.ui create mode 100644 chart2/uiconfig/ui/charttypedialog.ui create mode 100644 chart2/uiconfig/ui/columnfragment.ui create mode 100644 chart2/uiconfig/ui/combobox.ui create mode 100644 chart2/uiconfig/ui/datarangedialog.ui create mode 100644 chart2/uiconfig/ui/dlg_DataLabel.ui create mode 100644 chart2/uiconfig/ui/dlg_InsertErrorBars.ui create mode 100644 chart2/uiconfig/ui/dlg_InsertLegend.ui create mode 100644 chart2/uiconfig/ui/imagefragment.ui create mode 100644 chart2/uiconfig/ui/insertaxisdlg.ui create mode 100644 chart2/uiconfig/ui/insertgriddlg.ui create mode 100644 chart2/uiconfig/ui/inserttitledlg.ui create mode 100644 chart2/uiconfig/ui/paradialog.ui create mode 100644 chart2/uiconfig/ui/sidebaraxis.ui create mode 100644 chart2/uiconfig/ui/sidebarelements.ui create mode 100644 chart2/uiconfig/ui/sidebarerrorbar.ui create mode 100644 chart2/uiconfig/ui/sidebarseries.ui create mode 100644 chart2/uiconfig/ui/sidebartype.ui create mode 100644 chart2/uiconfig/ui/smoothlinesdlg.ui create mode 100644 chart2/uiconfig/ui/steppedlinesdlg.ui create mode 100644 chart2/uiconfig/ui/titlerotationtabpage.ui create mode 100644 chart2/uiconfig/ui/tp_3D_SceneAppearance.ui create mode 100644 chart2/uiconfig/ui/tp_3D_SceneGeometry.ui create mode 100644 chart2/uiconfig/ui/tp_3D_SceneIllumination.ui create mode 100644 chart2/uiconfig/ui/tp_AxisPositions.ui create mode 100644 chart2/uiconfig/ui/tp_ChartType.ui create mode 100644 chart2/uiconfig/ui/tp_DataLabel.ui create mode 100644 chart2/uiconfig/ui/tp_DataPointOption.ui create mode 100644 chart2/uiconfig/ui/tp_DataSource.ui create mode 100644 chart2/uiconfig/ui/tp_ErrorBars.ui create mode 100644 chart2/uiconfig/ui/tp_LegendPosition.ui create mode 100644 chart2/uiconfig/ui/tp_PolarOptions.ui create mode 100644 chart2/uiconfig/ui/tp_RangeChooser.ui create mode 100644 chart2/uiconfig/ui/tp_Scale.ui create mode 100644 chart2/uiconfig/ui/tp_SeriesToAxis.ui create mode 100644 chart2/uiconfig/ui/tp_Trendline.ui create mode 100644 chart2/uiconfig/ui/tp_axisLabel.ui create mode 100644 chart2/uiconfig/ui/wizelementspage.ui create mode 100644 chart2/workbench/addin/exports.dxp create mode 100644 chart2/workbench/addin/makefile.mk create mode 100644 chart2/workbench/addin/sampleaddin.cxx create mode 100644 chart2/workbench/addin/sampleaddin.def create mode 100644 chart2/workbench/addin/sampleaddin.hxx (limited to 'chart2') diff --git a/chart2/AllLangMoTarget_chart.mk b/chart2/AllLangMoTarget_chart.mk new file mode 100644 index 000000000..bf3b19b38 --- /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 000000000..947ae6b4e --- /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 000000000..bfbd0d3d3 --- /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 000000000..3eb7d06a4 --- /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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + 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 \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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 000000000..8caf285b1 --- /dev/null +++ b/chart2/CppunitTest_chart2_export.mk @@ -0,0 +1,139 @@ +# -*- 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_export)) + +$(eval $(call gb_CppunitTest_use_externals,chart2_export, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,chart2_export, \ + chart2/qa/extras/chart2export \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,chart2_export, \ + $(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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vbahelper \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,chart2_export,\ + -I$(SRCDIR)/chart2/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,chart2_export)) + +$(eval $(call gb_CppunitTest_use_ure,chart2_export)) +$(eval $(call gb_CppunitTest_use_vcl,chart2_export)) + +$(eval $(call gb_CppunitTest_use_components,chart2_export,\ + basic/util/sb \ + animations/source/animcore/animcore \ + chart2/source/controller/chartcontroller \ + chart2/source/chartcore \ + comphelper/util/comphelp \ + configmgr/source/configmgr \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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_export, \ + modules/swriter \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,chart2_export)) + +$(call gb_CppunitTest_get_target,chart2_export): $(call gb_Package_get_target,postprocess_images) + +# 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 000000000..fb07f9108 --- /dev/null +++ b/chart2/CppunitTest_chart2_geometry.mk @@ -0,0 +1,139 @@ +# -*- 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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + 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 \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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)) + +$(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 000000000..18c264bbc --- /dev/null +++ b/chart2/CppunitTest_chart2_import.mk @@ -0,0 +1,132 @@ +# -*- 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_import)) + +$(eval $(call gb_CppunitTest_use_externals,chart2_import, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,chart2_import, \ + chart2/qa/extras/chart2import \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,chart2_import, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + vcl \ + oox \ + sal \ + salhelper \ + sax \ + sb \ + sc \ + sw \ + sd \ + sfx \ + sot \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vbahelper \ + xo \ + sw \ +)) + +$(eval $(call gb_CppunitTest_set_include,chart2_import,\ + -I$(SRCDIR)/chart2/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,chart2_import)) + +$(eval $(call gb_CppunitTest_use_ure,chart2_import)) +$(eval $(call gb_CppunitTest_use_vcl,chart2_import)) + +$(eval $(call gb_CppunitTest_use_components,chart2_import,\ + basic/util/sb \ + animations/source/animcore/animcore \ + chart2/source/controller/chartcontroller \ + chart2/source/chartcore \ + comphelper/util/comphelp \ + configmgr/source/configmgr \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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_import)) + +# 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 000000000..960c0a511 --- /dev/null +++ b/chart2/CppunitTest_chart2_pivot_chart_test.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_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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + 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 \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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)) + +# 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 000000000..afbb7c0ef --- /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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + 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 \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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_xshape.mk b/chart2/CppunitTest_chart2_xshape.mk new file mode 100644 index 000000000..9e048bce9 --- /dev/null +++ b/chart2/CppunitTest_chart2_xshape.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_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 \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + 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 \ + dtrans/util/mcnttype \ + 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/sdfilt \ + 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)) + +# vim: set noet sw=4 ts=4: diff --git a/chart2/IwyuFilter_chart2.yaml b/chart2/IwyuFilter_chart2.yaml new file mode 100644 index 000000000..fba041a9f --- /dev/null +++ b/chart2/IwyuFilter_chart2.yaml @@ -0,0 +1,840 @@ +--- +assumeFilename: chart2/source/controller/main/ChartWindow.cxx +blacklist: + 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/DiagramHelper.hxx: + # # typedef in base class needs a complete type + - com/sun/star/chart2/XChartTypeTemplate.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/util/XModifyListener.hpp + - 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/BaseCoordinateSystem.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XChartTypeContainer.hpp + - com/sun/star/chart2/XCoordinateSystem.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/inc/ChartTypeManager.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XChartTypeManager.hpp + - com/sun/star/lang/XMultiServiceFactory.hpp + - com/sun/star/lang/XServiceInfo.hpp + chart2/source/model/inc/DataSeries.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XDataSeries.hpp + - com/sun/star/chart2/XRegressionCurveContainer.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/model/inc/Diagram.hxx: + # base class has to be a complete type + - com/sun/star/chart/X3DDefaultSetter.hpp + - com/sun/star/chart2/XCoordinateSystemContainer.hpp + - com/sun/star/chart2/XDiagram.hpp + - com/sun/star/chart2/XTitled.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/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/io/XActiveDataSource.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/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.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XAxis.hpp + - com/sun/star/chart2/XTitled.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/model/main/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.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XLegend.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/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/ChartType.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XChartType.hpp + - com/sun/star/chart2/XDataSeriesContainer.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/template/ChartTypeTemplate.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XChartTypeTemplate.hpp + - com/sun/star/lang/XServiceName.hpp + chart2/source/model/template/DataInterpreter.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XDataInterpreter.hpp + - com/sun/star/lang/XServiceInfo.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/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/RegressionCurveModel.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XRegressionCurve.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XServiceName.hpp + - com/sun/star/util/XCloneable.hpp + - com/sun/star/util/XModifyBroadcaster.hpp + - com/sun/star/util/XModifyListener.hpp + chart2/source/tools/ImplOPropertySet.cxx: + # Needed for template + - com/sun/star/style/XStyle.hpp + 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/ReferenceSizeProvider.cxx: + # Actually used + - com/sun/star/chart2/XTitle.hpp + chart2/source/tools/RegressionCurveHelper.cxx: + # Actually used + - com/sun/star/chart2/XRegressionCurveCalculator.hpp + 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/UncachedDataSequence.cxx: + # Actually used + - com/sun/star/chart2/XInternalDataProvider.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/3DChartObjects.hxx: + # base class has to be a complete type + - boost/shared_array.hpp + - map + chart2/source/view/inc/Linear3DTransformation.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XTransformation.hpp + chart2/source/view/inc/VLineProperties.hxx: + # base class has to be a complete type + - com/sun/star/uno/Reference.h + chart2/source/view/inc/VPolarTransformation.hxx: + # base class has to be a complete type + - com/sun/star/chart2/XTransformation.hpp + 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/VAxisBase.cxx: + # Needed for direct member access + - com/sun/star/drawing/XShapes.hpp + chart2/source/view/axes/VAxisProperties.cxx: + # Actually used + - com/sun/star/chart2/XAxis.hpp + # Needed for rtl::math::round + - rtl/math.hxx + chart2/source/view/axes/VCartesianCoordinateSystem.cxx: + # Actually used + - com/sun/star/chart2/XCoordinateSystem.hpp + chart2/source/view/axes/VPolarCoordinateSystem.cxx: + # Actually used + - com/sun/star/chart2/XCoordinateSystem.hpp + chart2/source/view/axes/VCartesianGrid.hxx: + # base class has to be a complete type + - com/sun/star/beans/XPropertySet.hpp + chart2/source/view/charttypes/Splines.cxx: + # Actually used + - com/sun/star/drawing/PolyPolygonShape3D.hpp + chart2/source/view/charttypes/AreaChart.cxx: + # Actually used + - com/sun/star/drawing/XShapes.hpp + chart2/source/view/charttypes/NetChart.cxx: + # Actually used + - com/sun/star/drawing/XShapes.hpp + chart2/source/view/charttypes/BarChart.cxx: + # comphelper::ScopeGuard being used + - comphelper/scopeguard.hxx + chart2/source/view/main/LabelPositionHelper.cxx: + # Actually used + - com/sun/star/beans/XPropertySet.hpp + - com/sun/star/drawing/XShape.hpp + chart2/source/view/main/VButton.cxx: + # Actually used + - com/sun/star/lang/XMultiServiceFactory.hpp + chart2/source/view/main/PlottingPositionHelper.cxx: + # Actually used + - com/sun/star/drawing/XShapes.hpp + 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 + - com/sun/star/lang/XMultiServiceFactory.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 + - com/sun/star/drawing/XShape.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/AccessibleBase.cxx: + # Needed for template + - com/sun/star/chart2/XChartDocument.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: + # Actually used + - vector + chart2/source/controller/dialogs/ChartTypeDialogController.cxx: + # Actually used + - com/sun/star/chart2/XChartDocument.hpp + chart2/source/controller/dialogs/DataBrowser.cxx: + # Needed for complex variable type + - com/sun/star/chart2/XChartDocument.hpp + chart2/source/controller/dialogs/DialogModel.cxx: + # Actually used + - com/sun/star/uno/XComponentContext.hpp + - com/sun/star/chart2/XChartDocument.hpp + chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx: + # Needed for complex variable type + - com/sun/star/frame/XModel.hpp + chart2/source/controller/dialogs/dlg_DataEditor.cxx: + # Needed for direct member access + - com/sun/star/awt/XWindow.hpp + chart2/source/controller/dialogs/RangeSelectionHelper.cxx: + # Actually used + - com/sun/star/chart2/XChartDocument.hpp + chart2/source/controller/dialogs/res_ErrorBar.cxx: + # Actually used + - com/sun/star/chart2/XChartDocument.hpp + 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_ChartType.cxx: + # Actually used + - com/sun/star/chart2/XChartDocument.hpp + 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/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 + chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx: + # Needed for rtl::math::round + - rtl/math.hxx + chart2/source/controller/main/ChartModelClone.hxx: + # Needed for implicit dtor + - com/sun/star/uno/Any.hxx + 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/ChartDropTargetHelper.cxx: + # Actually used + - com/sun/star/chart2/XChartDocument.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/CommandDispatchContainer.cxx: + # Actually used + - com/sun/star/frame/XModel.hpp + 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/ObjectHierarchy.cxx: + # Actually used + - com/sun/star/awt/KeyEvent.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_EditData.cxx: + # Needed for member access + - ChartWindow.hxx + chart2/source/controller/main/ChartController_Position.cxx: + # Needed for member access + - ChartWindow.hxx + chart2/source/controller/main/ChartController_Properties.cxx: + # Needed for member access + - ChartWindow.hxx + chart2/source/controller/main/ChartController_Tools.cxx: + # Needed for template + - com/sun/star/graphic/XGraphic.hpp + chart2/source/controller/main/PositionAndSizeHelper.cxx: + # Actually used + - com/sun/star/awt/Rectangle.hpp + 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/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/itemsetwrapper/MultipleChartConverters.cxx: + # Needed for compound type declaration + - com/sun/star/chart2/XAxis.hpp diff --git a/chart2/JunitTest_chart2_unoapi.mk b/chart2/JunitTest_chart2_unoapi.mk new file mode 100644 index 000000000..7607c4648 --- /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 000000000..48115dd2a --- /dev/null +++ b/chart2/Library_chartcontroller.mk @@ -0,0 +1,205 @@ +# -*- 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_libraries,chartcontroller,\ + basegfx \ + chartcore \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + 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)) + +$(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 \ + 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_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_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_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/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/ConfigurationAccess \ + 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 000000000..f42dfecd4 --- /dev/null +++ b/chart2/Library_chartcore.mk @@ -0,0 +1,242 @@ +# -*- 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 \ +)) + +ifeq ($(DISABLE_GUI),) +$(eval $(call gb_Library_use_externals,chartcore,\ + epoxy \ +)) +endif + +$(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 \ + fwe \ + i18nlangtag \ + sal \ + salhelper \ + sfx \ + svl \ + svt \ + svxcore \ + tl \ + ucbhelper \ + utl \ + vcl \ +)) + +$(eval $(call gb_Library_set_componentfile,chartcore,chart2/source/chartcore)) + +# 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/ConfigAccess \ + 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/DrawModelWrapper \ + 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/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/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/ImplOPropertySet \ + 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/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/TrueGuard \ + 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 000000000..0997e6284 --- /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 000000000..37acfdc37 --- /dev/null +++ b/chart2/Module_chart2.mk @@ -0,0 +1,54 @@ +# -*- 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_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_import \ + CppunitTest_chart2_trendcalculators \ + CppunitTest_chart2_dump \ + CppunitTest_chart2_pivot_chart_test \ + CppunitTest_chart2_geometry \ +)) + +ifeq ($(ENABLE_CHART_TESTS),TRUE) +ifeq ($(WITH_FONTS), TRUE) +$(eval $(call gb_Module_add_slowcheck_targets,chart2,\ + CppunitTest_chart2_xshape \ +)) +endif +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 b/chart2/README new file mode 100644 index 000000000..56eb0ed08 --- /dev/null +++ b/chart2/README @@ -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 == + +=== CTRL + F12 === +This 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 000000000..67d64b18b --- /dev/null +++ b/chart2/UIConfig_chart2.mk @@ -0,0 +1,81 @@ +# -*- 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_InsertErrorBars \ + 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/dlg_InsertLegend \ + 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_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/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx new file mode 100644 index 000000000..8c9c4ad69 --- /dev/null +++ b/chart2/inc/ChartModel.hxx @@ -0,0 +1,475 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// public API +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::awt { class XRequestCallback; } +namespace com::sun::star::chart2 { class XChartTypeTemplate; } +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; + +namespace chart +{ + +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 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; + + rtl::Reference 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; + css::uno::Reference< css::chart2::data::XRangeHighlighter > m_xRangeHighlighter; + css::uno::Reference 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 + */ + css::uno::Reference< css::chart2::data::XDataProvider > m_xInternalDataProvider; + + css::uno::Reference< css::util::XNumberFormatsSupplier > + m_xOwnNumberFormatsSupplier; + css::uno::Reference< css::util::XNumberFormatsSupplier > + m_xNumberFormatsSupplier; + std::unique_ptr< SvNumberFormatter > m_apSvNumberFormatter; // #i113784# avoid memory leak + + css::uno::Reference< css::chart2::XChartTypeManager > + m_xChartTypeManager; + + // Diagram Access + css::uno::Reference< css::chart2::XDiagram > + m_xDiagram; + + css::uno::Reference< css::chart2::XTitle > + m_xTitle; + + css::uno::Reference< css::beans::XPropertySet > + m_xPageBackground; + + css::uno::Reference< css::container::XNameAccess> 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 ); + + css::uno::Reference< css::chart2::XChartTypeTemplate > 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 > const & 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 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() override; + + // normal methods + css::uno::Reference< css::util::XNumberFormatsSupplier > const & + getNumberFormatsSupplier(); + + css::uno::Reference< css::uno::XInterface > getChartView() const; + + bool isTimeBased() const { return mbTimeBased;} + + void setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd); + + bool isDataFromSpreadsheet(); + + bool isDataFromPivotTable() const; + + void removeDataProviders(); + +private: + sal_Int32 mnStart; + sal_Int32 mnEnd; +}; + +} // 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 000000000..de9459ed6 --- /dev/null +++ b/chart2/inc/ChartView.hxx @@ -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 . + */ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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; + + // 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 ChartView final : public ::cppu::WeakImplHelper< + css::lang::XInitialization + ,css::lang::XServiceInfo + ,css::datatransfer::XTransferable + ,css::lang::XUnoTunnel + ,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 > const & 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( + css::uno::Reference< css::chart2::XAxis > xAxis + , ExplicitScaleData& rExplicitScale + , ExplicitIncrementData& rExplicitIncrement ) override; + virtual css::uno::Reference< css::drawing::XShape > + 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; + + // for ExplicitValueProvider + // ____ XUnoTunnel ___ + virtual ::sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< ::sal_Int8 >& aIdentifier ) override; + + // XDumper + virtual OUString SAL_CALL dump() override; + + void setViewDirty(); + +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 + ::osl::Mutex m_aMutex; + + css::uno::Reference< css::uno::XComponentContext> + m_xCC; + + chart::ChartModel& mrChartModel; + + css::uno::Reference< css::lang::XMultiServiceFactory> + m_xShapeFactory; + css::uno::Reference< css::drawing::XDrawPage> + m_xDrawPage; + css::uno::Reference< css::drawing::XShapes > + 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 > m_aVCooSysList; + + ::cppu::OMultiTypeInterfaceContainerHelper + m_aListenerContainer; + + 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; + osl::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 000000000..b02ab1049 --- /dev/null +++ b/chart2/inc/SpecialCharacters.hxx @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +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 000000000..3274c7fa7 --- /dev/null +++ b/chart2/inc/bitmaps.hlst @@ -0,0 +1,138 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_CHART2_INC_BITMAPS_HRC +#define INCLUDED_CHART2_INC_BITMAPS_HRC + +#define BMP_TYPE_COLUMN "chart2/res/typecolumn_16.png" +#define BMP_TYPE_BAR "chart2/res/typebar_16.png" +#define BMP_TYPE_PIE "chart2/res/typepie_16.png" +#define BMP_TYPE_LINE "chart2/res/typepointline_16.png" +#define BMP_TYPE_XY "chart2/res/typexy_16.png" +#define BMP_TYPE_AREA "chart2/res/typearea_16.png" +#define BMP_TYPE_NET "chart2/res/typenet_16.png" +#define BMP_TYPE_STOCK "chart2/res/typestock_16.png" +#define BMP_TYPE_COLUMN_LINE "chart2/res/typecolumnline_16.png" +#define BMP_TYPE_BUBBLE "chart2/res/typebubble_16.png" +#define BMP_BUBBLE_1 "chart2/res/bubble_52x60.png" +#define BMP_AREAS_2D "chart2/res/areas_52x60.png" +#define BMP_AREAS_2D_1 "chart2/res/areaspiled_52x60.png" +#define BMP_AREAS_2D_3 "chart2/res/areasfull_52x60.png" +#define BMP_AREAS_3D "chart2/res/areaspiled3d_52x60.png" +#define BMP_AREAS_3D_1 "chart2/res/areas3d_52x60.png" +#define BMP_AREAS_3D_2 "chart2/res/areasfull3d_52x60.png" +#define BMP_BARS_2D_1 "chart2/res/bar_52x60.png" +#define BMP_BARS_2D_2 "chart2/res/barstack_52x60.png" +#define BMP_BARS_2D_3 "chart2/res/barpercent_52x60.png" +#define BMP_BARS_3D "chart2/res/bar3ddeep_52x60.png" +#define BMP_BARS_3D_1 "chart2/res/bar3d_52x60.png" +#define BMP_BARS_3D_2 "chart2/res/barstack3d_52x60.png" +#define BMP_BARS_3D_3 "chart2/res/barpercent3d_52x60.png" +#define BMP_CIRCLES_2D "chart2/res/pie_52x60.png" +#define BMP_CIRCLES_2D_EXPLODED "chart2/res/pieexploded_52x60.png" +#define BMP_CIRCLES_3D "chart2/res/pie3d_52x60.png" +#define BMP_CIRCLES_3D_EXPLODED "chart2/res/pie3dexploded_52x60.png" +#define BMP_DONUT_2D "chart2/res/donut_52x60.png" +#define BMP_DONUT_2D_EXPLODED "chart2/res/donutexploded_52x60.png" +#define BMP_DONUT_3D "chart2/res/donut3d_52x60.png" +#define BMP_DONUT_3D_EXPLODED "chart2/res/donut3dexploded_52x60.png" +#define BMP_COLUMNS_2D_1 "chart2/res/columns_52x60.png" +#define BMP_COLUMNS_2D_2 "chart2/res/columnstack_52x60.png" +#define BMP_COLUMNS_2D_3 "chart2/res/columnpercent_52x60.png" +#define BMP_COLUMN_LINE "chart2/res/columnline_52x60.png" +#define BMP_COLUMN_LINE_STACKED "chart2/res/columnstackline_52x60.png" +#define BMP_COLUMNS_3D "chart2/res/columns3ddeep_52x60.png" +#define BMP_COLUMNS_3D_1 "chart2/res/columns3d_52x60.png" +#define BMP_COLUMNS_3D_2 "chart2/res/columnstack3d_52x60.png" +#define BMP_COLUMNS_3D_3 "chart2/res/columnpercent3d_52x60.png" +#define BMP_KEGELQ_3D_1 "chart2/res/conehori_52x60.png" +#define BMP_KEGELQ_3D_2 "chart2/res/conehoristack_52x60.png" +#define BMP_KEGELQ_3D_3 "chart2/res/conehoripercent_52x60.png" +#define BMP_KEGELQ_3D_4 "chart2/res/conehorideep_52x60.png" +#define BMP_KEGEL_3D_1 "chart2/res/cone_52x60.png" +#define BMP_KEGEL_3D_2 "chart2/res/conestack_52x60.png" +#define BMP_KEGEL_3D_3 "chart2/res/conepercent_52x60.png" +#define BMP_KEGEL_3D_4 "chart2/res/conedeep_52x60.png" +#define BMP_POINTS_XVALUES "chart2/res/valueaxisdirectpoints_52x60.png" +#define BMP_POINTS_XCATEGORY "chart2/res/nostackdirectpoints_52x60.png" +#define BMP_POINTS_STACKED "chart2/res/stackdirectpoints_52x60.png" +#define BMP_LINE_P_XVALUES "chart2/res/valueaxisdirectboth_52x60.png" +#define BMP_LINE_O_XVALUES "chart2/res/valueaxisdirectlines_52x60.png" +#define BMP_LINE3D_XVALUES "chart2/res/valueaxisdirect3d_52x60.png" +#define BMP_LINE_P_XCATEGORY "chart2/res/nostackdirectboth_52x60.png" +#define BMP_LINE_O_XCATEGORY "chart2/res/nostackdirectlines_52x60.png" +#define BMP_LINE3D_XCATEGORY "chart2/res/nostackdirect3d_52x60.png" +#define BMP_LINE_P_STACKED "chart2/res/stackdirectboth_52x60.png" +#define BMP_LINE_O_STACKED "chart2/res/stackdirectlines_52x60.png" +#define BMP_LINE3D_STACKED "chart2/res/stackdirect3d_52x60.png" +#define BMP_LINE_P_XVALUES_SMOOTH "chart2/res/valueaxissmoothboth_52x60.png" +#define BMP_LINE_O_XVALUES_SMOOTH "chart2/res/valueaxissmoothlines_52x60.png" +#define BMP_LINE3D_XVALUES_SMOOTH "chart2/res/valueaxissmooth3d_52x60.png" +#define BMP_LINE_P_XCATEGORY_SMOOTH "chart2/res/nostacksmoothboth_52x60.png" +#define BMP_LINE_O_XCATEGORY_SMOOTH "chart2/res/nostacksmoothlines_52x60.png" +#define BMP_LINE3D_XCATEGORY_SMOOTH "chart2/res/nostacksmooth3d_52x60.png" +#define BMP_LINE_P_STACKED_SMOOTH "chart2/res/stacksmoothboth_52x60.png" +#define BMP_LINE_O_STACKED_SMOOTH "chart2/res/stacksmoothlines_52x60.png" +#define BMP_LINE3D_STACKED_SMOOTH "chart2/res/stacksmooth3d_52x60.png" +#define BMP_LINE_P_XVALUES_STEPPED "chart2/res/valueaxissteppedboth_52x60.png" +#define BMP_LINE_O_XVALUES_STEPPED "chart2/res/valueaxissteppedlines_52x60.png" +#define BMP_LINE3D_XVALUES_STEPPED "chart2/res/valueaxisstepped3d_52x60.png" +#define BMP_LINE_P_XCATEGORY_STEPPED "chart2/res/nostacksteppedboth_52x60.png" +#define BMP_LINE_O_XCATEGORY_STEPPED "chart2/res/nostacksteppedlines_52x60.png" +#define BMP_LINE3D_XCATEGORY_STEPPED "chart2/res/nostackstepped3d_52x60.png" +#define BMP_LINE_P_STACKED_STEPPED "chart2/res/stacksteppedboth_52x60.png" +#define BMP_LINE_O_STACKED_STEPPED "chart2/res/stacksteppedlines_52x60.png" +#define BMP_LINE3D_STACKED_STEPPED "chart2/res/stackstepped3d_52x60.png" +#define BMP_NET "chart2/res/net_52x60.png" +#define BMP_NET_STACK "chart2/res/netstack_52x60.png" +#define BMP_NET_SYMB "chart2/res/netpoint_52x60.png" +#define BMP_NET_SYMB_STACK "chart2/res/netpointstack_52x60.png" +#define BMP_NET_LINESYMB "chart2/res/netlinepoint_52x60.png" +#define BMP_NET_LINESYMB_STACK "chart2/res/netlinepointstack_52x60.png" +#define BMP_NET_FILL "chart2/res/netfill_52x60.png" +#define BMP_NET_FILL_STACK "chart2/res/netstackfill_52x60.png" +#define BMP_PYRAMIDQ_3D_1 "chart2/res/pyramindhori_52x60.png" +#define BMP_PYRAMIDQ_3D_2 "chart2/res/pyramindhoristack_52x60.png" +#define BMP_PYRAMIDQ_3D_3 "chart2/res/pyramindhoripercent_52x60.png" +#define BMP_PYRAMIDQ_3D_4 "chart2/res/pyramindhorideep_52x60.png" +#define BMP_PYRAMID_3D_1 "chart2/res/pyramind_52x60.png" +#define BMP_PYRAMID_3D_2 "chart2/res/pyramindstack_52x60.png" +#define BMP_PYRAMID_3D_3 "chart2/res/pyramindpercent_52x60.png" +#define BMP_PYRAMID_3D_4 "chart2/res/pyraminddeep_52x60.png" +#define BMP_ROEHRE_3D_1 "chart2/res/cylinderhori_52x60.png" +#define BMP_ROEHRE_3D_2 "chart2/res/cylinderhoristack_52x60.png" +#define BMP_ROEHRE_3D_3 "chart2/res/cylinderhoriprocent_52x60.png" +#define BMP_ROEHRE_3D_4 "chart2/res/cylinderhorideep_52x60.png" +#define BMP_SAEULE_3D_1 "chart2/res/cylinder_52x60.png" +#define BMP_SAEULE_3D_2 "chart2/res/cylinderstack_52x60.png" +#define BMP_SAEULE_3D_3 "chart2/res/cylinderpercent_52x60.png" +#define BMP_SAEULE_3D_4 "chart2/res/cylinderdeep_52x60.png" +#define BMP_STOCK_1 "chart2/res/stock_52x60.png" +#define BMP_STOCK_2 "chart2/res/stockblock_52x60.png" +#define BMP_STOCK_3 "chart2/res/stockcolumns_52x60.png" +#define BMP_STOCK_4 "chart2/res/stockcolumnsattach_52x60.png" +#define BMP_INDICATE_BOTH_VERTI "chart2/res/errorbothverti_30.png" +#define BMP_INDICATE_DOWN "chart2/res/errordown_30.png" +#define BMP_INDICATE_UP "chart2/res/errorup_30.png" +#define BMP_INDICATE_BOTH_HORI "chart2/res/errorbothhori_30.png" +#define BMP_INDICATE_RIGHT "chart2/res/errorright_30.png" +#define BMP_INDICATE_LEFT "chart2/res/errorleft_30.png" +#define BMP_REGRESSION_LINEAR "chart2/res/reglin.png" +#define BMP_REGRESSION_LOG "chart2/res/reglog.png" +#define BMP_REGRESSION_EXP "chart2/res/regexp.png" +#define BMP_REGRESSION_POWER "chart2/res/regpow.png" +#define BMP_REGRESSION_POLYNOMIAL "chart2/res/regpoly.png" +#define BMP_REGRESSION_MOVING_AVERAGE "chart2/res/regavg.png" + +#define RID_SVXBMP_LAMP_ON "svx/res/lighton.png" +#define RID_SVXBMP_LAMP_OFF "svx/res/light.png" + +#endif + +/* 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 000000000..8a1195635 --- /dev/null +++ b/chart2/inc/chart.hrc @@ -0,0 +1,25 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_CHART_INC_CHART_HRC +#define INCLUDED_CHART_INC_CHART_HRC + +#define NC_(Context, String) reinterpret_cast(Context "\004" u8##String) + +const char* CHART_TYPE[] = +{ + NC_("tp_ChartType|liststore1", "Bar"), + NC_("tp_ChartType|liststore1", "Cylinder"), + NC_("tp_ChartType|liststore1", "Cone"), + NC_("tp_ChartType|liststore1", "Pyramid") +}; + +#endif + +/* 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 000000000..44d47c4a4 --- /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 000000000..da780cfc1 --- /dev/null +++ b/chart2/inc/pch/precompiled_chartcontroller.hxx @@ -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 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 2020-04-25 20:54:50 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 +*/ + +#if PCH_LEVEL >= 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 000000000..10d8b365b --- /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 000000000..c245c9905 --- /dev/null +++ b/chart2/inc/pch/precompiled_chartcore.hxx @@ -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 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 2020-04-21 11:13:20 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 +*/ + +#if PCH_LEVEL >= 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 000000000..163b0f44e --- /dev/null +++ b/chart2/inc/strings.hrc @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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) reinterpret_cast(Context "\004" 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_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 000000000..2174f4abb --- /dev/null +++ b/chart2/inc/unonames.hxx @@ -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/. + */ + +#pragma once + +#define CHART_UNONAME_SORT_BY_XVALUES "SortByXValues" +#define CHART_UNONAME_SPLINE_TYPE "SplineType" +#define CHART_UNONAME_SPLINE_ORDER "SplineOrder" +#define CHART_UNONAME_SPLINE_RESOLUTION "SplineResolution" +#define CHART_UNONAME_CURVE_STYLE "CurveStyle" +#define CHART_UNONAME_CURVE_RESOLUTION "CurveResolution" +#define CHART_UNONAME_NUMFMT "NumberFormat" +#define CHART_UNONAME_LINK_TO_SRC_NUMFMT "LinkNumberFormatToSource" +#define CHART_UNONAME_ERRORBAR_X "ErrorBarX" +#define CHART_UNONAME_ERRORBAR_Y "ErrorBarY" +#define CHART_UNONAME_LABEL "Label" +#define CHART_UNONAME_LABEL_SEP "LabelSeparator" +#define CHART_UNONAME_LABEL_BORDER_STYLE "LabelBorderStyle" +#define CHART_UNONAME_LABEL_BORDER_WIDTH "LabelBorderWidth" +#define CHART_UNONAME_LABEL_BORDER_COLOR "LabelBorderColor" +#define CHART_UNONAME_LABEL_BORDER_DASH "LabelBorderDash" +#define CHART_UNONAME_LABEL_BORDER_DASHNAME "LabelBorderDashName" +#define CHART_UNONAME_LABEL_BORDER_TRANS "LabelBorderTransparency" +#define CHART_UNONAME_LABEL_FILL_STYLE "LabelFillStyle" +#define CHART_UNONAME_LABEL_FILL_BACKGROUND "LabelFillBackground" +#define CHART_UNONAME_LABEL_FILL_HATCH_NAME "LabelFillHatchName" +#define CHART_UNONAME_LABEL_FILL_COLOR "LabelFillColor" +#define CHART_UNONAME_CUSTOM_LABEL_FIELDS "CustomLabelFields" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/TestCaseOldAPI.java b/chart2/qa/TestCaseOldAPI.java new file mode 100644 index 000000000..613ba480e --- /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", new Float( 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", new Float( fWeight )); + xTitleProp.setPropertyValue( "CharHeight", new Float( 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", new Double( 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", new Double( 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", new Float( 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", new Double( 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", new Double( 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", new Float( 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= b )); + } +} diff --git a/chart2/qa/data.chd b/chart2/qa/data.chd new file mode 100644 index 000000000..01888e4c1 --- /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 000000000..91a43cf33 --- /dev/null +++ b/chart2/qa/extras/PivotChartTest.cxx @@ -0,0 +1,986 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace com::sun::star::table { class XCellRange; } +namespace com::sun::star::util { class XNumberFormats; } + +class PivotChartTest : public ChartTest +{ +public: + PivotChartTest() : ChartTest() + {} + + 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 const & xDescriptor, + OUString const & sFieldName, + sheet::DataPilotFieldOrientation eOrientation) +{ + uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); + sal_Int32 nCount = xIndexAccess->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); + OUString aName = xNamed->getName(); + uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); + if (aName == sFieldName) + xPropSet->setPropertyValue("Orientation", uno::makeAny(eOrientation)); + } +} + +void lclModifyFunction(uno::Reference const & xDescriptor, + OUString const & sFieldName, + sheet::GeneralFunction eFunction) +{ + uno::Reference xPilotIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); + sal_Int32 nCount = xPilotIndexAccess->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference xNamed(xPilotIndexAccess->getByIndex(i), UNO_QUERY_THROW); + OUString aName = xNamed->getName(); + uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); + if (aName == sFieldName) + xPropSet->setPropertyValue("Function", uno::makeAny(eFunction)); + } +} + +void lclModifyLayoutInfo(uno::Reference const & xDescriptor, + OUString const & sFieldName, + sheet::DataPilotFieldLayoutInfo aLayoutInfo) +{ + uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); + sal_Int32 nCount = xIndexAccess->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); + OUString aName = xNamed->getName(); + uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); + if (aName == sFieldName) + { + uno::Any aValue; + aValue <<= aLayoutInfo; + xPropSet->setPropertyValue("LayoutInfo", aValue); + } + } +} + +void lclModifySubtotals(uno::Reference const & xDescriptor, + OUString const & sFieldName, + uno::Sequence const & rSubtotalFunctions) +{ + uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); + sal_Int32 nCount = xIndexAccess->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); + OUString aName = xNamed->getName(); + uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); + if (aName == sFieldName) + { + uno::Any aValue; + aValue <<= rSubtotalFunctions; + xPropSet->setPropertyValue("Subtotals", aValue); + } + } +} + +void lclModifyColumnGrandTotal(uno::Reference const & xDataPilotDescriptor, bool bTotal) +{ + uno::Reference xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue("ColumnGrand", uno::makeAny(bTotal)); +} + +void lclModifyRowGrandTotal(uno::Reference const & xDataPilotDescriptor, bool bTotal) +{ + uno::Reference xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue("RowGrand", uno::makeAny(bTotal)); +} + +void lclCheckSequence(std::vector const & reference, + uno::Sequence 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(), delta); + } +} + +void lclCheckCategories(std::vector const & reference, + uno::Reference const & xSequence) +{ + uno::Reference xTextualDataSequence(xSequence, uno::UNO_QUERY_THROW); + uno::Sequence 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 const & xChartDoc, sal_Int32 nSeriesIndex) +{ + Reference xLabelDataSequence = getLabelDataSequenceFromDoc(xChartDoc, nSeriesIndex); + return xLabelDataSequence->getData()[0].get(); +} + +uno::Reference lclGetPivotTableByName(sal_Int32 nIndex, OUString const & sPivotTableName, + uno::Reference const & xComponent) +{ + uno::Reference xDoc(xComponent, UNO_QUERY_THROW); + uno::Reference xSheetIndexAccess(xDoc->getSheets(), UNO_QUERY_THROW); + uno::Any aAny = xSheetIndexAccess->getByIndex(nIndex); + uno::Reference xSheet; + CPPUNIT_ASSERT(aAny >>= xSheet); + uno::Reference xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW); + uno::Reference xDataPilotTables = xDataPilotTablesSupplier->getDataPilotTables(); + return uno::Reference(xDataPilotTables->getByName(sPivotTableName), UNO_QUERY_THROW); +} + +uno::Sequence> + lclGetCategories(Reference const & xChartDoc) +{ + uno::Sequence aArguments( comphelper::InitPropertySequence( + {{"CellRangeRepresentation", uno::Any(OUString("PT@categories"))}} )); + + uno::Reference 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 const & xSheetDoc) +{ + uno::Reference xSpreadsheets = xSheetDoc->getSheets(); + uno::Reference oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW); + uno::Reference 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 const & xSheetDoc) +{ + CPPUNIT_ASSERT_MESSAGE("no calc document!", xSheetDoc.is()); + + std::vector aHeaders { + "Country", "City", "Type", "Sales T1", "Sales T2", "Sales T3", "Sales T4", "Date" + }; + + std::vector> 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 xSpreadsheets = xSheetDoc->getSheets(); + uno::Reference oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW); + uno::Reference xSheet; + CPPUNIT_ASSERT(oIndexAccess->getByIndex(0) >>= xSheet); + + uno::Reference 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 const & rRowOfData : aData) + { + for (size_t column = 0; column < rRowOfData.size(); ++column) + { + Value const & rValue = rRowOfData[column]; + uno::Reference 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 xNumberFormatsSupplier(xSheetDoc, UNO_QUERY_THROW); + uno::Reference xNumberFormats = xNumberFormatsSupplier->getNumberFormats(); + uno::Reference xNumberFormatTypes(xNumberFormats, UNO_QUERY_THROW); + lang::Locale aLocale; + sal_Int32 nDateKey = xNumberFormatTypes->getStandardFormat(util::NumberFormat::DATE, aLocale); + uno::Reference xCellRange = xSheet->getCellRangeByPosition(nEndCol, 1, nEndCol, nEndRow); + uno::Reference xCellProp(xCellRange, UNO_QUERY_THROW); + xCellProp->setPropertyValue("NumberFormat", uno::makeAny(nDateKey)); + + table::CellRangeAddress sCellRangeAdress; + sCellRangeAdress.Sheet = 0; + sCellRangeAdress.StartColumn = 0; + sCellRangeAdress.StartRow = 0; + sCellRangeAdress.EndColumn = nEndCol; + sCellRangeAdress.EndRow = nEndRow; + + return sCellRangeAdress; +} + +} // end anonymous namespace + +void PivotChartTest::testRoundtrip() +{ + uno::Sequence xSequence; + Reference xChartDoc; + + std::vector aReference1 { 10162.033139, 16614.523063, 27944.146101 }; + OUString const aExpectedLabel1("Exp."); + + std::vector aReference2 { 101879.458079, 178636.929704, 314626.484864 }; + OUString const aExpectedLabel2("Rev."); + + load("/chart2/qa/extras/data/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, "values-y", 0)->getData(); + lclCheckSequence(aReference1, xSequence, 1E-4); + CPPUNIT_ASSERT_EQUAL(aExpectedLabel1, lclGetLabel(xChartDoc, 0)); + } + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference2, xSequence, 1E-4); + CPPUNIT_ASSERT_EQUAL(aExpectedLabel2, lclGetLabel(xChartDoc, 1)); + } + + // Modify the pivot table + { + uno::Reference xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent); + uno::Reference xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); + lclModifyOrientation(xDataPilotDescriptor, "Exp.", sheet::DataPilotFieldOrientation_HIDDEN); + } + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); + + // Check again the data series + { + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference2, xSequence, 1E-4); + CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); + } + + reload("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, "values-y", 0)->getData(); + lclCheckSequence(aReference2, xSequence, 1E-4); + CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); + } +} + +void PivotChartTest::testChangePivotTable() +{ + uno::Sequence xSequence; + Reference xChartDoc; + + load("/chart2/qa/extras/data/ods/", "PivotTableExample.ods"); + + // Check we have the Pivot Table + OUString sPivotTableName("DataPilot1"); + uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); + CPPUNIT_ASSERT(xDataPilotTable.is()); + + // Check that we don't have any pivot chart in the document + uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 aReference { 10162.033139, 16614.523063, 27944.146101 }; + OUString const aExpectedLabel("Exp."); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } + + // Check second data series + { + std::vector aReference { 101879.458079, 178636.929704, 314626.484864 }; + OUString const aExpectedLabel("Rev."); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, 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 xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); + + lclModifyOrientation(xDataPilotDescriptor, "Service Month", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Group Segment", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "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 aReference { 2855.559, 1780.326, 2208.713, 2130.064, 1187.371 }; + OUString const aExpectedLabel("Big"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } + + // Check the second data series + { + std::vector aReference { 4098.908, 2527.286, 4299.716, 2362.225, 3326.389 }; + OUString const aExpectedLabel("Medium"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 1)); + } + + // Check the third data series + { + std::vector aReference { 4926.303, 5684.060, 4201.398, 7290.795, 5841.591 }; + OUString const aExpectedLabel("Small"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 2)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 2)); + } + + // Remove "Service Month" so row fields are empty - check we handle empty rows + { + uno::Reference xDataPilotDescriptor(xDataPilotTable, uno::UNO_QUERY_THROW); + lclModifyOrientation(xDataPilotDescriptor, "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 aReference { 10162.033139 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); + } + // Check the second data series + { + std::vector aReference { 16614.523063 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); + } + // Check the third data series + { + std::vector aReference { 27944.146101 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "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 xProperties(xDataPilotTable, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue("ColumnGrand", uno::makeAny(true)); + } + + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); + + // Check the first data series + { + std::vector aReference { 10162.033139 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); + } + // Check the second data series + { + std::vector aReference { 16614.523063 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference, xSequence, 1E-3); + CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); + } + // Check the third data series + { + std::vector aReference { 27944.146101 }; + xSequence = getDataSequenceFromDocByRole(xChartDoc, "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 + + if (!mxComponent.is()) + mxComponent = loadFromDesktop("private:factory/scalc"); + + uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); + + OUString sPivotTableName("DataPilotTable"); + + table::CellRangeAddress sCellRangeAdress = lclCreateTestData(xSheetDoc); + + uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); + + uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); + xDataPilotDescriptor->setSourceRange(sCellRangeAdress); + + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "Sales T1", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T1", sheet::GeneralFunction_SUM); + + xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); + + // TEST + + uno::Sequence xSequence; + Reference xChartDoc; + + // Check we have the Pivot Table + + uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); + CPPUNIT_ASSERT(xDataPilotTable.is()); + + // Check that we don't have any pivot chart in the document + uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 aReference { 1738.0 }; + OUString const aExpectedLabel("DE"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } + + // Check data series 2 + { + std::vector aReference { 2003.0 }; + OUString const aExpectedLabel("EN"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 1)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 1)); + } + // Check data series 3 + { + std::vector aReference { 1936.0 }; + OUString const aExpectedLabel("FR"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 2)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, 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 + + if (!mxComponent.is()) + mxComponent = loadFromDesktop("private:factory/scalc"); + + uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); + + OUString sPivotTableName("DataPilotTable"); + + table::CellRangeAddress sCellRangeAdress = lclCreateTestData(xSheetDoc); + + uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); + + uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); + xDataPilotDescriptor->setSourceRange(sCellRangeAdress); + + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Sales T1", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T1", sheet::GeneralFunction_SUM); + + xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); + + // TEST + + uno::Sequence xSequence; + Reference xChartDoc; + + // Check we have the Pivot Table + + uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); + CPPUNIT_ASSERT(xDataPilotTable.is()); + + // Check that we don't have any pivot chart in the document + uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 aReference { 1738.0, 2003.0, 1936.0 }; + OUString const aExpectedLabel("Total"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, lclGetLabel(xChartDoc, 0)); + } +} + +void PivotChartTest::testPivotTableDataProvider_PivotTableFields() +{ + // SETUP DATA and PIVOT TABLE + + if (!mxComponent.is()) + mxComponent = loadFromDesktop("private:factory/scalc"); + + uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); + + OUString sPivotTableName("DataPilotTable"); + + table::CellRangeAddress sCellRangeAdress = lclCreateTestData(xSheetDoc); + + uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); + + uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); + xDataPilotDescriptor->setSourceRange(sCellRangeAdress); + + lclModifyOrientation(xDataPilotDescriptor, "City", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "Type", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "Sales T1", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T1", sheet::GeneralFunction_SUM); + lclModifyOrientation(xDataPilotDescriptor, "Sales T2", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T2", sheet::GeneralFunction_SUM); + + lclModifyColumnGrandTotal(xDataPilotDescriptor, true); + lclModifyRowGrandTotal(xDataPilotDescriptor, true); + + xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); + + // TEST + Reference xChartDoc; + + // Check we have the Pivot Table + uno::Reference 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 xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 xPivotTableDataProvider(xChartDoc->getDataProvider(), UNO_QUERY_THROW); + uno::Sequence 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, "Data", sheet::DataPilotFieldOrientation_COLUMN); + + // Change the order of column fields: expected data, type, country + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_HIDDEN); + lclModifyOrientation(xDataPilotDescriptor, "Type", sheet::DataPilotFieldOrientation_HIDDEN); + + lclModifyOrientation(xDataPilotDescriptor, "Type", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "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 + + if (!mxComponent.is()) + mxComponent = loadFromDesktop("private:factory/scalc"); + + uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); + + OUString sPivotTableName("DataPilotTable"); + + table::CellRangeAddress sCellRangeAdress = lclCreateTestData(xSheetDoc); + + uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); + + uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); + xDataPilotDescriptor->setSourceRange(sCellRangeAdress); + + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "City", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Sales T1", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T1", sheet::GeneralFunction_SUM); + xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); + + // TEST + uno::Sequence xSequence; + Reference xChartDoc; + + // Check we have the Pivot Table + uno::Reference 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 xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; + OUString const aExpectedLabel("Total"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, 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; + uno::Sequence aGeneralFunctionSequence(1); + + // 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 + aGeneralFunctionSequence[0] = sheet::GeneralFunction_AUTO; + lclModifySubtotals(xDataPilotDescriptor, "Country", aGeneralFunctionSequence); + // Set Subtotals layout to bottom + add empty lines + aLayoutInfoValue.AddEmptyLines = true; + aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM; + lclModifyLayoutInfo(xDataPilotDescriptor, "Country", aLayoutInfoValue); + + // Check data is unchanged + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); + { + std::vector aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; + OUString const aExpectedLabel("Total"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, 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[0] = sheet::GeneralFunction_AUTO; + lclModifySubtotals(xDataPilotDescriptor, "Country", aGeneralFunctionSequence); + // Set Subtotals layout to top + add empty lines + aLayoutInfoValue.AddEmptyLines = true; + aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP; + lclModifyLayoutInfo(xDataPilotDescriptor, "Country", aLayoutInfoValue); + + // Check data is unchanged + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); + { + std::vector aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; + OUString const aExpectedLabel("Total"); + + xSequence = getDataSequenceFromDocByRole(xChartDoc, "values-y", 0)->getData(); + lclCheckSequence(aReference, xSequence, 1E-4); + + CPPUNIT_ASSERT_EQUAL(aExpectedLabel, 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 + + if (!mxComponent.is()) + mxComponent = loadFromDesktop("private:factory/scalc"); + + uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); + + OUString sPivotTableName("DataPilotTable"); + + table::CellRangeAddress sCellRangeAdress = lclCreateTestData(xSheetDoc); + + uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); + + uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); + xDataPilotDescriptor->setSourceRange(sCellRangeAdress); + + lclModifyOrientation(xDataPilotDescriptor, "Date", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "City", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Country", sheet::DataPilotFieldOrientation_ROW); + lclModifyOrientation(xDataPilotDescriptor, "Type", sheet::DataPilotFieldOrientation_COLUMN); + lclModifyOrientation(xDataPilotDescriptor, "Sales T1", sheet::DataPilotFieldOrientation_DATA); + lclModifyFunction(xDataPilotDescriptor, "Sales T1", sheet::GeneralFunction_SUM); + + lclModifyColumnGrandTotal(xDataPilotDescriptor, true); + lclModifyRowGrandTotal(xDataPilotDescriptor, true); + + xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); + + // TEST + Reference xChartDoc; + + // Check we have the Pivot Table + uno::Reference 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 xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); + uno::Reference 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 000000000..42dce791d --- /dev/null +++ b/chart2/qa/extras/chart2_trendcalculators.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 "charttest.hxx" +#include +#include +#include + + +// Define the index of sheets in the test document +#define SHEET_POTENTIAL1 0 +#define SHEET_POTENTIAL2 ( SHEET_POTENTIAL1 + 1) +#define SHEET_POTENTIAL_LAST ( SHEET_POTENTIAL2 ) + +#define SHEET_LINEAR1 ( SHEET_POTENTIAL_LAST + 1 ) +#define SHEET_LINEAR_LAST ( SHEET_LINEAR1 ) + +#define SHEET_POLYNOMIAL1 ( SHEET_LINEAR_LAST + 1 ) +#define SHEET_POLYNOMIAL_LAST ( SHEET_POLYNOMIAL1 ) + +#define SHEET_EXPONENTIAL1 ( SHEET_POLYNOMIAL_LAST + 1 ) +#define SHEET_EXPONENTIAL2 ( SHEET_EXPONENTIAL1 + 1 ) + +class Chart2TrendCalculators : public ChartTest +{ +public: + 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 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(); + load("/chart2/qa/extras/data/ods/", "trend_calculators.ods"); +} + +void Chart2TrendCalculators::tearDown() +{ + m_xRegressionCurveCalculator.clear(); + m_xCurve.clear(); + ChartTest::tearDown(); +} + +void Chart2TrendCalculators::loadCalculatorFromSheet(sal_Int32 nSheet) +{ + Reference xChartDoc = getChartDocFromSheet(nSheet, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + + Reference 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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 ); + Sequence< double > xValues( 7 ); + Sequence< double > yValues( 7 ); + for (int i=0; i<7; i++) + { + const double d = static_cast(i); + xValues[i] = d; + yValues[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 000000000..680744bab --- /dev/null +++ b/chart2/qa/extras/chart2dump/chart2dump.cxx @@ -0,0 +1,1147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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(#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(#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(#aActual), aActual.trim()); \ + } + +#define CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aActual, EPS_) \ + if(isInDumpMode()) \ + writeActualTransformation(aActual, #aActual); \ + else \ + { \ + OUString expectedTransform; \ + if (!readAndCheckTransformation (aActual, #aActual, EPS_, expectedTransform)) \ + { \ + OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \ + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), expectedTransform, transformationToOneLineString(aActual)); \ + } \ + } + +#define CPPUNIT_DUMP_ASSERT_NOTE(Note) \ + if(isInDumpMode()) \ + writeNote(Note); \ + else \ + readNote(Note);\ + + +class Chart2DumpTest : public ChartTest, public XmlTestTools +{ +protected: + Chart2DumpTest(bool bDumpMode) + { + m_bDumpMode = bDumpMode; + } + + virtual ~Chart2DumpTest() override + { + } + + bool isInDumpMode () const {return m_bDumpMode;} + + virtual OUString getTestName() { return OUString(); } + OUString const & getTestFileName() const { return m_sTestFileName; } + OUString getTestFileDirName() const { return "/chart2/qa/extras/chart2dump/data/"; } + 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 = sFileName.copy(0, sFileName.lastIndexOf('.')) + ".txt"; + if (!m_bDumpMode) + { + if (m_aReferenceFile.is_open()) + m_aReferenceFile.close(); + OString sReferenceFile = OUStringToOString(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(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(const OUString& 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("// " + sCheck), OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8)); + getline(m_aReferenceFile, sTemp); + return OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8); + } + + void writeActual(const OUString& 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 << sActualValue.trim() << "\n"; // Write out the checked value, will be used as reference later + } + + void readNote(const OUString& 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("/// " + 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(const OUString& 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, const OUString& 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 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line1.Column2 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line1.Column3 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line2.Column1 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line2.Column2 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line2.Column3 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line3.Column1 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line3.Column2 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + aExpectedTransform.Line3.Column3 = rExpectedTransform.getToken(0, ';', nIdx).toDouble(); + + // 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& rSeq) + { + OUStringBuffer aBufer; + for (const OUString& seqItem : rSeq) + { + aBufer.append(seqItem).append(";"); + } + return aBufer.makeStringAndClear(); + } + + OUString doubleVectorToOneLineString(const std::vector& rVector) + { + OUStringBuffer aBufer; + for (const double& vectorItem : rVector) + { + aBufer.append(OUString::number(vectorItem)).append(";"); + } + return aBufer.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); + } + + uno::Reference getShapeByName(const uno::Reference& rShapes, const OUString& rName, bool (*pCondition)(const uno::Reference&) = nullptr) + { + for (sal_Int32 i = 0; i < rShapes->getCount(); ++i) + { + uno::Reference xShapes(rShapes->getByIndex(i), uno::UNO_QUERY); + if (xShapes.is()) + { + uno::Reference xRet = getShapeByName(xShapes, rName, pCondition); + if (xRet.is()) + return xRet; + } + uno::Reference xNamedShape(rShapes->getByIndex(i), uno::UNO_QUERY); + if (xNamedShape->getName() == rName) + { + uno::Reference xShape(xNamedShape, uno::UNO_QUERY); + if (pCondition == nullptr || (*pCondition)(xShape)) + return xShape; + } + } + return uno::Reference(); + } + +private: + OUString m_sTestFileName; + bool m_bDumpMode; + std::ifstream m_aReferenceFile; + std::ofstream m_aDumpFile; +}; + +DECLARE_DUMP_TEST(ChartDataTest, Chart2DumpTest, false) +{ + const std::vector aTestFiles = + { + "simple_chart.ods", + "multiple_categories.ods" + }; + + for (const OUString& aTestFile : aTestFiles) + { + setTestFileName(aTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc (getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + + // Check title + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + uno::Reference xTitle = xTitled->getTitleObject(); + if(xTitle.is()) + { + OUString sChartTitle = getTitleString(xTitled); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartTitle); + } + + // Check chart type + Reference 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 xAxis = getAxisFromDoc(xChartDoc2, 0, 0, 0); + Reference xAxisTitled(xAxis, UNO_QUERY_THROW); + uno::Reference 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 > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aDataSeriesYValues.size()); + for (const std::vector& 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, "values-x", nIndex); + if (xDataSeq.is()) + { + OUString aXValuesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aXValuesSourceRange); + } + xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, "values-y", nIndex)); + if (xDataSeq.is()) + { + OUString aYValuesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aYValuesSourceRange); + } + xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, "categories", nIndex)); + if (xDataSeq.is()) + { + OUString aCategoriesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aCategoriesSourceRange); + } + } + } +} + +DECLARE_DUMP_TEST(LegendTest, Chart2DumpTest, false) +{ + const std::vector 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); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + // Get legend shape + uno::Reference 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 xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + std::vector > 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 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 xLegendEntryContainer(xLegendEntry, UNO_QUERY_THROW); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(xLegendEntryContainer->getCount()); + for (sal_Int32 nEntryGeometryElement = 1; nEntryGeometryElement < xLegendEntryContainer->getCount(); ++nEntryGeometryElement) + { + uno::Reference 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(aEntryGeomColor)); + } + } + // Check legend entries' text + uno::Reference xLegendContainer(xLegend, UNO_QUERY_THROW); + for (sal_Int32 i = 0; i < xLegendContainer->getCount(); ++i) + { + uno::Reference 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 xLegendEntryText = uno::Reference(xShape, uno::UNO_QUERY_THROW)->getText(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLegendEntryText->getString()); + } + } + } +} + +DECLARE_DUMP_TEST(GridTest, Chart2DumpTest, false) +{ + const std::vector aTestFiles = + { + "vertical_grid.ods", + "horizontal_grid.ods", + "minor_grid.ods", + "formated_grid_line.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector 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 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 xIndexAccess(xGrid, UNO_QUERY_THROW); + uno::Reference 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(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(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 aTestFiles = + { + "default_formated_axis.odp", + "axis_special_positioning.odp", + "formated_axis_lines.odp", + "rotated_axis_labels.odp" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector 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 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 xIndexAccess(xXAxis, UNO_QUERY_THROW); + sal_Int32 nAxisGeometriesCount = xIndexAccess->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisGeometriesCount); + uno::Reference 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(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(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 aTestFiles = + { + "default_formated_axis.odp", + "rotated_axis_labels.odp", + "formated_axis_labels.odp", + "percent_stacked_column_chart.odp", + "tdf118150.xlsx", + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector 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 xXAxis = getShapeByName(xShapes, sAxisShapeName, + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference& rXShape) -> bool + { + uno::Reference xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference 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 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 xLabel(xIndexAccess->getByIndex(nLabelIndex), uno::UNO_QUERY); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLabel->getString()); + + // Check size and position + uno::Reference 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(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 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); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + std::vector > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference 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 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(aSeriesColumnOrBarFillStyle)); + util::Color aSeriesColumnOrBarFillColor = 0; + xColumnOrBarPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSeriesColumnOrBarFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast(aSeriesColumnOrBarFillColor)); + + for (sal_Int32 nColumnOrBar = 0; nColumnOrBar < nColumnOrBarCountInSeries; ++nColumnOrBar) + { + uno::Reference xColumnOrBar(xIndexAccess->getByIndex(nColumnOrBar), UNO_QUERY_THROW); + uno::Reference 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 aTestFiles = + { + "chartwall_auto_adjust_with_titles.ods", + "chartwall_auto_adjust_without_titles.ods", + "chartwall_custom_positioning.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference 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(aChartWallFillStyle)); + util::Color aChartWallFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aChartWallFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast(aChartWallFillColor)); + + // Check line properties + // Line type + drawing::LineDash aLineDash; + xPropSet->getPropertyValue("LineDash") >>= aLineDash; + OUString sChartWallLineDash = + OUString::number(static_cast(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(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 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); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference 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 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 xSlice(xIndexAccess->getByIndex(nSlice), UNO_QUERY_THROW); + uno::Reference 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(aSliceFillStyle)); + util::Color aSliceFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSliceFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast(aSliceFillColor)); + } + } + } +} + +DECLARE_DUMP_TEST(AreaChartTest, Chart2DumpTest, false) +{ + const std::vector aTestFiles = + { + "normal_area_chart.ods", + "stacked_area_chart.ods", + "percent_stacked_area_chart.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference 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 xIndexAccess(xSeries, UNO_QUERY_THROW); + uno::Reference xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); // Why this second group shape is here? + uno::Reference 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(aAreaFillStyle)); + util::Color aAreaFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aAreaFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast(aAreaFillColor)); + } + } +} + + +DECLARE_DUMP_TEST(PointLineChartTest, Chart2DumpTest, false) +{ + const std::vector 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); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference 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 xIndexAccess(xSeries, UNO_QUERY_THROW); + uno::Reference xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + uno::Reference 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(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 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 XPointContainer ( + getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries) + ":Point=" + OUString::number(nPoint)), UNO_QUERY_THROW); + uno::Reference XPoint(XPointContainer->getByIndex(0), UNO_QUERY_THROW); + uno::Reference 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(aPointFillStyle)); + util::Color aPointFillColor = 0; + xPointPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aPointFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast(aPointFillColor)); + } + } + } + } +} + +DECLARE_DUMP_TEST( PivotChartDataButtonTest, Chart2DumpTest, false ) +{ + const OUString aTestFile = "pivotchart_data_button.ods"; + + setTestFileName( aTestFile ); + load( getTestFileDirName(), getTestFileName() ); + + // Check that we have pivot chart in the document + uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet( 1, mxComponent ); + uno::Reference 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 xChartDoc; + xChartDoc.set( getPivotChartDocFromSheet( xTablePivotCharts, 0 ) ); + CPPUNIT_ASSERT( xChartDoc.is() ); + + uno::Reference xDrawPageSupplier( xChartDoc, uno::UNO_QUERY ); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes( xDrawPage->getByIndex(0), uno::UNO_QUERY ); + CPPUNIT_ASSERT( xShapes.is() ); + + // Get the shape that represents the "Data" button. + uno::Reference xButton = getShapeByName( xShapes, "FieldButton.Row.8", + []( const uno::Reference& xShapeNode ) + { + return xShapeNode->getShapeType() == "com.sun.star.drawing.TextShape"; + } ); + CPPUNIT_ASSERT_MESSAGE( OString( "Cannot find Data button shape" ).getStr(), xButton.is() ); + + // Make sure that there is no arrow shape with the Data button + uno::Reference xArrow = getShapeByName( xShapes, "FieldButton.Row.8", + []( const uno::Reference& xShapeNode ) + { + return xShapeNode->getShapeType() == "com.sun.star.drawing.PolyPolygonShape"; + } ); + CPPUNIT_ASSERT_MESSAGE( OString( "Arrow shape should not be present for the Data button" ).getStr(), !xArrow.is() ); + + // Assert the background color of the Data button + util::Color aButtonFillColor = 0; + uno::Reference xPropSet( xButton, UNO_QUERY_THROW ); + xPropSet->getPropertyValue( UNO_NAME_FILLCOLOR ) >>= aButtonFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL( static_cast( 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 000000000..a09ddb893 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/axis_special_positioning.odp 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 000000000..1b41db316 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.ods 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 000000000..be5b11804 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.ods 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 000000000..b6ba87221 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.ods 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 000000000..1206a4e19 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/column_chart_small_spacing.ods 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 000000000..d36677ab4 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/custom_legend_position.odp 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 000000000..a5cdd0522 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/default_formated_axis.odp 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 000000000..4490f7695 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/donut_chart.ods 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 000000000..68a9c9842 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/exploded_pie_chart.ods 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 000000000..a94c8c4d0 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/formated_axis_labels.odp 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 000000000..7a421497b Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/formated_axis_lines.odp 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 000000000..1d0ef5389 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/formated_grid_line.ods 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 000000000..c9f913067 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/horizontal_grid.ods 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 000000000..b080d3311 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/legend_on_bottom.odp 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 000000000..71e2947c6 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/legend_on_left_side.odp 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 000000000..7aac4d3f3 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/legend_on_right_side.odp 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 000000000..318901f2e Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/legend_on_top.odp 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 000000000..8f02a99f6 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/many_legend_entries.odp 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 000000000..63911f119 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/minimal_legend_test.odp 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 000000000..f8f30198b Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/minor_grid.ods 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 000000000..95e51f3f6 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/multiple_categories.odp 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 000000000..67e00525b Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/multiple_categories.ods 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 000000000..84b9ec224 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_area_chart.ods 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 000000000..531f406f9 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_bar_chart.ods 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 000000000..a8c640400 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_column_chart.ods 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 000000000..4dd613b6f Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.ods 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 000000000..c4f57a6f3 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.ods 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 000000000..e55b41115 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.ods 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 000000000..3c3a6a327 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/normal_pie_chart.ods 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 000000000..0cc5d1728 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.ods 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 000000000..2d337a5b3 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.ods 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 000000000..e8180cfc7 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odp 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 000000000..ce7440aa7 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.ods 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 000000000..ade9ea8f1 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.ods 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 000000000..3228f51a3 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.ods 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 000000000..b2483b6da Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.ods 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 000000000..2cc2e8b7b Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/pie_chart_many_slices.ods 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 000000000..d57edf66d Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/pivotchart_data_button.ods 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 000000000..24e9cf05b Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/rotated_axis_labels.odp 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 000000000..ee8b3a7d9 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/rotated_pie_chart.ods 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 000000000..de7b1c67c Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.ods 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 000000000..fed578992 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.ods 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 000000000..dd1626d7a Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/scatter_chart_points_only.ods 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 000000000..f65584d12 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/simple_chart.ods 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 000000000..56bc4e499 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_area_chart.ods 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 000000000..2e8ca327e Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_bar_chart.ods 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 000000000..159df229a Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_column_chart.ods 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 000000000..d11ecb705 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.ods 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 000000000..1652c3a58 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.ods 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 000000000..a85a2abe8 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.ods differ diff --git a/chart2/qa/extras/chart2dump/data/tdf118150.xlsx b/chart2/qa/extras/chart2dump/data/tdf118150.xlsx new file mode 100644 index 000000000..f29b9a1c2 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/tdf118150.xlsx 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 000000000..9f2ed7838 Binary files /dev/null and b/chart2/qa/extras/chart2dump/data/vertical_grid.ods 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 000000000..4f4a5181f --- /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(aAreaFillStyle) +1 +// static_cast(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(aAreaFillStyle) +2 +// static_cast(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(aAreaFillStyle) +4 +// static_cast(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(aAreaFillStyle) +3 +// static_cast(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 000000000..b8769b7ad --- /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(aAreaFillStyle) +1 +// static_cast(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(aAreaFillStyle) +2 +// static_cast(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(aAreaFillStyle) +4 +// static_cast(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(aAreaFillStyle) +3 +// static_cast(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 000000000..00934b44b --- /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(aAreaFillStyle) +1 +// static_cast(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(aAreaFillStyle) +2 +// static_cast(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(aAreaFillStyle) +4 +// static_cast(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(aAreaFillStyle) +3 +// static_cast(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 000000000..e34ef3c10 --- /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(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(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 000000000..46eec6d76 --- /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(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(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 000000000..980e2592d --- /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(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(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 000000000..151ab21ac --- /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(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(aAxisLineColor) +0 +// nAxisLineWidth +0 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 000000000..51c1e37d6 --- /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(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +2. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +3. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +4. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +/// CID/D=0:CS=0:Axis=1,0 +// nAxisLabelsCount +11 +// xLabel->getString() +- Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +2000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +4000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +6000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +8000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +10000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +12000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +14000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +16000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +18000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +20000000 Ft +// static_cast(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 000000000..ffc0877e4 --- /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(aLabelFontColor) +8388352 +// fLabelFontHeight +12 +// xLabel->getString() +2. quarter +// static_cast(aLabelFontColor) +8388352 +// fLabelFontHeight +12 +// xLabel->getString() +2. quarter +// static_cast(aLabelFontColor) +8388352 +// fLabelFontHeight +12 +// xLabel->getString() +2. quarter +// static_cast(aLabelFontColor) +8388352 +// fLabelFontHeight +12 +/// CID/D=0:CS=0:Axis=1,0 +// nAxisLabelsCount +11 +// xLabel->getString() +- Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +2000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +4000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +6000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +8000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +10000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +12000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +14000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +16000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +18000000 Ft +// static_cast(aLabelFontColor) +16711935 +// fLabelFontHeight +14 +// xLabel->getString() +20000000 Ft +// static_cast(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 000000000..304f9abf0 --- /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(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Leser +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Multifunction +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Picture +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +/// CID/D=0:CS=0:Axis=1,0 +// nAxisLabelsCount +11 +// xLabel->getString() +0,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +10,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +20,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +30,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +40,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +50,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +60,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +70,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +80,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +90,00% +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +100,00% +// static_cast(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 000000000..52aceba87 --- /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(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +2. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +3. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +4. quarter +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +/// CID/D=0:CS=0:Axis=1,0 +// nAxisLabelsCount +5 +// xLabel->getString() +- Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +5000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +10000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +15000000 Ft +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +20000000 Ft +// static_cast(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 000000000..fabf4acac --- /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(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Oct 2013 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Nov 2013 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Dec 2013 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jan 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Feb 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Mar 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Apr 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +May 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jun 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jul 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Aug 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Sep 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Oct 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Nov 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Dec 2014 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jan 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Feb 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Mar 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Apr 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +May 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jun 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Jul 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Aug 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Sep 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Oct 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Nov 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +Dec 2015 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +/// CID/D=0:CS=0:Axis=1,0 +// nAxisLabelsCount +7 +// xLabel->getString() +0.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +2.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +4.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +6.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +8.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +10.00 +// static_cast(aLabelFontColor) +0 +// fLabelFontHeight +10 +// xLabel->getString() +12.00 +// static_cast(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 000000000..1d0e3ea39 --- /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 000000000..28a125d7a --- /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 +151 +// 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 000000000..83e9596f2 --- /dev/null +++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt @@ -0,0 +1,10 @@ +// static_cast(aChartWallFillStyle) +2 +// static_cast(aChartWallFillColor) +15132390 +// sChartWallLineDash +0;1;200710;0;152 +// static_cast(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 000000000..83e9596f2 --- /dev/null +++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt @@ -0,0 +1,10 @@ +// static_cast(aChartWallFillStyle) +2 +// static_cast(aChartWallFillColor) +15132390 +// sChartWallLineDash +0;1;200710;0;152 +// static_cast(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 000000000..f689425ec --- /dev/null +++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt @@ -0,0 +1,10 @@ +// static_cast(aChartWallFillStyle) +1 +// static_cast(aChartWallFillColor) +13773611 +// sChartWallLineDash +0;2;01;203;203 +// static_cast(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 000000000..83e9596f2 --- /dev/null +++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt @@ -0,0 +1,10 @@ +// static_cast(aChartWallFillStyle) +2 +// static_cast(aChartWallFillColor) +15132390 +// sChartWallLineDash +0;1;200710;0;152 +// static_cast(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 000000000..b3192a728 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3698 +// aColumnOrBarPosition.Y +4414 +// aColumnOrBarSize.Height +2935 +// aColumnOrBarSize.Width +1170 +// aColumnOrBarTransformation +1170;0;3698;0;2935;4414;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +4868 +// aColumnOrBarPosition.Y +5247 +// aColumnOrBarSize.Height +2102 +// aColumnOrBarSize.Width +1169 +// aColumnOrBarTransformation +1169;0;4868;0;2102;5247;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +3 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +6037 +// aColumnOrBarPosition.Y +6281 +// aColumnOrBarSize.Height +1068 +// aColumnOrBarSize.Width +1170 +// aColumnOrBarTransformation +1170;0;6037;0;1068;6281;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +2 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +7207 +// aColumnOrBarPosition.Y +5677 +// aColumnOrBarSize.Height +1672 +// aColumnOrBarSize.Width +1169 +// aColumnOrBarTransformation +1169;0;7207;0;1672;5677;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 000000000..7828d7907 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +6712 +// aColumnOrBarSize.Height +364 +// aColumnOrBarSize.Width +6482 +// aColumnOrBarTransformation +6482;0;3582;0;364;6712;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +6348 +// aColumnOrBarSize.Height +364 +// aColumnOrBarSize.Width +4641 +// aColumnOrBarTransformation +4641;0;3582;0;364;6348;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +5984 +// aColumnOrBarSize.Height +364 +// aColumnOrBarSize.Width +2357 +// aColumnOrBarTransformation +2357;0;3582;0;364;5984;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +5620 +// aColumnOrBarSize.Height +364 +// aColumnOrBarSize.Width +3690 +// aColumnOrBarTransformation +3690;0;3582;0;364;5620;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 000000000..3c4dad8c5 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +4359 +// aColumnOrBarPosition.Y +4414 +// aColumnOrBarSize.Height +2935 +// aColumnOrBarSize.Width +916 +// aColumnOrBarTransformation +916;0;4359;0;2935;4414;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5275 +// aColumnOrBarPosition.Y +5247 +// aColumnOrBarSize.Height +2102 +// aColumnOrBarSize.Width +916 +// aColumnOrBarTransformation +916;0;5275;0;2102;5247;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +6191 +// aColumnOrBarPosition.Y +6281 +// aColumnOrBarSize.Height +1068 +// aColumnOrBarSize.Width +916 +// aColumnOrBarTransformation +916;0;6191;0;1068;6281;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +7107 +// aColumnOrBarPosition.Y +5677 +// aColumnOrBarSize.Height +1672 +// aColumnOrBarSize.Width +916 +// aColumnOrBarTransformation +916;0;7107;0;1672;5677;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 000000000..5fa9301b1 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +5681 +// aColumnOrBarSize.Height +1334 +// aColumnOrBarSize.Width +5562 +// aColumnOrBarTransformation +5562;0;3582;0;1334;5681;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +9144 +// aColumnOrBarPosition.Y +5681 +// aColumnOrBarSize.Height +1334 +// aColumnOrBarSize.Width +3982 +// aColumnOrBarTransformation +3982;0;9144;0;1334;5681;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +255 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +13126 +// aColumnOrBarPosition.Y +5681 +// aColumnOrBarSize.Height +1334 +// aColumnOrBarSize.Width +2023 +// aColumnOrBarTransformation +2023;0;13126;0;1334;5681;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +15149 +// aColumnOrBarPosition.Y +5681 +// aColumnOrBarSize.Height +1334 +// aColumnOrBarSize.Width +3168 +// aColumnOrBarTransformation +3168;0;15149;0;1334;5681;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 000000000..c183d4ea5 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +5082 +// aColumnOrBarSize.Height +2267 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;2267;5082;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +3459 +// aColumnOrBarSize.Height +1623 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;1623;3459;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +3 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +2635 +// aColumnOrBarSize.Height +824 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;824;2635;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +2 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +1345 +// aColumnOrBarSize.Height +1290 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;1290;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 000000000..228bc26b8 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +3582 +// aColumnOrBarPosition.Y +5948 +// aColumnOrBarSize.Height +800 +// aColumnOrBarSize.Width +2592 +// aColumnOrBarTransformation +2592;0;3582;0;800;5948;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +6174 +// aColumnOrBarPosition.Y +5948 +// aColumnOrBarSize.Height +800 +// aColumnOrBarSize.Width +1857 +// aColumnOrBarTransformation +1857;0;6174;0;800;5948;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +255 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +8031 +// aColumnOrBarPosition.Y +5948 +// aColumnOrBarSize.Height +800 +// aColumnOrBarSize.Width +943 +// aColumnOrBarTransformation +943;0;8031;0;800;5948;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +8974 +// aColumnOrBarPosition.Y +5948 +// aColumnOrBarSize.Height +800 +// aColumnOrBarSize.Width +1476 +// aColumnOrBarTransformation +1476;0;8974;0;800;5948;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 000000000..032645258 --- /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(aSeriesColumnOrBarFillStyle) +1 +// static_cast(aSeriesColumnOrBarFillColor) +16711807 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +6292 +// aColumnOrBarSize.Height +1057 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;1057;6292;0;0;1 +/// Series 1 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +5536 +// aColumnOrBarSize.Height +756 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;756;5536;0;0;1 +/// Series 2 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +4 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +5151 +// aColumnOrBarSize.Height +385 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;385;5151;0;0;1 +/// Series 3 ColumnsOrBars +// nColumnOrBarCountInSeries +3 +// static_cast(aSeriesColumnOrBarFillStyle) +2 +// static_cast(aSeriesColumnOrBarFillColor) +10079487 +/// 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 +/// 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=0 +// aColumnOrBarPosition.X +5055 +// aColumnOrBarPosition.Y +4550 +// aColumnOrBarSize.Height +601 +// aColumnOrBarSize.Width +1965 +// aColumnOrBarTransformation +1965;0;5055;0;601;4550;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 000000000..b3d3c0987 --- /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(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 000000000..428a206de --- /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(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 000000000..35f3d560e --- /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(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(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(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(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 000000000..a0c341dc6 --- /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(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 000000000..ad31f8c86 --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +43091 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8388352 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16765728 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..5d2a2c011 --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +43091 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8388352 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16765728 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..7f55f8918 --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +17798 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8388352 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16765728 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..78c83ef62 --- /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(aEntryGeomColor) +17798 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.RectangleShape +// static_cast(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 000000000..5d2a2c011 --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +43091 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8388352 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16765728 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..a3ef82203 --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +43091 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8388352 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16765728 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16711807 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8257569 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +8637183 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +3227652 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +11456256 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +4923247 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16749838 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +12910603 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +34001 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +17798 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(aEntryGeomColor) +16728590 +// xLegendEntryContainer->getCount() +3 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..63a2980cf --- /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(aEntryGeomColor) +7512015 +// sEntryGeomShapeType +com.sun.star.drawing.PolyPolygonShape +// static_cast(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 000000000..9c207c981 --- /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(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(aEntryGeomColor) +7512015 +// xLegendEntryContainer->getCount() +2 +// sEntryGeomShapeType +com.sun.star.drawing.LineShape +// static_cast(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 000000000..b2dfd3329 --- /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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(aSliceFillColor) +16728590 +/// /D=0:CS=0:CT=0:Series=0:Point=2 +// aSlicePosition.X +8909 +// aSlicePosition.Y +4532 +// aSliceSize.Height +4689 +// aSliceSize.Width +2544 +// aSliceTransformation +2544;0;8909;0;4689;4532;0;0;1 +// static_cast(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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 000000000..9cbc93de4 --- /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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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 000000000..1b97446cc --- /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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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 000000000..820a34444 --- /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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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 000000000..e1a370859 --- /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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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(aSliceFillStyle) +1 +// static_cast(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 000000000..3d7d8a55c --- /dev/null +++ b/chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt @@ -0,0 +1,2 @@ +// static_cast( 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 000000000..007a25ed4 --- /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(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16711807 +/// Series 1 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +10079487 +/// Series 2 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +10079487 +/// Series 3 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..c92fbb1bf --- /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(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(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(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(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 000000000..61c521ff3 --- /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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..01c6448c2 --- /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(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +17798 +/// Series 1 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16728590 +/// Series 2 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16765728 +/// Series 3 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..42eaae0b2 --- /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(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(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(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(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 000000000..c8d1819f9 --- /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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..c6ef9431c --- /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(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +17798 +/// Series 1 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16728590 +/// Series 2 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16765728 +/// Series 3 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..55a84b00f --- /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(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(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(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(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 000000000..1107f97cd --- /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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..d58d57d1e --- /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(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +17798 +/// Series 1 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16728590 +/// Series 2 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +16765728 +/// Series 3 +/// Lines are displayed +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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 000000000..b8d7c7a24 --- /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(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(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(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(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 000000000..8803c6e02 --- /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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(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(aPointFillStyle) +1 +// static_cast(aPointFillColor) +5741852 diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx new file mode 100644 index 000000000..b1bc22c61 --- /dev/null +++ b/chart2/qa/extras/chart2export.cxx @@ -0,0 +1,2834 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +using uno::Reference; +using beans::XPropertySet; + +class Chart2ExportTest : public ChartTest, public XmlTestTools +{ +protected: + + virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override; +public: + Chart2ExportTest() : ChartTest() {} + void testErrorBarXLSX(); + void testErrorBarPropXLSX(); + void testTrendline(); + void testTrendlineOOXML(); + void testTrendlineXLS(); + void testStockChart(); + void testBarChart(); + void testCrosses(); + void testScatterChartTextXValues(); + void testScatterXAxisValues(); + void testScatterXAxisCategories(); + void testChartDataTable(); + void testChartExternalData(); + void testEmbeddingsGrabBag(); + void testAreaChartLoad(); + void testUpDownBars(); + void testDoughnutChart(); + void testDisplayUnits(); + // void testFdo74115WallGradientFill(); + void testFdo74115WallBitmapFill(); + void testPieChartWallLineStyle(); + void testBarChartRotation(); + void testShapeFollowedByChart(); + void testPieChartDataLabels(); + void testSeriesIdxOrder(); + void testScatterPlotLabels(); + void testErrorBarDataRangeODS(); + void testChartCrash(); + void testPieChartRotation(); + void testEmbeddingsOleObjectGrabBag(); + void testGapWidthXLSX(); + void testSmoothedLines(); + void testLabelStringODS(); + void testFdo78290LineChartMarkerX(); + void testFdo78290ScatterChartMarkerX(); + void testFdo78290CombinationChartMarkerX(); + void testTdf126115IndividualMarker(); + void testAxisNumberFormatODS(); + void testAxisNumberFormatXLS(); + void testDataLabelBordersDOCX(); + void testDataLabel3DChartDOCX(); + void testDataLabelBarChartDOCX(); + void testDataLabelClusteredBarChartDOCX(); + void testDataLabelRadarChartDOCX(); + void testDataLabelDoughnutChartDOCX(); + void testDataLabelAreaChartDOCX(); + void testDataLabelDefaultLineChartDOCX(); + void testIndividualDataLabelProps(); + void testTdf108107(); + void testTdf114139(); + void testTdf64224(); + void testChartTitlePropertiesColorFillDOCX(); + void testChartTitlePropertiesGradientFillDOCX(); + void testChartTitlePropertiesBitmapFillDOCX(); + void testColorGradientWithTransparancyDOCX(); + void testColorGradientWithTransparancyODS(); + void testColorGradientStopXLSX(); + void testRadialColorGradientDOCX(); + void testBarChartDataPointPropDOCX(); + void testFdo83058dlblPos(); + void testAutoTitleDelXLSX(); + void testDispBlanksAsXLSX(); + void testMarkerColorXLSX(); + void testRoundedCornersXLSX(); + void testAxisNumberFormatXLSX(); + void testDataPointLabelNumberFormatXLSX(); + void testDataLabelDefaultValuesXLSX(); + void testTitleOverlayXLSX(); + void testInvertIfNegativeXLSX(); + void testBubble3DXLSX(); + void testNoMarkerXLSX(); + void testTitleManualLayoutXLSX(); + void testPlotAreaManualLayoutXLSX(); + void testLegendManualLayoutXLSX(); + void testChartSubTitle(); + void testChartMainWithSubTitle(); + void testAutoTitleDeleted(); + void testChartTitlePropertiesColorFillXLSX(); + void testChartTitlePropertiesGradientFillXLSX(); + void testChartTitlePropertiesBitmapFillXLSX(); + void testBarChartDataPointPropXLSX(); + void testDataseriesOverlapStackedChartXLSX(); + void testAxisCharacterPropertiesXLSX(); + void testTitleCharacterPropertiesXLSX(); + void testPlotVisOnlyXLSX(); + void testBarChartVaryColorsXLSX(); + void testMultipleAxisXLSX(); + void testSecondaryAxisXLSX(); + void testSetSeriesToSecondaryAxisXLSX(); + void testCombinedChartSecondaryAxisXLSX(); + void testCombinedChartSecondaryAxisODS(); + void testCrossBetweenXLSX(); + void testCrossBetweenWithDeletedAxis(); + void testCrossBetweenODS(); + void testAxisTitleRotationXLSX(); + void testAxisTitlePositionDOCX(); + void testAxisCrossBetweenDOCX(); + void testPieChartDataPointExplosionXLSX(); + void testCustomDataLabel(); + void testCustomPositionofDataLabel(); + void testCustomDataLabelMultipleSeries(); + void testLeaderLines(); + void testNumberFormatExportPPTX(); + void testLabelSeparatorExportDOCX(); + void testChartTitlePropertiesColorFillPPTX(); + void testChartTitlePropertiesGradientFillPPTX(); + void testChartTitlePropertiesBitmapFillPPTX(); + void testxAxisLabelsRotation(); + void testMultipleCategoryAxisLablesXLSX(); + void testMultipleCategoryAxisLablesDOCX(); + void testTdf116163(); + void testTdf111824(); + void test3DAreaChartZAxis(); + void testTdf119029(); + void testTdf108022(); + void testTdf121744(); + void testTdf121189(); + void testTdf122031(); + void testTdf115012(); + void testTdf123206_customLabelText(); + void testCustomLabelText(); + void testDeletedLegendEntries(); + void testTdf130225(); + void testTdf59857(); + void testTdf126076(); + void testTdf75330(); + void testTdf127792(); + void testTdf131979(); + void testTdf132076(); + void testTdf125812(); + void testTdf133190(); + void testTdf133191(); + void testTdf132594(); + void testTdf136267(); + + CPPUNIT_TEST_SUITE(Chart2ExportTest); + CPPUNIT_TEST(testErrorBarXLSX); + CPPUNIT_TEST(testErrorBarPropXLSX); + CPPUNIT_TEST(testTrendline); + CPPUNIT_TEST(testTrendlineOOXML); + CPPUNIT_TEST(testTrendlineXLS); + CPPUNIT_TEST(testStockChart); + CPPUNIT_TEST(testBarChart); + CPPUNIT_TEST(testCrosses); + CPPUNIT_TEST(testScatterChartTextXValues); + CPPUNIT_TEST(testScatterXAxisValues); + CPPUNIT_TEST(testScatterXAxisCategories); + CPPUNIT_TEST(testChartDataTable); + CPPUNIT_TEST(testChartExternalData); + CPPUNIT_TEST(testEmbeddingsGrabBag); + CPPUNIT_TEST(testAreaChartLoad); + CPPUNIT_TEST(testUpDownBars); + CPPUNIT_TEST(testDoughnutChart); + CPPUNIT_TEST(testDisplayUnits); + // CPPUNIT_TEST(testFdo74115WallGradientFill); + CPPUNIT_TEST(testFdo74115WallBitmapFill); + CPPUNIT_TEST(testPieChartWallLineStyle); + CPPUNIT_TEST(testBarChartRotation); + CPPUNIT_TEST(testShapeFollowedByChart); + CPPUNIT_TEST(testPieChartDataLabels); + CPPUNIT_TEST(testSeriesIdxOrder); + CPPUNIT_TEST(testScatterPlotLabels); + CPPUNIT_TEST(testErrorBarDataRangeODS); + CPPUNIT_TEST(testChartCrash); + CPPUNIT_TEST(testPieChartRotation); + CPPUNIT_TEST(testEmbeddingsOleObjectGrabBag); + CPPUNIT_TEST(testGapWidthXLSX); + CPPUNIT_TEST(testSmoothedLines); + CPPUNIT_TEST(testLabelStringODS); + CPPUNIT_TEST(testFdo78290LineChartMarkerX); + CPPUNIT_TEST(testFdo78290ScatterChartMarkerX); + CPPUNIT_TEST(testFdo78290CombinationChartMarkerX); + CPPUNIT_TEST(testTdf126115IndividualMarker); + CPPUNIT_TEST(testAxisNumberFormatODS); + CPPUNIT_TEST(testAxisNumberFormatXLS); + CPPUNIT_TEST(testDataLabelBordersDOCX); + CPPUNIT_TEST(testDataLabel3DChartDOCX); + CPPUNIT_TEST(testDataLabelBarChartDOCX); + CPPUNIT_TEST(testDataLabelClusteredBarChartDOCX); + CPPUNIT_TEST(testDataLabelRadarChartDOCX); + CPPUNIT_TEST(testDataLabelDoughnutChartDOCX); + CPPUNIT_TEST(testDataLabelAreaChartDOCX); + CPPUNIT_TEST(testDataLabelDefaultLineChartDOCX); + CPPUNIT_TEST(testIndividualDataLabelProps); + CPPUNIT_TEST(testTdf108107); + CPPUNIT_TEST(testTdf114139); + CPPUNIT_TEST(testTdf64224); + CPPUNIT_TEST(testChartTitlePropertiesColorFillDOCX); + CPPUNIT_TEST(testChartTitlePropertiesGradientFillDOCX); + CPPUNIT_TEST(testChartTitlePropertiesBitmapFillDOCX); + CPPUNIT_TEST(testColorGradientWithTransparancyDOCX); + CPPUNIT_TEST(testColorGradientWithTransparancyODS); + CPPUNIT_TEST(testColorGradientStopXLSX); + CPPUNIT_TEST(testRadialColorGradientDOCX); + CPPUNIT_TEST(testBarChartDataPointPropDOCX); + CPPUNIT_TEST(testFdo83058dlblPos); + CPPUNIT_TEST(testAutoTitleDelXLSX); + CPPUNIT_TEST(testDispBlanksAsXLSX); + CPPUNIT_TEST(testMarkerColorXLSX); + CPPUNIT_TEST(testRoundedCornersXLSX); + CPPUNIT_TEST(testAxisNumberFormatXLSX); + CPPUNIT_TEST(testDataPointLabelNumberFormatXLSX); + CPPUNIT_TEST(testDataLabelDefaultValuesXLSX); + CPPUNIT_TEST(testTitleOverlayXLSX); + CPPUNIT_TEST(testInvertIfNegativeXLSX); + CPPUNIT_TEST(testBubble3DXLSX); + CPPUNIT_TEST(testNoMarkerXLSX); + CPPUNIT_TEST(testTitleManualLayoutXLSX); + CPPUNIT_TEST(testPlotAreaManualLayoutXLSX); + CPPUNIT_TEST(testLegendManualLayoutXLSX); + CPPUNIT_TEST(testChartSubTitle); + CPPUNIT_TEST(testChartMainWithSubTitle); + CPPUNIT_TEST(testAutoTitleDeleted); + CPPUNIT_TEST(testChartTitlePropertiesColorFillXLSX); + CPPUNIT_TEST(testChartTitlePropertiesGradientFillXLSX); + CPPUNIT_TEST(testChartTitlePropertiesBitmapFillXLSX); + CPPUNIT_TEST(testBarChartDataPointPropXLSX); + CPPUNIT_TEST(testDataseriesOverlapStackedChartXLSX); + CPPUNIT_TEST(testAxisCharacterPropertiesXLSX); + CPPUNIT_TEST(testTitleCharacterPropertiesXLSX); + CPPUNIT_TEST(testPlotVisOnlyXLSX); + CPPUNIT_TEST(testBarChartVaryColorsXLSX); + CPPUNIT_TEST(testMultipleAxisXLSX); + CPPUNIT_TEST(testSecondaryAxisXLSX); + CPPUNIT_TEST(testSetSeriesToSecondaryAxisXLSX); + CPPUNIT_TEST(testCombinedChartSecondaryAxisXLSX); + CPPUNIT_TEST(testCombinedChartSecondaryAxisODS); + CPPUNIT_TEST(testCrossBetweenXLSX); + CPPUNIT_TEST(testCrossBetweenWithDeletedAxis); + CPPUNIT_TEST(testCrossBetweenODS); + CPPUNIT_TEST(testAxisTitleRotationXLSX); + CPPUNIT_TEST(testAxisTitlePositionDOCX); + CPPUNIT_TEST(testAxisCrossBetweenDOCX); + CPPUNIT_TEST(testPieChartDataPointExplosionXLSX); + CPPUNIT_TEST(testCustomDataLabel); + CPPUNIT_TEST(testCustomPositionofDataLabel); + CPPUNIT_TEST(testCustomDataLabelMultipleSeries); + CPPUNIT_TEST(testLeaderLines); + CPPUNIT_TEST(testNumberFormatExportPPTX); + CPPUNIT_TEST(testLabelSeparatorExportDOCX); + CPPUNIT_TEST(testChartTitlePropertiesColorFillPPTX); + CPPUNIT_TEST(testChartTitlePropertiesGradientFillPPTX); + CPPUNIT_TEST(testChartTitlePropertiesBitmapFillPPTX); + CPPUNIT_TEST(testxAxisLabelsRotation); + CPPUNIT_TEST(testMultipleCategoryAxisLablesXLSX); + CPPUNIT_TEST(testMultipleCategoryAxisLablesDOCX); + CPPUNIT_TEST(testTdf116163); + CPPUNIT_TEST(testTdf111824); + CPPUNIT_TEST(test3DAreaChartZAxis); + CPPUNIT_TEST(testTdf119029); + CPPUNIT_TEST(testTdf108022); + CPPUNIT_TEST(testTdf121744); + CPPUNIT_TEST(testTdf121189); + CPPUNIT_TEST(testTdf122031); + CPPUNIT_TEST(testTdf115012); + CPPUNIT_TEST(testTdf123206_customLabelText); + CPPUNIT_TEST(testCustomLabelText); + CPPUNIT_TEST(testDeletedLegendEntries); + CPPUNIT_TEST(testTdf130225); + CPPUNIT_TEST(testTdf59857); + CPPUNIT_TEST(testTdf126076); + CPPUNIT_TEST(testTdf75330); + CPPUNIT_TEST(testTdf127792); + CPPUNIT_TEST(testTdf131979); + CPPUNIT_TEST(testTdf132076); + CPPUNIT_TEST(testTdf125812); + CPPUNIT_TEST(testTdf133190); + CPPUNIT_TEST(testTdf133191); + CPPUNIT_TEST(testTdf132594); + CPPUNIT_TEST(testTdf136267); + + CPPUNIT_TEST_SUITE_END(); + +protected: + /** + * Given that some problem doesn't affect the result in the importer, we + * test the resulting file directly, by opening the zip file, parsing an + * xml stream, and asserting an XPath expression. This method returns the + * xml stream, so that you can do the asserting. + */ + xmlDocUniquePtr parseExport(const OUString& rDir, const OUString& rFilterFormat); + +}; + +namespace { + +struct CheckForChartName +{ +private: + OUString aDir; + +public: + explicit CheckForChartName( const OUString& rDir ): + aDir(rDir) {} + + bool operator()(const OUString& rName) + { + if(!rName.startsWith(aDir)) + return false; + + if(!rName.endsWith(".xml")) + return false; + + return true; + } +}; + +OUString findChartFile(const OUString& rDir, uno::Reference< container::XNameAccess > const & xNames ) +{ + uno::Sequence aNames = xNames->getElementNames(); + OUString* pElement = std::find_if(aNames.begin(), aNames.end(), CheckForChartName(rDir)); + + CPPUNIT_ASSERT(pElement != aNames.end()); + return *pElement; +} + +} + +xmlDocUniquePtr Chart2ExportTest::parseExport(const OUString& rDir, const OUString& rFilterFormat) +{ + std::shared_ptr pTempFile = save(rFilterFormat); + + // Read the XML stream we're interested in. + uno::Reference xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), pTempFile->GetURL()); + uno::Reference xInputStream(xNameAccess->getByName(findChartFile(rDir, xNameAccess)), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInputStream.is()); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + + return parseXmlStream(pStream.get()); +} + +void Chart2ExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) +{ + static struct { char const * pPrefix; char const * pURI; } const aNamespaces[] = + { + { "w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main" }, + { "v", "urn:schemas-microsoft-com:vml" }, + { "c", "http://schemas.openxmlformats.org/drawingml/2006/chart" }, + { "a", "http://schemas.openxmlformats.org/drawingml/2006/main" }, + { "mc", "http://schemas.openxmlformats.org/markup-compatibility/2006" }, + { "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" }, + { "wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" }, + { "wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" }, + { "office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" }, + { "table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" }, + { "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" }, + { "xlink", "http://www.w3c.org/1999/xlink" }, + { "c15", "http://schemas.microsoft.com/office/drawing/2012/chart" } + }; + for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i) + { + xmlXPathRegisterNs( + pXmlXPathCtx, + reinterpret_cast(aNamespaces[i].pPrefix), + reinterpret_cast(aNamespaces[i].pURI)); + } +} + +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 const & xCurve, + double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward, + bool aExpectedForceIntercept, double aExpectedInterceptValue, + bool aExpectedShowEquation, bool aExpectedR2) +{ + Reference 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); +} + +void checkNameAndType(Reference 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 const & xCurve, const OUString& aExpectedName, + double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward, + double aExpectedInterceptValue) +{ + Reference 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); +} + +void checkPolynomialTrendline( + Reference const & xCurve, const OUString& aExpectedName, + sal_Int32 aExpectedDegree, + double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward, + double aExpectedInterceptValue) +{ + Reference 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); +} + +void checkMovingAverageTrendline( + Reference const & xCurve, const OUString& aExpectedName, sal_Int32 aExpectedPeriod) +{ + Reference 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); +} + +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 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 +void Chart2ExportTest::testErrorBarXLSX() +{ + load("/chart2/qa/extras/data/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); + } + + reload("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); + } +} + +void Chart2ExportTest::testErrorBarPropXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testErrorBarProp.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open 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", "val", "y"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[1]/c:spPr/a:ln", "w", "12600"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[1]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "ff0000"); + + // test x error bars property + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:errDir", "val", "x"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:spPr/a:ln", "w", "9360"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "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. +void Chart2ExportTest::testTrendline() +{ + mbSkipValidation = true; + load("/chart2/qa/extras/data/ods/", "trendline.ods"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); + reload("calc8"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); +} + +void Chart2ExportTest::testTrendlineOOXML() +{ + load("/chart2/qa/extras/data/ods/", "trendline.ods"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); + reload("Calc Office Open XML"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); +} + +void Chart2ExportTest::testTrendlineXLS() +{ + mbSkipValidation = true; + load("/chart2/qa/extras/data/ods/", "trendline.ods"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); + reload("MS Excel 97"); + checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent)); +} + +void Chart2ExportTest::testStockChart() +{ + /* For attached file Stock_Chart.docx, in chart1.xml, + * , there are four types of series as + * Open,Low,High and Close. + * For Open series, in + * an attribute val of index should start from 1 and not from 0. + * Which was problem area. + */ + load("/chart2/qa/extras/data/docx/", "testStockChart.docx"); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + if (!pXmlDoc) + return; + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:idx", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:order", "val", "1"); + assertXPathContent( + pXmlDoc, + "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:tx/c:strRef/c:strCache/c:pt/c:v", + "Open"); +} + +void Chart2ExportTest::testBarChart() +{ + load("/chart2/qa/extras/data/docx/", "testBarChart.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + if (!pXmlDoc) + return; + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:barDir", "val", "col"); +} + +void Chart2ExportTest::testCrosses() +{ + load("/chart2/qa/extras/data/docx/", "Bar_horizontal_cone.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses", "val", "autoZero"); +} + +void Chart2ExportTest::testScatterChartTextXValues() +{ + load("/chart2/qa/extras/data/docx/", "scatter-chart-text-x-values.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + // Make sure we have exactly 3 data series. + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 1"), aLabels[0][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 2"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[2][0].get()); + + std::vector > 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. + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + if (!pXmlDoc) + return; + + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal[1]/c:numRef[1]/c:numCache[1]/c:pt[1]/c:v[1]", "1"); +} + +void Chart2ExportTest::testScatterXAxisValues() +{ + load("/chart2/qa/extras/data/odt/", "tdf114657.odt"); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:ptCount", "val", "5"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[1]/c:v", "15"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[2]/c:v", "11"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[3]/c:v", "20"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[4]/c:v", "16"); +} + +void Chart2ExportTest::testScatterXAxisCategories() +{ + load("/chart2/qa/extras/data/odt/", "tdf131143.odt"); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:ptCount", "val", "4"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:pt[1]/c:v", "Row 1"); + assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:pt[2]/c:v", "Row 2"); +} + +void Chart2ExportTest::testChartDataTable() +{ + load("/chart2/qa/extras/data/docx/", "testChartDataTable.docx"); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showHorzBorder", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showVertBorder", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showOutline", "val", "1"); +} + +void Chart2ExportTest::testChartExternalData() +{ + load("/chart2/qa/extras/data/docx/", "testMultipleChart.docx"); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + xmlXPathObjectPtr pXmlPathObj = getXPathNode(pXmlDoc, "/c:chartSpace/c:externalData"); + xmlNodeSetPtr pXmlNodes = pXmlPathObj->nodesetval; + CPPUNIT_ASSERT(pXmlNodes); +} + +void 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. + + load("/chart2/qa/extras/data/docx/", "testMultiplechartembeddings.docx" ); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY); + uno::Sequence 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 aEmbeddingsList(0); + uno::Reference 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.get()); // Reference not empty + CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(testEmbeddedFileNames[j]),aEmbeddedfileName); + } + } + } + CPPUNIT_ASSERT(bEmbeddings); // Grab Bag has all the expected elements +} + +void Chart2ExportTest::testAreaChartLoad() +{ + load ("/chart2/qa/extras/data/docx/", "testAreaChartLoad.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:showVal", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLbl", 0); +} + +void Chart2ExportTest::testUpDownBars() +{ + /* + load("/chart2/qa/extras/data/docx/", "UpDownBars.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:upDownBars"); + */ +} + +void Chart2ExportTest::testDoughnutChart() +{ + load("/chart2/qa/extras/data/docx/", "doughnutChart.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart"); +} + +void Chart2ExportTest::testDisplayUnits() +{ + load("/chart2/qa/extras/data/docx/", "DisplayUnits.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:dispUnits/c:builtInUnit", "val", "billions"); +} + +// void Chart2ExportTest::testFdo74115WallGradientFill() +// { +// load("/chart2/qa/extras/data/docx/", "fdo74115_WallGradientFill.docx"); +// xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); +// CPPUNIT_ASSERT(pXmlDoc); +// +// assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill"); +// } + +void Chart2ExportTest::testFdo74115WallBitmapFill() +{ + load("/chart2/qa/extras/data/docx/", "fdo74115_WallBitmapFill.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:blipFill"); +} + +void Chart2ExportTest::testPieChartWallLineStyle() +{ + load("/chart2/qa/extras/data/odt/", "testPieChartWallLineStyle.odt"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:ln/a:noFill"); +} + +//The below test case tests the built in marker 'x' for Office 2010 in Line charts + +void Chart2ExportTest::testFdo78290LineChartMarkerX() +{ + load("/chart2/qa/extras/data/docx/", "fdo78290_Line_Chart_Marker_x.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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]","val","x"); + assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:size[1]","val","7"); +} + +// We can also use the built in marker 'x' in scatter chart, hence writing the test case for the same. + +void Chart2ExportTest::testFdo78290ScatterChartMarkerX() +{ + load("/chart2/qa/extras/data/docx/", "fdo78290_Scatter_Chart_Marker_x.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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]","val","x"); + assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:scatterChart[1]/c:ser[1]/c:marker[1]/c:size[1]","val","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. + +void Chart2ExportTest::testFdo78290CombinationChartMarkerX() +{ + load("/chart2/qa/extras/data/docx/", "fdo78290_Combination_Chart_Marker_x.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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]","val","x"); + assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:size[1]","val","7"); +} + +void Chart2ExportTest::testTdf126115IndividualMarker() +{ + // Check individual marker properties. + load("/chart2/qa/extras/data/xlsx/", "tdf126115.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "val", "square"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dPt/c:marker/c:size", "val", "8"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dPt/c:marker/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + // 2. series + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:symbol", "val", "x"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:size", "val", "15"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:spPr/a:solidFill/a:srgbClr", "val", "7030a0"); +} + +void Chart2ExportTest::testAxisNumberFormatODS() +{ + struct + { + void check( const Reference& xChartDoc ) + { + Reference xAxisX = getAxisFromDoc(xChartDoc, 0, 0, 0); + Reference 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 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 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; + + load("/chart2/qa/extras/data/ods/", "axis-numformats-linked.ods"); + + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + aTest.check(xChartDoc); + + // Reload the document and make sure everything remains intact. + reload("calc8"); + xChartDoc = getChartDocFromSheet(0, mxComponent); + aTest.check(xChartDoc); +} + +void Chart2ExportTest::testAxisNumberFormatXLS() +{ + struct + { + void check( const Reference& xChartDoc, bool bNumFmtLinkedActual, sal_Int16 nNumFmtTypeFlag ) const + { + Reference xAxisY = getAxisFromDoc( xChartDoc, 0, 1, 0 ); + bool bNumFmtLinked = false; + Reference 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& xChartDoc, sal_Int16 nNumFmtTypeFlag ) + { + Reference xAxisY = getAxisFromDoc( xChartDoc, 0, 1, 0 ); + Reference xPS( xAxisY, uno::UNO_QUERY_THROW ); + Any aAny( false ); + xPS->setPropertyValue( "LinkNumberFormatToSource", aAny ); + + Reference xNFS( xChartDoc, uno::UNO_QUERY_THROW ); + Reference xNumberFormats = xNFS->getNumberFormats(); + CPPUNIT_ASSERT( xNumberFormats.is() ); + lang::Locale aLocale{ "en", "US", "" }; + Sequence aNumFmts = xNumberFormats->queryKeys( nNumFmtTypeFlag, aLocale, false ); + CPPUNIT_ASSERT( aNumFmts.hasElements() ); + aAny <<= aNumFmts[0]; + xPS->setPropertyValue( CHART_UNONAME_NUMFMT, aAny ); + } + + } aTest; + + load( "/chart2/qa/extras/data/xls/", "axis_sourceformatting.xls" ); + + Reference 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 + reload( "MS Excel 97" ); + xChartDoc = getChartDocFromSheet( 0, mxComponent ); + aTest.check( xChartDoc, false, util::NumberFormat::NUMBER ); +} + +void Chart2ExportTest::testDataLabelBordersDOCX() +{ + struct Check + { + sal_Int32 mnIndex; + css::drawing::LineStyle meStyle; + sal_Int32 mnColor; + }; + + struct + { + /** + * Chart 1 has 4 bars of which 1st and 3rd have labels with borders + * around them. + */ + void checkObject1( const Reference& xChartDoc ) + { + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + + // Check to make sure that data points 0 and 2 have local properties. + Reference xPropSet(xDataSeries, uno::UNO_QUERY); + CPPUNIT_ASSERT(xPropSet.is()); + + Sequence 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 < SAL_N_ELEMENTS(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); + + sal_Int32 nColor = -1; + 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& xChartDoc ) + { + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + + Reference 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); + + sal_Int32 nColor = -1; + xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_COLOR) >>= nColor; + CPPUNIT_ASSERT_EQUAL_MESSAGE("Border color should be green.", sal_Int32(0x0000FF00), nColor); + } + + } aTest; + + load("/chart2/qa/extras/data/docx/", "data-label-borders.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + + // "Automatic" chart background fill in docx should be loaded as solid white. + Reference xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get(); + sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get(); + 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); + + reload("Office Open XML Text"); + + xChartDoc.set(getChartDocFromWriter(0), uno::UNO_QUERY); + aTest.checkObject1(xChartDoc); + xChartDoc.set(getChartDocFromWriter(1), uno::UNO_QUERY); + aTest.checkObject2(xChartDoc); +} + +void Chart2ExportTest::testDataLabel3DChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "3d-bar-label.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bar3DChart/c:ser/c:dLbls/c:dLbl/c:dLblPos", 0); +} + +void Chart2ExportTest::testDataLabelBarChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "bar-chart-labels.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls/c:dLblPos", "val", "ctr"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[2]/c:dLbls/c:dLblPos", "val", "inEnd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[3]/c:dLbls/c:dLblPos", "val", "inBase"); +} + +void Chart2ExportTest::testDataLabelClusteredBarChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "clustered-bar-chart-labels.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", "val", "outEnd"); +} + +void Chart2ExportTest::testDataLabelRadarChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "radar-chart-labels.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:radarChart/c:ser/c:dLbls/c:dLbl/c:dLblPos", 0); +} + +void Chart2ExportTest::testDataLabelDoughnutChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "doughnut-chart-labels.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart/c:ser/c:dLbls/c:dLbl/c:dLblPos", 0); +} + +void Chart2ExportTest::testDataLabelAreaChartDOCX() +{ + load("/chart2/qa/extras/data/docx/", "area-chart-labels.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLbl/c:dLblPos", 0); +} + +void 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. + + load("/chart2/qa/extras/data/docx/", "line-chart-label-default-placement.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + reload("Office Open XML Text"); + + xChartDoc.set(getChartDocFromWriter(0), uno::UNO_QUERY); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + Reference 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 ); +} + +void Chart2ExportTest::testIndividualDataLabelProps() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf122915.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open 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", "b", "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", "sz", "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", "val", "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", "typeface", "Times New Roman"); +} + +void Chart2ExportTest::testTdf108107() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf108107.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[1]/c:idx", "val", "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", "b", "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", "sz", "2000"); +} + +void Chart2ExportTest::testTdf114139() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf114139.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pie3DChart", 1); + //no fill + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:solidFill", 0); +} + +void Chart2ExportTest::testTdf64224() +{ + load("/chart2/qa/extras/data/ods/", "tdf64224.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + //no fill + assertXPath(pXmlDoc, "/c:chartSpace/c:spPr/a:noFill", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:spPr/a:solidFill", 0); +} + +void Chart2ExportTest::testChartTitlePropertiesColorFillDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testChartTitlePropertiesColorFill.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesGradientFillDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testChartTitlePropertiesGradientFill.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr", "val", "cccccc"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr", "val", "666666"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesBitmapFillDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testChartTitlePropertiesBitmapFill.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip", "embed", "rId1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testColorGradientWithTransparancyDOCX() +{ + // Test color gradient (two color) with gradient transparency + load("/chart2/qa/extras/data/docx/", "testColorGradientWithTransparancy.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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", "val", "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", "val", "90196"); +} + +void Chart2ExportTest::testColorGradientWithTransparancyODS() +{ + // Test color gradient (two color) with simple transparency + load("/chart2/qa/extras/data/ods/", "testColorGradientWithTransparancy.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "val", "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", "val", "60000"); +} + +void Chart2ExportTest::testColorGradientStopXLSX() +{ + // Test color gradient (two color) stop of the first color + load("/chart2/qa/extras/data/xlsx/", "tdf128619.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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]", "pos", "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]", "pos", "100000"); +} + +void Chart2ExportTest::testRadialColorGradientDOCX() +{ + load("/chart2/qa/extras/data/docx/", "tdf128794.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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", 0); + // Test the linear gradient angle + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:lin", "ang", "13500000"); +} + +void Chart2ExportTest::testBarChartDataPointPropDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testBarChartDataPointPropDOCX.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors", "val", "0"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:idx", "val", "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", "val", "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", "val", "c7d5ed"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "70ad47"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:idx", "val", "2"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "000000"); +} + +void Chart2ExportTest::testBarChartRotation() +{ + load ("/chart2/qa/extras/data/docx/", "barChartRotation.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX", "val", "30"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY", "val", "50"); +} + +void 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. + */ + load("/chart2/qa/extras/data/docx/", "FDO74430.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/document", "Office Open XML Text" ); + 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]", "id"); + 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]", "id"); + + CPPUNIT_ASSERT( aValueOfFirstDocPR != aValueOfSecondDocPR ); +} + +void Chart2ExportTest::testPieChartDataLabels() +{ + load("/chart2/qa/extras/data/docx/", "PieChartDataLabels.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pie3DChart/c:ser[1]/c:dLbls/c:dLbl[1]/c:dLblPos", "val", "bestFit"); +} + +void Chart2ExportTest::testSeriesIdxOrder() +{ + load("/chart2/qa/extras/data/docx/", "testSeriesIdxOrder.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:idx[1]", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:order[1]", "val", "1"); +} + +void Chart2ExportTest::testScatterPlotLabels() +{ + load("/chart2/qa/extras/data/odt/", "scatter-plot-labels.odt"); + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + // Make sure the original chart has 'a', 'b', 'c' as its data labels. + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("a"), aLabels[0][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("b"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aLabels[2][0].get()); + + // Reload the doc and check again. The labels should not change. + reload("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()); + CPPUNIT_ASSERT_EQUAL(OUString("b"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aLabels[2][0].get()); +} + +void Chart2ExportTest::testErrorBarDataRangeODS() +{ + load("/chart2/qa/extras/data/ods/", "ErrorBarRange.ods"); + reload("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); +} + +void Chart2ExportTest::testChartCrash() +{ + load("/chart2/qa/extras/data/docx/", "FDO75975.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); +} + +void Chart2ExportTest::testPieChartRotation() +{ + load ("/chart2/qa/extras/data/docx/", "pieChartRotation.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX", "val", "40"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY", "val", "30"); +} + +void 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. + + load("/chart2/qa/extras/data/docx/", "testchartoleobjectembeddings.docx" ); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY); + uno::Sequence 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 aEmbeddingsList(0); + uno::Reference 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.get()); // 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 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 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); + +} + +} + +void Chart2ExportTest::testGapWidthXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "gapWidth.xlsx"); + + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60); + + xChartDoc = getChartDocFromSheet( 1, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30); + + reload("Calc Office Open XML"); + + xChartDoc = getChartDocFromSheet( 0, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60); + + xChartDoc = getChartDocFromSheet( 1, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30); +} + +void Chart2ExportTest::testSmoothedLines() +{ + load("/chart2/qa/extras/data/ods/", "smoothedLines.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:smooth", "val", "0"); +} + +void Chart2ExportTest::testLabelStringODS() +{ + load("/chart2/qa/extras/data/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); + + reload("calc8"); + + xChartDoc = getChartDocFromSheet( 0, mxComponent ); + xLabelSeq = getLabelDataSequenceFromDoc(xChartDoc); + CPPUNIT_ASSERT(xLabelSeq.is()); + + aLabelString = xLabelSeq->getSourceRangeRepresentation(); + CPPUNIT_ASSERT_EQUAL(OUString("\"LabelName\""), aLabelString); +} + +void Chart2ExportTest::testFdo83058dlblPos() +{ + load ("/chart2/qa/extras/data/docx/", "fdo83058_dlblPos.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[2]/c:dLblPos", "val", "outEnd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[3]/c:dLblPos", "val", "outEnd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[4]/c:dLblPos", "val", "outEnd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[5]/c:dLblPos", "val", "outEnd"); +} + +void Chart2ExportTest::testAutoTitleDelXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "autotitledel_2007.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:autoTitleDeleted", "val", "0"); +} + +void Chart2ExportTest::testDispBlanksAsXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "dispBlanksAs_2007.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:dispBlanksAs", "val", "gap"); +} + +void Chart2ExportTest::testMarkerColorXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "markerColor.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:marker/c:spPr/a:solidFill/a:srgbClr", "val", "92d050"); +} + +void Chart2ExportTest::testRoundedCornersXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "markerColor.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:roundedCorners", "val", "0"); +} + +void Chart2ExportTest::testAxisNumberFormatXLSX() +{ + load("/chart2/qa/extras/data/ods/", "axis_number_format.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx", 2); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:numFmt", "formatCode", "0.00E+000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:numFmt", "sourceLinked", "0"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:numFmt", "formatCode", "[$$-409]#,##0;\\-[$$-409]#,##0"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:numFmt", "sourceLinked", "1"); +} + +void Chart2ExportTest::testDataPointLabelNumberFormatXLSX() +{ + load("/chart2/qa/extras/data/ods/", "tdf123774.ods"); + { + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt", "formatCode", "[$-40E]0.00%"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt", "sourceLinked", "0"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt", "formatCode", "[$-40E]0.00%"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt", "sourceLinked", "0"); + } + + load("/chart2/qa/extras/data/xlsx/", "tdf130986.xlsx"); + { + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:idx", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:numFmt", "formatCode", "0.00E+00"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:numFmt", "sourceLinked", "0"); + } +} + +void Chart2ExportTest::testDataLabelDefaultValuesXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "data_label.xlsx"); + Reference< chart2::XChartDocument> xDoc = getChartDocFromSheet(0, mxComponent); + Reference xSeries = getDataSeriesFromDoc(xDoc, 0); + Reference xPropSet(xSeries, uno::UNO_QUERY_THROW); + uno::Any aAny = xPropSet->getPropertyValue("Label"); + chart2::DataPointLabel aLabel; + CPPUNIT_ASSERT(aAny >>= aLabel); + CPPUNIT_ASSERT(aLabel.ShowNumber); + + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:showVal", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLblPos", "val", "outEnd"); +} + +void Chart2ExportTest::testTitleOverlayXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "chart_title.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:overlay", "val", "0"); +} + +void Chart2ExportTest::testInvertIfNegativeXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "bar_chart_simple.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:invertIfNegative", "val", "0"); +} + +void Chart2ExportTest::testBubble3DXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "bubble_chart_simple.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[1]/c:bubble3D", "val", "0"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[2]/c:bubble3D", "val", "0"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[3]/c:bubble3D", "val", "0"); +} + +void Chart2ExportTest::testNoMarkerXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "no_marker.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:marker/c:symbol", "val", "none"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:marker/c:symbol", "val", "none"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:marker", "val", "0"); +} + +void Chart2ExportTest::testTitleManualLayoutXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "title_manual_layout.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:layoutTarget", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:xMode", "val", "edge"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:yMode", "val", "edge"); + + OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:x", "val"); + double nX = aXVal.toDouble(); + CPPUNIT_ASSERT(nX > 0 && nX < 1); + + OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:y", "val"); + double nY = aYVal.toDouble(); + CPPUNIT_ASSERT(nY > 0 && nY < 1); + CPPUNIT_ASSERT(nX != nY); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:bodyPr", "rot", "1200000"); +} + +void Chart2ExportTest::testPlotAreaManualLayoutXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "plot_area_manual_layout.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:layoutTarget", "val", "inner"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:xMode", "val", "edge"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:yMode", "val", "edge"); + + OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:x", "val"); + double nX = aXVal.toDouble(); + CPPUNIT_ASSERT(nX > 0 && nX < 1); + + OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:y", "val"); + double nY = aYVal.toDouble(); + CPPUNIT_ASSERT(nY > 0 && nY < 1); + CPPUNIT_ASSERT(nX != nY); + + OUString aWVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:w", "val"); + double nW = aWVal.toDouble(); + CPPUNIT_ASSERT(nW > 0 && nW < 1); + + OUString aHVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:h", "val"); + double nH = aHVal.toDouble(); + CPPUNIT_ASSERT(nH > 0 && nH < 1); + CPPUNIT_ASSERT(nH != nW); +} + +void Chart2ExportTest::testLegendManualLayoutXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "legend_manual_layout.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:layoutTarget", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:xMode", "val", "edge"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:yMode", "val", "edge"); + + OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:x", "val"); + double nX = aXVal.toDouble(); + CPPUNIT_ASSERT(nX > 0 && nX < 1); + + OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:y", "val"); + double nY = aYVal.toDouble(); + CPPUNIT_ASSERT(nY > 0 && nY < 1); + CPPUNIT_ASSERT(nX != nY); + + OUString aWVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:w", "val"); + double nW = aWVal.toDouble(); + CPPUNIT_ASSERT(nW > 0 && nW < 1); + + OUString aHVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:h", "val"); + double nH = aHVal.toDouble(); + CPPUNIT_ASSERT(nH > 0 && 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", "sz", "900"); +} + +void Chart2ExportTest::testChartSubTitle() +{ + load("/chart2/qa/extras/data/ods/", "testChartSubTitle.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "sz", "1100"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr", "b", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr", "val", "00a933"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr/a:latin", "typeface", "Times New Roman"); + assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:t", "It is a Subtitle"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr", "val", "b2b2b2"); +} + +void Chart2ExportTest::testChartMainWithSubTitle() +{ + load("/chart2/qa/extras/data/ods/", "testChartMainWithSubTitle.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "sz", "1300"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr", "b", "0"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr", "i", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr", "val", "f10d0c"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr/a:latin", "typeface", "Arial"); + assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:t", "It is a Maintitle\nIt is a Subtitle"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr", "val", "81d41a"); +} + +void Chart2ExportTest::testAutoTitleDeleted() +{ + load("/chart2/qa/extras/data/xlsx/", "testAutoTitleDeleted.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:autoTitleDeleted", "val", "1"); +} + +void Chart2ExportTest::testChartTitlePropertiesColorFillXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testChartTitlePropertiesColorFill.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesGradientFillXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testChartTitlePropertiesGradientFill.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr", "val", "cccccc"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr", "val", "666666"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesBitmapFillXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testChartTitlePropertiesBitmapFill.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip", "embed", "rId1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testBarChartDataPointPropXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testBarChartDataPointPropXLSX.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors", "val", "0"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:idx", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "000000"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:idx", "val", "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", "val", "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", "val", "c7d5ed"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "70ad47"); +} + +void Chart2ExportTest::testDataseriesOverlapStackedChartXLSX() +{ + load("/chart2/qa/extras/data/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); + + reload("Calc Office Open XML"); + + xChartDoc = getChartDocFromSheet( 0, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 100, 100); + + xChartDoc = getChartDocFromSheet( 1, mxComponent ); + checkSheetForGapWidthAndOverlap(xChartDoc, 100, 100); +} + +void Chart2ExportTest::testAxisCharacterPropertiesXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "axis_character_properties.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr", "sz", "1000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr", "b", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr", "i", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr", "u", "sng"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr", "sz", "900"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr", "b", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr", "strike", "sngStrike"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr", "val", "ff0000"); +} + +void Chart2ExportTest::testTitleCharacterPropertiesXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "title_character_properties.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr", "sz", "2400"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr", "b", "1"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr", "sz", "2400"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr", "b", "1"); +} + +void Chart2ExportTest::testPlotVisOnlyXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "hidden_cells.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotVisOnly", "val", "0"); +} + +void Chart2ExportTest::testBarChartVaryColorsXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf90876.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors", "val", "0"); +} + +void Chart2ExportTest::testMultipleAxisXLSX() +{ + load("/chart2/qa/extras/data/ods/", "multiple_axis.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart", 2); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[1]/c:ser", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[2]/c:ser", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx", 4); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:delete[@val='1']", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:axPos[@val='l']", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:axPos[@val='r']", 1); +} + +void Chart2ExportTest::testSecondaryAxisXLSX() +{ + load("/chart2/qa/extras/data/ods/", "secondary_axis.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart", 2); + // test there is just those series in the first tag which are attached to the primary axis + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[1]/c:ser", 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", "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", "c"); + // test there is just those series in the second tag which are attached to the secondary axis + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[2]/c:ser", 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", "a"); +} + +void Chart2ExportTest::testSetSeriesToSecondaryAxisXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "add_series_secondary_axis.xlsx"); + Reference< chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent); + // Second series + Reference xSeries = getDataSeriesFromDoc(xChartDoc, 1); + CPPUNIT_ASSERT(xSeries.is()); + + Reference 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)); + + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + // Check there are only two tag in the XML, one for the primary and one for the secondary axis. + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart", 2); +} + +void Chart2ExportTest::testCombinedChartSecondaryAxisXLSX() +{ + // Original file was created with MS Office + load("/chart2/qa/extras/data/xlsx/", "combined_chart_secondary_axis.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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]", "val"); + OUString YValueIdOfBarchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]", "val"); + // Collect linechart axID on primary Axis + OUString XValueIdOfLinechart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]", "val"); + OUString YValueIdOfLinechart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]", "val"); + // 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", "val", XValueIdOfLinechart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:axId", "val", YValueIdOfLinechart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:axId", "val", XValueIdOfBarchart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId", "val", YValueIdOfBarchart); +} + +void Chart2ExportTest::testCombinedChartSecondaryAxisODS() +{ + // Original file was created with LibreOffice + load("/chart2/qa/extras/data/ods/", "combined_chart_secondary_axis.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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]", "val"); + OUString YValueIdOfBarchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]", "val"); + // Collect linechart axID on primary Axis + OUString XValueIdOfLinechart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]", "val"); + OUString YValueIdOfLinechart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]", "val"); + // 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", "val", XValueIdOfLinechart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:axId", "val", YValueIdOfLinechart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:axId", "val", XValueIdOfBarchart); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId", "val", 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", 0); +} + +void Chart2ExportTest::testCrossBetweenXLSX() +{ + // Original files were created with MS Office + { + load("/chart2/qa/extras/data/xlsx/", "tdf127777.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); + } + { + load("/chart2/qa/extras/data/xlsx/", "tdf132076.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); + } +} + +void Chart2ExportTest::testCrossBetweenWithDeletedAxis() +{ + // Original file was created with MS Office (the category axis is deleted in the file) + load("/chart2/qa/extras/data/xlsx/", "tdf128633.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); +} + +void Chart2ExportTest::testCrossBetweenODS() +{ + // Original file was created with LibreOffice + load("/chart2/qa/extras/data/ods/", "test_CrossBetween.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); +} + +void Chart2ExportTest::testAxisTitleRotationXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "axis_title_rotation.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:title/c:tx/c:rich/a:bodyPr", "rot", "0"); +} + +void Chart2ExportTest::testAxisTitlePositionDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testAxisTitlePosition.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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", "val"); + 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", "val"); + 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", "val"); + 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", "val"); + 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); +} + +void Chart2ExportTest::testAxisCrossBetweenDOCX() +{ + load("/chart2/qa/extras/data/odt/", "axis-position.odt"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + assertXPath(pXmlDoc, "(//c:crossBetween)[1]", "val", "midCat"); +} + +void Chart2ExportTest::testPieChartDataPointExplosionXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "pie_chart_datapoint_explosion.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dPt/c:explosion", "val", "28"); +} + +void Chart2ExportTest::testCustomDataLabel() +{ + load("/chart2/qa/extras/data/pptx/", "tdf115107.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1", "Impress MS PowerPoint 2007 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", "val", "404040"); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + float nFontSize; + sal_Int64 nFontColor; + sal_Int32 nCharUnderline; + uno::Reference xPropertySet; + uno::Sequence> aFields; + + // 1 + xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(16), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(13), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(12), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(0xa9d18e), nFontColor); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nCharUnderline); + + // 3 + xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(" getString()); +} + +void Chart2ExportTest::testCustomPositionofDataLabel() +{ + load("/chart2/qa/extras/data/xlsx/", "testCustomPosDataLabels.xlsx"); + { + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "val", "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", "val"); + 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", "val"); + double nY = aYVal.toDouble(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.0742140311063737, nY, 1e-7); + } + + load("/chart2/qa/extras/data/docx/", "testTdf108110.docx"); + { + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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", "val", "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", "val"); + 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", "val"); + double nY = aYVal.toDouble(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.172648731408574, nY, 1e-7); + } +} + +void Chart2ExportTest::testCustomDataLabelMultipleSeries() +{ + load("/chart2/qa/extras/data/pptx/", "tdf115107-2.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart2", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + float nFontSize; + sal_Int64 nFontColor; + uno::Reference xPropertySet; + uno::Sequence> aFields; + + // First series + xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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()); + +} + +void Chart2ExportTest::testLeaderLines() +{ + load("/chart2/qa/extras/data/xlsx/", "testTdf90749.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "val", "1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:dLbls/c:extLst/c:ext/c15:showLeaderLines", "val", "1"); +} + +void Chart2ExportTest::testNumberFormatExportPPTX() +{ + load("/chart2/qa/extras/data/pptx/", "tdf115859.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:numFmt", "formatCode", "#,##0.00,\\K"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:numFmt", "sourceLinked", "0"); +} + +void Chart2ExportTest::testLabelSeparatorExportDOCX() +{ + load("/chart2/qa/extras/data/docx/", "testLabelSeparator.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", "\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", ", "); + // The text separator should be a semicolon + assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[3]/c:dLbls/c:separator", "; "); +} + +void Chart2ExportTest::testChartTitlePropertiesColorFillPPTX() +{ + load("/chart2/qa/extras/data/pptx/", "testChartTitlePropertiesColorFill.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr", "val", "ff0000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesGradientFillPPTX() +{ + load("/chart2/qa/extras/data/pptx/", "testChartTitlePropertiesGradientFill.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr", "val", "f6f8fc"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr", "val", "c7d5ed"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testChartTitlePropertiesBitmapFillPPTX() +{ + load("/chart2/qa/extras/data/pptx/", "testChartTitlePropertiesBitmapFill.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip", "embed", "rId1"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill", 1); +} + +void Chart2ExportTest::testxAxisLabelsRotation() +{ + load ("/chart2/qa/extras/data/xlsx/", "xAxisLabelsRotation.xlsx"); + xmlDocUniquePtr pXmlDoc1 = parseExport("xl/charts/chart","Calc Office Open 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", "rot", "2700000"); +} + +void Chart2ExportTest::testMultipleCategoryAxisLablesXLSX() +{ + load("/chart2/qa/extras/data/ods/", "multilevelcat.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "val", "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", "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", "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", "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", "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", "val", "0"); +} + +void Chart2ExportTest::testMultipleCategoryAxisLablesDOCX() +{ + load("/chart2/qa/extras/data/odt/", "multilevelcat.odt"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + 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", "val", "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", "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", "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", "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", "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", "val", "0"); +} + +void Chart2ExportTest::testTdf116163() +{ + load("/chart2/qa/extras/data/pptx/", "tdf116163.pptx"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:bodyPr", "rot", "-5400000"); +} + +void Chart2ExportTest::testTdf111824() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf111824.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + // Collect 3D barchart Z axID + OUString zAxisIdOf3DBarchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bar3DChart/c:axId[3]", "val"); + // 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", "val", zAxisIdOf3DBarchart); +} + +void Chart2ExportTest::test3DAreaChartZAxis() +{ + load("/chart2/qa/extras/data/xlsx/", "test3DAreaChartZAxis.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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]", "val"); + // 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", "val", zAxisIdOf3DAreachart); +} + +void Chart2ExportTest::testTdf119029() +{ + load("/chart2/qa/extras/data/odp/", "tdf119029.odp"); + // Only use "chart", without number, because the number depends on the previous tests + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, + "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:txPr/a:bodyPr", "rot", + "-5400000"); +} + +void Chart2ExportTest::testTdf108022() +{ + load("/chart2/qa/extras/data/odt/", "tdf108022.odt"); + reload("Office Open XML Text"); + + // assert we really have two charts + Reference xChartDoc1(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc1.is()); + Reference xChartDoc2(getChartDocFromWriter(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc2.is()); +} + +void Chart2ExportTest::testTdf121744() +{ + load("/chart2/qa/extras/data/docx/", "tdf121744.docx"); + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + OUString XValueId = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[1]", "val"); + OUString YValueId = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]", "val"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]", "val", XValueId ); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]", "val", YValueId ); +} + +void Chart2ExportTest::testTdf121189() +{ + load("/chart2/qa/extras/data/odp/", "tdf121189.odp"); + reload("Impress Office Open XML"); + + uno::Reference xDoc(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPage->getCount()); + uno::Reference xShape(xPage->getByIndex(0), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.OLE2Shape"), xShape->getShapeType()); +} + +void Chart2ExportTest::testTdf122031() +{ + //Checks pie chart data label format. + + load("/chart2/qa/extras/data/xlsx/", "tdf122031.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt", "formatCode", "0.000%"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt", "formatCode", "0.000%"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:numFmt", "formatCode", "0.000%"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[3]/c:numFmt", "formatCode", "0.000%"); +} + +void Chart2ExportTest::testTdf115012() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf115012.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open 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", "val", "zero"); +} + +void Chart2ExportTest::testTdf123206_customLabelText() +{ + load("/chart2/qa/extras/data/docx/", "tdf123206.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text"); + 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", "kiscica"); +} + +void Chart2ExportTest::testCustomLabelText() +{ + load("/chart2/qa/extras/data/docx/", "testCustomlabeltext.docx"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[1]/c:idx", "val", "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", "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", "CustomLabel 1"); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[2]/c:idx", "val", "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", "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", "CustomLabel 2"); +} + +void Chart2ExportTest::testDeletedLegendEntries() +{ + load("/chart2/qa/extras/data/xlsx/", "deleted_legend_entry.xlsx"); + { + reload("Calc Office Open XML"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 1)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPropertySet(xDataSeries, uno::UNO_QUERY_THROW); + bool bShowLegendEntry = true; + CPPUNIT_ASSERT(xPropertySet->getPropertyValue("ShowLegendEntry") >>= bShowLegendEntry); + CPPUNIT_ASSERT(!bShowLegendEntry); + } + + load("/chart2/qa/extras/data/xlsx/", "deleted_legend_entry2.xlsx"); + { + reload("Calc Office Open XML"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPropertySet(xDataSeries, uno::UNO_QUERY_THROW); + bool bShowLegendEntry = true; + CPPUNIT_ASSERT(xPropertySet->getPropertyValue("ShowLegendEntry") >>= bShowLegendEntry); + CPPUNIT_ASSERT(!bShowLegendEntry); + + Reference xChartDoc2 = getChartDocFromSheet(1, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries2(getDataSeriesFromDoc(xChartDoc2, 0)); + CPPUNIT_ASSERT(xDataSeries2.is()); + Reference xPropertySet2(xDataSeries2, uno::UNO_QUERY_THROW); + Sequence deletedLegendEntriesSeq; + CPPUNIT_ASSERT(xPropertySet2->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), deletedLegendEntriesSeq[0]); + } +} + +void Chart2ExportTest::testTdf130225() +{ + load("/chart2/qa/extras/data/docx/", "piechart_deleted_legend_entry.docx"); + reload("Office Open XML Text"); + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPropertySet(xDataSeries, uno::UNO_QUERY_THROW); + Sequence deletedLegendEntriesSeq; + CPPUNIT_ASSERT(xPropertySet->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), deletedLegendEntriesSeq[0]); +} + +void Chart2ExportTest::testTdf59857() +{ + load("/chart2/qa/extras/data/ods/", "tdf59857.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:floor/c:spPr/a:ln/a:noFill", 1); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:floor/c:spPr/a:solidFill/a:srgbClr", "val", "cccccc"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:backWall/c:spPr/a:ln/a:noFill", 0); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:backWall/c:spPr/a:ln/a:solidFill/a:srgbClr", "val", "b3b3b3"); +} + +void Chart2ExportTest::testTdf126076() +{ + load("/chart2/qa/extras/data/xlsx/", "auto_marker_excel10.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open 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']", 0); + // instead of skipping markers + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:marker", 0); +} + +void Chart2ExportTest::testTdf75330() +{ + load("/chart2/qa/extras/data/ods/", "legend_overlay.ods"); + reload("calc8"); + { + uno::Reference xChart2Doc = getChartDocFromSheet(0, mxComponent); + uno::Reference xChartDoc(xChart2Doc, uno::UNO_QUERY); + uno::Reference xLegend = xChartDoc->getLegend(); + Reference xPropertySet(xLegend, uno::UNO_QUERY_THROW); + bool bOverlay = false; + CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Overlay") >>= bOverlay); + CPPUNIT_ASSERT(bOverlay); + } + reload("Calc Office Open XML"); + { + uno::Reference xChart2Doc = getChartDocFromSheet(0, mxComponent); + uno::Reference xChartDoc(xChart2Doc, uno::UNO_QUERY); + uno::Reference xLegend = xChartDoc->getLegend(); + Reference xPropertySet(xLegend, uno::UNO_QUERY_THROW); + bool bOverlay = false; + CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Overlay") >>= bOverlay); + CPPUNIT_ASSERT(bOverlay); + } +} + +void Chart2ExportTest::testTdf127792() +{ + load("/chart2/qa/extras/data/docx/", "MSO_axis_position.docx"); + { + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); + } + { + xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart2", "Office Open XML Text"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "midCat"); + } +} + +void Chart2ExportTest::testTdf131979() +{ + load("/chart2/qa/extras/data/ods/", "tdf131115.ods"); + { + reload("calc8"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference 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); + } + + load("/chart2/qa/extras/data/ods/", "tdf131979.ods"); + { + reload("calc8"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference 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); + } +} + +void Chart2ExportTest::testTdf132076() +{ + { + load("/chart2/qa/extras/data/ods/", "tdf132076.ods"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:numFmt", "formatCode", "dd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:numFmt", "sourceLinked", "0"); + } + { + load("/chart2/qa/extras/data/xlsx/", "tdf132076.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:numFmt", "formatCode", "dd"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:numFmt", "sourceLinked", "0"); + } +} + +void Chart2ExportTest::testTdf125812() +{ + load("/chart2/qa/extras/data/odp/", "ellipticalGradientFill.odp"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart", "Impress MS PowerPoint 2007 XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path", "path", "circle"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect", "l", "50000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect", "t", "49000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect", "r", "50000"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect", "b", "51000"); +} + +void Chart2ExportTest::testTdf133190() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf133190_tdf133191.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "wrap", "none"); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:txPr/a:bodyPr", "wrap", "square"); +} + +void Chart2ExportTest::testTdf133191() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf133190_tdf133191.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "rot", "-4500000"); +} + +void Chart2ExportTest::testTdf132594() +{ + load("/chart2/qa/extras/data/xlsx/", "chart_pie2007.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart","Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:cat", 1); +} + +void Chart2ExportTest::testTdf136267() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf136267.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open 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", "John"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ExportTest); + +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 000000000..dedfda6e1 --- /dev/null +++ b/chart2/qa/extras/chart2geometry.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/. + */ + +#include "charttest.hxx" + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +using uno::Reference; +using beans::XPropertySet; + +class Chart2GeometryTest : public ChartTest, public XmlTestTools +{ +protected: + virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override; + +public: + Chart2GeometryTest() + : ChartTest() + { + } + void testTdf135184RoundLineCap(); + void testTdf135184RoundLineCap2(); + void testTdf135184RoundLineCap3(); + void testTdf135184RoundLineCap4(); + + CPPUNIT_TEST_SUITE(Chart2GeometryTest); + CPPUNIT_TEST(testTdf135184RoundLineCap); + CPPUNIT_TEST(testTdf135184RoundLineCap2); + CPPUNIT_TEST(testTdf135184RoundLineCap3); + CPPUNIT_TEST(testTdf135184RoundLineCap4); + + CPPUNIT_TEST_SUITE_END(); + +protected: + /** + * Given that some problem doesn't affect the result in the importer, we + * test the resulting file directly, by opening the zip file, parsing an + * xml stream, and asserting an XPath expression. This method returns the + * xml stream, so that you can do the asserting. + */ + xmlDocUniquePtr parseExport(const OUString& rDir, const OUString& rFilterFormat); +}; + +namespace +{ +struct CheckForChartName +{ +private: + OUString aDir; + +public: + explicit CheckForChartName(const OUString& rDir) + : aDir(rDir) + { + } + + bool operator()(const OUString& rName) + { + if (!rName.startsWith(aDir)) + return false; + + if (!rName.endsWith(".xml")) + return false; + + return true; + } +}; + +OUString findChartFile(const OUString& rDir, uno::Reference const& xNames) +{ + uno::Sequence aNames = xNames->getElementNames(); + OUString* pElement = std::find_if(aNames.begin(), aNames.end(), CheckForChartName(rDir)); + + CPPUNIT_ASSERT(pElement != aNames.end()); + return *pElement; +} +} + +xmlDocUniquePtr Chart2GeometryTest::parseExport(const OUString& rDir, const OUString& rFilterFormat) +{ + std::shared_ptr pTempFile = save(rFilterFormat); + + // Read the XML stream we're interested in. + uno::Reference xNameAccess + = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), + pTempFile->GetURL()); + uno::Reference xInputStream( + xNameAccess->getByName(findChartFile(rDir, xNameAccess)), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInputStream.is()); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + + return parseXmlStream(pStream.get()); +} + +void Chart2GeometryTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) +{ + static struct + { + char const* pPrefix; + char const* pURI; + } const aNamespaces[] + = { { "w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main" }, + { "v", "urn:schemas-microsoft-com:vml" }, + { "c", "http://schemas.openxmlformats.org/drawingml/2006/chart" }, + { "a", "http://schemas.openxmlformats.org/drawingml/2006/main" }, + { "mc", "http://schemas.openxmlformats.org/markup-compatibility/2006" }, + { "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" }, + { "wpg", "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" }, + { "wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" }, + { "c15", "http://schemas.microsoft.com/office/drawing/2012/chart" }, + { "office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" }, + { "chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" }, + { "style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0" }, + { "svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" }, + { "table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" }, + { "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" }, + { "xlink", "http://www.w3c.org/1999/xlink" }, + { "c15", "http://schemas.microsoft.com/office/drawing/2012/chart" } }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i) + { + xmlXPathRegisterNs(pXmlXPathCtx, reinterpret_cast(aNamespaces[i].pPrefix), + reinterpret_cast(aNamespaces[i].pURI)); + } +} + +static OString OU2O(const OUString& 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. + load("/chart2/qa/extras/data/xlsx/", "tdf135184RoundLineCap.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml", "calc8"); + CPPUNIT_ASSERT(pXmlDoc); + + const OString sStyleStart("/office:document-content/office:automatic-styles"); + const OString sCap("/style:graphic-properties[@svg:stroke-linecap='round']"); + const OString sChartStart("/office:document-content/office:body/office:chart/chart:chart"); + 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. + load("/chart2/qa/extras/data/xlsx/", "tdf135184RoundLineCap2.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml", "calc8"); + CPPUNIT_ASSERT(pXmlDoc); + + const OString sStyleStart("/office:document-content/office:automatic-styles"); + const OString sCap("/style:graphic-properties[@svg:stroke-linecap='round']"); + const OString sChartStart("/office:document-content/office:body/office:chart/chart:chart"); + 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. + load("/chart2/qa/extras/data/xlsx/", "tdf135184RoundLineCap.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + const OString sDash("/c:spPr/a:ln/a:prstDash"); + // chart area + assertXPath(pXmlDoc, "/c:chartSpace" + sDash, "val", "dashDot"); + // data series line + const OString sStart("/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser"); + assertXPath(pXmlDoc, sStart + sDash, "val", "dash"); + // regression-curve (trendline) + assertXPath(pXmlDoc, sStart + "/c:trendline" + sDash, "val", "sysDot"); +} + +void Chart2GeometryTest::testTdf135184RoundLineCap4() +{ + // It tests legend, data series sector and title. + load("/chart2/qa/extras/data/xlsx/", "tdf135184RoundLineCap2.xlsx"); + xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + + const OString sChartStart("/c:chartSpace/c:chart"); + const OString sDash("/c:spPr/a:ln/a:prstDash"); + assertXPath(pXmlDoc, sChartStart + "/c:legend" + sDash, "val", "sysDot"); + const OString sSeries(sChartStart + "/c:plotArea/c:pieChart/c:ser/c:dPt[3]"); + assertXPath(pXmlDoc, sSeries + sDash, "val", "dash"); + assertXPath(pXmlDoc, sChartStart + "/c:title" + sDash, "val", "dashDot"); +} + +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 000000000..8fd7ca7a2 --- /dev/null +++ b/chart2/qa/extras/chart2import.cxx @@ -0,0 +1,2603 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class Chart2ImportTest : public ChartTest +{ +public: + void Fdo60083(); + void testSteppedLines(); + void testErrorBarRange(); + void testErrorBarFormatting(); + void testODSChartSeries(); + void testXLSXChartSeries(); + void testXLSChartSeries(); + void testODTChartSeries(); + void testDOCChartSeries(); + void testDOCXChartSeries(); + void testDOCXChartEmptySeries(); + void testDOCXChartValuesSize(); + void testPPTXChartSeries(); + void testPPTXSparseChartSeries(); + /** + * 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). + */ + void testPPTXHiddenDataSeries(); + void testPPTXPercentageNumberFormats(); + void testPieChartLabelsNumFormat(); + void testPPTXStackedNonStackedYAxis(); + void testPPTChartSeries(); + void testODPChartSeries(); + void testBnc864396(); + void testBnc882383(); + void testTransparancyGradientValue(); + void testBnc889755(); + void testSimpleStrictXLSX(); + void testDelayedCellImport(); // chart range referencing content on later sheets + void testFlatODSStackedColumnChart(); + void testFdo78080(); + void testFdo54361(); + void testFdo54361_1(); + void testTdf86624(); // manually placed legends + void testTdf105517(); + void testTdf106217(); + void testTdf108021(); + void testTdf100084(); + void testTdf124817(); + void testTdf126033(); + void testAutoBackgroundXLSX(); + void testAutoChartAreaBorderPropXLSX(); + void testChartAreaStyleBackgroundXLSX(); + void testChartHatchFillXLSX(); + void testAxisTextRotationXLSX(); + // void testTextCanOverlapXLSX(); // TODO : temporarily disabled. + void testTextBreakXLSX(); + void testNumberFormatsXLSX(); + void testNumberFormatsDOCX(); + void testPercentageNumberFormatsDOCX(); + + void testTransparentBackground(OUString const & filename); + + // below are OOXML default value tests for cases + // where we fixed the handling of MSO 2007 vs OOXML + void testAutoTitleDelDefaultValue2007XLSX(); + void testAutoTitleDelDefaultValue2013XLSX(); + void testDispBlanksAsDefaultValue2007XLSX(); + void testDispBlanksAsDefaultValue2013XLSX(); + + void testSmoothDefaultValue2007XLSX(); + void testSmoothDefaultValue2013XLSX(); + void testTrendlineDefaultValue2007XLSX(); + void testTrendlineDefaultValue2013XLSX(); + void testVaryColorDefaultValues2007XLSX(); + void testVaryColorDefaultValues2013XLSX(); + void testPlotVisOnlyDefaultValue2013XLSX(); + void testRAngAxDefaultValue2013XLSX(); + void testMajorTickMarksDefaultValue2013XLSX(); + void testMinorTickMarksDefaultValue2013XLSX(); + + void testAxisTitleDefaultRotationXLSX(); + void testSecondaryAxisTitleDefaultRotationXLSX(); + void testAxisTitleRotationXLSX(); + void testAxisTitlePositionDOCX(); + void testCombinedChartAttachedAxisXLSX(); + + void testTdf90510(); // Pie chart label placement settings(XLS) + void testTdf109858(); // Pie chart label placement settings(XLSX) + void testTdf130105(); + + void testTdf111173(); + void testTdf122226(); + + void testInternalDataProvider(); + + void testTdf115107(); // import complex data point labels + void testTdf115107_2(); // import complex data point labels in cobo charts with multiple data series + + void testTdf116163(); + + void testTdf48041(); + + void testTdf121205(); + + void testTdf114179(); + void testTdf124243(); + void testTdf127393(); + void testTdf128733(); + void testTdf128432(); + void testTdf128627(); + void testTdf128634(); + void testTdf130657(); + void testDeletedDataLabel(); + void testDataPointInheritedColorDOCX(); + void testExternalStrRefsXLSX(); + void testSourceNumberFormatComplexCategoriesXLS(); + void testSimpleCategoryAxis(); + void testMultilevelCategoryAxis(); + void testXaxisValues(); + void testTdf123504(); + void testTdf122765(); + void testTdf123206CustomLabelField(); + void testTdf125444PercentageCustomLabel(); + void testDataPointLabelCustomPos(); + void testTdf130032(); + void testTdf119138MissingAutoTitleDeleted(); + void testStockChartShiftedCategoryPosition(); + void testTdf133376(); + void testTdf134225(); + void testTdf91250(); + + CPPUNIT_TEST_SUITE(Chart2ImportTest); + CPPUNIT_TEST(Fdo60083); + CPPUNIT_TEST(testSteppedLines); + CPPUNIT_TEST(testErrorBarRange); + CPPUNIT_TEST(testErrorBarFormatting); + CPPUNIT_TEST(testODSChartSeries); + CPPUNIT_TEST(testXLSXChartSeries); + CPPUNIT_TEST(testXLSChartSeries); + CPPUNIT_TEST(testODTChartSeries); + CPPUNIT_TEST(testDOCChartSeries); + CPPUNIT_TEST(testDOCXChartSeries); + CPPUNIT_TEST(testDOCXChartEmptySeries); + CPPUNIT_TEST(testDOCXChartValuesSize); + CPPUNIT_TEST(testPPTChartSeries); + CPPUNIT_TEST(testPPTXChartSeries); + CPPUNIT_TEST(testPPTXSparseChartSeries); + CPPUNIT_TEST(testPPTXHiddenDataSeries); + CPPUNIT_TEST(testPPTXPercentageNumberFormats); + CPPUNIT_TEST(testPieChartLabelsNumFormat); + CPPUNIT_TEST(testPPTXStackedNonStackedYAxis); + CPPUNIT_TEST(testODPChartSeries); + CPPUNIT_TEST(testBnc864396); + CPPUNIT_TEST(testBnc882383); + CPPUNIT_TEST(testTransparancyGradientValue); + CPPUNIT_TEST(testBnc889755); + CPPUNIT_TEST(testSimpleStrictXLSX); + CPPUNIT_TEST(testDelayedCellImport); + CPPUNIT_TEST(testFlatODSStackedColumnChart); + CPPUNIT_TEST(testFdo78080); + CPPUNIT_TEST(testFdo54361); + CPPUNIT_TEST(testFdo54361_1); + CPPUNIT_TEST(testTdf86624); + CPPUNIT_TEST(testTdf105517); + CPPUNIT_TEST(testTdf106217); + CPPUNIT_TEST(testTdf108021); + CPPUNIT_TEST(testTdf100084); + CPPUNIT_TEST(testTdf124817); + CPPUNIT_TEST(testTdf126033); + CPPUNIT_TEST(testAutoBackgroundXLSX); + CPPUNIT_TEST(testAutoChartAreaBorderPropXLSX); + CPPUNIT_TEST(testChartAreaStyleBackgroundXLSX); + CPPUNIT_TEST(testChartHatchFillXLSX); + CPPUNIT_TEST(testAxisTextRotationXLSX); + // CPPUNIT_TEST(testTextCanOverlapXLSX); // TODO : temporarily disabled. + CPPUNIT_TEST(testTextBreakXLSX); + CPPUNIT_TEST(testNumberFormatsXLSX); + CPPUNIT_TEST(testNumberFormatsDOCX); + CPPUNIT_TEST(testPercentageNumberFormatsDOCX); + CPPUNIT_TEST(testAutoTitleDelDefaultValue2007XLSX); + CPPUNIT_TEST(testAutoTitleDelDefaultValue2013XLSX); + CPPUNIT_TEST(testDispBlanksAsDefaultValue2007XLSX); + CPPUNIT_TEST(testDispBlanksAsDefaultValue2013XLSX); + CPPUNIT_TEST(testSmoothDefaultValue2007XLSX); + CPPUNIT_TEST(testSmoothDefaultValue2013XLSX); + CPPUNIT_TEST(testTrendlineDefaultValue2007XLSX); + CPPUNIT_TEST(testTrendlineDefaultValue2013XLSX); + CPPUNIT_TEST(testVaryColorDefaultValues2007XLSX); + CPPUNIT_TEST(testVaryColorDefaultValues2013XLSX); + CPPUNIT_TEST(testPlotVisOnlyDefaultValue2013XLSX); + CPPUNIT_TEST(testRAngAxDefaultValue2013XLSX); + CPPUNIT_TEST(testMajorTickMarksDefaultValue2013XLSX); + CPPUNIT_TEST(testMinorTickMarksDefaultValue2013XLSX); + CPPUNIT_TEST(testAxisTitleDefaultRotationXLSX); + CPPUNIT_TEST(testSecondaryAxisTitleDefaultRotationXLSX); + CPPUNIT_TEST(testAxisTitleRotationXLSX); + CPPUNIT_TEST(testAxisTitlePositionDOCX); + CPPUNIT_TEST(testCombinedChartAttachedAxisXLSX); + CPPUNIT_TEST(testTdf90510); + CPPUNIT_TEST(testTdf109858); + CPPUNIT_TEST(testTdf130105); + CPPUNIT_TEST(testTdf111173); + CPPUNIT_TEST(testTdf122226); + + CPPUNIT_TEST(testInternalDataProvider); + + CPPUNIT_TEST(testTdf115107); + CPPUNIT_TEST(testTdf115107_2); + + CPPUNIT_TEST(testTdf116163); + + CPPUNIT_TEST(testTdf48041); + + CPPUNIT_TEST(testTdf121205); + + CPPUNIT_TEST(testTdf114179); + CPPUNIT_TEST(testTdf124243); + CPPUNIT_TEST(testTdf127393); + CPPUNIT_TEST(testTdf128733); + CPPUNIT_TEST(testTdf128432); + CPPUNIT_TEST(testTdf128627); + CPPUNIT_TEST(testTdf128634); + CPPUNIT_TEST(testTdf130657); + CPPUNIT_TEST(testDeletedDataLabel); + CPPUNIT_TEST(testDataPointInheritedColorDOCX); + CPPUNIT_TEST(testExternalStrRefsXLSX); + CPPUNIT_TEST(testSourceNumberFormatComplexCategoriesXLS); + CPPUNIT_TEST(testSimpleCategoryAxis); + CPPUNIT_TEST(testMultilevelCategoryAxis); + CPPUNIT_TEST(testXaxisValues); + CPPUNIT_TEST(testTdf123504); + CPPUNIT_TEST(testTdf122765); + CPPUNIT_TEST(testTdf123206CustomLabelField); + CPPUNIT_TEST(testTdf125444PercentageCustomLabel); + CPPUNIT_TEST(testDataPointLabelCustomPos); + CPPUNIT_TEST(testTdf130032); + CPPUNIT_TEST(testTdf119138MissingAutoTitleDeleted); + CPPUNIT_TEST(testStockChartShiftedCategoryPosition); + CPPUNIT_TEST(testTdf133376); + CPPUNIT_TEST(testTdf134225); + CPPUNIT_TEST(testTdf91250); + + CPPUNIT_TEST_SUITE_END(); + +private: + +}; + +static uno::Reference +getShapeByName(const uno::Reference& rShapes, const OUString& rName, + const std::function&)>& pCondition + = nullptr) +{ + for (sal_Int32 i = 0; i < rShapes->getCount(); ++i) + { + uno::Reference xShapes(rShapes->getByIndex(i), uno::UNO_QUERY); + if (xShapes.is()) + { + uno::Reference xRet = getShapeByName(xShapes, rName, pCondition); + if (xRet.is()) + return xRet; + } + uno::Reference xNamedShape(rShapes->getByIndex(i), uno::UNO_QUERY); + if (xNamedShape->getName() == rName) + { + uno::Reference xShape(xNamedShape, uno::UNO_QUERY); + if (pCondition == nullptr || pCondition(xShape)) + return xShape; + } + } + return uno::Reference(); +} + +// error bar import +// split method up into smaller chunks for more detailed tests +void Chart2ImportTest::Fdo60083() +{ + load("/chart2/qa/extras/data/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()); +} + +void Chart2ImportTest::testErrorBarRange() +{ + load("/chart2/qa/extras/data/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); +} + +void Chart2ImportTest::testErrorBarFormatting() +{ + load("/chart2/qa/extras/data/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 +void 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 + }; + + load("/chart2/qa/extras/data/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; +} + +void Chart2ImportTest::testODSChartSeries() +{ + load("/chart2/qa/extras/data/ods/", "chart.ods"); + uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 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]); + +} + +void Chart2ImportTest::testXLSXChartSeries() +{ + load("/chart2/qa/extras/data/xlsx/", "chart.xlsx"); + uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 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]); + +} + +void Chart2ImportTest::testXLSChartSeries() +{ + load("/chart2/qa/extras/data/xls/", "chart.xls"); + uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 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]); + +} + +void Chart2ImportTest::testODTChartSeries() +{ + load("/chart2/qa/extras/data/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]); + +} + +void Chart2ImportTest::testDOCChartSeries() +{ + load("/chart2/qa/extras/data/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]); +} + +void Chart2ImportTest::testDOCXChartSeries() +{ + load("/chart2/qa/extras/data/docx/", "chart.docx"); + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 1"), aLabels[0][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 2"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[2][0].get()); +} + +void Chart2ImportTest::testDOCXChartEmptySeries() +{ + load("/chart2/qa/extras/data/docx/", "tdf125337.docx"); + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("1. dataseries"), aLabels[0][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("2. dataseries"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), aLabels[2][0].get()); + + //test chart series sparse data for docx + std::vector > 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])); +} + +void Chart2ImportTest::testDOCXChartValuesSize() +{ + load( "/chart2/qa/extras/data/docx/", "bubblechart.docx" ); + Reference xChartDoc( getChartDocFromWriter(0), uno::UNO_QUERY ); + CPPUNIT_ASSERT( xChartDoc.is() ); + + uno::Reference< chart::XChartDataArray > xDataArray( xChartDoc->getDataProvider(), UNO_QUERY_THROW ); + Sequence 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(3), aColumnDesc.getLength() ); + Sequence> aData = xDataArray->getData(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "There must be exactly 3 data points", static_cast(3), aData.getLength() ); + + std::vector> 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 ); +} + +void Chart2ImportTest::testPPTChartSeries() +{ + //test chart series names for ppt + uno::Sequence < OUString > seriesList = getImpressChartColumnDescriptions("/chart2/qa/extras/data/ppt/", "chart.ppt"); + + CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]); + CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]); + CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]); + +} + +void Chart2ImportTest::testPPTXChartSeries() +{ + //test chart series names for pptx + load("/chart2/qa/extras/data/pptx/", "chart.pptx"); + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), aLabels[0][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), aLabels[1][0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), aLabels[2][0].get()); +} + +void Chart2ImportTest::testPPTXSparseChartSeries() +{ + //test chart series sparse data for pptx + load("/chart2/qa/extras/data/pptx/", "sparse-chart.pptx"); + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + std::vector > 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]); +} + +void Chart2ImportTest::testPPTXHiddenDataSeries() +{ + load("/chart2/qa/extras/data/pptx/", "stacked-bar-chart-hidden-series.pptx"); + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + // "Automatic" chart background fill in pptx should be loaded as no fill. + Reference xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in pptx should be loaded as no fill (transparent).", + drawing::FillStyle_NONE, eStyle); + + Reference xCT = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xCT.is()); + + // There should be only one data series present. + std::vector > aLabels = getDataSeriesLabelsFromChartType(xCT); + CPPUNIT_ASSERT_EQUAL(size_t(1), aLabels.size()); + CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[0][0].get()); + + // Test the internal data. + CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider()); + + Reference xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInternalProvider.is()); + + Reference xDescAccess(xInternalProvider, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDescAccess.is()); + + // Get the category labels. + Sequence > 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]); +} + +void Chart2ImportTest::testPPTXPercentageNumberFormats() +{ + load("/chart2/qa/extras/data/pptx/", "percentage-number-formats.pptx"); + + // 1st chart + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference 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 xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0); + CPPUNIT_ASSERT(xYAxis.is()); + + Reference 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 && !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)); +} + +void Chart2ImportTest::testPieChartLabelsNumFormat() +{ + load("/chart2/qa/extras/data/xlsx/", "tdfPieNumFormat.xlsx"); + uno::Reference< chart::XChartDocument > xChartDoc(getChartCompFromSheet(0, mxComponent), UNO_QUERY_THROW); + CPPUNIT_ASSERT(xChartDoc.is()); + // test data point labels format + Reference xDataPointPropSet(xChartDoc->getDiagram()->getDataPointProperties(0, 0), uno::UNO_SET_THROW); + chart2::DataPointLabel aLabel; + xDataPointPropSet->getPropertyValue("Label") >>= aLabel; + CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber); +} + +void Chart2ImportTest::testPPTXStackedNonStackedYAxis() +{ + load("/chart2/qa/extras/data/pptx/", "stacked-non-stacked-mix-y-axis.pptx"); + + // 1st chart is a normal stacked column. + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + OUString aTitle = getTitleString(xTitled); + CPPUNIT_ASSERT_EQUAL(OUString("Stacked"), aTitle); + + // Get the Y-axis. + Reference 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)); +} + +void Chart2ImportTest::testODPChartSeries() +{ + //test chart series names for odp + uno::Sequence < OUString > seriesList = getImpressChartColumnDescriptions("/chart2/qa/extras/data/odp/", "chart.odp"); + CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]); + CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]); + CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]); + +} + +void Chart2ImportTest::testBnc864396() +{ + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromImpress("/chart2/qa/extras/data/pptx/", "bnc864396.pptx"), 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]); + } +} + +void Chart2ImportTest::testBnc889755() +{ + load("/chart2/qa/extras/data/pptx/", "bnc889755.pptx"); + uno::Reference xChartDoc(getChartDocFromDrawImpress(0, 6), 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(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), aRowLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("Oct-12"), aRowLabels[0]); + CPPUNIT_ASSERT_EQUAL(OUString("Nov-12"), aRowLabels[1]); + CPPUNIT_ASSERT_EQUAL(OUString("Dec-12"), aRowLabels[2]); + CPPUNIT_ASSERT_EQUAL(OUString("Jan-13"), aRowLabels[3]); + CPPUNIT_ASSERT_EQUAL(OUString("Feb-13"), aRowLabels[4]); + CPPUNIT_ASSERT_EQUAL(OUString("Mar-13"), aRowLabels[5]); + CPPUNIT_ASSERT_EQUAL(OUString("Apr-13"), aRowLabels[6]); + CPPUNIT_ASSERT_EQUAL(OUString("May-13"), aRowLabels[7]); + CPPUNIT_ASSERT_EQUAL(OUString("Jun-13"), aRowLabels[8]); + CPPUNIT_ASSERT_EQUAL(OUString("Jul-13"), aRowLabels[9]); + CPPUNIT_ASSERT_EQUAL(OUString("Aug-13"), aRowLabels[10]); + CPPUNIT_ASSERT_EQUAL(OUString("Sep-13"), aRowLabels[11]); + CPPUNIT_ASSERT_EQUAL(OUString("Oct-13"), aRowLabels[12]); + CPPUNIT_ASSERT_EQUAL(OUString("Nov-13"), aRowLabels[13]); + CPPUNIT_ASSERT_EQUAL(OUString("Dec-13"), aRowLabels[14]); + CPPUNIT_ASSERT_EQUAL(OUString("Jan-14"), aRowLabels[15]); +} + +void Chart2ImportTest::testBnc882383() +{ + load("/chart2/qa/extras/data/pptx/", "bnc882383.pptx"); + uno::Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY_THROW); + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + OUString sGradientName; + xPropertySet->getPropertyValue("GradientName") >>= sGradientName; + CPPUNIT_ASSERT(!sGradientName.isEmpty()); +} + +void Chart2ImportTest::testTransparancyGradientValue() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf128732.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + OUString sTranspGradientName; + xPropertySet->getPropertyValue("FillTransparenceGradientName") >>= sTranspGradientName; + CPPUNIT_ASSERT(!sTranspGradientName.isEmpty()); + + awt::Gradient 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); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3355443), aTransparenceGradient.EndColor); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5000268), aTransparenceGradient.StartColor); +} + +void Chart2ImportTest::testSimpleStrictXLSX() +{ + load("/chart2/qa/extras/data/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()); + +} + +void Chart2ImportTest::testDelayedCellImport() +{ + load("/chart2/qa/extras/data/xlsx/", "fdo70609.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent ); + Reference< chart2::data::XDataSequence > xDataSeq = + getDataSequenceFromDocByRole(xChartDoc, "values-x"); + + OUString aRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_ASSERT_EQUAL(OUString("$Sheet2.$C$5:$C$9"), aRange); +} + +void Chart2ImportTest::testFlatODSStackedColumnChart() +{ + load("/chart2/qa/extras/data/fods/", "stacked-column-chart.fods"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xDSCont(xChartType, UNO_QUERY); + CPPUNIT_ASSERT(xDSCont.is()); + Sequence > aSeriesSeq = xDSCont->getDataSeries(); + + // The stacked column chart should consist of 5 data series. + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aSeriesSeq.getLength()); +} + +void Chart2ImportTest::testFdo78080() +{ + load("/chart2/qa/extras/data/xlsx/", "fdo78080.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(!xTitle.is()); +} + +void Chart2ImportTest::testTdf86624() +{ + load("/chart2/qa/extras/data/ods/", "tdf86624.ods"); + uno::Reference< chart2::XChartDocument > xChart2Doc = getChartDocFromSheet(0, mxComponent); + uno::Reference< chart::XChartDocument > xChartDoc (xChart2Doc, uno::UNO_QUERY); + uno::Reference 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 +} + +void Chart2ImportTest::testTdf105517() +{ + load("/chart2/qa/extras/data/pptx/", "tdf105517.pptx"); + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCoordContainer(xChartDoc->getFirstDiagram(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xCoordContainer.is()); + Reference xChartTypeContainer(xCoordContainer->getCoordinateSystems()[0], uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartTypeContainer.is()); + Reference xDSContainer(xChartTypeContainer->getChartTypes()[0], uno::UNO_QUERY); + CPPUNIT_ASSERT(xDSContainer.is()); + Reference xPropSet1(xDSContainer->getDataSeries()[0], uno::UNO_QUERY); + CPPUNIT_ASSERT(xPropSet1.is()); + + long lineColor; + xPropSet1->getPropertyValue("Color") >>= lineColor; + // incorrect line color was 0x4a7ebb due to not handling themeOverride + CPPUNIT_ASSERT_EQUAL(long(0xeaa700), lineColor); + + Reference xPropSet2(xDSContainer->getDataSeries()[1], uno::UNO_QUERY); + CPPUNIT_ASSERT(xPropSet2.is()); + + xPropSet2->getPropertyValue("Color") >>= lineColor; + // incorrect line color was 0x98b855 + CPPUNIT_ASSERT_EQUAL(long(0x1e69a8), lineColor); +} + +void Chart2ImportTest::testTdf106217() +{ + load("/chart2/qa/extras/data/pptx/", "tdf106217.pptx"); + uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromDrawImpress(0, 0); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xCircle(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xCircle.is()); + + uno::Reference 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); +} + +void Chart2ImportTest::testTdf108021() +{ + // Tdf108021 : To check TextBreak value is true. + load("/chart2/qa/extras/data/ods/", "tdf108021.ods"); + uno::Reference< chart::XDiagram > mxDiagram; + uno::Reference< beans::XPropertySet > xAxisProp; + bool bTextBreak = false; + uno::Reference< chart::XChartDocument > xChartDoc ( getChartCompFromSheet( 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); +} + +void Chart2ImportTest::testTdf100084() +{ + // The test file was created with IBM Cognos, make sure there is a diagram. + load("/chart2/qa/extras/data/xlsx/", "tdf100084.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("There should be a Diagram.", xDiagram.is()); +} + +void Chart2ImportTest::testTdf124817() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf124817.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + uno::Reference xDataSeries; + chart2::Symbol aSymblProp; + + // Check the symbol of data series 1 (marker style none) + xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference xPropSet_0(xDataSeries, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT((xPropSet_0->getPropertyValue("Symbol") >>= aSymblProp) && (aSymblProp.Style == chart2::SymbolStyle_NONE)); + + // Check the symbol of data series 2 (marker style square) + xDataSeries = getDataSeriesFromDoc(xChartDoc, 1); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference xPropSet_1(xDataSeries, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT((xPropSet_1->getPropertyValue("Symbol") >>= aSymblProp) && (aSymblProp.FillColor == static_cast(0xED7D31))); + + // Check the symbol of data series 3 (marker style diagonal cross) + xDataSeries = getDataSeriesFromDoc(xChartDoc, 2); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference xPropSet_2(xDataSeries, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT((xPropSet_2->getPropertyValue("Symbol") >>= aSymblProp) && (aSymblProp.BorderColor == static_cast(0xFF0000))); +} + +void Chart2ImportTest::testTdf126033() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf126033.xlsx"); + Reference 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 xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference 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(176), aSymblProp.Size.Width); + CPPUNIT_ASSERT_EQUAL(static_cast(176), aSymblProp.Size.Height); +} + +void Chart2ImportTest::testTransparentBackground(OUString const & filename) +{ + load("/chart2/qa/extras/data/xlsx/", 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 +void Chart2ImportTest::testFdo54361() +{ + testTransparentBackground("fdo54361.xlsx"); +} +void Chart2ImportTest::testFdo54361_1() +{ + testTransparentBackground("fdo54361-1.xlsx"); +} + +void Chart2ImportTest::testAutoBackgroundXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "chart-auto-background.xlsx"); + uno::Reference 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 xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get(); + sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get(); + 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. +} + +void Chart2ImportTest::testAutoChartAreaBorderPropXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "chart-area-style-border.xlsx"); + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + // Test "Automatic" chartarea border style/color/width. + Reference xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::LineStyle eStyle = xPropSet->getPropertyValue("LineStyle").get(); + sal_Int32 nColor = xPropSet->getPropertyValue("LineColor").get(); + sal_Int32 nWidth = xPropSet->getPropertyValue("LineWidth").get(); + 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); +} + +void Chart2ImportTest::testChartAreaStyleBackgroundXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "chart-area-style-background.xlsx"); + uno::Reference 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 xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get(); + sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get(); + 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); +} + +void Chart2ImportTest::testChartHatchFillXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "chart-hatch-fill.xlsx"); + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + // Check the chart background FillStyle is HATCH + Reference xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get(); + + 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); + + sal_Int32 nBackgroundColor; + xPropSet->getPropertyValue("FillColor") >>= nBackgroundColor; + CPPUNIT_ASSERT_EQUAL(static_cast(0xFFFFFF), nBackgroundColor); + + // Check the datapoint has HatchName value + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference 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(0x00B050), nBackgroundColorofDatapoint); +} + +void Chart2ImportTest::testAxisTextRotationXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "axis-label-rotation.xlsx"); + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xYAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xYAxis.is()); + + Reference 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); +} + +/* TODO : temporarily disabled. +void Chart2ImportTest::testTextCanOverlapXLSX() +{ + // fdo#84647 : To check textoverlap value is imported correctly. + load("/chart2/qa/extras/data/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, 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; + // Expected value of 'TextCanOverlap' is true + CPPUNIT_ASSERT(bTextCanOverlap); +} +*/ + +void Chart2ImportTest::testTextBreakXLSX() +{ + // tdf#122091: To check textbreak value is true in case of 0° degree of Axis label rotation. + load("/chart2/qa/extras/data/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, 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); +} + +void Chart2ImportTest::testNumberFormatsXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "number-formats.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + uno::Reference 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 && 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 && 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 && bLinkNumberFormatToSource); +} + +void Chart2ImportTest::testNumberFormatsDOCX() +{ + load("/chart2/qa/extras/data/docx/", "tdf132174.docx"); + { + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + css::uno::Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + uno::Reference 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); + } + + load("/chart2/qa/extras/data/docx/", "tdf136650.docx"); + { + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + css::uno::Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference 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); + } +} + +void Chart2ImportTest::testPercentageNumberFormatsDOCX() +{ + load("/chart2/qa/extras/data/docx/", "tdf133632.docx"); + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + css::uno::Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + uno::Reference 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 && bLinkNumberFormatToSource); +} + +void Chart2ImportTest::testAutoTitleDelDefaultValue2007XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "autotitledel_2007.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + OUString aTitle = getTitleString(xTitled); + CPPUNIT_ASSERT_MESSAGE("autoTitleDel default value is false in MSO 2007 documents", + !aTitle.isEmpty()); +} + +void Chart2ImportTest::testAutoTitleDelDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "autotitledel_2013.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + uno::Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT_MESSAGE("autoTitleDel default value is true in the OOXML spec", + !xTitle.is()); +} + +void Chart2ImportTest::testDispBlanksAsDefaultValue2007XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "dispBlanksAs_2007.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference 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); +} + +void Chart2ImportTest::testDispBlanksAsDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "dispBlanksAs_2013.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference 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); +} + +void Chart2ImportTest::testSmoothDefaultValue2007XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "smoothed_series2007.xlsx"); + Reference 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); +} + +void Chart2ImportTest::testSmoothDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "smoothed_series.xlsx"); + Reference 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); +} + +void Chart2ImportTest::testTrendlineDefaultValue2007XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "trendline2007.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xRegressionCurveContainer(xDataSeries, UNO_QUERY_THROW); + Sequence< Reference > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength()); + + Reference xCurve = xRegressionCurveSequence[0]; + + Reference 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); +} + +void Chart2ImportTest::testTrendlineDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "trendline.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xRegressionCurveContainer(xDataSeries, UNO_QUERY_THROW); + Sequence< Reference > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength()); + + Reference xCurve = xRegressionCurveSequence[0]; + + Reference 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); +} + +void Chart2ImportTest::testVaryColorDefaultValues2007XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "vary_color2007.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPropSet(xDataSeries, uno::UNO_QUERY_THROW); + uno::Any aAny = xPropSet->getPropertyValue("VaryColorsByPoint"); + bool bVaryColor = true; + CPPUNIT_ASSERT(aAny >>= bVaryColor); + CPPUNIT_ASSERT(!bVaryColor); +} + +void Chart2ImportTest::testVaryColorDefaultValues2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "vary_color.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPropSet(xDataSeries, uno::UNO_QUERY_THROW); + uno::Any aAny = xPropSet->getPropertyValue("VaryColorsByPoint"); + bool bVaryColor = false; + CPPUNIT_ASSERT(aAny >>= bVaryColor); + CPPUNIT_ASSERT(bVaryColor); +} + +void Chart2ImportTest::testPlotVisOnlyDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "plotVisOnly.xlsx"); + uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW); + Reference 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); +} + +void Chart2ImportTest::testRAngAxDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "rAngAx.xlsx"); + uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW); + Reference 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); +} + +void Chart2ImportTest::testMajorTickMarksDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "majorTickMark.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + Reference 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); +} + +void Chart2ImportTest::testMinorTickMarksDefaultValue2013XLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "minorTickMark.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + Reference 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); +} + +void Chart2ImportTest::testAxisTitleDefaultRotationXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "axis_title_default_rotation.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + Reference xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0); + CPPUNIT_ASSERT(xYAxis.is()); + Reference xTitled(xYAxis, uno::UNO_QUERY_THROW); + Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(xTitle.is()); + Reference 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); +} + +void Chart2ImportTest::testSecondaryAxisTitleDefaultRotationXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "secondary_axis_title_default_rotation.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + Reference xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 1); + CPPUNIT_ASSERT(xYAxis.is()); + Reference xTitled(xYAxis, uno::UNO_QUERY_THROW); + Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(xTitle.is()); + Reference 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); +} + +void Chart2ImportTest::testAxisTitleRotationXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "axis_title_rotated.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + { + Reference xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0); + CPPUNIT_ASSERT(xYAxis.is()); + Reference xTitled(xYAxis, uno::UNO_QUERY_THROW); + Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(xTitle.is()); + Reference 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 xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 1); + CPPUNIT_ASSERT(xYAxis.is()); + Reference xTitled(xYAxis, uno::UNO_QUERY_THROW); + Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(xTitle.is()); + Reference 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); + } + +} + +void Chart2ImportTest::testAxisTitlePositionDOCX() +{ + load("/chart2/qa/extras/data/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); +} + +void Chart2ImportTest::testCombinedChartAttachedAxisXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "testCombinedChartAxis.xlsx"); + Reference< chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent); + // First series + Reference xSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xSeries.is()); + + Reference 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); +} + +void Chart2ImportTest::testInternalDataProvider() { + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromImpress("/chart2/qa/extras/data/odp/", "chart.odp"), uno::UNO_QUERY_THROW); + const uno::Reference< chart2::data::XDataProvider >& rxDataProvider = xChartDoc->getDataProvider(); + + // Parse 42 array + Reference xDataSeq = rxDataProvider->createDataSequenceByValueArray("values-y", "{42;42;42;42}"); + Sequence 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(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(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(xSequence[1].getValue())) ); + CPPUNIT_ASSERT( std::isnan( *static_cast(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]); +} + +void Chart2ImportTest::testTdf90510() +{ + load("/chart2/qa/extras/data/xls/", "piechart_outside.xls"); + uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); + Reference 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 ); +} + +void Chart2ImportTest::testTdf109858() +{ + load("/chart2/qa/extras/data/xlsx/", "piechart_outside.xlsx"); + uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); + + // test data point labels position + Reference 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::AVOID_OVERLAP, nLabelPlacement ); + + // test data series label position + Reference 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 ); +} + +void Chart2ImportTest::testTdf130105() +{ + load("/chart2/qa/extras/data/xlsx/", "barchart_outend.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference 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); +} + +void Chart2ImportTest::testTdf111173() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf111173.xlsx"); + uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); +} + +void Chart2ImportTest::testTdf122226() +{ + load( "/chart2/qa/extras/data/docx/", "testTdf122226.docx" ); + uno::Reference< chart2::XChartDocument > xChartDoc ( getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT( xChartDoc.is() ); + + css::uno::Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + uno::Reference 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 ); +} + +void Chart2ImportTest::testTdf115107() +{ + load("/chart2/qa/extras/data/pptx/", "tdf115107.pptx"); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + float nFontSize; + sal_Int64 nFontColor; + sal_Int32 nCharUnderline; + uno::Reference xPropertySet; + uno::Sequence> aFields; + + // 1 + xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(16), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(13), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(12), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(0xa9d18e), nFontColor); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nCharUnderline); + + // 3 + xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(" getString()); +} + +void Chart2ImportTest::testTdf115107_2() +{ + load("/chart2/qa/extras/data/pptx/", "tdf115107-2.pptx"); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + float nFontSize; + sal_Int64 nFontColor; + uno::Reference xPropertySet; + uno::Sequence> aFields; + + // First series + xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields; + CPPUNIT_ASSERT_EQUAL(static_cast(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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(18), nFontSize); + CPPUNIT_ASSERT_EQUAL(static_cast(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()); + +} + +void Chart2ImportTest::testTdf116163() +{ + load("/chart2/qa/extras/data/pptx/", "tdf116163.pptx"); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xHAxis.is()); + + chart2::ScaleData aScaleData = xHAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xLabeledDataSequence = aScaleData.Categories; + CPPUNIT_ASSERT(xLabeledDataSequence.is()); + + Reference xDataSequence = xLabeledDataSequence->getValues(); + CPPUNIT_ASSERT(xDataSequence.is()); + + Reference xTextualDataSequence(xDataSequence, uno::UNO_QUERY); + CPPUNIT_ASSERT(xTextualDataSequence.is()); + + std::vector aCategories; + Sequence 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 xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const OUString sXAxisName = "CID/D=0:CS=0:Axis=0,0"; + uno::Reference xXAxis = getShapeByName(xShapes, sXAxisName, + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference& rXShape) -> bool + { + uno::Reference xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference 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 xIndexAccess(xXAxis, UNO_QUERY_THROW); + + // Check text + uno::Reference xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Aaaa"), xLabel0->getString()); + uno::Reference 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 xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Ccc"), xLabel2->getString()); + uno::Reference xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Dddd..."), xLabel3->getString()); +} + +void Chart2ImportTest::testTdf48041() +{ + load("/chart2/qa/extras/data/pptx/", "tdf48041.pptx"); + + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference 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 xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const OUString sYAxisName = "CID/D=0:CS=0:Axis=1,0"; // Y Axis + uno::Reference xYAxisShape = getShapeByName(xShapes, sYAxisName, + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference& rXShape) -> bool + { + uno::Reference xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference 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 xIndexAccess(xYAxisShape, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(static_cast(6), xIndexAccess->getCount()); + + // Check text + uno::Reference xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("0"), xLabel0->getString()); + uno::Reference xLabel1(xIndexAccess->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("1"), xLabel1->getString()); + uno::Reference xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("2"), xLabel2->getString()); + uno::Reference xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("3"), xLabel3->getString()); + uno::Reference xLabel4(xIndexAccess->getByIndex(4), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("4"), xLabel4->getString()); + uno::Reference xLabel5(xIndexAccess->getByIndex(5), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("5"), xLabel5->getString()); +} + +void Chart2ImportTest::testTdf121205() +{ + load("/chart2/qa/extras/data/pptx/", "tdf121205.pptx"); + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + + uno::Reference 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); +} + +void Chart2ImportTest::testTdf114179() +{ + load( "/chart2/qa/extras/data/docx/", "testTdf114179.docx" ); + uno::Reference< chart2::XChartDocument > xChartDoc ( getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT( xChartDoc.is() ); + css::uno::Reference 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); +} + +void Chart2ImportTest::testTdf124243() +{ + load("/chart2/qa/extras/data/docx/", "tdf124243.docx"); + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + Reference 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); +} + +void Chart2ImportTest::testTdf127393() +{ + load("/chart2/qa/extras/data/pptx/", "tdf127393.pptx"); + + // 1st chart + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference 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); +} + +void Chart2ImportTest::testTdf128733() +{ + load("/chart2/qa/extras/data/odt/", "tdf128733.odt"); + + Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + // test secondary X axis ShiftedCategoryPosition value + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 1); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); +} + +void Chart2ImportTest::testTdf128432() +{ + load("/chart2/qa/extras/data/ods/", "tdf128432.ods"); + + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); +} + +void Chart2ImportTest::testTdf128627() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf128627.xlsx"); + // Test ShiftedCategoryPosition for Radar Chart + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + CPPUNIT_ASSERT(!aScaleData.ShiftedCategoryPosition); +} + +void Chart2ImportTest::testTdf128634() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf128634.xlsx"); + // Test ShiftedCategoryPosition for 3D Charts + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); +} + +void Chart2ImportTest::testTdf130657() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf130657.xlsx"); + // Test ShiftedCategoryPosition for charts which is not contain a "crossbetween" OOXML tag. + uno::Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference 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& xDataSeries, sal_Int32 nDataPointIndex, bool bValueVisible) +{ + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(nDataPointIndex), uno::UNO_SET_THROW); + chart2::DataPointLabel aLabel; + xPropertySet->getPropertyValue("Label") >>= aLabel; + CPPUNIT_ASSERT_EQUAL(bValueVisible, static_cast(aLabel.ShowNumber)); + CPPUNIT_ASSERT_EQUAL(false, static_cast(aLabel.ShowNumberInPercent)); +} + +} + +void Chart2ImportTest::testDeletedDataLabel() +{ + load("/chart2/qa/extras/data/xlsx/", "deleted_data_labels.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); + Reference xDataSeries0 = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries0.is()); + checkDataLabelProperties(xDataSeries0, 0, true); + checkDataLabelProperties(xDataSeries0, 1, false); + checkDataLabelProperties(xDataSeries0, 2, true); + Reference xDataSeries1 = getDataSeriesFromDoc(xChartDoc, 1); + CPPUNIT_ASSERT(xDataSeries1.is()); + checkDataLabelProperties(xDataSeries1, 0, false); + checkDataLabelProperties(xDataSeries1, 1, false); + checkDataLabelProperties(xDataSeries1, 2, false); +} + +void Chart2ImportTest::testDataPointInheritedColorDOCX() +{ + load( "/chart2/qa/extras/data/docx/", "data_point_inherited_color.docx" ); + uno::Reference< chart2::XChartDocument > xChartDoc ( getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT( xChartDoc.is() ); + css::uno::Reference xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW); + + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + CPPUNIT_ASSERT(xPropertySet.is()); + sal_Int32 nColor = xPropertySet->getPropertyValue("FillColor").get(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16776960), nColor); +} + +void Chart2ImportTest::testExternalStrRefsXLSX() +{ + load("/chart2/qa/extras/data/xlsx/", "external_str_ref.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + chart2::ScaleData aScaleData = xAxis->getScaleData(); + css::uno::Sequence aValues = aScaleData.Categories->getValues()->getData(); + CPPUNIT_ASSERT_EQUAL(OUString("test1"), aValues[0].get()); + CPPUNIT_ASSERT_EQUAL(OUString("test2"), aValues[1].get()); +} + +void Chart2ImportTest::testSourceNumberFormatComplexCategoriesXLS() +{ + load("/chart2/qa/extras/data/xls/", "source_number_format_axis.xls"); + uno::Reference< chart2::XChartDocument > xChartDoc( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW ); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + chart2::ScaleData aScaleData = xAxis->getScaleData(); + sal_Int32 nNumberFormat = aScaleData.Categories->getValues()->getNumberFormatKeyByIndex(-1); + CPPUNIT_ASSERT(nNumberFormat != 0); +} + +void Chart2ImportTest::testSimpleCategoryAxis() +{ + load("/chart2/qa/extras/data/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 xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInternalProvider.is()); + + Reference xDescAccess(xInternalProvider, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDescAccess.is()); + + // Get the category labels. + Sequence > 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")); +} + +void Chart2ImportTest::testMultilevelCategoryAxis() +{ + load("/chart2/qa/extras/data/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 xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInternalProvider.is()); + + Reference xDescAccess(xInternalProvider, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDescAccess.is()); + + // Get the complex category labels. + Sequence > 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]); +} + +void Chart2ImportTest::testXaxisValues() +{ + load("/chart2/qa/extras/data/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, "values-x"); + Sequence xSequence = xDataSeq->getData(); + // test X values + CPPUNIT_ASSERT_EQUAL(uno::Any(0.04), xSequence[0]); + CPPUNIT_ASSERT(std::isnan(*static_cast(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(xSequence[4].getValue()))); +} + +void Chart2ImportTest::testTdf123504() +{ + load("/chart2/qa/extras/data/ods/", "pie_chart_100_and_0.ods"); + Reference xChartDoc(getChartDocFromSheet(0, mxComponent), + UNO_QUERY_THROW); + + Reference xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference xChartType(getChartTypeFromDoc(xChartDoc2, 0), UNO_SET_THROW); + std::vector aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + CPPUNIT_ASSERT_EQUAL(size_t(1), aDataSeriesYValues.size()); + + Reference xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference xSeriesSlices(getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=0"), + UNO_SET_THROW); + + Reference xIndexAccess(xSeriesSlices, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); + Reference 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_GREATER(sal_Int32(8500), aSliceSize.Height); + CPPUNIT_ASSERT_GREATER(sal_Int32(8500), aSliceSize.Width); +} + +void Chart2ImportTest::testTdf122765() +{ + // The horizontal position of the slices was wrong. + load("/chart2/qa/extras/data/pptx/", "tdf122765.pptx"); + Reference xChartDoc = getChartDocFromDrawImpress(0, 0); + Reference xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference xSeriesSlices(getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=0"), + UNO_SET_THROW); + + Reference xIndexAccess(xSeriesSlices, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(9), xIndexAccess->getCount()); + Reference 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); +} + +void Chart2ImportTest::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. + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromImpress("/chart2/qa/extras/data/odp/", "tdf123206.odp"), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xDp = xDataSeries->getDataPointByIndex(1); + Sequence> aLabelFields; + CPPUNIT_ASSERT(xDp->getPropertyValue("CustomLabelFields") >>= aLabelFields); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aLabelFields.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("Kiskacsa"), aLabelFields[0]->getString()); + +} + +void Chart2ImportTest::testTdf125444PercentageCustomLabel() +{ + load("/chart2/qa/extras/data/pptx/", "tdf125444.pptx"); + + // 1st chart + Reference xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xDp = xDataSeries->getDataPointByIndex(1); + Sequence> 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(3), aLabelFields.getLength()); + CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType_PERCENTAGE, aLabelFields[2]->getFieldType()); +} + +void Chart2ImportTest::testDataPointLabelCustomPos() +{ + // test CustomLabelPosition on Bar chart + load("/chart2/qa/extras/data/xlsx/", "testDataPointLabelCustomPos.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + CPPUNIT_ASSERT(xPropertySet.is()); + + chart2::RelativePosition aCustomLabelPosition; + xPropertySet->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition; + CPPUNIT_ASSERT_DOUBLES_EQUAL(aCustomLabelPosition.Primary, -0.14621409921671025, 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aCustomLabelPosition.Secondary, -5.2887961029923464E-2, 1e-7); + + sal_Int32 aPlacement; + xPropertySet->getPropertyValue("LabelPlacement") >>= aPlacement; + CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::OUTSIDE, aPlacement); +} + +void Chart2ImportTest::testTdf130032() +{ + // test CustomLabelPosition on Line chart + load("/chart2/qa/extras/data/xlsx/", "testTdf130032.xlsx"); + uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT(xChartDoc.is()); + uno::Reference xDataSeries(getDataSeriesFromDoc(xChartDoc, 0)); + CPPUNIT_ASSERT(xDataSeries.is()); + + uno::Reference xPropertySet(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW); + CPPUNIT_ASSERT(xPropertySet.is()); + + chart2::RelativePosition aCustomLabelPosition; + xPropertySet->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition; + CPPUNIT_ASSERT_DOUBLES_EQUAL(aCustomLabelPosition.Primary, -0.0438333333333334, 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aCustomLabelPosition.Secondary, 0.086794050743657, 1e-7); + + sal_Int32 aPlacement; + xPropertySet->getPropertyValue("LabelPlacement") >>= aPlacement; + CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::RIGHT, aPlacement); +} + +void Chart2ImportTest::testTdf119138MissingAutoTitleDeleted() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf119138-missing-autotitledeleted.xlsx"); + Reference xChartDoc = getChartDocFromSheet(0, mxComponent); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xTitled(xChartDoc, uno::UNO_QUERY_THROW); + uno::Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT_MESSAGE("Missing autoTitleDeleted is implied to be True if title text is present", xTitle.is()); +} + +void Chart2ImportTest::testStockChartShiftedCategoryPosition() +{ + load("/chart2/qa/extras/data/odt/", "stock_chart_LO_6_2.odt"); + + uno::Reference xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); +} + +void Chart2ImportTest::testTdf133376() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf133376.xlsx"); + Reference xChartDoc(getChartDocFromSheet(0, mxComponent), + UNO_QUERY_THROW); + + Reference xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference 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(1071, aLabelPosition.X, 30); + CPPUNIT_ASSERT_DOUBLES_EQUAL(5269, aLabelPosition.Y, 30); +} + +void Chart2ImportTest::testTdf134225() +{ + load("/chart2/qa/extras/data/xlsx/", "tdf134225.xlsx"); + Reference xChartDoc(getChartDocFromSheet(0, mxComponent), + UNO_QUERY_THROW); + + Reference xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference xDataPointLabel1(getShapeByName(xShapes, + "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"), UNO_SET_THROW); + CPPUNIT_ASSERT(xDataPointLabel1.is()); + awt::Point aLabelPosition1 = xDataPointLabel1->getPosition(); + + Reference xDataPointLabel2(getShapeByName(xShapes, + "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1"), UNO_SET_THROW); + CPPUNIT_ASSERT(xDataPointLabel2.is()); + 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(1800, sal_Int32(aLabelPosition2.X - aLabelPosition1.X), 200); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2123, sal_Int32(aLabelPosition2.Y - aLabelPosition1.Y), 200); +} + +void Chart2ImportTest::testTdf91250() +{ + load("/chart2/qa/extras/data/docx/", "tdf91250.docx"); + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInternalProvider.is()); + + Reference xDescAccess(xInternalProvider, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDescAccess.is()); + + // Get the category labels. + Sequence 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_SUITE_REGISTRATION(Chart2ImportTest); + +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 000000000..9b8e98a48 --- /dev/null +++ b/chart2/qa/extras/charttest.hxx @@ -0,0 +1,614 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_CHART2_QA_EXTRAS_CHARTTEST_HXX +#define INCLUDED_CHART2_QA_EXTRAS_CHARTTEST_HXX + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +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 test::BootstrapFixture, public unotest::MacrosTest +{ +public: + ChartTest():mbSkipValidation(false) {} + void load( const OUString& rDir, const OUString& rFileName ); + std::shared_ptr save( const OUString& rFileName ); + std::shared_ptr reload( const OUString& rFileName ); + uno::Sequence < OUString > getImpressChartColumnDescriptions( const OUString& pDir, const char* pName ); + OUString getFileExtension( const OUString& rFileName ); + + uno::Reference< chart::XChartDocument > getChartDocFromImpress( const OUString& pDir, const char* pName ); + + uno::Reference getChartDocFromDrawImpress( sal_Int32 nPage, sal_Int32 nShape ); + + uno::Reference getChartDocFromWriter( sal_Int32 nShape ); + awt::Size getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ); + awt::Size getSize(css::uno::Reference xDiagram, const awt::Size& rPageSize); + + virtual void setUp() override; + virtual void tearDown() override; + +protected: + Reference< lang::XComponent > mxComponent; + OUString maServiceName; + bool mbSkipValidation; // if you set this flag for a new test I'm going to haunt you! +}; + +OUString ChartTest::getFileExtension( const OUString& aFileName ) +{ + sal_Int32 nDotLocation = aFileName.lastIndexOf('.'); + CPPUNIT_ASSERT(nDotLocation != -1); + return aFileName.copy(nDotLocation+1); // Skip the dot. +} + +void ChartTest::load( const OUString& aDir, const OUString& aName ) +{ + OUString extension = getFileExtension(aName); + if (extension == "ods" || extension == "xlsx" || extension == "fods") + { + maServiceName = "com.sun.star.sheet.SpreadsheetDocument"; + } + else if (extension == "docx") + { + maServiceName = "com.sun.star.text.TextDocument"; + } + else if (extension == "odg") + { + maServiceName = "com.sun.star.drawing.DrawingDocument"; + } + if (mxComponent.is()) + mxComponent->dispose(); + mxComponent = loadFromDesktop(m_directories.getURLFromSrc(aDir) + aName, maServiceName); + CPPUNIT_ASSERT(mxComponent.is()); +} + +std::shared_ptr ChartTest::save(const OUString& rFilterName) +{ + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + auto aArgs(::comphelper::InitPropertySequence({ + { "FilterName", Any(rFilterName) } + })); + std::shared_ptr pTempFile = std::make_shared(); + pTempFile->EnableKillingFile(); + xStorable->storeToURL(pTempFile->GetURL(), aArgs); + + return pTempFile; +} + +std::shared_ptr ChartTest::reload(const OUString& rFilterName) +{ + std::shared_ptr pTempFile = save(rFilterName); + mxComponent->dispose(); + mxComponent = loadFromDesktop(pTempFile->GetURL(), maServiceName); + std::cout << pTempFile->GetURL(); + if(rFilterName == "Calc Office Open XML") + { + validate(pTempFile->GetFileName(), test::OOXML); + } + else if(rFilterName == "Office Open XML Text") + { + // validate(pTempFile->GetFileName(), test::OOXML); + } + else if(rFilterName == "calc8") + { + if(!mbSkipValidation) + validate(pTempFile->GetFileName(), test::ODF); + } + else if(rFilterName == "MS Excel 97") + { + if(!mbSkipValidation) + validate(pTempFile->GetFileName(), test::MSBINARY); + } + CPPUNIT_ASSERT(mxComponent.is()); + return pTempFile; +} + +void ChartTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set( css::frame::Desktop::create( comphelper::getComponentContext(getMultiServiceFactory()) ) ); +} + +void ChartTest::tearDown() +{ + if(mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); + +} + +Reference< lang::XComponent > getChartCompFromSheet( sal_Int32 nSheet, 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(0), 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, xComponent), UNO_QUERY_THROW ); + return xChartDoc; +} + +uno::Reference getTablePivotChartsFromSheet(sal_Int32 nSheet, uno::Reference const & xComponent) +{ + uno::Reference xDoc(xComponent, UNO_QUERY_THROW); + + uno::Reference xIA(xDoc->getSheets(), UNO_QUERY_THROW); + + uno::Reference xChartSupplier(xIA->getByIndex(nSheet), UNO_QUERY_THROW); + + uno::Reference xTablePivotCharts = xChartSupplier->getPivotCharts(); + CPPUNIT_ASSERT(xTablePivotCharts.is()); + + return xTablePivotCharts; +} + +Reference getPivotChartCompFromSheet(sal_Int32 nSheet, uno::Reference const & xComponent) +{ + uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(nSheet, xComponent); + + uno::Reference xIACharts(xTablePivotCharts, UNO_QUERY_THROW); + uno::Reference xTablePivotChart(xIACharts->getByIndex(0), UNO_QUERY_THROW); + + uno::Reference xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW); + + uno::Reference xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_SET_THROW); + + return xChartComp; +} + +Reference getPivotChartDocFromSheet(sal_Int32 nSheet, uno::Reference const & xComponent) +{ + uno::Reference xChartDoc(getPivotChartCompFromSheet(nSheet, xComponent), UNO_QUERY_THROW); + return xChartDoc; +} + +Reference getPivotChartDocFromSheet(uno::Reference const & xTablePivotCharts, sal_Int32 nIndex) +{ + uno::Reference xIACharts(xTablePivotCharts, UNO_QUERY_THROW); + uno::Reference xTablePivotChart(xIACharts->getByIndex(nIndex), UNO_QUERY_THROW); + + uno::Reference xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW); + + uno::Reference xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_SET_THROW); + + uno::Reference 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 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 getAxisFromDoc( + const Reference& xChartDoc, sal_Int32 nCooSys, sal_Int32 nAxisDim, sal_Int32 nAxisIndex ) +{ + Reference xDiagram = xChartDoc->getFirstDiagram(); + CPPUNIT_ASSERT(xDiagram.is()); + + Reference xCooSysContainer(xDiagram, UNO_QUERY_THROW); + + Sequence > xCooSysSequence = xCooSysContainer->getCoordinateSystems(); + CPPUNIT_ASSERT(xCooSysSequence.getLength() > nCooSys); + + Reference xCoord = xCooSysSequence[nCooSys]; + CPPUNIT_ASSERT(xCoord.is()); + + Reference xAxis = xCoord->getAxisByDimension(nAxisDim, nAxisIndex); + CPPUNIT_ASSERT(xAxis.is()); + + return xAxis; +} + +sal_Int32 getNumberOfDataSeries(uno::Reference const & xChartDoc, + sal_Int32 nChartType = 0, sal_Int32 nCooSys = 0) +{ + Reference xChartType = getChartTypeFromDoc(xChartDoc, nChartType, nCooSys); + Reference xDataSeriesContainer(xChartType, UNO_QUERY_THROW); + + uno::Sequence> xSeriesSequence(xDataSeriesContainer->getDataSeries()); + return xSeriesSequence.getLength(); +} + +Reference< chart2::XDataSeries > getDataSeriesFromDoc(uno::Reference 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, const OUString& 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(); + + if(aRoleName == rRole) + return xLabelSeq; + } + + return Reference< chart2::data::XDataSequence > (); +} + +uno::Sequence < OUString > getWriterChartColumnDescriptions( Reference< lang::XComponent > const & mxComponent ) +{ + uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT( xShape.is() ); + uno::Reference 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 > getDataSeriesYValuesFromChartType( const Reference& xCT ) +{ + Reference xDSCont(xCT, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDSCont.is()); + const Sequence > aDataSeriesSeq = xDSCont->getDataSeries(); + + double fNan; + rtl::math::setNan(&fNan); + + std::vector > aRet; + for (uno::Reference const & ds : aDataSeriesSeq) + { + uno::Reference xDSrc(ds, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDSrc.is()); + const uno::Sequence > aDataSeqs = xDSrc->getDataSequences(); + for (auto const & lds : aDataSeqs) + { + Reference xValues = lds->getValues(); + CPPUNIT_ASSERT(xValues.is()); + Reference xPropSet(xValues, uno::UNO_QUERY); + if (!xPropSet.is()) + continue; + + OUString aRoleName; + xPropSet->getPropertyValue("Role") >>= aRoleName; + if (aRoleName == "values-y") + { + const uno::Sequence aData = xValues->getData(); + std::vector aValues; + aValues.reserve(aData.getLength()); + for (uno::Any const & any : aData) + { + double fVal; + if (any >>= fVal) + aValues.push_back(fVal); + else + aValues.push_back(fNan); + } + aRet.push_back(aValues); + } + } + } + + return aRet; +} + +std::vector > getDataSeriesLabelsFromChartType( const Reference& xCT ) +{ + OUString aLabelRole = xCT->getRoleOfSequenceForSeriesLabel(); + + Reference xDSCont(xCT, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDSCont.is()); + const Sequence > aDataSeriesSeq = xDSCont->getDataSeries(); + + std::vector > aRet; + for (auto const & ds : aDataSeriesSeq) + { + uno::Reference xDSrc(ds, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDSrc.is()); + const uno::Sequence > aDataSeqs = xDSrc->getDataSequences(); + for (auto const & lds : aDataSeqs) + { + Reference xValues = lds->getValues(); + CPPUNIT_ASSERT(xValues.is()); + Reference xPropSet(xValues, uno::UNO_QUERY); + if (!xPropSet.is()) + continue; + + OUString aRoleName; + xPropSet->getPropertyValue("Role") >>= aRoleName; + if (aRoleName == aLabelRole) + { + Reference xLabel = lds; + CPPUNIT_ASSERT(xLabel.is()); + Reference xDS2 = xLabel->getLabel(); + CPPUNIT_ASSERT(xDS2.is()); + uno::Sequence aData = xDS2->getData(); + aRet.push_back(aData); + } + } + } + + return aRet; +} + +uno::Reference< chart::XChartDocument > ChartTest::getChartDocFromImpress( const OUString& pDir, const char* pName ) +{ + mxComponent = loadFromDesktop(m_directories.getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.comp.Draw.PresentationDocument"); + uno::Reference< drawing::XDrawPagesSupplier > xDoc(mxComponent, uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XDrawPage > xPage( + xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xShapeProps( + xPage->getByIndex(0), uno::UNO_QUERY ); + CPPUNIT_ASSERT(xShapeProps.is()); + uno::Reference< frame::XModel > xDocModel; + xShapeProps->getPropertyValue("Model") >>= xDocModel; + CPPUNIT_ASSERT(xDocModel.is()); + uno::Reference< chart::XChartDocument > xChartDoc( xDocModel, uno::UNO_QUERY_THROW ); + + return xChartDoc; +} + +uno::Reference ChartTest::getChartDocFromDrawImpress( + sal_Int32 nPage, sal_Int32 nShape ) +{ + uno::Reference xEmpty; + + uno::Reference xPages(mxComponent, uno::UNO_QUERY); + if (!xPages.is()) + return xEmpty; + + uno::Reference xPage( + xPages->getDrawPages()->getByIndex(nPage), uno::UNO_QUERY_THROW); + + uno::Reference xShapeProps(xPage->getByIndex(nShape), uno::UNO_QUERY); + if (!xShapeProps.is()) + return xEmpty; + + uno::Reference xDocModel; + xShapeProps->getPropertyValue("Model") >>= xDocModel; + if (!xDocModel.is()) + return xEmpty; + + uno::Reference xChartDoc(xDocModel, uno::UNO_QUERY); + return xChartDoc; +} + +uno::Reference ChartTest::getChartDocFromWriter( sal_Int32 nShape ) +{ + // DO NOT use XDrawPageSupplier since SwVirtFlyDrawObj are not created + // during import, only in layout! + Reference xEOS(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xEOS.is()); + Reference xEmbeddeds(xEOS->getEmbeddedObjects(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xEmbeddeds.is()); + + Reference xShapeProps(xEmbeddeds->getByIndex(nShape), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapeProps.is()); + + Reference xDocModel; + xShapeProps->getPropertyValue("Model") >>= xDocModel; + CPPUNIT_ASSERT(xDocModel.is()); + + uno::Reference xChartDoc(xDocModel, uno::UNO_QUERY); + return xChartDoc; +} + +uno::Sequence < OUString > ChartTest::getImpressChartColumnDescriptions( const OUString& pDir, const char* pName ) +{ + uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromImpress( pDir, pName ); + uno::Reference< chart::XChartDataArray > xChartData ( xChartDoc->getData(), uno::UNO_QUERY_THROW); + uno::Sequence < OUString > seriesList = xChartData->getColumnDescriptions(); + return seriesList; +} + +OUString getTitleString( const Reference& xTitled ) +{ + uno::Reference xTitle = xTitled->getTitleObject(); + CPPUNIT_ASSERT(xTitle.is()); + const uno::Sequence > aFSSeq = xTitle->getText(); + OUString aText; + for (auto const & fs : aFSSeq) + aText += fs->getString(); + + return aText; +} + +sal_Int32 getNumberFormat( const Reference& xChartDoc, const OUString& sFormat ) +{ + Reference xNFS(xChartDoc, uno::UNO_QUERY_THROW); + Reference xNumberFormats = xNFS->getNumberFormats(); + CPPUNIT_ASSERT(xNumberFormats.is()); + + return xNumberFormats->queryKey(sFormat, css::lang::Locale(), false); +} + +sal_Int32 getNumberFormatFromAxis( const Reference& xAxis ) +{ + Reference 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& xChartDoc, sal_Int32 nNumberFormat ) +{ + Reference xNFS(xChartDoc, uno::UNO_QUERY_THROW); + Reference xNumberFormats = xNFS->getNumberFormats(); + CPPUNIT_ASSERT(xNumberFormats.is()); + + Reference xNumPS = xNumberFormats->getByKey(nNumberFormat); + CPPUNIT_ASSERT(xNumPS.is()); + + sal_Int16 nType = util::NumberFormat::UNDEFINED; + xNumPS->getPropertyValue("Type") >>= nType; + + return nType; +} + +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 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; +} + +#endif // INCLUDED_CHART2_QA_EXTRAS_CHARTTEST_HXX + +/* 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 000000000..2bfa5aed2 Binary files /dev/null and b/chart2/qa/extras/data/doc/chart.doc 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 000000000..69cab8e71 Binary files /dev/null and b/chart2/qa/extras/data/docx/3d-bar-label.docx 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 000000000..2280d89fc Binary files /dev/null and b/chart2/qa/extras/data/docx/Bar_horizontal_cone.docx differ diff --git a/chart2/qa/extras/data/docx/DisplayUnits.docx b/chart2/qa/extras/data/docx/DisplayUnits.docx new file mode 100644 index 000000000..97092a3ed Binary files /dev/null and b/chart2/qa/extras/data/docx/DisplayUnits.docx differ diff --git a/chart2/qa/extras/data/docx/FDO74430.docx b/chart2/qa/extras/data/docx/FDO74430.docx new file mode 100644 index 000000000..f4a68b519 Binary files /dev/null and b/chart2/qa/extras/data/docx/FDO74430.docx differ diff --git a/chart2/qa/extras/data/docx/FDO75975.docx b/chart2/qa/extras/data/docx/FDO75975.docx new file mode 100644 index 000000000..30f251014 Binary files /dev/null and b/chart2/qa/extras/data/docx/FDO75975.docx 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 000000000..a9955b7b1 Binary files /dev/null and b/chart2/qa/extras/data/docx/MSO_axis_position.docx differ diff --git a/chart2/qa/extras/data/docx/PieChartDataLabels.docx b/chart2/qa/extras/data/docx/PieChartDataLabels.docx new file mode 100644 index 000000000..99a72c0f2 Binary files /dev/null and b/chart2/qa/extras/data/docx/PieChartDataLabels.docx differ diff --git a/chart2/qa/extras/data/docx/UpDownBars.docx b/chart2/qa/extras/data/docx/UpDownBars.docx new file mode 100644 index 000000000..755f81499 Binary files /dev/null and b/chart2/qa/extras/data/docx/UpDownBars.docx 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 000000000..4db844112 Binary files /dev/null and b/chart2/qa/extras/data/docx/area-chart-labels.docx 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 000000000..9ff8b4fd1 Binary files /dev/null and b/chart2/qa/extras/data/docx/bar-chart-labels.docx differ diff --git a/chart2/qa/extras/data/docx/barChartRotation.docx b/chart2/qa/extras/data/docx/barChartRotation.docx new file mode 100644 index 000000000..bf4be47b3 Binary files /dev/null and b/chart2/qa/extras/data/docx/barChartRotation.docx differ diff --git a/chart2/qa/extras/data/docx/bubblechart.docx b/chart2/qa/extras/data/docx/bubblechart.docx new file mode 100644 index 000000000..c2040730c Binary files /dev/null and b/chart2/qa/extras/data/docx/bubblechart.docx differ diff --git a/chart2/qa/extras/data/docx/chart.docx b/chart2/qa/extras/data/docx/chart.docx new file mode 100644 index 000000000..f9cddd494 Binary files /dev/null and b/chart2/qa/extras/data/docx/chart.docx 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 000000000..3b9941cc1 Binary files /dev/null and b/chart2/qa/extras/data/docx/clustered-bar-chart-labels.docx 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 000000000..6f2b94d98 Binary files /dev/null and b/chart2/qa/extras/data/docx/data-label-borders.docx 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 000000000..70de8b218 Binary files /dev/null and b/chart2/qa/extras/data/docx/data_point_inherited_color.docx 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 000000000..559208578 Binary files /dev/null and b/chart2/qa/extras/data/docx/doughnut-chart-labels.docx differ diff --git a/chart2/qa/extras/data/docx/doughnutChart.docx b/chart2/qa/extras/data/docx/doughnutChart.docx new file mode 100644 index 000000000..f0642d4d5 Binary files /dev/null and b/chart2/qa/extras/data/docx/doughnutChart.docx 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 000000000..15f42b0cf Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docx 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 000000000..e10334bd9 Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docx 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 000000000..ee2489d21 Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docx 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 000000000..7e4b096b8 Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docx 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 000000000..2edc8f086 Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docx 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 000000000..721a71789 Binary files /dev/null and b/chart2/qa/extras/data/docx/fdo83058_dlblPos.docx 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 000000000..ab9548d59 Binary files /dev/null and b/chart2/qa/extras/data/docx/line-chart-label-default-placement.docx differ diff --git a/chart2/qa/extras/data/docx/pieChartRotation.docx b/chart2/qa/extras/data/docx/pieChartRotation.docx new file mode 100644 index 000000000..f76f60237 Binary files /dev/null and b/chart2/qa/extras/data/docx/pieChartRotation.docx 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 000000000..da6b2fa19 Binary files /dev/null and b/chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docx 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 000000000..2cb876dd2 Binary files /dev/null and b/chart2/qa/extras/data/docx/radar-chart-labels.docx 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 000000000..b741bbce2 Binary files /dev/null and b/chart2/qa/extras/data/docx/scatter-chart-text-x-values.docx differ diff --git a/chart2/qa/extras/data/docx/tdf121744.docx b/chart2/qa/extras/data/docx/tdf121744.docx new file mode 100644 index 000000000..b5ff10098 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf121744.docx differ diff --git a/chart2/qa/extras/data/docx/tdf123206.docx b/chart2/qa/extras/data/docx/tdf123206.docx new file mode 100644 index 000000000..f47089fe3 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf123206.docx differ diff --git a/chart2/qa/extras/data/docx/tdf124083.docx b/chart2/qa/extras/data/docx/tdf124083.docx new file mode 100644 index 000000000..b8030ca9a Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf124083.docx differ diff --git a/chart2/qa/extras/data/docx/tdf124243.docx b/chart2/qa/extras/data/docx/tdf124243.docx new file mode 100644 index 000000000..e58ef6a02 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf124243.docx differ diff --git a/chart2/qa/extras/data/docx/tdf125337.docx b/chart2/qa/extras/data/docx/tdf125337.docx new file mode 100644 index 000000000..811f12d89 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf125337.docx differ diff --git a/chart2/qa/extras/data/docx/tdf128794.docx b/chart2/qa/extras/data/docx/tdf128794.docx new file mode 100644 index 000000000..098c0a00e Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf128794.docx differ diff --git a/chart2/qa/extras/data/docx/tdf132174.docx b/chart2/qa/extras/data/docx/tdf132174.docx new file mode 100644 index 000000000..4f4369578 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf132174.docx differ diff --git a/chart2/qa/extras/data/docx/tdf133632.docx b/chart2/qa/extras/data/docx/tdf133632.docx new file mode 100644 index 000000000..b970e73f4 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf133632.docx differ diff --git a/chart2/qa/extras/data/docx/tdf136650.docx b/chart2/qa/extras/data/docx/tdf136650.docx new file mode 100644 index 000000000..cd095ec63 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf136650.docx differ diff --git a/chart2/qa/extras/data/docx/tdf91250.docx b/chart2/qa/extras/data/docx/tdf91250.docx new file mode 100644 index 000000000..4cb199b45 Binary files /dev/null and b/chart2/qa/extras/data/docx/tdf91250.docx differ diff --git a/chart2/qa/extras/data/docx/testAreaChartLoad.docx b/chart2/qa/extras/data/docx/testAreaChartLoad.docx new file mode 100644 index 000000000..9383f75cd Binary files /dev/null and b/chart2/qa/extras/data/docx/testAreaChartLoad.docx differ diff --git a/chart2/qa/extras/data/docx/testAxisTitlePosition.docx b/chart2/qa/extras/data/docx/testAxisTitlePosition.docx new file mode 100644 index 000000000..6abd37eec Binary files /dev/null and b/chart2/qa/extras/data/docx/testAxisTitlePosition.docx differ diff --git a/chart2/qa/extras/data/docx/testBarChart.docx b/chart2/qa/extras/data/docx/testBarChart.docx new file mode 100644 index 000000000..b92260f71 Binary files /dev/null and b/chart2/qa/extras/data/docx/testBarChart.docx differ diff --git a/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx b/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx new file mode 100644 index 000000000..66df9153d Binary files /dev/null and b/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx differ diff --git a/chart2/qa/extras/data/docx/testChartDataTable.docx b/chart2/qa/extras/data/docx/testChartDataTable.docx new file mode 100644 index 000000000..8663e8937 Binary files /dev/null and b/chart2/qa/extras/data/docx/testChartDataTable.docx differ diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx new file mode 100644 index 000000000..462c15976 Binary files /dev/null and b/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx differ diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx new file mode 100644 index 000000000..d86928d61 Binary files /dev/null and b/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx differ diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx new file mode 100644 index 000000000..a72600d09 Binary files /dev/null and b/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx differ diff --git a/chart2/qa/extras/data/docx/testColorGradientWithTransparancy.docx b/chart2/qa/extras/data/docx/testColorGradientWithTransparancy.docx new file mode 100644 index 000000000..adc2aff04 Binary files /dev/null and b/chart2/qa/extras/data/docx/testColorGradientWithTransparancy.docx differ diff --git a/chart2/qa/extras/data/docx/testCustomlabeltext.docx b/chart2/qa/extras/data/docx/testCustomlabeltext.docx new file mode 100644 index 000000000..db28209c9 Binary files /dev/null and b/chart2/qa/extras/data/docx/testCustomlabeltext.docx differ diff --git a/chart2/qa/extras/data/docx/testLabelSeparator.docx b/chart2/qa/extras/data/docx/testLabelSeparator.docx new file mode 100644 index 000000000..452fdccc9 Binary files /dev/null and b/chart2/qa/extras/data/docx/testLabelSeparator.docx differ diff --git a/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx new file mode 100644 index 000000000..75605de72 Binary files /dev/null and b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx differ diff --git a/chart2/qa/extras/data/docx/testMultipleChart.docx b/chart2/qa/extras/data/docx/testMultipleChart.docx new file mode 100644 index 000000000..28d8bbcfe Binary files /dev/null and b/chart2/qa/extras/data/docx/testMultipleChart.docx differ diff --git a/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx b/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx new file mode 100644 index 000000000..28d8bbcfe Binary files /dev/null and b/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx differ diff --git a/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx b/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx new file mode 100644 index 000000000..9274e2c2c Binary files /dev/null and b/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx differ diff --git a/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx b/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx new file mode 100644 index 000000000..de511664a Binary files /dev/null and b/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx differ diff --git a/chart2/qa/extras/data/docx/testStockChart.docx b/chart2/qa/extras/data/docx/testStockChart.docx new file mode 100644 index 000000000..a804e7df2 Binary files /dev/null and b/chart2/qa/extras/data/docx/testStockChart.docx differ diff --git a/chart2/qa/extras/data/docx/testTdf108110.docx b/chart2/qa/extras/data/docx/testTdf108110.docx new file mode 100644 index 000000000..769360c15 Binary files /dev/null and b/chart2/qa/extras/data/docx/testTdf108110.docx differ diff --git a/chart2/qa/extras/data/docx/testTdf114179.docx b/chart2/qa/extras/data/docx/testTdf114179.docx new file mode 100644 index 000000000..36fb11e17 Binary files /dev/null and b/chart2/qa/extras/data/docx/testTdf114179.docx differ diff --git a/chart2/qa/extras/data/docx/testTdf122226.docx b/chart2/qa/extras/data/docx/testTdf122226.docx new file mode 100644 index 000000000..7205525a7 Binary files /dev/null and b/chart2/qa/extras/data/docx/testTdf122226.docx differ diff --git a/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx b/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx new file mode 100644 index 000000000..8167de7a3 Binary files /dev/null and b/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx 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 000000000..8a142120b --- /dev/null +++ b/chart2/qa/extras/data/fods/stacked-column-chart.fods @@ -0,0 +1,861 @@ + + + + Michael Meeks2014-06-05T11:25:47.3465744642014-06-05T11:32:25.317381922Michael MeeksPT3M51S6LibreOffice/3.5$Linux_X86_64 LibreOffice_project/f647884-246edd6 + + + 0 + 0 + 27093 + 9934 + + + view1 + + + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 130 + 60 + true + + + 1 + 16 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 130 + 60 + true + + + Summary + 270 + 0 + 130 + 60 + false + true + true + true + 12632256 + true + true + true + true + false + false + 1000 + 1000 + 1 + 1 + true + + + + + true + false + true + 12632256 + true + false + 1 + 1 + + + en + GB + + + + + + true + fwH+/0Nhbm9uLTg2MGkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ1VQUzpDYW5vbi04NjBpAAAAAAAAAAAAAAAAAAAAAAAWAAMApQAAAAAAAAAIAFZUAAAkbQAASm9iRGF0YSAxCnByaW50ZXI9Q2Fub24tODYwaQpvcmllbnRhdGlvbj1Qb3J0cmFpdApjb3BpZXM9MQptYXJnaW5kYWp1c3RtZW50PTAsMCwwLDAKY29sb3JkZXB0aD0yNApwc2xldmVsPTAKcGRmZGV2aWNlPTEKY29sb3JkZXZpY2U9MApQUERDb250ZXhEYXRhClBhZ2VTaXplOkxldHRlcgAAEgBDT01QQVRfRFVQTEVYX01PREUKAERVUExFWF9PRkY= + true + false + true + Canon-860i + 3 + false + false + false + true + 1000 + 1000 + true + true + true + 0 + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + Page 1 + + + + + + + ??? (???) + + + 00/00/0000, 00:00:00 + + + + + Page 1 / 99 + + + + + + + + + + + + LibreOffice/3.5$Linux_X86_64 LibreOffice_project/f647884-246edd6 + + + + + + + £ + + + + + - + £ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Some + + Summary.B1:Summary.B1 + + + + + + + One + + Summary.A2:Summary.A2 + + + 956.594173563644 + + Summary.B2:Summary.B2 + + + + + Two + + Summary.A3:Summary.A3 + + + 207.425649510697 + + Summary.B3:Summary.B3 + + + + + Three + + Summary.A4:Summary.A4 + + + 689.508363604546 + + Summary.B4:Summary.B4 + + + + + Four + + Summary.A5:Summary.A5 + + + 346.062566153705 + + Summary.B5:Summary.B5 + + + + + Five + + Summary.A6:Summary.A6 + + + 893.98120646365 + + Summary.B6:Summary.B6 + + + + + + + + + + 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== + + + + + + + + Summary + + + Some + + + + + + One + + + £957 + + + + + + Two + + + £207 + + + + + + Three + + + £690 + + + + + + Four + + + £346 + + + + + + Five + + + £894 + + + + + + + + + + To reproduce bug: + + + + + + + Save as Flat ODS: extension '.fods' + + + + + + + Reload … bingo … + + + + + + + + + 956.5941735636 + + + 573.4103277791 + + + + + 207.4256495107 + + + 604.592139367 + + + + + 689.5083636045 + + + 44.302029768 + + + + + 346.0625661537 + + + 835.6307845097 + + + + + 893.9812064637 + + + 220.4455654137 + + + + + 140.1847645175 + + + 130.7745140512 + + + + + + + \ No newline at end of file diff --git a/chart2/qa/extras/data/odp/chart.odp b/chart2/qa/extras/data/odp/chart.odp new file mode 100644 index 000000000..81a5f56b2 Binary files /dev/null and b/chart2/qa/extras/data/odp/chart.odp differ diff --git a/chart2/qa/extras/data/odp/ellipticalGradientFill.odp b/chart2/qa/extras/data/odp/ellipticalGradientFill.odp new file mode 100644 index 000000000..754f439e5 Binary files /dev/null and b/chart2/qa/extras/data/odp/ellipticalGradientFill.odp differ diff --git a/chart2/qa/extras/data/odp/tdf119029.odp b/chart2/qa/extras/data/odp/tdf119029.odp new file mode 100644 index 000000000..87e4a03c8 Binary files /dev/null and b/chart2/qa/extras/data/odp/tdf119029.odp differ diff --git a/chart2/qa/extras/data/odp/tdf121189.odp b/chart2/qa/extras/data/odp/tdf121189.odp new file mode 100644 index 000000000..6f99e0054 Binary files /dev/null and b/chart2/qa/extras/data/odp/tdf121189.odp differ diff --git a/chart2/qa/extras/data/odp/tdf123206.odp b/chart2/qa/extras/data/odp/tdf123206.odp new file mode 100644 index 000000000..1975756bc Binary files /dev/null and b/chart2/qa/extras/data/odp/tdf123206.odp differ diff --git a/chart2/qa/extras/data/ods/ErrorBarRange.ods b/chart2/qa/extras/data/ods/ErrorBarRange.ods new file mode 100644 index 000000000..28e6aeedd Binary files /dev/null and b/chart2/qa/extras/data/ods/ErrorBarRange.ods differ diff --git a/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods new file mode 100644 index 000000000..c34521e0b Binary files /dev/null and b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods differ diff --git a/chart2/qa/extras/data/ods/PivotTableExample.ods b/chart2/qa/extras/data/ods/PivotTableExample.ods new file mode 100644 index 000000000..bc8df8170 Binary files /dev/null and b/chart2/qa/extras/data/ods/PivotTableExample.ods 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 000000000..ddaa9c901 Binary files /dev/null and b/chart2/qa/extras/data/ods/axis-numformats-linked.ods 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 000000000..52e979a49 Binary files /dev/null and b/chart2/qa/extras/data/ods/axis_number_format.ods differ diff --git a/chart2/qa/extras/data/ods/chart.ods b/chart2/qa/extras/data/ods/chart.ods new file mode 100644 index 000000000..2a9916aca Binary files /dev/null and b/chart2/qa/extras/data/ods/chart.ods 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 000000000..d125bc23d Binary files /dev/null and b/chart2/qa/extras/data/ods/combined_chart_secondary_axis.ods 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 000000000..9c3adbbca Binary files /dev/null and b/chart2/qa/extras/data/ods/error_bar.ods 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 000000000..056be88b2 Binary files /dev/null and b/chart2/qa/extras/data/ods/error_bar_properties.ods 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 000000000..27a0103e5 Binary files /dev/null and b/chart2/qa/extras/data/ods/error_bar_range.ods differ diff --git a/chart2/qa/extras/data/ods/fdo60083.ods b/chart2/qa/extras/data/ods/fdo60083.ods new file mode 100644 index 000000000..74704f618 Binary files /dev/null and b/chart2/qa/extras/data/ods/fdo60083.ods differ diff --git a/chart2/qa/extras/data/ods/labelString.ods b/chart2/qa/extras/data/ods/labelString.ods new file mode 100644 index 000000000..2b7e03c8e Binary files /dev/null and b/chart2/qa/extras/data/ods/labelString.ods 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 000000000..fade62640 Binary files /dev/null and b/chart2/qa/extras/data/ods/legend_overlay.ods differ diff --git a/chart2/qa/extras/data/ods/multilevelcat.ods b/chart2/qa/extras/data/ods/multilevelcat.ods new file mode 100644 index 000000000..76b140a87 Binary files /dev/null and b/chart2/qa/extras/data/ods/multilevelcat.ods 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 000000000..7e2a505cc Binary files /dev/null and b/chart2/qa/extras/data/ods/multiple_axis.ods 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 000000000..a6ff5d6aa Binary files /dev/null and b/chart2/qa/extras/data/ods/pie_chart_100_and_0.ods 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 000000000..3f8f269c0 Binary files /dev/null and b/chart2/qa/extras/data/ods/secondary_axis.ods differ diff --git a/chart2/qa/extras/data/ods/smoothedLines.ods b/chart2/qa/extras/data/ods/smoothedLines.ods new file mode 100644 index 000000000..725827e63 Binary files /dev/null and b/chart2/qa/extras/data/ods/smoothedLines.ods 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 000000000..23d443ab5 Binary files /dev/null and b/chart2/qa/extras/data/ods/stepped_lines.ods differ diff --git a/chart2/qa/extras/data/ods/tdf108021.ods b/chart2/qa/extras/data/ods/tdf108021.ods new file mode 100644 index 000000000..ebbc5e56f Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf108021.ods differ diff --git a/chart2/qa/extras/data/ods/tdf123774.ods b/chart2/qa/extras/data/ods/tdf123774.ods new file mode 100644 index 000000000..5c422b58c Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf123774.ods differ diff --git a/chart2/qa/extras/data/ods/tdf128432.ods b/chart2/qa/extras/data/ods/tdf128432.ods new file mode 100644 index 000000000..a93822fc9 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf128432.ods differ diff --git a/chart2/qa/extras/data/ods/tdf131115.ods b/chart2/qa/extras/data/ods/tdf131115.ods new file mode 100644 index 000000000..76a87c2c2 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf131115.ods differ diff --git a/chart2/qa/extras/data/ods/tdf131979.ods b/chart2/qa/extras/data/ods/tdf131979.ods new file mode 100644 index 000000000..3dfcf6b69 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf131979.ods differ diff --git a/chart2/qa/extras/data/ods/tdf132076.ods b/chart2/qa/extras/data/ods/tdf132076.ods new file mode 100644 index 000000000..348dd0d71 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf132076.ods differ diff --git a/chart2/qa/extras/data/ods/tdf59857.ods b/chart2/qa/extras/data/ods/tdf59857.ods new file mode 100644 index 000000000..e60e9c4c1 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf59857.ods differ diff --git a/chart2/qa/extras/data/ods/tdf64224.ods b/chart2/qa/extras/data/ods/tdf64224.ods new file mode 100644 index 000000000..e60e9c4c1 Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf64224.ods differ diff --git a/chart2/qa/extras/data/ods/tdf86624.ods b/chart2/qa/extras/data/ods/tdf86624.ods new file mode 100644 index 000000000..05702371a Binary files /dev/null and b/chart2/qa/extras/data/ods/tdf86624.ods differ diff --git a/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods b/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods new file mode 100644 index 000000000..5ae4fa7d9 Binary files /dev/null and b/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods differ diff --git a/chart2/qa/extras/data/ods/testChartSubTitle.ods b/chart2/qa/extras/data/ods/testChartSubTitle.ods new file mode 100644 index 000000000..1c7814195 Binary files /dev/null and b/chart2/qa/extras/data/ods/testChartSubTitle.ods differ diff --git a/chart2/qa/extras/data/ods/testColorGradientWithTransparancy.ods b/chart2/qa/extras/data/ods/testColorGradientWithTransparancy.ods new file mode 100644 index 000000000..d8a41c02c Binary files /dev/null and b/chart2/qa/extras/data/ods/testColorGradientWithTransparancy.ods 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 000000000..e59546b3d Binary files /dev/null and b/chart2/qa/extras/data/ods/test_CrossBetween.ods 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 000000000..fdc5ea42d Binary files /dev/null and b/chart2/qa/extras/data/ods/trend_calculators.ods differ diff --git a/chart2/qa/extras/data/ods/trendline.ods b/chart2/qa/extras/data/ods/trendline.ods new file mode 100644 index 000000000..707d51020 Binary files /dev/null and b/chart2/qa/extras/data/ods/trendline.ods 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 000000000..35ea152aa Binary files /dev/null and b/chart2/qa/extras/data/odt/axis-position.odt differ diff --git a/chart2/qa/extras/data/odt/chart.odt b/chart2/qa/extras/data/odt/chart.odt new file mode 100644 index 000000000..5f2dd34d2 Binary files /dev/null and b/chart2/qa/extras/data/odt/chart.odt differ diff --git a/chart2/qa/extras/data/odt/multilevelcat.odt b/chart2/qa/extras/data/odt/multilevelcat.odt new file mode 100644 index 000000000..8148e1be1 Binary files /dev/null and b/chart2/qa/extras/data/odt/multilevelcat.odt 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 000000000..ab8f24324 Binary files /dev/null and b/chart2/qa/extras/data/odt/scatter-plot-labels.odt 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 000000000..06e15a6b0 Binary files /dev/null and b/chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt differ diff --git a/chart2/qa/extras/data/odt/tdf108022.odt b/chart2/qa/extras/data/odt/tdf108022.odt new file mode 100644 index 000000000..b8659ec32 Binary files /dev/null and b/chart2/qa/extras/data/odt/tdf108022.odt differ diff --git a/chart2/qa/extras/data/odt/tdf114657.odt b/chart2/qa/extras/data/odt/tdf114657.odt new file mode 100644 index 000000000..4c99963b0 Binary files /dev/null and b/chart2/qa/extras/data/odt/tdf114657.odt differ diff --git a/chart2/qa/extras/data/odt/tdf128733.odt b/chart2/qa/extras/data/odt/tdf128733.odt new file mode 100644 index 000000000..18aace26c Binary files /dev/null and b/chart2/qa/extras/data/odt/tdf128733.odt differ diff --git a/chart2/qa/extras/data/odt/tdf131143.odt b/chart2/qa/extras/data/odt/tdf131143.odt new file mode 100644 index 000000000..e8ffeaf5a Binary files /dev/null and b/chart2/qa/extras/data/odt/tdf131143.odt differ diff --git a/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt b/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt new file mode 100644 index 000000000..0e1ab533b Binary files /dev/null and b/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt differ diff --git a/chart2/qa/extras/data/ppt/chart.ppt b/chart2/qa/extras/data/ppt/chart.ppt new file mode 100644 index 000000000..0efffaf36 Binary files /dev/null and b/chart2/qa/extras/data/ppt/chart.ppt differ diff --git a/chart2/qa/extras/data/pptx/bnc864396.pptx b/chart2/qa/extras/data/pptx/bnc864396.pptx new file mode 100644 index 000000000..e2e05c516 Binary files /dev/null and b/chart2/qa/extras/data/pptx/bnc864396.pptx differ diff --git a/chart2/qa/extras/data/pptx/bnc882383.pptx b/chart2/qa/extras/data/pptx/bnc882383.pptx new file mode 100644 index 000000000..18b44f0c1 Binary files /dev/null and b/chart2/qa/extras/data/pptx/bnc882383.pptx differ diff --git a/chart2/qa/extras/data/pptx/bnc889755.pptx b/chart2/qa/extras/data/pptx/bnc889755.pptx new file mode 100644 index 000000000..f3af67765 Binary files /dev/null and b/chart2/qa/extras/data/pptx/bnc889755.pptx differ diff --git a/chart2/qa/extras/data/pptx/chart.pptx b/chart2/qa/extras/data/pptx/chart.pptx new file mode 100644 index 000000000..8f11ea53d Binary files /dev/null and b/chart2/qa/extras/data/pptx/chart.pptx 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 000000000..280c7ef29 Binary files /dev/null and b/chart2/qa/extras/data/pptx/percentage-number-formats.pptx 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 000000000..d91e8f52f Binary files /dev/null and b/chart2/qa/extras/data/pptx/sparse-chart.pptx 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 000000000..20ba89a0b Binary files /dev/null and b/chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptx 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 000000000..27d099d40 Binary files /dev/null and b/chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf105517.pptx b/chart2/qa/extras/data/pptx/tdf105517.pptx new file mode 100644 index 000000000..ff9d747f0 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf105517.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf106217.pptx b/chart2/qa/extras/data/pptx/tdf106217.pptx new file mode 100644 index 000000000..64fb968b8 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf106217.pptx 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 000000000..629056ecc Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf115107-2.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf115107.pptx b/chart2/qa/extras/data/pptx/tdf115107.pptx new file mode 100644 index 000000000..2ec5c2cd2 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf115107.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf115859.pptx b/chart2/qa/extras/data/pptx/tdf115859.pptx new file mode 100644 index 000000000..07943041b Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf115859.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf116163.pptx b/chart2/qa/extras/data/pptx/tdf116163.pptx new file mode 100644 index 000000000..5fbee8304 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf116163.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf121205.pptx b/chart2/qa/extras/data/pptx/tdf121205.pptx new file mode 100644 index 000000000..e60849ec0 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf121205.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf122765.pptx b/chart2/qa/extras/data/pptx/tdf122765.pptx new file mode 100644 index 000000000..948190c30 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf122765.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf125444.pptx b/chart2/qa/extras/data/pptx/tdf125444.pptx new file mode 100644 index 000000000..e78efecd6 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf125444.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf127393.pptx b/chart2/qa/extras/data/pptx/tdf127393.pptx new file mode 100644 index 000000000..7c4047817 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf127393.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf48041.pptx b/chart2/qa/extras/data/pptx/tdf48041.pptx new file mode 100644 index 000000000..b0872f84f Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf48041.pptx differ diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx new file mode 100644 index 000000000..395546edb Binary files /dev/null and b/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx differ diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx new file mode 100644 index 000000000..361bdd643 Binary files /dev/null and b/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx differ diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx new file mode 100644 index 000000000..a77896dcd Binary files /dev/null and b/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx 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 000000000..2ee38b720 Binary files /dev/null and b/chart2/qa/extras/data/xls/axis_sourceformatting.xls differ diff --git a/chart2/qa/extras/data/xls/chart.xls b/chart2/qa/extras/data/xls/chart.xls new file mode 100644 index 000000000..7c81d7f49 Binary files /dev/null and b/chart2/qa/extras/data/xls/chart.xls 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 000000000..02a4f7b85 Binary files /dev/null and b/chart2/qa/extras/data/xls/piechart_outside.xls 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 000000000..bc54593ac Binary files /dev/null and b/chart2/qa/extras/data/xls/source_number_format_axis.xls 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 000000000..03d7a47f6 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsx 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 000000000..c15756257 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsx 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 000000000..9ce71cf4e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx 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 000000000..a5070273a Binary files /dev/null and b/chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx 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 000000000..cc3b1df8a Binary files /dev/null and b/chart2/qa/extras/data/xlsx/axis-label-rotation.xlsx 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 000000000..635aafe81 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/axis_character_properties.xlsx 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 000000000..5cda3af37 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsx 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 000000000..29e42d8a4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx 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 000000000..fc90e2bf4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/axis_title_rotation.xlsx 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 000000000..52040bf2c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx 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 000000000..621c0c284 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/barchart_outend.xlsx 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 000000000..d13fe5ef4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsx 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 000000000..2baf1e206 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart-area-style-background.xlsx 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 000000000..81a6a6e60 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart-area-style-border.xlsx 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 000000000..a4594ad4f Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart-auto-background.xlsx 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 000000000..4e3394c8e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx 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 000000000..59f907dff Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/chart.xlsx b/chart2/qa/extras/data/xlsx/chart.xlsx new file mode 100644 index 000000000..193bfc49d Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart.xlsx 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 000000000..81c495860 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart_label_text_break.xlsx 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 000000000..b12268025 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart_pie2007.xlsx 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 000000000..0b7985546 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/chart_title.xlsx 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 000000000..e922d4df4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsx 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 000000000..1ccf9b698 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/data_label.xlsx 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 000000000..587c95608 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/deleted_data_labels.xlsx 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 000000000..06a052646 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsx 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 000000000..ea02464b1 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsx 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 000000000..64e673e7c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx 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 000000000..86a0a3596 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx 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 000000000..f2dde80e1 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/external_str_ref.xlsx 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 000000000..dba79ef9c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/fdo54361-1.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/fdo54361.xlsx b/chart2/qa/extras/data/xlsx/fdo54361.xlsx new file mode 100644 index 000000000..2c49802a0 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/fdo54361.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/fdo70609.xlsx b/chart2/qa/extras/data/xlsx/fdo70609.xlsx new file mode 100644 index 000000000..261ef8805 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/fdo70609.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/fdo78080.xlsx b/chart2/qa/extras/data/xlsx/fdo78080.xlsx new file mode 100644 index 000000000..c4a4e3e00 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/fdo78080.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/gapWidth.xlsx b/chart2/qa/extras/data/xlsx/gapWidth.xlsx new file mode 100644 index 000000000..0e9c0eec0 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/gapWidth.xlsx 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 000000000..da3e2da77 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/hidden_cells.xlsx 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 000000000..16ea01142 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/legend_manual_layout.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/majorTickMark.xlsx b/chart2/qa/extras/data/xlsx/majorTickMark.xlsx new file mode 100644 index 000000000..2b6cdcfb3 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/majorTickMark.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/markerColor.xlsx b/chart2/qa/extras/data/xlsx/markerColor.xlsx new file mode 100644 index 000000000..65e87ff38 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/markerColor.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/minorTickMark.xlsx b/chart2/qa/extras/data/xlsx/minorTickMark.xlsx new file mode 100644 index 000000000..2d6879247 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/minorTickMark.xlsx 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 000000000..228c4590f Binary files /dev/null and b/chart2/qa/extras/data/xlsx/no_marker.xlsx 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 000000000..f5250c52e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/number-formats.xlsx 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 000000000..273ebeb82 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsx 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 000000000..e90eab1e9 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/piechart_outside.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx b/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx new file mode 100644 index 000000000..8e4fcbd5e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx 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 000000000..f0bc58813 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/rAngAx.xlsx b/chart2/qa/extras/data/xlsx/rAngAx.xlsx new file mode 100644 index 000000000..f6d521a3e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/rAngAx.xlsx 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 000000000..de5d0391d Binary files /dev/null and b/chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsx 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 000000000..bab00ce13 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/smoothed_series.xlsx 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 000000000..3c8f0cc46 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/smoothed_series2007.xlsx 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 000000000..43789331a Binary files /dev/null and b/chart2/qa/extras/data/xlsx/strict_chart.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf100084.xlsx b/chart2/qa/extras/data/xlsx/tdf100084.xlsx new file mode 100644 index 000000000..5f03f3924 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf100084.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf108107.xlsx b/chart2/qa/extras/data/xlsx/tdf108107.xlsx new file mode 100644 index 000000000..3f86326fa Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf108107.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf111173.xlsx b/chart2/qa/extras/data/xlsx/tdf111173.xlsx new file mode 100644 index 000000000..e62c6747b Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf111173.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf111824.xlsx b/chart2/qa/extras/data/xlsx/tdf111824.xlsx new file mode 100644 index 000000000..ae86756c4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf111824.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf114139.xlsx b/chart2/qa/extras/data/xlsx/tdf114139.xlsx new file mode 100644 index 000000000..ef09575c1 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf114139.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf115012.xlsx b/chart2/qa/extras/data/xlsx/tdf115012.xlsx new file mode 100644 index 000000000..cf8ac7d81 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf115012.xlsx 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 000000000..a20aa0bb1 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf122031.xlsx b/chart2/qa/extras/data/xlsx/tdf122031.xlsx new file mode 100644 index 000000000..ac937a8c7 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf122031.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf122915.xlsx b/chart2/qa/extras/data/xlsx/tdf122915.xlsx new file mode 100644 index 000000000..ff20e04ba Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf122915.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf124817.xlsx b/chart2/qa/extras/data/xlsx/tdf124817.xlsx new file mode 100644 index 000000000..d9b09644e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf124817.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf126033.xlsx b/chart2/qa/extras/data/xlsx/tdf126033.xlsx new file mode 100644 index 000000000..ee60103c9 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf126033.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf126115.xlsx b/chart2/qa/extras/data/xlsx/tdf126115.xlsx new file mode 100644 index 000000000..f845c06e3 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf126115.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf127777.xlsx b/chart2/qa/extras/data/xlsx/tdf127777.xlsx new file mode 100644 index 000000000..c04de30fc Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf127777.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf128619.xlsx b/chart2/qa/extras/data/xlsx/tdf128619.xlsx new file mode 100644 index 000000000..e6eb14259 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf128619.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf128627.xlsx b/chart2/qa/extras/data/xlsx/tdf128627.xlsx new file mode 100644 index 000000000..419c1ad2f Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf128627.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf128633.xlsx b/chart2/qa/extras/data/xlsx/tdf128633.xlsx new file mode 100644 index 000000000..fa186895d Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf128633.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf128634.xlsx b/chart2/qa/extras/data/xlsx/tdf128634.xlsx new file mode 100644 index 000000000..91baa780c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf128634.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf128732.xlsx b/chart2/qa/extras/data/xlsx/tdf128732.xlsx new file mode 100644 index 000000000..b92afb1ed Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf128732.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf130657.xlsx b/chart2/qa/extras/data/xlsx/tdf130657.xlsx new file mode 100644 index 000000000..036da200a Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf130657.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf130986.xlsx b/chart2/qa/extras/data/xlsx/tdf130986.xlsx new file mode 100644 index 000000000..9674fd1ab Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf130986.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf132076.xlsx b/chart2/qa/extras/data/xlsx/tdf132076.xlsx new file mode 100644 index 000000000..799ef9c85 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf132076.xlsx 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 000000000..f8cad0e8c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf133376.xlsx b/chart2/qa/extras/data/xlsx/tdf133376.xlsx new file mode 100644 index 000000000..2000733ec Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf133376.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf134225.xlsx b/chart2/qa/extras/data/xlsx/tdf134225.xlsx new file mode 100644 index 000000000..ae7bdc66e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf134225.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx new file mode 100644 index 000000000..69cad0d67 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx new file mode 100644 index 000000000..ced797258 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf136267.xlsx b/chart2/qa/extras/data/xlsx/tdf136267.xlsx new file mode 100644 index 000000000..741a33c42 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf136267.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf90876.xlsx b/chart2/qa/extras/data/xlsx/tdf90876.xlsx new file mode 100644 index 000000000..3cf60e816 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf90876.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx b/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx new file mode 100644 index 000000000..0835cb333 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx b/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx new file mode 100644 index 000000000..01c6fe56f Binary files /dev/null and b/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx b/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx new file mode 100644 index 000000000..409389e23 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx b/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx new file mode 100644 index 000000000..e73d16bd2 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx new file mode 100644 index 000000000..9d2dff9b3 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx new file mode 100644 index 000000000..9e9aa0bea Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx new file mode 100644 index 000000000..b5b617754 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx b/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx new file mode 100644 index 000000000..47f8246e2 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx b/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx new file mode 100644 index 000000000..caa08956c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx b/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx new file mode 100644 index 000000000..69f89ec0e Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx b/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx new file mode 100644 index 000000000..ba1c526b4 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx b/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx new file mode 100644 index 000000000..ac9dde9b7 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testTdf130032.xlsx b/chart2/qa/extras/data/xlsx/testTdf130032.xlsx new file mode 100644 index 000000000..03a3dbf40 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testTdf130032.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/testTdf90749.xlsx b/chart2/qa/extras/data/xlsx/testTdf90749.xlsx new file mode 100644 index 000000000..ca3bc806c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/testTdf90749.xlsx 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 000000000..2a239936c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/title_character_properties.xlsx 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 000000000..c89b2af4d Binary files /dev/null and b/chart2/qa/extras/data/xlsx/title_manual_layout.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/trendline.xlsx b/chart2/qa/extras/data/xlsx/trendline.xlsx new file mode 100644 index 000000000..701fcfd01 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/trendline.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/trendline2007.xlsx b/chart2/qa/extras/data/xlsx/trendline2007.xlsx new file mode 100644 index 000000000..87d4d5a9c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/trendline2007.xlsx 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 000000000..980cdda34 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/vary_color.xlsx 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 000000000..657c2176d Binary files /dev/null and b/chart2/qa/extras/data/xlsx/vary_color2007.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx b/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx new file mode 100644 index 000000000..cf511dfaf Binary files /dev/null and b/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx differ diff --git a/chart2/qa/extras/xshape/chart2xshape.cxx b/chart2/qa/extras/xshape/chart2xshape.cxx new file mode 100644 index 000000000..a4f24e666 --- /dev/null +++ b/chart2/qa/extras/xshape/chart2xshape.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include + +#include + +#include +#include +#include +#include + +#include + +class Chart2XShapeTest : public ChartTest, public XmlTestTools +{ +public: + + void testFdo75075(); + void testPropertyMappingBarChart(); + void testPieChartLabels1(); + void testPieChartLabels2(); + void testPieChartLabels3(); + void testPieChartLabels4(); + void testTdf76649TrendLineBug(); + void testTdf88154LabelRotatedLayout(); + + CPPUNIT_TEST_SUITE(Chart2XShapeTest); + CPPUNIT_TEST(testFdo75075); + CPPUNIT_TEST(testPropertyMappingBarChart); + CPPUNIT_TEST(testPieChartLabels1); + CPPUNIT_TEST(testPieChartLabels2); + CPPUNIT_TEST(testPieChartLabels3); + CPPUNIT_TEST(testPieChartLabels4); + CPPUNIT_TEST(testTdf76649TrendLineBug); + CPPUNIT_TEST(testTdf88154LabelRotatedLayout); + + CPPUNIT_TEST_SUITE_END(); + +private: + + void compareAgainstReference(const OUString& rReferenceFile, bool bCreateReference = false); + OUString getXShapeDumpString(); + xmlDocUniquePtr getXShapeDumpXmlDoc(); +}; + +namespace { + +bool checkDumpAgainstFile( const OUString& rDump, const OUString& aFilePath) +{ + OString aOFile = OUStringToOString(aFilePath, RTL_TEXTENCODING_UTF8); + + CPPUNIT_ASSERT_MESSAGE("dump is empty", !rDump.isEmpty()); + + OString aDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8); + return doXMLDiff(aOFile.getStr(), aDump.getStr(), + static_cast(rDump.getLength()), nullptr); +} + +} + +OUString Chart2XShapeTest::getXShapeDumpString() +{ + uno::Reference< chart::XChartDocument > xChartDoc ( getChartCompFromSheet( 0, mxComponent ), UNO_QUERY_THROW); + uno::Reference< qa::XDumper > xDumper( xChartDoc, UNO_QUERY_THROW ); + return xDumper->dump(); +} + +xmlDocUniquePtr Chart2XShapeTest::getXShapeDumpXmlDoc() +{ + OUString rDump = getXShapeDumpString(); + OString aXmlDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8); + return xmlDocUniquePtr(xmlParseDoc(reinterpret_cast(aXmlDump.getStr()))); +} + +void Chart2XShapeTest::compareAgainstReference(const OUString& rReferenceFile, bool bCreateReference) +{ + OUString aDump = getXShapeDumpString(); + + OUString aReference = m_directories.getPathFromSrc("/chart2/qa/extras/xshape/data/reference/") + rReferenceFile; + if(bCreateReference) + { + OString aOFile = OUStringToOString(aReference, RTL_TEXTENCODING_UTF8); + OString aODump = OUStringToOString(aDump, RTL_TEXTENCODING_UTF8); + std::ofstream aReferenceFile(aOFile.getStr()); + aReferenceFile << aODump; + } + else + { + checkDumpAgainstFile(aDump, aReference); + } +} + +void Chart2XShapeTest::testFdo75075() +{ +#if 0 + load("chart2/qa/extras/xshape/data/ods/", "fdo75075.ods"); + compareAgainstReference("fdo75075.xml"); +#endif +} + +void Chart2XShapeTest::testPropertyMappingBarChart() +{ +#if 0 + load("chart2/qa/extras/xshape/data/ods/", "property-mapping-bar.ods"); + compareAgainstReference("property-mapping-bar.xml"); +#endif +} + +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 (Application::GetDefaultDevice()->GetDPIX() != 96 + || Application::GetDefaultDevice()->GetDPIY() != 96) + return; + + // inside placement for the best fit case + load("chart2/qa/extras/xshape/data/xlsx/", "tdf90839-1.xlsx"); + compareAgainstReference("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 (Application::GetDefaultDevice()->GetDPIX() != 96 + || Application::GetDefaultDevice()->GetDPIY() != 96) + return; + + // text wrap: wrap all text labels except one + load("chart2/qa/extras/xshape/data/xlsx/", "tdf90839-2.xlsx"); + compareAgainstReference("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 (Application::GetDefaultDevice()->GetDPIX() != 96 + || Application::GetDefaultDevice()->GetDPIY() != 96) + return; + + // text wrap: wrap no text label except one + load("chart2/qa/extras/xshape/data/xlsx/", "tdf90839-3.xlsx"); + compareAgainstReference("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 (Application::GetDefaultDevice()->GetDPIX() != 96 + || Application::GetDefaultDevice()->GetDPIY() != 96) + return; + + // data value and percent value are centered horizontally + load("chart2/qa/extras/xshape/data/ods/", "tdf90839-4.ods"); + compareAgainstReference("tdf90839-4.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. + + load("chart2/qa/extras/xshape/data/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']", 1); +} + +void Chart2XShapeTest::testTdf88154LabelRotatedLayout() +{ + load("chart2/qa/extras/xshape/data/pptx/", "tdf88154_LabelRotatedLayout.pptx"); + uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromDrawImpress(0,6); + uno::Reference< qa::XDumper > xDumper( xChartDoc, UNO_QUERY_THROW ); + OUString rDump = xDumper->dump(); + OString aXmlDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8); + xmlDocUniquePtr pXmlDoc(xmlParseDoc(reinterpret_cast(aXmlDump.getStr()))); + + { + OString aPath( "//XShape[@text='Oct-12']/Transformation" ); + assertXPath(pXmlDoc, aPath, 1); + double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1").toDouble(); + double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2").toDouble(); + double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1").toDouble(); + double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2").toDouble(); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8); + } + { + OString aPath( "//XShape[@text='Nov-12']/Transformation" ); + assertXPath(pXmlDoc, aPath, 1); + double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1").toDouble(); + double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2").toDouble(); + double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1").toDouble(); + double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2").toDouble(); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8); + } + { + OString aPath( "//XShape[@text='Dec-12']/Transformation" ); + assertXPath(pXmlDoc, aPath, 1); + double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1").toDouble(); + double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2").toDouble(); + double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1").toDouble(); + double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2").toDouble(); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8); + } + { + OString aPath( "//XShape[@text='May-13']/Transformation" ); + assertXPath(pXmlDoc, aPath, 1); + double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1").toDouble(); + double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2").toDouble(); + double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1").toDouble(); + double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2").toDouble(); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8); + } + { + OString aPath( "//XShape[@text='Jan-14']/Transformation" ); + assertXPath(pXmlDoc, aPath, 1); + double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1").toDouble(); + double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2").toDouble(); + double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1").toDouble(); + double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2").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 000000000..d2a1be49b Binary files /dev/null and b/chart2/qa/extras/xshape/data/ods/fdo75075.ods 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 000000000..1a4e826df Binary files /dev/null and b/chart2/qa/extras/xshape/data/ods/property-mapping-bar.ods 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 000000000..1032e960b Binary files /dev/null and b/chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.ods 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 000000000..fe9950f27 Binary files /dev/null and b/chart2/qa/extras/xshape/data/ods/tdf90839-4.ods 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 000000000..f3af67765 Binary files /dev/null and b/chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptx 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 000000000..93becacff --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/fdo75075.xml @@ -0,0 +1,1692 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..cc172969f --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml @@ -0,0 +1,1164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..2e255433d --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/tdf90839-1.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..46a4d7986 --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/tdf90839-2.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..074e3df51 --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/tdf90839-3.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..54e0ad187 --- /dev/null +++ b/chart2/qa/extras/xshape/data/reference/tdf90839-4.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..9474de35f Binary files /dev/null and b/chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx 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 000000000..9a5b35228 Binary files /dev/null and b/chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx 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 000000000..e256c3a0b Binary files /dev/null and b/chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx differ diff --git a/chart2/qa/unit/chart2-dialogs-test.cxx b/chart2/qa/unit/chart2-dialogs-test.cxx new file mode 100644 index 000000000..c37fb1e1b --- /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 +#include +#include + +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 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 Chart2DialogsTest::createDialogByID(sal_uInt32 /*nID*/) +{ + return nullptr; +} + +void Chart2DialogsTest::openAnyDialog() +{ + /// process input file containing the UXMLDescriptions of the dialogs to dump + processDialogBatchFile("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 000000000..eaa5a29fc --- /dev/null +++ b/chart2/qa/unit/common_functor_test.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/. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + + +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 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 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 aInput; + aInput.push_back(2.0); + aInput.push_back(10.0); + aInput.push_back(12.0); + aInput.push_back(15.0); + aInput.push_back(25.234); + aInput.push_back(123.456); + aInput.push_back(0.123450); + + std::vector 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 000000000..42deae23e --- /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 VclBuilder +# + +# 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/ods/testChart.ods b/chart2/qa/unit/data/ods/testChart.ods new file mode 100644 index 000000000..956f57d52 Binary files /dev/null and b/chart2/qa/unit/data/ods/testChart.ods differ diff --git a/chart2/qa/unit/data/reference/testChart.xml b/chart2/qa/unit/data/reference/testChart.xml new file mode 100644 index 000000000..03ad3d95f --- /dev/null +++ b/chart2/qa/unit/data/reference/testChart.xml @@ -0,0 +1,1216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/qa/unit/data/tolerance.xml b/chart2/qa/unit/data/tolerance.xml new file mode 100644 index 000000000..b73b0ff15 --- /dev/null +++ b/chart2/qa/unit/data/tolerance.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/chart2/qa/unoapi/knownissues.xcl b/chart2/qa/unoapi/knownissues.xcl new file mode 100644 index 000000000..8321f45d0 --- /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 000000000..54842bfd7 --- /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 000000000..c3a5833ae Binary files /dev/null and b/chart2/qa/unoapi/testdocuments/TransparencyChart.sxs differ diff --git a/chart2/qa/unoapi/testdocuments/emptyChart.sds b/chart2/qa/unoapi/testdocuments/emptyChart.sds new file mode 100644 index 000000000..853a44a12 Binary files /dev/null and b/chart2/qa/unoapi/testdocuments/emptyChart.sds differ diff --git a/chart2/qa/unoapi/testdocuments/space-metal.jpg b/chart2/qa/unoapi/testdocuments/space-metal.jpg new file mode 100644 index 000000000..d23344389 Binary files /dev/null and b/chart2/qa/unoapi/testdocuments/space-metal.jpg differ diff --git a/chart2/source/chartcore.component b/chart2/source/chartcore.component new file mode 100644 index 000000000..f58ba98ba --- /dev/null +++ b/chart2/source/chartcore.component @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/source/controller/accessibility/AccessibleBase.cxx b/chart2/source/controller/accessibility/AccessibleBase.cxx new file mode 100644 index 000000000..6f9192eba --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleBase.cxx @@ -0,0 +1,865 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "AccessibleChartShape.hxx" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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( + const AccessibleElementInfo & rAccInfo, + bool bMayHaveChildren, + bool bAlwaysTransparent /* default: false */ ) : + impl::AccessibleBase_Base( m_aMutex ), + m_bIsDisposed( false ), + m_bMayHaveChildren( bMayHaveChildren ), + m_bChildrenInitialized( false ), + m_nEventNotifierId(0), + m_xStateSetHelper( new ::utl::AccessibleStateSetHelper() ), + m_aAccInfo( rAccInfo ), + m_bAlwaysTransparent( bAlwaysTransparent ), + m_bStateSetInitialized( false ) +{ + // initialize some states + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->AddState( AccessibleStateType::ENABLED ); + m_xStateSetHelper->AddState( AccessibleStateType::SHOWING ); + m_xStateSetHelper->AddState( AccessibleStateType::VISIBLE ); + m_xStateSetHelper->AddState( AccessibleStateType::SELECTABLE ); + m_xStateSetHelper->AddState( 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, true ); + + 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, true ); + 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_Int16 aState ) +{ + CheckDisposeState(); + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->AddState( aState ); +} + +void AccessibleBase::RemoveState( sal_Int16 aState ) +{ + CheckDisposeState(); + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->RemoveState( 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 ) ); + } + 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, + bool bSendGlobally ) const +{ + ClearableMutexGuard aGuard( m_aMutex ); + + if ( !m_nEventNotifierId && !bSendGlobally ) + 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 + //except SendGlobally for focus handling? + + // 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 ); + + if ( m_nEventNotifierId ) // let the notifier handle this event + ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent ); + + aGuard.clear(); + + // send event to global message queue + if( bSendGlobally ) + { + vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); + } +} + +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(), + true /* global notification */ ); +} + +// ________ (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; + + // attach new empty state set helper to member reference + ::utl::AccessibleStateSetHelper * pHelper = new ::utl::AccessibleStateSetHelper(); + pHelper->AddState(AccessibleStateType::DEFUNC); + // release old helper and attach new one + m_xStateSetHelper = pHelper; + + 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_Int32 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_Int32 AccessibleBase::ImplGetAccessibleChildCount() const +{ + return m_aChildList.size(); +} + +Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int32 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_Int32 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_Int32 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; +} + +Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet() +{ + if( ! m_bStateSetInitialized ) + { + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + if ( xSelSupp.is() ) + { + ObjectIdentifier aOID( xSelSupp->getSelection() ); + if ( aOID.isValid() && GetId() == aOID ) + { + AddState( AccessibleStateType::SELECTED ); + AddState( AccessibleStateType::FOCUSED ); + } + } + m_bStateSetInitialized = true; + } + + return m_xStateSetHelper.get(); +} + +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() +{ + ExplicitValueProvider *pExplicitValueProvider( + comphelper::getUnoTunnelImplementation( m_aAccInfo.m_xView )); + if( pExplicitValueProvider ) + { + VclPtr pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow )); + awt::Rectangle aLogicRect( pExplicitValueProvider->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.getX() - aOffset.X, aRect.getY() - aOffset.Y, + aRect.getWidth(), aRect.getHeight()); + } + } + + 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(); + + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + 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 + OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID )); + aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); + } + + xObjProp = + ObjectIdentifier::getObjectPropertySet( + aObjectCID, Reference< chart2::XChartDocument >( 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 000000000..cbee2ddbb --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartElement.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 "AccessibleChartElement.hxx" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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(), Reference< chart2::XChartDocument >( 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 + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + // get factory from selection supplier (controller) + Reference< lang::XMultiServiceFactory > xFact( xSelSupp, uno::UNO_QUERY ); + if( xFact.is()) + { + m_xTextHelper.set( + xFact->createInstance( CHART_ACCESSIBLE_TEXT_SERVICE_NAME ), uno::UNO_QUERY ); + } + } + + if( !m_xTextHelper.is()) + return; + + try + { + Reference< lang::XInitialization > xInit( m_xTextHelper, uno::UNO_QUERY_THROW ); + Sequence< uno::Any > aArgs( 3 ); + aArgs[0] <<= GetInfo().m_aOID.getObjectCID(); + aArgs[1] <<= Reference< XAccessible >( this ); + aArgs[2] <<= Reference< awt::XWindow >( GetInfo().m_xWindow ); + xInit->initialize( aArgs ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// Interfaces + +// ________ AccessibleBase::XAccessibleContext ________ +Reference< XAccessible > AccessibleChartElement::ImplGetAccessibleChildById( sal_Int32 i ) const +{ + Reference< XAccessible > xResult; + + if( m_bHasText ) + xResult.set( m_xTextHelper->getAccessibleChild( i )); + else + xResult.set( AccessibleBase::ImplGetAccessibleChildById( i )); + + return xResult; +} + +sal_Int32 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(), Reference< chart2::XChartDocument >( 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(), Reference< chart2::XChartDocument >( 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 000000000..3e42ea784 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartElement.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTELEMENT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTELEMENT_HXX + +#include +#include + +namespace com::sun::star::accessibility { class XAccessible; } +namespace com::sun::star::accessibility { class XAccessibleContext; } +namespace com::sun::star::awt { class XFont; } + +namespace chart +{ + +/** 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: + +
    +
  • define the getAccessibleName() method of XAccessibleContext
  • +
  • set the ChartModel using SetChartModel() for the first node before + creating any children
  • +
  • override UpdateChildren()
  • +
+ */ + +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_Int32 i ) const override; + virtual sal_Int32 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; + css::uno::Reference< css::accessibility::XAccessibleContext > + m_xTextHelper; + + void InitTextEdit(); +}; + +} // namespace chart + +#endif + +/* 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 000000000..d9c2f7071 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartShape.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include + +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.SetDevice( 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_Int32 AccessibleChartShape::getAccessibleChildCount() +{ + sal_Int32 nCount(0); + if ( m_pAccShape.is() ) + { + nCount = m_pAccShape->getAccessibleChildCount(); + } + return nCount; +} + +Reference< XAccessible > AccessibleChartShape::getAccessibleChild( sal_Int32 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 000000000..d113c03f8 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartShape.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTSHAPE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTSHAPE_HXX + +#include + +#include +#include +#include + +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_Int32 SAL_CALL getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleChild( sal_Int32 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 m_pAccShape; + ::accessibility::AccessibleShapeTreeInfo m_aShapeTreeInfo; +}; + +} // namespace chart + +#endif + +/* 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 000000000..0738f52ab --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartView.cxx @@ -0,0 +1,358 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include "AccessibleViewForwarder.hxx" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +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 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_Int32 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; +} + +// lang::XInitialization + +void SAL_CALL AccessibleChartView::initialize( const Sequence< Any >& rArguments ) +{ + //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; + + Reference< view::XSelectionSupplier > xSelectionSupplier; + Reference< frame::XModel > xChartModel; + Reference< uno::XInterface > xChartView; + Reference< XAccessible > xParent; + Reference< awt::XWindow > xWindow; + { + MutexGuard aGuard( m_aMutex); + xSelectionSupplier.set( m_xSelectionSupplier ); + xChartModel.set( m_xChartModel ); + xChartView.set( m_xChartView ); + xParent.set( m_xParent ); + xWindow.set( m_xWindow ); + } + + if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) + { + bOldInvalid = true; + } + + if( rArguments.getLength() > 1 ) + { + Reference< frame::XModel > xNewChartModel; + rArguments[1] >>= xNewChartModel; + if( xNewChartModel != xChartModel ) + { + xChartModel = xNewChartModel; + bChanged = true; + } + } + else if( xChartModel.is() ) + { + bChanged = true; + xChartModel = nullptr; + } + + if( rArguments.getLength() > 2 ) + { + Reference< uno::XInterface > xNewChartView; + rArguments[2] >>= xNewChartView; + if( xNewChartView != xChartView ) + { + xChartView = xNewChartView; + bChanged = true; + } + } + else if( xChartView.is() ) + { + bChanged = true; + xChartView = nullptr; + } + + if( rArguments.getLength() > 3 ) + { + Reference< XAccessible > xNewParent; + rArguments[3] >>= xNewParent; + if( xNewParent != xParent ) + { + xParent = xNewParent; + bChanged = true; + } + } + + if( rArguments.getLength() > 4 ) + { + Reference< awt::XWindow > xNewWindow; + rArguments[4] >>= xNewWindow; + if( xNewWindow != xWindow ) + { + xWindow.set( xNewWindow ); + bChanged = true; + } + } + + if( rArguments.hasElements() && xChartModel.is() && xChartView.is() ) + { + Reference< view::XSelectionSupplier > xNewSelectionSupplier; + rArguments[0] >>= xNewSelectionSupplier; + if(xSelectionSupplier!=xNewSelectionSupplier) + { + bChanged = true; + if(xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(this); + if(xNewSelectionSupplier.is()) + xNewSelectionSupplier->addSelectionChangeListener(this); + xSelectionSupplier = xNewSelectionSupplier; + } + } + else if( xSelectionSupplier.is() ) + { + bChanged = true; + xSelectionSupplier->removeSelectionChangeListener(this); + xSelectionSupplier = nullptr; + } + + if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) + { + if(xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(this); + xSelectionSupplier = nullptr; + xChartModel.clear(); + xChartView.clear(); + xParent.clear(); + xWindow.clear(); + + bNewInvalid = true; + } + + { + MutexGuard aGuard( m_aMutex); + m_xSelectionSupplier = WeakReference< view::XSelectionSupplier >(xSelectionSupplier); + m_xChartModel = WeakReference< frame::XModel >(xChartModel); + m_xChartView = WeakReference< uno::XInterface >(xChartView); + m_xParent = WeakReference< XAccessible >(xParent); + m_xWindow = WeakReference< awt::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); + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); + if( xChartDoc.is()) + m_spObjectHierarchy = + std::make_shared( xChartDoc, comphelper::getUnoTunnelImplementation(m_xChartView) ); + else + m_spObjectHierarchy.reset(); + } + + { + AccessibleElementInfo aAccInfo; + aAccInfo.m_aOID = ObjectIdentifier("ROOT"); + aAccInfo.m_xChartDocument = uno::WeakReference< chart2::XChartDocument >( + uno::Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY )); + aAccInfo.m_xSelectionSupplier = m_xSelectionSupplier; + 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 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*/ ) +{ + Reference< view::XSelectionSupplier > xSelectionSupplier; + { + MutexGuard aGuard( m_aMutex); + xSelectionSupplier.set(m_xSelectionSupplier); + } + + if( !xSelectionSupplier.is() ) + return; + + ObjectIdentifier aSelectedOID( xSelectionSupplier->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 000000000..620897210 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleTextHelper.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +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 ) : + impl::AccessibleTextHelper_Base( m_aMutex ), + m_pDrawViewWrapper( pDrawViewWrapper ) +{} + +AccessibleTextHelper::~AccessibleTextHelper() +{ +} + +// ____ XInitialization ____ +void SAL_CALL AccessibleTextHelper::initialize( const Sequence< uno::Any >& aArguments ) +{ + OUString aCID; + Reference< XAccessible > xEventSource; + Reference< awt::XWindow > xWindow; + + if( aArguments.getLength() >= 3 ) + { + aArguments[0] >>= aCID; + aArguments[1] >>= xEventSource; + aArguments[2] >>= 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 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(*pTextObj, nullptr, *pView, *pWindow)) ); + m_pTextHelper->SetEventSource( xEventSource ); + } + } + } + + OSL_ENSURE( m_pTextHelper, "Couldn't create text helper" ); +} + +// ____ XAccessibleContext ____ +::sal_Int32 SAL_CALL AccessibleTextHelper::getAccessibleChildCount() +{ + if( m_pTextHelper ) + { + SolarMutexGuard aSolarGuard; + return m_pTextHelper->GetChildCount(); + } + return 0; +} + +Reference< XAccessible > SAL_CALL AccessibleTextHelper::getAccessibleChild( ::sal_Int32 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_Int32 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 >(); +} + +Reference< XAccessibleStateSet > SAL_CALL AccessibleTextHelper::getAccessibleStateSet() +{ + OSL_FAIL( "Not implemented in this helper" ); + return Reference< XAccessibleStateSet >(); +} + +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 000000000..31395f118 --- /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 + +#include + +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.SetPos( Point( 0, 0 ) ); + aVisibleArea.SetSize( m_pWindow->GetOutputSizePixel() ); + aVisibleArea = m_pWindow->PixelToLogic( aVisibleArea, 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 000000000..147b252a6 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLEVIEWFORWARDER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLEVIEWFORWARDER_HXX + +#include +#include +#include + +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 m_pWindow; + MapMode m_aMapMode; +}; + +} // namespace chart + +#endif + +/* 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 000000000..c935074e4 --- /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 +#include "AccessibleChartElement.hxx" + +namespace chart +{ + +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 000000000..2d0b29b9c --- /dev/null +++ b/chart2/source/controller/accessibility/ChartElementFactory.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_CHARTELEMENTFACTORY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_CHARTELEMENTFACTORY_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 AccessibleBase* CreateChartElement( const AccessibleElementInfo& rAccInfo ); +}; + +} // namespace chart + +#endif + +/* 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 000000000..8920b1eda --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/AreaWrapper.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 "AreaWrapper.hxx" +#include "Chart2ModelContact.hxx" +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +struct StaticAreaWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticAreaWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticAreaWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +AreaWrapper::AreaWrapper(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact(spChart2ModelContact) + , m_aEventListenerContainer(m_aMutex) +{ +} + +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() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + MutexGuard aGuard( m_aMutex); + clearWrappedPropertySet(); +} + +void SAL_CALL AreaWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL AreaWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +// WrappedPropertySet +Reference< beans::XPropertySet > AreaWrapper::getInnerPropertySet() +{ + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + if( xChartDoc.is() ) + return xChartDoc->getPageBackground(); + OSL_FAIL("AreaWrapper::getInnerPropertySet() is NULL"); + return nullptr; +} + +const Sequence< beans::Property >& AreaWrapper::getPropertySequence() +{ + return *StaticAreaWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > AreaWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..a0ea50f67 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/AreaWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AREAWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AREAWRAPPER_HXX + +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +namespace wrapper +{ + +class Chart2ModelContact; + +class AreaWrapper : public ::cppu::ImplInheritanceHelper< + WrappedPropertySet + , css::drawing::XShape + , css::lang::XComponent + , css::lang::XServiceInfo + > +{ +public: + explicit AreaWrapper(const std::shared_ptr& 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override; + +private: + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AREAWRAPPER_HXX +#endif + +/* 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 000000000..b15f33f18 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx @@ -0,0 +1,674 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include "Chart2ModelContact.hxx" +#include +#include "GridWrapper.hxx" +#include "TitleWrapper.hxx" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "WrappedCharacterHeightProperty.hxx" +#include "WrappedTextRotationProperty.hxx" +#include "WrappedGapwidthProperty.hxx" +#include "WrappedScaleProperty.hxx" +#include "WrappedNumberFormatProperty.hxx" +#include "WrappedScaleTextProperties.hxx" + +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "Min", + PROP_AXIS_MIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "StepMain", + PROP_AXIS_STEPMAIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "StepHelpCount", + PROP_AXIS_STEPHELP_COUNT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + //deprecated property use 'StepHelpCount' instead + rOutProperties.emplace_back( "StepHelp", + PROP_AXIS_STEPHELP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "AutoMax", + PROP_AXIS_AUTO_MAX, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AutoMin", + PROP_AXIS_AUTO_MIN, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AutoStepMain", + PROP_AXIS_AUTO_STEPMAIN, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AutoStepHelp", + PROP_AXIS_AUTO_STEPHELP, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AxisType", + PROP_AXIS_TYPE, + cppu::UnoType::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::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ExplicitTimeIncrement", + PROP_AXIS_EXPLICIT_TIME_INCREMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::READONLY | + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "Logarithmic", + PROP_AXIS_LOGARITHMIC, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReverseDirection", + PROP_AXIS_REVERSEDIRECTION, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverPosition", + PROP_AXIS_CROSSOVER_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverValue", + PROP_AXIS_CROSSOVER_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "Origin", + PROP_AXIS_ORIGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "AutoOrigin", + PROP_AXIS_AUTO_ORIGIN, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "HelpMarks", + PROP_AXIS_HELPMARKS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MarkPosition", + PROP_AXIS_MARK_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for labels: + rOutProperties.emplace_back( "DisplayLabels", + PROP_AXIS_DISPLAY_LABELS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_AXIS_NUMBERFORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LabelPosition", + PROP_AXIS_LABEL_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextRotation", + PROP_AXIS_TEXT_ROTATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ArrangeOrder", + PROP_AXIS_ARRANGE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextBreak", + PROP_AXIS_TEXTBREAK, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextCanOverlap", + PROP_AXIS_CAN_OVERLAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "StackedText", + PROP_AXIS_STACKEDTEXT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // Properties related to bar charts: + rOutProperties.emplace_back( "Overlap", + PROP_AXIS_OVERLAP, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GapWidth", + PROP_AXIS_GAP_WIDTH, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for labels: + rOutProperties.emplace_back( "BuiltInUnit", + PROP_AXIS_BUILTINUNIT, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MajorOrigin", + PROP_AXIS_MAJOR_ORIGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticAxisWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticAxisWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticAxisWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +AxisWrapper::AxisWrapper( + tAxisType eType, const std::shared_ptr& spChart2ModelContact) : + m_spChart2ModelContact( spChart2ModelContact ), + m_aEventListenerContainer( m_aMutex ), + 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() +{ + Reference< util::XNumberFormatsSupplier > xNumSuppl( m_spChart2ModelContact->getChartModel(), uno::UNO_QUERY ); + if( xNumSuppl.is() ) + return xNumSuppl->getNumberFormatSettings(); + + return uno::Reference< beans::XPropertySet >(); +} + +uno::Reference< util::XNumberFormats > SAL_CALL AxisWrapper::getNumberFormats() +{ + Reference< util::XNumberFormatsSupplier > xNumSuppl( m_spChart2ModelContact->getChartModel(), uno::UNO_QUERY ); + if( xNumSuppl.is() ) + return xNumSuppl->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() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( 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 ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL AxisWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( 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() +{ + Reference< chart2::XAxis > xAxis; + try + { + sal_Int32 nDimensionIndex = 0; + bool bMainAxis = true; + AxisWrapper::getDimensionAndMainAxisBool( m_eType, nDimensionIndex, bMainAxis ); + + Reference< XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + xAxis = AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ); + if( !xAxis.is() ) + { + xAxis = AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, m_spChart2ModelContact->m_xContext ); + Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY ); + if( xProp.is() ) + xProp->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::get(); +} + +std::vector< std::unique_ptr > AxisWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..b6770a5a2 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/AxisWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AXISWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AXISWRAPPER_HXX + +#include +#include "ReferenceSizePropertyProvider.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::chart2 { class XAxis; } + +namespace chart +{ +namespace 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, const std::shared_ptr& 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 > 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::OInterfaceContainerHelper2 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 wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_AXISWRAPPER_HXX +#endif + +/* 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 000000000..e0cd9e031 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx @@ -0,0 +1,295 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 ), + mpModel( nullptr ) +{ +} + +Chart2ModelContact::~Chart2ModelContact() +{ + clear(); +} + +void Chart2ModelContact::setModel( const css::uno::Reference< css::frame::XModel >& xChartModel ) +{ + clear(); + m_xChartModel = xChartModel; + mpModel = dynamic_cast(xChartModel.get()); + uno::Reference< lang::XMultiServiceFactory > xTableFactory( xChartModel, uno::UNO_QUERY ); + if( !xTableFactory.is() ) + return; + + uno::Reference< container::XNameContainer > xDashTable( xTableFactory->createInstance("com.sun.star.drawing.DashTable"), uno::UNO_QUERY ); + uno::Reference< container::XNameContainer > xGradientTable( xTableFactory->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY ); + uno::Reference< container::XNameContainer > xHatchTable( xTableFactory->createInstance("com.sun.star.drawing.HatchTable"), uno::UNO_QUERY ); + uno::Reference< container::XNameContainer > xBitmapTable( xTableFactory->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY ); + uno::Reference< container::XNameContainer > xTransparencyGradientTable( xTableFactory->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(); + mpModel = nullptr; +} + +Reference< frame::XModel > Chart2ModelContact::getChartModel() const +{ + return Reference< frame::XModel >( m_xChartModel.get(), uno::UNO_QUERY ); +} + +Reference< chart2::XChartDocument > Chart2ModelContact::getChart2Document() const +{ + return Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY ); +} + +Reference< chart2::XDiagram > Chart2ModelContact::getChart2Diagram() const +{ + return ChartModelHelper::findDiagram( getChartModel() ); +} + +uno::Reference< lang::XUnoTunnel > const & Chart2ModelContact::getChartView() const +{ + if(!m_xChartView.is()) + { + // get the chart view + Reference xModel(m_xChartModel); + uno::Reference< lang::XMultiServiceFactory > xFact( xModel, uno::UNO_QUERY ); + if( xFact.is() ) + m_xChartView.set( xFact->createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + } + return m_xChartView; +} + +ExplicitValueProvider* Chart2ModelContact::getExplicitValueProvider() const +{ + getChartView(); + if(!m_xChartView.is()) + return nullptr; + + //obtain the ExplicitValueProvider from the chart view + ExplicitValueProvider* pProvider = reinterpret_cast(m_xChartView->getSomething( + ExplicitValueProvider::getUnoTunnelId() )); + return pProvider; +} + +uno::Reference< drawing::XDrawPage > Chart2ModelContact::getDrawPage() const +{ + uno::Reference< drawing::XDrawPage > xResult; + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + { + xResult.set( pProvider->getDrawModelWrapper()->getMainDrawPage() ); + } + return xResult; +} + +void Chart2ModelContact::getExplicitValuesForAxis( + const Reference< XAxis > & xAxis, + ExplicitScaleData & rOutExplicitScale, + ExplicitIncrementData & rOutExplicitIncrement ) +{ + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + { + pProvider->getExplicitValuesForAxis( + xAxis, rOutExplicitScale, rOutExplicitIncrement ); + } +} + +sal_Int32 Chart2ModelContact::getExplicitNumberFormatKeyForAxis( + const Reference< chart2::XAxis >& xAxis ) +{ + Reference< chart2::XCoordinateSystem > xCooSys( + AxisHelper::getCoordinateSystemOfAxis( + xAxis, ChartModelHelper::findDiagram( m_xChartModel ) ) ); + + return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( xAxis, xCooSys + , getChart2Document()); +} + +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); +} + +awt::Rectangle Chart2ModelContact::SubstractAxisTitleSizes( const awt::Rectangle& rPositionRect ) +{ + awt::Rectangle aRect = ExplicitValueProvider::AddSubtractAxisTitleSizes( + *mpModel, getChartView(), rPositionRect, true ); + return aRect; +} + +awt::Rectangle Chart2ModelContact::GetDiagramRectangleIncludingTitle() const +{ + awt::Rectangle aRect( GetDiagramRectangleIncludingAxes() ); + + //add axis title sizes to the diagram size + aRect = ExplicitValueProvider::AddSubtractAxisTitleSizes( + *mpModel, getChartView(), aRect, false ); + + return aRect; +} + +awt::Rectangle Chart2ModelContact::GetDiagramRectangleIncludingAxes() const +{ + awt::Rectangle aRect(0,0,0,0); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + + if( DiagramHelper::getDiagramPositioningMode( xDiagram ) == DiagramPositioningMode_INCLUDING ) + aRect = DiagramHelper::getDiagramRectangleFromModel(m_xChartModel); + else + { + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + aRect = pProvider->getRectangleOfObject("PlotAreaIncludingAxes"); + } + return aRect; +} + +awt::Rectangle Chart2ModelContact::GetDiagramRectangleExcludingAxes() const +{ + awt::Rectangle aRect(0,0,0,0); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + + if( DiagramHelper::getDiagramPositioningMode( xDiagram ) == DiagramPositioningMode_EXCLUDING ) + aRect = DiagramHelper::getDiagramRectangleFromModel(m_xChartModel); + else + { + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + aRect = pProvider->getDiagramRectangleExcludingAxes(); + } + return aRect; +} + +awt::Size Chart2ModelContact::GetLegendSize() const +{ + awt::Size aSize; + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + { + uno::Reference< chart2::XLegend > xLegend( LegendHelper::getLegend( *mpModel ) ); + OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, *mpModel ) ); + aSize = ToSize( pProvider->getRectangleOfObject( aCID ) ); + } + return aSize; +} + +awt::Point Chart2ModelContact::GetLegendPosition() const +{ + awt::Point aPoint; + ExplicitValueProvider* pProvider( getExplicitValueProvider() ); + if( pProvider ) + { + uno::Reference< chart2::XLegend > xLegend( LegendHelper::getLegend( *mpModel ) ); + OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, *mpModel ) ); + 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 ) ); + 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 ) ); + 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 ) ); + 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 000000000..5f3448edc --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHART2MODELCONTACT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHART2MODELCONTACT_HXX + +#include +#include +#include +#include + +#include + +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 setModel( const css::uno::Reference< css::frame::XModel >& xChartModel ); + void clear(); + + css::uno::Reference< css::frame::XModel > getChartModel() const; + + ChartModel* getModel() const { return mpModel;} + + css::uno::Reference< css::chart2::XChartDocument > getChart2Document() const; + css::uno::Reference< css::chart2::XDiagram > getChart2Diagram() const; + + css::uno::Reference< css::drawing::XDrawPage > getDrawPage() const; + + /** get the current values calculated for an axis in the current view in + case properties are 'auto'. + */ + void getExplicitValuesForAxis( + const css::uno::Reference< css::chart2::XAxis > & xAxis, + ExplicitScaleData & rOutExplicitScale, + ExplicitIncrementData & rOutExplicitIncrement ); + + sal_Int32 getExplicitNumberFormatKeyForAxis( + const css::uno::Reference< css::chart2::XAxis >& 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; + css::uno::Reference< css::lang::XUnoTunnel > const & getChartView() const; + +public: //member + css::uno::Reference< css::uno::XComponentContext > m_xContext; + +private: //member + css::uno::WeakReference< css::frame::XModel > m_xChartModel; + + ChartModel* mpModel; + + mutable css::uno::Reference< css::lang::XUnoTunnel > m_xChartView; + + std::map< OUString, css::uno::Reference< css::container::XNameContainer > > m_aTableMap; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHART2MODELCONTACT_HXX +#endif + +/* 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 000000000..48a448edf --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx @@ -0,0 +1,695 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include "Chart2ModelContact.hxx" +#include +#include +#include + +#include +#include +#include + +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 ); + for( sal_Int32 nOuter=0; nOuter > 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 ); + for( sal_Int32 nOuter=0; nOuter& xDataAccess ) = 0; + + virtual bool setsCategories( bool /*bDataInColumns*/ ) + { + return false; + } +}; + +namespace { + +struct lcl_AllOperator : public lcl_Operator +{ + explicit lcl_AllOperator( const Reference< XChartData >& xDataToApply ) + : lcl_Operator() + , 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 ) + : lcl_Operator() + , 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 + , const Reference< chart2::XChartDocument >& xChartDoc ) + : lcl_Operator() + , m_rRowDescriptions( rRowDescriptions ) + , m_xChartDoc(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; + Reference< chart2::XChartDocument > m_xChartDoc; + bool m_bDataInColumns; +}; + +struct lcl_ComplexRowDescriptionsOperator : public lcl_Operator +{ + lcl_ComplexRowDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexRowDescriptions + , const Reference< chart2::XChartDocument >& xChartDoc ) + : lcl_Operator() + , m_rComplexRowDescriptions( rComplexRowDescriptions ) + , m_xChartDoc(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; + Reference< chart2::XChartDocument > m_xChartDoc; + bool m_bDataInColumns; +}; + +struct lcl_AnyRowDescriptionsOperator : public lcl_Operator +{ + explicit lcl_AnyRowDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyRowDescriptions ) + : lcl_Operator() + , 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 + , const Reference< chart2::XChartDocument >& xChartDoc ) + : lcl_Operator() + , m_rColumnDescriptions( rColumnDescriptions ) + , m_xChartDoc(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; + Reference< chart2::XChartDocument > m_xChartDoc; + bool m_bDataInColumns; +}; + +struct lcl_ComplexColumnDescriptionsOperator : public lcl_Operator +{ + lcl_ComplexColumnDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexColumnDescriptions + , const Reference< chart2::XChartDocument >& xChartDoc ) + : lcl_Operator() + , m_rComplexColumnDescriptions( rComplexColumnDescriptions ) + , m_xChartDoc(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; + Reference< chart2::XChartDocument > m_xChartDoc; + bool m_bDataInColumns; +}; + +struct lcl_AnyColumnDescriptionsOperator : public lcl_Operator +{ + explicit lcl_AnyColumnDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyColumnDescriptions ) + : lcl_Operator() + , 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 ) + : lcl_Operator() + , 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(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact(spChart2ModelContact) + , m_aEventListenerContainer(m_aMutex) +{ + osl_atomic_increment( &m_refCount ); + initDataAccess(); + osl_atomic_decrement( &m_refCount ); +} + +ChartDataWrapper::ChartDataWrapper( const std::shared_ptr& spChart2ModelContact, + const Reference< XChartData >& xNewData ) : + m_spChart2ModelContact( spChart2ModelContact ), + m_aEventListenerContainer( m_aMutex ) +{ + 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->getChart2Document() ); + applyData( aOperator ); +} +void SAL_CALL ChartDataWrapper::setColumnDescriptions( const Sequence< OUString >& rColumnDescriptions ) +{ + lcl_ColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() ); + applyData( aOperator ); +} + +// ____ XComplexDescriptionAccess (write) ____ +void SAL_CALL ChartDataWrapper::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& rRowDescriptions ) +{ + lcl_ComplexRowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getChart2Document() ); + applyData( aOperator ); +} +void SAL_CALL ChartDataWrapper::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& rColumnDescriptions ) +{ + lcl_ComplexColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() ); + 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 ) +{ + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + 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 ) +{ + m_aEventListenerContainer.addInterface( aListener ); +} + +void SAL_CALL ChartDataWrapper::removeChartDataChangeEventListener( + const uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( 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() +{ + m_aEventListenerContainer.disposeAndClear( lang::EventObject( static_cast< ::cppu::OWeakObject* >( this ))); + m_xDataAccess=nullptr; +} + +void SAL_CALL ChartDataWrapper::addEventListener( + const uno::Reference< lang::XEventListener > & xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL ChartDataWrapper::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +// ____ XEventListener ____ +void SAL_CALL ChartDataWrapper::disposing( const lang::EventObject& /* Source */ ) +{ +} + +void ChartDataWrapper::fireChartDataChangeEvent( css::chart::ChartDataChangeEvent& aEvent ) +{ + if( ! m_aEventListenerContainer.getLength() ) + return; + + uno::Reference< uno::XInterface > xSrc( static_cast< cppu::OWeakObject* >( this )); + OSL_ASSERT( xSrc.is()); + if( xSrc.is() ) + aEvent.Source = xSrc; + + m_aEventListenerContainer.notifyEach( &css::chart::XChartDataChangeEventListener::chartDataChanged, aEvent ); +} + +void ChartDataWrapper::switchToInternalDataProvider() +{ + //create an internal data provider that is connected to the model + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + if( xChartDoc.is() ) + xChartDoc->createInternalDataProvider( true /*bCloneExistingData*/ ); + initDataAccess(); +} + +void ChartDataWrapper::initDataAccess() +{ + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + 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 + m_xDataAccess.set( ChartModelHelper::createInternalDataProvider( + xChartDoc, false /*bConnectToModel*/ ), uno::UNO_QUERY_THROW ); + } +} + +void ChartDataWrapper::applyData( lcl_Operator& rDataOperator ) +{ + //bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + 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( xChartDoc, 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; + + 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 ) ); + + uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram() ); + 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; + DiagramHelper::setStackMode( xDia, 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 000000000..55bb8c63b --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHARTDATAWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHARTDATAWRAPPER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ +namespace wrapper +{ + +class Chart2ModelContact; +struct lcl_Operator; + +class ChartDataWrapper final : public MutexContainer, public + ::cppu::WeakImplHelper< + css::chart2::XAnyDescriptionAccess, + css::chart::XDateCategories, + css::lang::XServiceInfo, + css::lang::XEventListener, + css::lang::XComponent > +{ +public: + explicit ChartDataWrapper(const std::shared_ptr& spChart2ModelContact); + ChartDataWrapper(const std::shared_ptr& 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 ); + + css::uno::Reference< css::chart2::XAnyDescriptionAccess > m_xDataAccess; + + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_CHARTDATAWRAPPER_HXX +#endif + +/* 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 000000000..f385c399c --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx @@ -0,0 +1,1454 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "DataSeriesPointWrapper.hxx" +#include +#include +#include "Chart2ModelContact.hxx" + +#include + +#include +#include +#include +#include +#include + +#include "TitleWrapper.hxx" +#include "ChartDataWrapper.hxx" +#include "DiagramWrapper.hxx" +#include "LegendWrapper.hxx" +#include "AreaWrapper.hxx" +#include "WrappedAddInProperty.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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.ExportGraphicStoreageHandler", SERVICE_NAME_EXPORT_GRAPHIC_STORAGE_RESOLVER}, + {"com.sun.star.document.ImportGraphicStoreageHandler", 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::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasSubTitle", + PROP_DOCUMENT_HAS_SUB_TITLE, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasLegend", + PROP_DOCUMENT_HAS_LEGEND, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataSourceLabelsInFirstColumn", + PROP_DOCUMENT_LABELS_IN_FIRST_COLUMN, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + //add-in + rOutProperties.emplace_back( "AddIn", + PROP_DOCUMENT_ADDIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "BaseDiagram", + PROP_DOCUMENT_BASEDIAGRAM, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "AdditionalShapes", + PROP_DOCUMENT_ADDITIONAL_SHAPES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::READONLY ); + rOutProperties.emplace_back( "RefreshAddInAllowed", + PROP_DOCUMENT_UPDATE_ADDIN, + cppu::UnoType::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::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "EnableComplexChartTypes", + PROP_DOCUMENT_ENABLE_COMPLEX_CHARTTYPES, + cppu::UnoType::get(), + //#i112666# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "EnableDataTableDialog", + PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG, + cppu::UnoType::get(), + //#i112666# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticChartDocumentWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticChartDocumentWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticChartDocumentWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +namespace { + +//PROP_DOCUMENT_LABELS_IN_FIRST_ROW +class WrappedDataSourceLabelsInFirstRowProperty : public WrappedProperty +{ +public: + explicit WrappedDataSourceLabelsInFirstRowProperty(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("DataSourceLabelsInFirstRow",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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->getChartModel(), aRangeString, aSequenceMapping, bUseColumns + , bFirstCellAsLabel, bHasCategories ) ) + return; + + if( bUseColumns && bNewValue != bFirstCellAsLabel ) + { + DataSourceHelper::setRangeSegmentation( + m_spChart2ModelContact->getChartModel(), aSequenceMapping, bUseColumns ,bNewValue, bHasCategories ); + } + else if( !bUseColumns && bNewValue != bHasCategories ) + { + DataSourceHelper::setRangeSegmentation( + m_spChart2ModelContact->getChartModel(), 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->getChartModel(), 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("DataSourceLabelsInFirstColumn",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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->getChartModel(), aRangeString, aSequenceMapping, bUseColumns + , bFirstCellAsLabel, bHasCategories ) ) + return; + + if( bUseColumns && bNewValue != bHasCategories ) + { + DataSourceHelper::setRangeSegmentation( + m_spChart2ModelContact->getChartModel(), aSequenceMapping, bUseColumns, bFirstCellAsLabel, bNewValue ); + } + else if( !bUseColumns && bNewValue != bFirstCellAsLabel ) + { + DataSourceHelper::setRangeSegmentation( + m_spChart2ModelContact->getChartModel(), 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->getChartModel(), 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("HasLegend",OUString()) + , m_spChart2ModelContact( 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 + { + Reference< chart2::XLegend > xLegend( LegendHelper::getLegend( *m_spChart2ModelContact->getModel(), m_spChart2ModelContact->m_xContext,bNewValue )); + if(xLegend.is()) + { + Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY_THROW ); + bool bOldValue = true; + Any aAOld = xLegendProp->getPropertyValue("Show"); + aAOld >>= bOldValue; + if( bOldValue != bNewValue ) + xLegendProp->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 + { + Reference< beans::XPropertySet > xLegendProp( + LegendHelper::getLegend( *m_spChart2ModelContact->getModel() ), uno::UNO_QUERY ); + if( xLegendProp.is()) + aRet = xLegendProp->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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("HasMainTitle",OUString()) + , m_spChart2ModelContact( 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->getChartModel(), m_spChart2ModelContact->m_xContext ); + else + TitleHelper::removeTitle( TitleHelper::MAIN_TITLE, m_spChart2ModelContact->getChartModel() ); + } + 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->getChartModel() ).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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("HasSubTitle",OUString()) + , m_spChart2ModelContact( 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->getChartModel(), m_spChart2ModelContact->m_xContext ); + else + TitleHelper::removeTitle( TitleHelper::SUB_TITLE, m_spChart2ModelContact->getChartModel() ); + } + 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->getChartModel() ).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( xContext ) ), + m_bUpdateAddIn( true ), + m_bIsDisposed( false ) +{ +} + +ChartDocumentWrapper::~ChartDocumentWrapper() +{ + stopAllComponentListening(); +} + +// ____ XInterface (for new interfaces) ____ +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->getChart2Document() ); + 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->getChart2Document() ); + 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 + { + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + 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->getChart2Document() ); + m_xChartData.set( new ChartDataWrapper( m_spChart2ModelContact, xNewData ) ); +} + +// ____ XModel ____ +sal_Bool SAL_CALL ChartDocumentWrapper::attachResource( + const OUString& URL, + const Sequence< beans::PropertyValue >& Arguments ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->attachResource( URL, Arguments ); + return false; +} + +OUString SAL_CALL ChartDocumentWrapper::getURL() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->getURL(); + return OUString(); +} + +Sequence< beans::PropertyValue > SAL_CALL ChartDocumentWrapper::getArgs() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->getArgs(); + return Sequence< beans::PropertyValue >(); +} + +void SAL_CALL ChartDocumentWrapper::connectController( const Reference< frame::XController >& Controller ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->connectController( Controller ); +} + +void SAL_CALL ChartDocumentWrapper::disconnectController( + const Reference< frame::XController >& Controller ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->disconnectController( Controller ); +} + +void SAL_CALL ChartDocumentWrapper::lockControllers() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->lockControllers(); +} + +void SAL_CALL ChartDocumentWrapper::unlockControllers() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->unlockControllers(); +} + +sal_Bool SAL_CALL ChartDocumentWrapper::hasControllersLocked() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->hasControllersLocked(); + return false; +} + +Reference< frame::XController > SAL_CALL ChartDocumentWrapper::getCurrentController() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->getCurrentController(); + return nullptr; +} + +void SAL_CALL ChartDocumentWrapper::setCurrentController( + const Reference< frame::XController >& Controller ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->setCurrentController( Controller ); +} + +Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::getCurrentSelection() +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + return xModel->getCurrentSelection(); + return nullptr; +} + +// ____ XComponent ____ +void SAL_CALL ChartDocumentWrapper::dispose() +{ + if( m_bIsDisposed ) + throw lang::DisposedException("ChartDocumentWrapper is disposed", + static_cast< ::cppu::OWeakObject* >( this )); + + 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.set( nullptr ); + m_xShapeFactory.set( nullptr ); + m_xDelegator.set( nullptr ); + + 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.set( nullptr ); + + 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->getChartModel() ); + 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->getChartModel() ); + 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( static_cast(this), uno::UNO_QUERY ); + 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; + uno::Reference< drawing::XDrawPage > xDrawPage( impl_getDrawPage() ); + + if( !xDrawPage.is() ) + return xFoundShapes; + + uno::Reference 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 ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->addEventListener( xListener ); +} + +void SAL_CALL ChartDocumentWrapper::removeEventListener( const Reference< lang::XEventListener >& aListener ) +{ + Reference< frame::XModel > xModel( m_spChart2ModelContact->getChartModel() ); + if( xModel.is() ) + xModel->removeEventListener( aListener ); +} + +// ____ XDrawPageSupplier ____ +uno::Reference< drawing::XDrawPage > SAL_CALL ChartDocumentWrapper::getDrawPage() +{ + return impl_getDrawPage(); +} + +uno::Reference< drawing::XDrawPage > ChartDocumentWrapper::impl_getDrawPage() const +{ + return m_spChart2ModelContact->getDrawPage(); +} + +namespace { + +uno::Reference< lang::XMultiServiceFactory > getShapeFactory(const uno::Reference& xChartView) +{ + auto pProvider = comphelper::getUnoTunnelImplementation(xChartView); + if( pProvider ) + return pProvider->getDrawModelWrapper()->getShapeFactory(); + + return uno::Reference< lang::XMultiServiceFactory >(); +} + +} + +// ____ XMultiServiceFactory ____ +uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance( + const OUString& aServiceSpecifier ) +{ + uno::Reference< uno::XInterface > xResult; + + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + 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; + uno::Reference< lang::XMultiServiceFactory > xManagerFact( + xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + uno::Reference< chart2::XChartTypeTemplate > xTemplate; + + switch( (*aIt).second ) + { + case SERVICE_NAME_AREA_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Area"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_BAR_DIAGRAM: + if( xManagerFact.is()) + { + // this is for bar and column (the latter is the default if + // no "Vertical=false" property was set) + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Column"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_DONUT_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Donut"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_LINE_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Line"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_NET_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Net"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_FILLED_NET_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.FilledNet"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_PIE_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Pie"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_STOCK_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.StockLowHighClose"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_XY_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.ScatterLineSymbol"), + uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + + case SERVICE_NAME_BUBBLE_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance("com.sun.star.chart2.template.Bubble"), + uno::UNO_QUERY ); + 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: + { + uno::Reference< lang::XMultiServiceFactory > xTableFactory( xChartDoc, uno::UNO_QUERY ); + OSL_ENSURE( xTableFactory.get() != this, "new model is expected to implement service factory for gradient table etc" ); + if( xTableFactory.is() && xTableFactory.get() != this ) + xResult.set( xTableFactory->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 ); + Reference< chart2::XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartDoc ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + Reference< lang::XMultiServiceFactory > xTemplateManager( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateWithService( + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateManager )); + if( aTemplateWithService.first.is()) + aTemplateWithService.first->resetStyles( xDiagram );//#i109371# + xTemplate->changeDiagram( xDiagram ); + if( AllSettings::GetMathLayoutRTL() ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + ThreeDHelper::setScheme( xDiagram, 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() ) + { + Reference< lang::XMultiServiceFactory > xFact( + m_spChart2ModelContact->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW ); + Reference< lang::XInitialization > xViewInit( xFact->createInstance( + CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if(xViewInit.is()) + { + try + { + m_xChartView = xViewInit; + + Sequence< Any > aArguments(2); + aArguments[0] <<= Reference(this); + aArguments[1] <<= true; // bRefreshAddIn + xViewInit->initialize(aArguments); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + xResult.set( m_xChartView ); + bServiceFound = true; + } + else + { + // try to create a shape + try + { + if( !m_xShapeFactory.is() && m_xChartView.is() ) + { + m_xShapeFactory = getShapeFactory( m_xChartView ); + } + else + { + ChartModel* pModel = m_spChart2ModelContact->getModel(); + 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; + m_spChart2ModelContact->setModel( uno::Reference< frame::XModel >(m_xDelegator, uno::UNO_QUERY) ); + } + 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.set( nullptr ); + else if( rSource.Source == m_xSubTitle ) + m_xSubTitle.set( nullptr ); + else if( rSource.Source == m_xLegend ) + m_xLegend.set( nullptr ); + else if( rSource.Source == m_xChartData ) + m_xChartData.set( nullptr ); + else if( rSource.Source == m_xDiagram ) + m_xDiagram.set( nullptr ); + else if( rSource.Source == m_xArea ) + m_xArea.set( nullptr ); + else if( rSource.Source == m_xAddIn ) + m_xAddIn.set( nullptr ); + else if( rSource.Source == m_xChartView ) + m_xChartView.set( nullptr ); +} + +// WrappedPropertySet +Reference< beans::XPropertySet > ChartDocumentWrapper::getInnerPropertySet() +{ + return nullptr; +} +const Sequence< beans::Property >& ChartDocumentWrapper::getPropertySequence() +{ + return *StaticChartDocumentWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > ChartDocumentWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 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 000000000..a6d45ddda --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx @@ -0,0 +1,885 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include "WrappedCharacterHeightProperty.hxx" +#include +#include +#include "WrappedStatisticProperties.hxx" +#include "WrappedSymbolProperties.hxx" +#include "WrappedDataCaptionProperties.hxx" +#include "WrappedSeriesAreaOrLineProperty.hxx" +#include "WrappedScaleTextProperties.hxx" +#include "WrappedNumberFormatProperty.hxx" +#include "WrappedTextRotationProperty.hxx" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::chart::wrapper; + +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_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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "SegmentOffset", + PROP_SERIES_DATAPOINT_SEGMENT_OFFSET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "D3DPercentDiagonal", + PROP_SERIES_DATAPOINT_PERCENT_DIAGONAL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LabelSeparator", + PROP_SERIES_DATAPOINT_LABEL_SEPARATOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_SERIES_NUMBERFORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "PercentageNumberFormat", + PROP_SERIES_PERCENTAGE_NUMBERFORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "TextWordWrap", + PROP_SERIES_DATAPOINT_TEXT_WORD_WRAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LabelPlacement", + PROP_SERIES_DATAPOINT_LABEL_PLACEMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "TextRotation", + PROP_SERIES_DATAPOINT_TEXT_ROTATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_STYLE, + PROP_SERIES_DATAPOINT_LABEL_BORDER_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_STYLE, + PROP_SERIES_DATAPOINT_LABEL_FILL_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_COLOR, + PROP_SERIES_DATAPOINT_LABEL_FILL_COLOR, + cppu::UnoType::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::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_WIDTH, + PROP_SERIES_DATAPOINT_LABEL_BORDER_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_COLOR, + PROP_SERIES_DATAPOINT_LABEL_BORDER_COLOR, + cppu::UnoType::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::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::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 ); +} + +struct StaticSeriesWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence( DataSeriesPointWrapper::DATA_SERIES ) ); + return &aPropSeq; + } +}; + +struct StaticSeriesWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticSeriesWrapperPropertyArray_Initializer > +{ +}; + +struct StaticPointWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence( DataSeriesPointWrapper::DATA_POINT ) ); + return &aPropSeq; + } +}; + +struct StaticPointWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticPointWrapperPropertyArray_Initializer > +{ +}; + +//PROP_SERIES_ATTACHED_AXIS +class WrappedAttachedAxisProperty : public ::chart::WrappedProperty +{ +public: + explicit WrappedAttachedAxisProperty(const std::shared_ptr& 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& 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; + + uno::Reference< chart2::XDataSeries > xDataSeries( xInnerPropertySet, uno::UNO_QUERY ); + 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 +{ + uno::Reference< chart2::XDataSeries > xDataSeries( xInnerPropertySet, uno::UNO_QUERY ); + + 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) + { + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + ::chart::DiagramHelper::attachSeriesToAxis( bNewAttachedToMainAxis, xDataSeries, xDiagram, 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(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact( spChart2ModelContact ) + , m_aEventListenerContainer( m_aMutex ) + , 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() ) + { + aArguments[0] >>= m_xDataSeries; + 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 + const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact( spChart2ModelContact ) + , m_aEventListenerContainer( m_aMutex ) + , m_eType( _eType ) + , m_nSeriesIndexInNewAPI( nSeriesIndexInNewAPI ) + , m_nPointIndex( (_eType == DATA_POINT) ? nPointIndex : -1 ) + , m_bLinesAllowed( false ) +{ +} + +DataSeriesPointWrapper::~DataSeriesPointWrapper() +{ +} + +// ____ XComponent ____ +void SAL_CALL DataSeriesPointWrapper::dispose() +{ + uno::Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + m_xDataSeries.clear(); + clearWrappedPropertySet(); +} + +void SAL_CALL DataSeriesPointWrapper::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL DataSeriesPointWrapper::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +// ____ XEventListener ____ +void SAL_CALL DataSeriesPointWrapper::disposing( const lang::EventObject& /*Source*/ ) +{ +} + +bool DataSeriesPointWrapper::isSupportingAreaProperties() +{ + Reference< chart2::XDataSeries > xSeries( getDataSeries() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + return ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount ); +} + +Reference< chart2::XDataSeries > DataSeriesPointWrapper::getDataSeries() +{ + Reference< chart2::XDataSeries > xSeries( m_xDataSeries ); + if( !xSeries.is() ) + { + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesList( + ::chart::DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + + if( m_nSeriesIndexInNewAPI >= 0 && m_nSeriesIndexInNewAPI < static_cast(aSeriesList.size()) ) + xSeries = aSeriesList[m_nSeriesIndexInNewAPI]; + } + + return xSeries; +} + +Reference< beans::XPropertySet > DataSeriesPointWrapper::getDataPointProperties() +{ + Reference< beans::XPropertySet > xPointProp; + + Reference< chart2::XDataSeries > 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") + { + Reference< beans::XPropertySet > xSeriesProp( getDataSeries(), uno::UNO_QUERY ); + bool bVaryColorsByPoint = false; + if( xSeriesProp.is() && (xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= 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(), a); + } + catch( const uno::Exception& e ) + { + css::uno::Any a(cppu::getCaughtException()); + throw css::lang::WrappedTargetRuntimeException( + "wrapped Exception " + e.Message, + css::uno::Reference(), 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 + Reference< beans::XPropertySet > xInnerPropertySet( getDataSeries(), uno::UNO_QUERY ); + 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 Reference< beans::XPropertySet >( getDataSeries(), uno::UNO_QUERY ); + return getDataPointProperties(); +} + +const Sequence< beans::Property >& DataSeriesPointWrapper::getPropertySequence() +{ + if( m_eType == DATA_SERIES ) + return *StaticSeriesWrapperPropertyArray::get(); + else + return *StaticPointWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > DataSeriesPointWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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" ) + { + Reference< beans::XPropertySet > xSeriesProp( getDataSeries(), uno::UNO_QUERY ); + bool bVaryColorsByPoint = false; + if( xSeriesProp.is() && (xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint) + && bVaryColorsByPoint ) + { + uno::Reference< beans::XPropertyState > xPointState( DataSeriesPointWrapper::getDataPointProperties(), uno::UNO_QUERY ); + if( xPointState.is() && xPointState->getPropertyState("Color") == beans::PropertyState_DEFAULT_VALUE ) + { + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + 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 000000000..98317470c --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DATASERIESPOINTWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DATASERIESPOINTWRAPPER_HXX + +#include +#include "ReferenceSizePropertyProvider.hxx" +#include +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart +{ + +namespace 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(const std::shared_ptr& spChart2ModelContact); + + DataSeriesPointWrapper(eType eType + , sal_Int32 nSeriesIndexInNewAPI + , sal_Int32 nPointIndex //ignored for series + , const std::shared_ptr& 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 > 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 + css::uno::Reference< css::chart2::XDataSeries > getDataSeries(); + css::uno::Reference< css::beans::XPropertySet > getDataPointProperties(); + + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 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 + css::uno::Reference< css::chart2::XDataSeries > m_xDataSeries; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DATASERIESPOINTWRAPPER_HXX +#endif + +/* 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 000000000..aa12dbc27 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx @@ -0,0 +1,1930 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include "DataSeriesPointWrapper.hxx" +#include "AxisWrapper.hxx" +#include "Chart2ModelContact.hxx" +#include "WallFloorWrapper.hxx" +#include "MinMaxLineWrapper.hxx" +#include "UpDownBarWrapper.hxx" +#include +#include +#include +#include +#include "WrappedAxisAndGridExistenceProperties.hxx" +#include "WrappedStatisticProperties.hxx" +#include "WrappedSymbolProperties.hxx" +#include "WrappedDataCaptionProperties.hxx" +#include "WrappedSplineProperties.hxx" +#include "WrappedStockProperties.hxx" +#include "WrappedSceneProperty.hxx" +#include +#include +#include "WrappedAutomaticPositionProperties.hxx" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::chart::wrapper; + +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; +using ::osl::MutexGuard; + +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_DATATABLEHBORDER, + PROP_DIAGRAM_DATATABLEVBORDER, + PROP_DIAGRAM_DATATABLEOUTLINE, + PROP_DIAGRAM_EXTERNALDATA +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "AttributedDataPoints", + PROP_DIAGRAM_ATTRIBUTED_DATA_POINTS, + cppu::UnoType >>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // see com.sun.star.chart.StackableDiagram + rOutProperties.emplace_back( "Percent", + PROP_DIAGRAM_PERCENT_STACKED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Stacked", + PROP_DIAGRAM_STACKED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Dim3D", + PROP_DIAGRAM_THREE_D, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // see com.sun.star.chart.Chart3DBarProperties + rOutProperties.emplace_back( "SolidType", + PROP_DIAGRAM_SOLIDTYPE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // see com.sun.star.chart.BarDiagram + rOutProperties.emplace_back( "Deep", + PROP_DIAGRAM_DEEP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Vertical", + PROP_DIAGRAM_VERTICAL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "NumberOfLines", + PROP_DIAGRAM_NUMBER_OF_LINES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "StackedBarsConnected", + PROP_DIAGRAM_STACKED_BARS_CONNECTED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "DataRowSource", + PROP_DIAGRAM_DATAROW_SOURCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GroupBarsPerAxis", + PROP_DIAGRAM_GROUP_BARS_PER_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "IncludeHiddenCells", + PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //for pie and donut charts + rOutProperties.emplace_back( "StartingAngle", + PROP_DIAGRAM_STARTING_ANGLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //new for 3D charts + rOutProperties.emplace_back( "RightAngledAxes", + PROP_DIAGRAM_RIGHT_ANGLED_AXES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Perspective", + PROP_DIAGRAM_PERSPECTIVE, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationHorizontal", + PROP_DIAGRAM_ROTATION_HORIZONTAL, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationVertical", + PROP_DIAGRAM_ROTATION_VERTICAL, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + // XAxisXSupplier + rOutProperties.emplace_back( "HasXAxis", + PROP_DIAGRAM_HAS_X_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasXAxisDescription", + PROP_DIAGRAM_HAS_X_AXIS_DESCR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasXAxisTitle", + PROP_DIAGRAM_HAS_X_AXIS_TITLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasXAxisGrid", + PROP_DIAGRAM_HAS_X_AXIS_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasXAxisHelpGrid", + PROP_DIAGRAM_HAS_X_AXIS_HELP_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // XAxisYSupplier + rOutProperties.emplace_back( "HasYAxis", + PROP_DIAGRAM_HAS_Y_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasYAxisDescription", + PROP_DIAGRAM_HAS_Y_AXIS_DESCR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasYAxisTitle", + PROP_DIAGRAM_HAS_Y_AXIS_TITLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasYAxisGrid", + PROP_DIAGRAM_HAS_Y_AXIS_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasYAxisHelpGrid", + PROP_DIAGRAM_HAS_Y_AXIS_HELP_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // XAxisZSupplier + rOutProperties.emplace_back( "HasZAxis", + PROP_DIAGRAM_HAS_Z_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasZAxisDescription", + PROP_DIAGRAM_HAS_Z_AXIS_DESCR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasZAxisTitle", + PROP_DIAGRAM_HAS_Z_AXIS_TITLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasZAxisGrid", + PROP_DIAGRAM_HAS_Z_AXIS_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasZAxisHelpGrid", + PROP_DIAGRAM_HAS_Z_AXIS_HELP_GRID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // XTwoAxisXSupplier + rOutProperties.emplace_back( "HasSecondaryXAxis", + PROP_DIAGRAM_HAS_SECOND_X_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasSecondaryXAxisDescription", + PROP_DIAGRAM_HAS_SECOND_X_AXIS_DESCR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // XTwoAxisYSupplier + rOutProperties.emplace_back( "HasSecondaryYAxis", + PROP_DIAGRAM_HAS_SECOND_Y_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasSecondaryYAxisDescription", + PROP_DIAGRAM_HAS_SECOND_Y_AXIS_DESCR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // XSecondAxisTitleSupplier + rOutProperties.emplace_back( "HasSecondaryXAxisTitle", + PROP_DIAGRAM_HAS_SECOND_X_AXIS_TITLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "HasSecondaryYAxisTitle", + PROP_DIAGRAM_HAS_SECOND_Y_AXIS_TITLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MissingValueTreatment", + PROP_DIAGRAM_MISSING_VALUE_TREATMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "AutomaticSize", + PROP_DIAGRAM_AUTOMATIC_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableHBorder", + PROP_DIAGRAM_DATATABLEHBORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableVBorder", + PROP_DIAGRAM_DATATABLEVBORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableOutline", + PROP_DIAGRAM_DATATABLEOUTLINE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ExternalData", + PROP_DIAGRAM_EXTERNALDATA, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticDiagramWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticDiagramWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticDiagramWrapperPropertyArray_Initializer > +{ +}; + +bool lcl_isXYChart( const Reference< chart2::XDiagram >& rDiagram ) +{ + bool bRet = false; + Reference< chart2::XChartType > xChartType( ::chart::DiagramHelper::getChartTypeByIndex( rDiagram, 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 Reference< chart2::XDiagram >& xDiagram ) +{ + sal_Int32 nNewAPIIndex = nOldAPIIndex; + + if( lcl_isXYChart( xDiagram ) ) + { + if( nNewAPIIndex >= 1 ) + nNewAPIIndex -= 1; + } + + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesList( + ::chart::DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + if( nNewAPIIndex >= static_cast(aSeriesList.size()) ) + nNewAPIIndex = -1; + + return nNewAPIIndex; +} + +OUString lcl_getDiagramType( const OUString & rTemplateServiceName ) +{ + const OUString aPrefix("com.sun.star.chart2.template."); + + if( rTemplateServiceName.match( aPrefix )) + { + const OUString aName( rTemplateServiceName.copy( aPrefix.getLength())); + + // "Area" "StackedArea" "PercentStackedArea" "ThreeDArea" + // "StackedThreeDArea" "PercentStackedThreeDArea" + if( aName.indexOf( "Area" ) != -1 ) + return "com.sun.star.chart.AreaDiagram"; + + // "Pie" "PieAllExploded" "ThreeDPie" "ThreeDPieAllExploded" + if( aName.indexOf( "Pie" ) != -1 ) + return "com.sun.star.chart.PieDiagram"; + + // "Column" "StackedColumn" "PercentStackedColumn" "ThreeDColumnDeep" + // "ThreeDColumnFlat" "StackedThreeDColumnFlat" + // "PercentStackedThreeDColumnFlat" "Bar" "StackedBar" + // "PercentStackedBar" "ThreeDBarDeep" "ThreeDBarFlat" + // "StackedThreeDBarFlat" "PercentStackedThreeDBarFlat" "ColumnWithLine" + // "StackedColumnWithLine" + if( aName.indexOf( "Column" ) != -1 || aName.indexOf( "Bar" ) != -1 ) + return "com.sun.star.chart.BarDiagram"; + + // "Donut" "DonutAllExploded" "ThreeDDonut" "ThreeDDonutAllExploded" + if( aName.indexOf( "Donut" ) != -1 ) + return "com.sun.star.chart.DonutDiagram"; + + // "ScatterLineSymbol" "ScatterLine" "ScatterSymbol" "ThreeDScatter" + if( aName.indexOf( "Scatter" ) != -1 ) + return "com.sun.star.chart.XYDiagram"; + + // "FilledNet" "StackedFilledNet" "PercentStackedFilledNet" + if( aName.indexOf( "FilledNet" ) != -1 ) + return "com.sun.star.chart.FilledNetDiagram"; + + // "Net" "NetSymbol" "NetLine" "StackedNet" "StackedNetSymbol" + // "StackedNetLine" "PercentStackedNet" "PercentStackedNetSymbol" + // "PercentStackedNetLine" + if( aName.indexOf( "Net" ) != -1 ) + return "com.sun.star.chart.NetDiagram"; + + // "StockLowHighClose" "StockOpenLowHighClose" "StockVolumeLowHighClose" + // "StockVolumeOpenLowHighClose" + if( aName.indexOf( "Stock" ) != -1 ) + return "com.sun.star.chart.StockDiagram"; + + if( aName.indexOf( "Bubble" ) != -1 ) + 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.indexOf( "Line" ) != -1 || aName.indexOf( "Symbol" ) != -1 ) + 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(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact(spChart2ModelContact) + , m_aEventListenerContainer(m_aMutex) +{ +} + +DiagramWrapper::~DiagramWrapper() +{} + +// ____ XDiagram ____ +OUString SAL_CALL DiagramWrapper::getDiagramType() +{ + OUString aRet; + + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xChartDoc.is() && xDiagram.is() ) + { + Reference< beans::XPropertySet > xChartDocProp( xChartDoc, 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(); + } + } + + Reference< lang::XMultiServiceFactory > xChartTypeManager( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xChartTypeManager ); + + aRet = lcl_getDiagramType( aTemplateAndService.second ); + } + + if( aRet.isEmpty()) + { + // none of the standard templates matched + // use first chart type + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 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->getChart2Diagram() ); + 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->getChart2Diagram() ); + 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->getChartModel() ); + 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->getChartModel() ); + 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->getChartModel() ); + 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->getChartModel() ); + DiagramHelper::setDiagramPositioning( m_spChart2ModelContact->getChartModel(), 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->getChartModel() ); + DiagramHelper::setDiagramPositioning( m_spChart2ModelContact->getChartModel(), 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->getChartModel() ); + 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() +{ + Reference< X3DDefaultSetter > x3DDefaultSetter( m_spChart2ModelContact->getChart2Diagram(), uno::UNO_QUERY ); + if( x3DDefaultSetter.is() ) + x3DDefaultSetter->set3DSettingsToDefault(); +} + +void SAL_CALL DiagramWrapper::setDefaultRotation() +{ + Reference< X3DDefaultSetter > x3DDefaultSetter( m_spChart2ModelContact->getChart2Diagram(), uno::UNO_QUERY ); + if( x3DDefaultSetter.is() ) + x3DDefaultSetter->setDefaultRotation(); +} + +void SAL_CALL DiagramWrapper::setDefaultIllumination() +{ + Reference< X3DDefaultSetter > x3DDefaultSetter( m_spChart2ModelContact->getChart2Diagram(), uno::UNO_QUERY ); + if( x3DDefaultSetter.is() ) + x3DDefaultSetter->setDefaultIllumination(); +} + +// ____ XComponent ____ +void SAL_CALL DiagramWrapper::dispose() +{ + m_aEventListenerContainer.disposeAndClear( lang::EventObject( static_cast< ::cppu::OWeakObject* >( this ))); + + MutexGuard aGuard( m_aMutex); + + 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 ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL DiagramWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +namespace { + +//PROP_DIAGRAM_DATAROW_SOURCE +class WrappedDataRowSourceProperty : public WrappedProperty +{ +public: + explicit WrappedDataRowSourceProperty(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("DataRowSource",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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->getChartModel(), aRangeString, aSequenceMapping, bUseColumns + , bFirstCellAsLabel, bHasCategories ) ) + { + if( bUseColumns != bNewUseColumns ) + { + aSequenceMapping.realloc(0); + DataSourceHelper::setRangeSegmentation( + m_spChart2ModelContact->getChartModel(), 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->getChartModel(), 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, const std::shared_ptr& 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, const std::shared_ptr& spChart2ModelContact) + : WrappedProperty(OUString(),OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_eStackMode( eStackMode ) + , m_aOuterValue() +{ + 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; + eStackMode = DiagramHelper::getStackMode( m_spChart2ModelContact->getChart2Diagram() + , bHasDetectableInnerValue, bIsAmbiguous ); + 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + StackMode eNewStackMode = bNewValue ? m_eStackMode : StackMode::NONE; + DiagramHelper::setStackMode( xDiagram, 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("Dim3D",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( !xDiagram.is() ) + return; + + bool bOld3D = DiagramHelper::getDimension( xDiagram ) == 3; + if( bOld3D != bNew3D ) + DiagramHelper::setDimension( xDiagram, bNew3D ? 3 : 2 ); +} + +Any WrappedDim3DProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + bool b3D = DiagramHelper::getDimension( xDiagram ) == 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("Vertical",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( !xDiagram.is() ) + return; + + bool bFound = false; + bool bAmbiguous = false; + bool bOldVertical = DiagramHelper::getVertical( xDiagram, bFound, bAmbiguous ); + if( bFound && ( bOldVertical != bNewVertical || bAmbiguous ) ) + DiagramHelper::setVertical( xDiagram, bNewVertical ); +} + +Any WrappedVerticalProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + bool bFound = false; + bool bAmbiguous = false; + bool bVertical = DiagramHelper::getVertical( xDiagram, 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("NumberOfLines",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue( getPropertyDefault(nullptr) ) +{ +} + +bool WrappedNumberOfLinesProperty::detectInnerValue( uno::Any& rInnerValue ) const +{ + sal_Int32 nNumberOfLines = 0; + bool bHasDetectableInnerValue = false; + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + uno::Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + if( xDiagram.is() && xChartDoc.is() ) + { + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + if( !aSeriesVector.empty() ) + { + Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + if( aTemplateAndService.second == "com.sun.star.chart2.template.ColumnWithLine" ) + { + try + { + uno::Reference< beans::XPropertySet > xProp( aTemplateAndService.first, 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; + + uno::Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + sal_Int32 nDimension = ::chart::DiagramHelper::getDimension( xDiagram ); + if( !(xChartDoc.is() && xDiagram.is() && nDimension == 2) ) + return; + + Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + + uno::Reference< chart2::XChartTypeTemplate > xTemplate; + if( aTemplateAndService.second == "com.sun.star.chart2.template.ColumnWithLine" ) + { + if( nNewValue != 0 ) + { + xTemplate.set( aTemplateAndService.first ); + try + { + sal_Int32 nOldValue = 0; + uno::Reference< beans::XPropertySet > xProp( xTemplate, uno::UNO_QUERY ); + xProp->getPropertyValue( m_aOuterName ) >>= nOldValue; + if( nOldValue == nNewValue ) + return; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + else + { + xTemplate.set( xFact->createInstance("com.sun.star.chart2.template.Column"), uno::UNO_QUERY ); + } + } + else if( aTemplateAndService.second == "com.sun.star.chart2.template.Column" ) + { + if( nNewValue == 0 ) + return; + xTemplate.set( xFact->createInstance( "com.sun.star.chart2.template.ColumnWithLine" ), uno::UNO_QUERY ); + } + + if(!xTemplate.is()) + return; + + try + { + // locked controllers + ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getChartModel() ); + uno::Reference< beans::XPropertySet > xProp( xTemplate, 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("AttributedDataPoints",OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY ); + + if( !(xDiagram.is() && xDiaProp.is())) + return; + + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( + ::chart::DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 i = 0; + for (auto const& series : aSeriesVector) + { + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY); + if( xProp.is()) + { + uno::Any aVal; + if( i < aNewValue.getLength() ) + aVal <<= aNewValue[i]; + else + { + //set empty sequence + uno::Sequence< sal_Int32 > aSeq; + aVal <<= aSeq; + } + xProp->setPropertyValue( "AttributedDataPoints", aVal ); + } + ++i; + } +} + +Any WrappedAttributedDataPointsProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY ); + + if( xDiagram.is() && xDiaProp.is()) + { + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( + ::chart::DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + + uno::Sequence< uno::Sequence< sal_Int32 > > aResult( aSeriesVector.size() ); + + sal_Int32 i = 0; + for (auto const& series : aSeriesVector) + { + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY); + if( xProp.is()) + { + uno::Any aVal( + xProp->getPropertyValue("AttributedDataPoints")); + uno::Sequence< sal_Int32 > aSeq; + if( aVal >>= aSeq ) + aResult[ 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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty( "SolidType", OUString() ) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_aOuterValue() +{ + 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( !xDiagram.is() ) + return; + + bool bFound = false; + bool bAmbiguous = false; + sal_Int32 nOldSolidType = DiagramHelper::getGeometry3D( xDiagram, bFound, bAmbiguous ); + if( bFound && ( nOldSolidType != nNewSolidType || bAmbiguous ) ) + DiagramHelper::setGeometry3D( xDiagram, nNewSolidType ); +} + +Any WrappedSolidTypeProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + bool bFound = false; + bool bAmbiguous = false; + sal_Int32 nGeometry = DiagramHelper::getGeometry3D( xDiagram, 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(const std::shared_ptr& spChart2ModelContact); + + virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override; + virtual Any getPropertyValue(const Reference& xInnerPropertySet) const override; + +private: //member + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; +}; + +} + +WrappedIncludeHiddenCellsProperty::WrappedIncludeHiddenCellsProperty(const std::shared_ptr& spChart2ModelContact) + : WrappedProperty("IncludeHiddenCells","IncludeHiddenCells") + , m_spChart2ModelContact( 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->getModel() ); +} + +Any WrappedIncludeHiddenCellsProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + bool bValue = ChartModelHelper::isIncludeHiddenCells( m_spChart2ModelContact->getChartModel() ); + return uno::Any(bValue); +} + +// ____ XDiagramProvider ____ +Reference< chart2::XDiagram > SAL_CALL DiagramWrapper::getDiagram() +{ + return m_spChart2ModelContact->getChart2Diagram(); +} + +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 Reference< beans::XPropertySet >( m_spChart2ModelContact->getChart2Diagram(), uno::UNO_QUERY ); +} + +const Sequence< beans::Property >& DiagramWrapper::getPropertySequence() +{ + return *StaticDiagramWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > DiagramWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..ca7d8ca89 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DIAGRAMWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DIAGRAMWRAPPER_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace com::sun::star::chart2 { class XDiagram; } +namespace com::sun::star::lang { class XEventListener; } + +namespace chart +{ +namespace 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(const std::shared_ptr& 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override; + +private: + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 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 wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_DIAGRAMWRAPPER_HXX +#endif + +/* 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 000000000..649086a1a --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/GridWrapper.cxx @@ -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 . + */ + +#include "GridWrapper.hxx" +#include +#include "Chart2ModelContact.hxx" +#include + +#include +#include +#include + +#include +#include +#include +#include + +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 +{ + +struct StaticGridWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticGridWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticGridWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +GridWrapper::GridWrapper(tGridType eType, const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact(spChart2ModelContact) + , m_aEventListenerContainer(m_aMutex) + , 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() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + clearWrappedPropertySet(); +} + +void SAL_CALL GridWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL GridWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +// WrappedPropertySet + +Reference< beans::XPropertySet > GridWrapper::getInnerPropertySet() +{ + Reference< beans::XPropertySet > xRet; + try + { + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + uno::Reference< XCoordinateSystem > 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.set( AxisHelper::getGridProperties( xCooSys , nDimensionIndex, MAIN_AXIS_INDEX, nSubGridIndex ) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xRet; +} + +const Sequence< beans::Property >& GridWrapper::getPropertySequence() +{ + return *StaticGridWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > GridWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..275d28279 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/GridWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_GRIDWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_GRIDWRAPPER_HXX + +#include +#include +#include +#include +#include + +#include + +namespace chart +{ +namespace 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, const std::shared_ptr& 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override; + +private: + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; + + tGridType m_eType; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_GRIDWRAPPER_HXX +#endif + +/* 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 000000000..01dc74e7b --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx @@ -0,0 +1,423 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "WrappedCharacterHeightProperty.hxx" +#include +#include +#include "WrappedAutomaticPositionProperties.hxx" +#include "WrappedScaleTextProperties.hxx" + +#include + +using namespace ::com::sun::star; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; +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::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Expansion", + PROP_LEGEND_EXPANSION, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticLegendWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticLegendWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticLegendWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +LegendWrapper::LegendWrapper(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact(spChart2ModelContact) + , m_aEventListenerContainer(m_aMutex) +{ +} + +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() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + MutexGuard aGuard( m_aMutex); + clearWrappedPropertySet(); +} + +void SAL_CALL LegendWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL LegendWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( 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; + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + 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::get(); +} + +std::vector< std::unique_ptr > LegendWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..b614b55ca --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/LegendWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_LEGENDWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_LEGENDWRAPPER_HXX + +#include +#include "ReferenceSizePropertyProvider.hxx" +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +namespace wrapper +{ + +class Chart2ModelContact; + +class LegendWrapper : public ::cppu::ImplInheritanceHelper< + WrappedPropertySet + , css::drawing::XShape + , css::lang::XComponent + , css::lang::XServiceInfo + > + , public ReferenceSizePropertyProvider +{ +public: + explicit LegendWrapper(const std::shared_ptr& 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override; + +private: + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_LEGENDWRAPPER_HXX +#endif + +/* 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 000000000..a0f39774b --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.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 "MinMaxLineWrapper.hxx" +#include "Chart2ModelContact.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 +{ + +struct StaticMinMaxLineWrapperDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::LinePropertiesHelper::AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +}; + +struct StaticMinMaxLineWrapperDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticMinMaxLineWrapperDefaults_Initializer > +{ +}; + +struct StaticMinMaxLineWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticMinMaxLineWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticMinMaxLineWrapperPropertyArray_Initializer > +{ +}; + +struct StaticMinMaxLineWrapperInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( *StaticMinMaxLineWrapperPropertyArray::get() ); + return &aPropHelper; + } +}; + +struct StaticMinMaxLineWrapperInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticMinMaxLineWrapperInfoHelper_Initializer > +{ +}; + +struct StaticMinMaxLineWrapperInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticMinMaxLineWrapperInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticMinMaxLineWrapperInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticMinMaxLineWrapperInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +MinMaxLineWrapper::MinMaxLineWrapper(const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact( spChart2ModelContact ) + , m_aEventListenerContainer( m_aMutex ) + , m_aWrappedLineJointProperty( "LineJoint", uno::Any( drawing::LineJoint_NONE )) +{ +} + +MinMaxLineWrapper::~MinMaxLineWrapper() +{ +} + +// ____ XComponent ____ +void SAL_CALL MinMaxLineWrapper::dispose() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); +} + +void SAL_CALL MinMaxLineWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL MinMaxLineWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +//XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL MinMaxLineWrapper::getPropertySetInfo() +{ + return *StaticMinMaxLineWrapperInfo::get(); +} + +void SAL_CALL MinMaxLineWrapper::setPropertyValue( const OUString& rPropertyName, const uno::Any& rValue ) +{ + Reference< beans::XPropertySet > xPropSet; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + const Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( Reference< chart2::XChartType > const & xType : aTypes ) + { + if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + Reference< chart2::XDataSeriesContainer > xSeriesContainer(xType,uno::UNO_QUERY); + if( xSeriesContainer.is() ) + { + Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() ); + if(aSeriesSeq.hasElements()) + { + xPropSet.set(aSeriesSeq[0],uno::UNO_QUERY); + if(xPropSet.is()) + { + if( rPropertyName == "LineColor" ) + xPropSet->setPropertyValue( "Color", rValue ); + else if( rPropertyName == "LineTransparence" ) + xPropSet->setPropertyValue( "Transparency", rValue ); + else if( rPropertyName == m_aWrappedLineJointProperty.getOuterName() ) + m_aWrappedLineJointProperty.setPropertyValue( rValue, xPropSet ); + else + xPropSet->setPropertyValue( rPropertyName, rValue ); + return; + } + } + } + } + } +} +uno::Any SAL_CALL MinMaxLineWrapper::getPropertyValue( const OUString& rPropertyName ) +{ + Any aRet; + + Reference< beans::XPropertySet > xPropSet; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + const Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( Reference< chart2::XChartType > const & xType : aTypes ) + { + if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + Reference< chart2::XDataSeriesContainer > xSeriesContainer(xType,uno::UNO_QUERY); + if( xSeriesContainer.is() ) + { + Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() ); + if(aSeriesSeq.hasElements()) + { + xPropSet.set(aSeriesSeq[0],uno::UNO_QUERY); + 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 SAL_CALL MinMaxLineWrapper::getPropertyValues( const uno::Sequence< OUString >& rNameSeq ) +{ + Sequence< Any > aRetSeq; + if( rNameSeq.hasElements() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN& /* 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() ); + for(sal_Int32 nN=0; nNgetHandleByName( rPropertyName ) ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +//XMultiPropertyStates +//getPropertyStates() already declared in XPropertyState +void SAL_CALL MinMaxLineWrapper::setAllPropertiesToDefault( ) +{ + const Sequence< beans::Property >& rPropSeq = *StaticMinMaxLineWrapperPropertyArray::get(); + 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() ); + for(sal_Int32 nN=0; nN 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 000000000..72966ee04 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_MINMAXLINEWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_MINMAXLINEWRAPPER_HXX + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +namespace wrapper +{ + +class Chart2ModelContact; + +class MinMaxLineWrapper : public MutexContainer + , public ::cppu::WeakImplHelper + < css::lang::XComponent + , css::lang::XServiceInfo + , css::beans::XPropertySet + , css::beans::XMultiPropertySet + , css::beans::XPropertyState + , css::beans::XMultiPropertyStates + > +{ +public: + explicit MinMaxLineWrapper(const std::shared_ptr& 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::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; + + WrappedIgnoreProperty m_aWrappedLineJointProperty; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_MINMAXLINEWRAPPER_HXX +#endif + +/* 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 000000000..432f3123c --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_REFERENCESIZEPROPERTYPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_REFERENCESIZEPROPERTYPROVIDER_HXX + +#include + +namespace chart +{ +namespace wrapper +{ +class ReferenceSizePropertyProvider +{ +public: + virtual void updateReferenceSize() = 0; + virtual css::uno::Any getReferenceSize() = 0; + virtual css::awt::Size getCurrentSizeForReference() = 0; + +protected: + ~ReferenceSizePropertyProvider() {} +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_REFERENCESIZEPROPERTYPROVIDER_HXX +#endif + +/* 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 000000000..7de1b376b --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx @@ -0,0 +1,512 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "WrappedCharacterHeightProperty.hxx" +#include "WrappedTextRotationProperty.hxx" +#include "WrappedAutomaticPositionProperties.hxx" +#include "WrappedScaleTextProperties.hxx" + +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; +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 +{ + Reference< chart2::XTitle > xTitle(xInnerPropertySet,uno::UNO_QUERY); + if(xTitle.is()) + { + OUString aString; + rOuterValue >>= aString; + TitleHelper::setCompleteString( aString, xTitle, 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "TextRotation", + PROP_TITLE_TEXT_ROTATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "StackedText", + PROP_TITLE_TEXT_STACKED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticTitleWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticTitleWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticTitleWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +TitleWrapper::TitleWrapper( ::chart::TitleHelper::eTitleType eTitleType, + const std::shared_ptr& spChart2ModelContact ) : + m_spChart2ModelContact( spChart2ModelContact ), + m_aEventListenerContainer( m_aMutex ), + m_eTitleType(eTitleType) +{ + ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getChart2Document() ); + 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->getChartModel(), 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() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + MutexGuard aGuard( m_aMutex); + clearWrappedPropertySet(); +} + +void SAL_CALL TitleWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL TitleWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( 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->getChartModel() ); +} + +// WrappedPropertySet + +Reference< beans::XPropertySet > TitleWrapper::getInnerPropertySet() +{ + return Reference< beans::XPropertySet >( getTitleObject(), uno::UNO_QUERY ); +} + +const Sequence< beans::Property >& TitleWrapper::getPropertySequence() +{ + return *StaticTitleWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > TitleWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..e1e7282af --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/TitleWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_TITLEWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_TITLEWRAPPER_HXX + +#include +#include "ReferenceSizePropertyProvider.hxx" +#include +#include +#include +#include +#include +#include + +#include + +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::chart2 { class XTitle; } + +namespace chart +{ +namespace 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, + const std::shared_ptr& 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 > createWrappedProperties() override; + + css::uno::Reference< css::beans::XPropertySet > getFirstCharacterPropertySet(); + + css::uno::Reference< css::chart2::XTitle > getTitleObject(); + + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; + + ::chart::TitleHelper::eTitleType m_eTitleType; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_TITLEWRAPPER_HXX +#endif + +/* 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 000000000..ab7e5b333 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.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 "UpDownBarWrapper.hxx" +#include "Chart2ModelContact.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 +{ + +struct StaticUpDownBarWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticUpDownBarWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticUpDownBarWrapperPropertyArray_Initializer > +{ +}; + +struct StaticUpDownBarWrapperInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( *StaticUpDownBarWrapperPropertyArray::get() ); + return &aPropHelper; + } +}; + +struct StaticUpDownBarWrapperInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticUpDownBarWrapperInfoHelper_Initializer > +{ +}; + +struct StaticUpDownBarWrapperInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticUpDownBarWrapperInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticUpDownBarWrapperInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticUpDownBarWrapperInfo_Initializer > +{ +}; + +struct StaticUpDownBarWrapperDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + } +}; + +struct StaticUpDownBarWrapperDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticUpDownBarWrapperDefaults_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +UpDownBarWrapper::UpDownBarWrapper( + bool bUp, const std::shared_ptr& spChart2ModelContact) + : m_spChart2ModelContact( spChart2ModelContact ) + , m_aEventListenerContainer( m_aMutex ) + , m_aPropertySetName( bUp ? OUString( "WhiteDay" ) : OUString( "BlackDay" )) +{ +} + +UpDownBarWrapper::~UpDownBarWrapper() +{ +} + +// ____ XComponent ____ +void SAL_CALL UpDownBarWrapper::dispose() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); +} + +void SAL_CALL UpDownBarWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL UpDownBarWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +//XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL UpDownBarWrapper::getPropertySetInfo() +{ + return *StaticUpDownBarWrapperInfo::get(); +} +void SAL_CALL UpDownBarWrapper::setPropertyValue( const OUString& rPropertyName, const uno::Any& rValue ) +{ + Reference< beans::XPropertySet > xPropSet; + + const Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for( Reference< chart2::XChartType > const & xType : aTypes ) + { + if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + Reference< beans::XPropertySet > xTypeProps( xType, uno::UNO_QUERY ); + if(xTypeProps.is()) + { + xTypeProps->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 Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for( Reference< chart2::XChartType > const & xType : aTypes ) + { + if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + Reference< beans::XPropertySet > xTypeProps( xType, uno::UNO_QUERY ); + if(xTypeProps.is()) + { + xTypeProps->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 SAL_CALL UpDownBarWrapper::getPropertyValues( const uno::Sequence< OUString >& rNameSeq ) +{ + Sequence< Any > aRetSeq; + if( rNameSeq.hasElements() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN& /* 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() ); + for(sal_Int32 nN=0; nNgetHandleByName( rPropertyName ) ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +//XMultiPropertyStates +//getPropertyStates() already declared in XPropertyState +void SAL_CALL UpDownBarWrapper::setAllPropertiesToDefault( ) +{ + const Sequence< beans::Property >& rPropSeq = *StaticUpDownBarWrapperPropertyArray::get(); + 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() ); + for(sal_Int32 nN=0; nN 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 000000000..a1b455bcc --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_UPDOWNBARWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_UPDOWNBARWRAPPER_HXX + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +namespace wrapper +{ + +class Chart2ModelContact; + +class UpDownBarWrapper : public MutexContainer + , 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, const std::shared_ptr& 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::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; + + OUString m_aPropertySetName; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_UPDOWNBARWRAPPER_HXX +#endif + +/* 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 000000000..daa0f1de4 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.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 "WallFloorWrapper.hxx" +#include "Chart2ModelContact.hxx" +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::beans::Property; +using ::osl::MutexGuard; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +struct StaticWallFloorWrapperPropertyArray_Initializer +{ + Sequence< Property >* operator()() + { + static Sequence< Property > aPropSeq( lcl_GetPropertySequence() ); + return &aPropSeq; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticWallFloorWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticWallFloorWrapperPropertyArray_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart::wrapper +{ + +WallFloorWrapper::WallFloorWrapper( bool bWall, + const std::shared_ptr& spChart2ModelContact ) : + m_spChart2ModelContact( spChart2ModelContact ), + m_aEventListenerContainer( m_aMutex ), + m_bWall( bWall ) + +{ +} + +WallFloorWrapper::~WallFloorWrapper() +{ +} + +// ____ XComponent ____ +void SAL_CALL WallFloorWrapper::dispose() +{ + Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); + + MutexGuard aGuard( m_aMutex); + clearWrappedPropertySet(); +} + +void SAL_CALL WallFloorWrapper::addEventListener( + const Reference< lang::XEventListener >& xListener ) +{ + m_aEventListenerContainer.addInterface( xListener ); +} + +void SAL_CALL WallFloorWrapper::removeEventListener( + const Reference< lang::XEventListener >& aListener ) +{ + m_aEventListenerContainer.removeInterface( aListener ); +} + +// WrappedPropertySet +Reference< beans::XPropertySet > WallFloorWrapper::getInnerPropertySet() +{ + Reference< beans::XPropertySet > xRet; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + if( m_bWall ) + xRet.set( xDiagram->getWall() ); + else + xRet.set( xDiagram->getFloor() ); + } + + return xRet; +} + +const Sequence< beans::Property >& WallFloorWrapper::getPropertySequence() +{ + return *StaticWallFloorWrapperPropertyArray::get(); +} + +std::vector< std::unique_ptr > WallFloorWrapper::createWrappedProperties() +{ + std::vector< std::unique_ptr > 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 000000000..2a79c211e --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WALLFLOORWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WALLFLOORWRAPPER_HXX + +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +namespace wrapper +{ + +class Chart2ModelContact; + +class WallFloorWrapper : public ::cppu::ImplInheritanceHelper< + WrappedPropertySet + , css::lang::XComponent + , css::lang::XServiceInfo + > +{ +public: + WallFloorWrapper(bool bWall, const std::shared_ptr& 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override; + +private: + std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact; + ::comphelper::OInterfaceContainerHelper2 m_aEventListenerContainer; + + bool m_bWall; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WALLFLOORWRAPPER_HXX +#endif + +/* 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 000000000..24a6dfb78 --- /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 +#include + +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 000000000..0cf598134 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDADDINPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDADDINPROPERTY_HXX + +#include + +namespace chart::wrapper { class ChartDocumentWrapper; } + +namespace chart +{ +namespace 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 wrapper + +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDADDINPROPERTY_HXX +#endif + +/* 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 000000000..2bfb5ed42 --- /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 +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +void WrappedAutomaticPositionProperties::addWrappedProperties( std::vector< std::unique_ptr >& 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 000000000..35a00856c --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDAUTOMATICPOSITIONPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDAUTOMATICPOSITIONPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedAutomaticPositionProperties +{ +public: + static void addProperties( std::vector< css::beans::Property >& rOutProperties ); + static void addWrappedProperties( std::vector< std::unique_ptr >& rList ); +}; + +} //namespace wrapper +} //namespace chart +#endif + +/* 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 000000000..7b9d07f00 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx @@ -0,0 +1,403 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "WrappedAxisAndGridExistenceProperties.hxx" +#include +#include +#include +#include +#include +#include "Chart2ModelContact.hxx" +#include +#include + +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 + , const std::shared_ptr& 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 >& 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 + , const std::shared_ptr& spChart2ModelContact ) + : WrappedProperty(OUString(),OUString()) + , m_spChart2ModelContact( 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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + 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; + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + 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 + , const std::shared_ptr& 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 >& 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 + , const std::shared_ptr& spChart2ModelContact) + : WrappedProperty(OUString(),OUString()) + , m_spChart2ModelContact( 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->getChartModel(), m_spChart2ModelContact->m_xContext ); + } + else + { + TitleHelper::removeTitle( m_eTitleType, m_spChart2ModelContact->getChartModel() ); + } +} + +Any WrappedAxisTitleExistenceProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + bool bHasTitle = false; + + Reference< chart2::XTitle > xTitle( TitleHelper::getTitle( m_eTitleType, m_spChart2ModelContact->getChartModel() ) ); + 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 + , const std::shared_ptr& 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 >& 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 + , const std::shared_ptr& spChart2ModelContact) + : WrappedProperty(OUString(),OUString()) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_bMain( bMain ) + , m_nDimensionIndex( nDimensionIndex ) +{ + switch( m_nDimensionIndex ) + { + case 0: + m_aOuterName = m_bMain ? OUStringLiteral("HasXAxisDescription") : OUStringLiteral("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 ? OUStringLiteral("HasYAxisDescription") : OUStringLiteral("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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< beans::XPropertySet > xProp( AxisHelper::getAxis( m_nDimensionIndex, m_bMain, xDiagram ), uno::UNO_QUERY ); + if( !xProp.is() && bNewValue ) + { + //create axis if needed + xProp.set( AxisHelper::createAxis( m_nDimensionIndex, m_bMain, xDiagram, m_spChart2ModelContact->m_xContext ), uno::UNO_QUERY ); + 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; + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< beans::XPropertySet > xProp( AxisHelper::getAxis( m_nDimensionIndex, m_bMain, xDiagram ), uno::UNO_QUERY ); + 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 000000000..cfc627345 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDAXISANDGRIDEXISTENCEPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDAXISANDGRIDEXISTENCEPROPERTIES_HXX + +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedAxisAndGridExistenceProperties +{ +public: + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +class WrappedAxisTitleExistenceProperties +{ +public: + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +class WrappedAxisLabelExistenceProperties +{ +public: + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDAXISANDGRIDEXISTENCEPROPERTIES_HXX + +/* 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 000000000..67ea51b0e --- /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 +#include "ReferenceSizePropertyProvider.hxx" +#include +#include +#include + +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 >& 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 000000000..5e43b37ae --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDCHARACTERHEIGHTPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDCHARACTERHEIGHTPROPERTY_HXX + +#include + +#include + +namespace chart +{ +namespace 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; + +protected: + ReferenceSizePropertyProvider* m_pRefSizePropProvider; +}; + +class WrappedCharacterHeightProperty : public WrappedCharacterHeightProperty_Base +{ +public: + explicit WrappedCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider ); + virtual ~WrappedCharacterHeightProperty() override; + + static void addWrappedProperties( std::vector< std::unique_ptr >& 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 wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDCHARACTERHEIGHTPROPERTY_HXX +#endif + +/* 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 000000000..f55540f67 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include + +#include +#include +#include +#include + +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& 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; + + return nCaption; +} + +chart2::DataPointLabel lcl_CaptionToLabel( sal_Int32 nCaption ) +{ + chart2::DataPointLabel aLabel(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; + + return aLabel; +} + +void lcl_addWrappedProperties( std::vector< std::unique_ptr >& 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +void WrappedDataCaptionProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES ); +} + +void WrappedDataCaptionProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + lcl_addWrappedProperties( rList, spChart2ModelContact, DIAGRAM ); +} + +WrappedDataCaptionProperty::WrappedDataCaptionProperty( + const std::shared_ptr& 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 000000000..7180f7e19 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDDATACAPTIONPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDDATACAPTIONPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedDataCaptionProperties +{ +public: + static void addProperties( std::vector< css::beans::Property > & rOutProperties ); + static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); + static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDDATACAPTIONPROPERTIES_HXX +#endif + +/* 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 000000000..63abadee1 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "WrappedGapwidthProperty.hxx" +#include "Chart2ModelContact.hxx" +#include + +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 + , const OUString& rInnerSequencePropertyName + , sal_Int32 nDefaultValue + , const std::shared_ptr& spChart2ModelContact ) + : WrappedDefaultProperty( rOuterName, OUString(), uno::Any( nDefaultValue ) ) + , m_nDimensionIndex(0) + , m_nAxisIndex(0) + , m_spChart2ModelContact( spChart2ModelContact ) + , m_nDefaultValue( nDefaultValue ) + , m_InnerSequencePropertyName( rInnerSequencePropertyName ) +{ +} + +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; + + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( !xDiagram.is() ) + return; + + if( m_nDimensionIndex!=1 ) + return; + + const Sequence< Reference< chart2::XChartType > > aChartTypeList( DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( Reference< chart2::XChartType > const & chartType : aChartTypeList ) + { + try + { + Reference< beans::XPropertySet > xProp( chartType, uno::UNO_QUERY ); + if( xProp.is() ) + { + Sequence< sal_Int32 > aBarPositionSequence; + xProp->getPropertyValue( m_InnerSequencePropertyName ) >>= aBarPositionSequence; + + long nOldLength = aBarPositionSequence.getLength(); + if( nOldLength <= m_nAxisIndex ) + { + aBarPositionSequence.realloc( m_nAxisIndex+1 ); + for( sal_Int32 i=nOldLength; isetPropertyValue( 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 +{ + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() ) + { + bool bInnerValueDetected = false; + sal_Int32 nInnerValue = m_nDefaultValue; + + if( m_nDimensionIndex==1 ) + { + Sequence< Reference< chart2::XChartType > > aChartTypeList( DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( sal_Int32 nN = 0; nN < aChartTypeList.getLength() && !bInnerValueDetected; nN++ ) + { + try + { + Reference< beans::XPropertySet > xProp( aChartTypeList[nN], uno::UNO_QUERY ); + if( xProp.is() ) + { + Sequence< sal_Int32 > aBarPositionSequence; + xProp->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& spChart2ModelContact) + : WrappedBarPositionProperty_Base( "GapWidth", "GapwidthSequence", DEFAULT_GAPWIDTH, spChart2ModelContact ) +{ +} +WrappedGapwidthProperty::~WrappedGapwidthProperty() +{ +} + +WrappedBarOverlapProperty::WrappedBarOverlapProperty( + const std::shared_ptr& 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 000000000..a20a4bbc3 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDGAPWIDTHPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDGAPWIDTHPROPERTY_HXX + +#include + +#include + +namespace chart::wrapper { class Chart2ModelContact; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedBarPositionProperty_Base : public WrappedDefaultProperty +{ +public: + WrappedBarPositionProperty_Base( + const OUString& rOuterName + , const OUString& rInnerSequencePropertyName + , sal_Int32 nDefaultValue + , const std::shared_ptr& 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 ); + +protected: + 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& spChart2ModelContact); + virtual ~WrappedGapwidthProperty() override; +}; + +class WrappedBarOverlapProperty : public WrappedBarPositionProperty_Base +{ +public: + explicit WrappedBarOverlapProperty(const std::shared_ptr& spChart2ModelContact); + virtual ~WrappedBarOverlapProperty() override; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDGAPWIDTHPROPERTY_HXX +#endif + +/* 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 000000000..1ce277c32 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.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 "WrappedNumberFormatProperty.hxx" +#include "Chart2ModelContact.hxx" +#include +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; + +namespace chart::wrapper +{ + +WrappedNumberFormatProperty::WrappedNumberFormatProperty(const std::shared_ptr& spChart2ModelContact) + : WrappedDirectStateProperty( CHART_UNONAME_NUMFMT, CHART_UNONAME_NUMFMT ) + , m_spChart2ModelContact(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 + { + Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); + 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 000000000..59bb1f3b1 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDNUMBERFORMATPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDNUMBERFORMATPROPERTY_HXX + +#include + +#include + +namespace chart::wrapper { class Chart2ModelContact; } + +namespace chart +{ +namespace wrapper +{ + + +class WrappedNumberFormatProperty : public WrappedDirectStateProperty +{ +public: + explicit WrappedNumberFormatProperty(const std::shared_ptr& 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 wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDNUMBERFORMATPROPERTY_HXX +#endif + +/* 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 000000000..d9ad4a3e6 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx @@ -0,0 +1,584 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include + +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 + , const std::shared_ptr& spChart2ModelContact) + : WrappedProperty(OUString(),OUString()) + , m_spChart2ModelContact( 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 >& 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 ); + + double fStepHelp = 0; + if( rOuterValue >>= fStepHelp ) + { + double fStepMain = 0; + if( AxisHelper::isLogarithmic(aScaleData.Scaling) ) + { + sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepHelp); + rSubIncrements[ 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 + rSubIncrements[ 0 ].IntervalCount <<= nIntervalCount; + } + } + bSetScaleData = true; + break; + } + case SCALE_PROP_STEPHELP_COUNT: + { + Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements ); + if( !rSubIncrements.hasElements() ) + rSubIncrements.realloc( 1 ); + sal_Int32 nIntervalCount=0; + if( rOuterValue>>=nIntervalCount ) + rSubIncrements[ 0 ].IntervalCount <<= nIntervalCount; + else + rSubIncrements[ 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 ); + + if( (rOuterValue >>= bBool) && bBool ) + rSubIncrements[ 0 ].IntervalCount = Any(); + else + rSubIncrements[ 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 ); + + Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); + 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 000000000..e62b5f702 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCALEPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCALEPROPERTY_HXX + +#include + +#include +#include + +namespace chart::wrapper { class Chart2ModelContact; } + +namespace chart +{ +namespace 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, const std::shared_ptr& spChart2ModelContact); + virtual ~WrappedScaleProperty() override; + + static void addWrappedProperties( std::vector< std::unique_ptr >& 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 wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCALEPROPERTY_HXX +#endif + +/* 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 000000000..373fec6c8 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.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 "WrappedScaleTextProperties.hxx" +#include "Chart2ModelContact.hxx" +#include +#include + +#include +#include +#include +#include + +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(const std::shared_ptr& 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(const std::shared_ptr& spChart2ModelContact) + : ::chart::WrappedProperty( "ScaleText" , OUString() ) + , m_spChart2ModelContact( spChart2ModelContact ) +{ +} + +void WrappedScaleTextProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const +{ + static const char aRefSizeName[] = "ReferencePageSize"; + + 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::get(), + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +void WrappedScaleTextProperties::addWrappedProperties( std::vector< std::unique_ptr >& 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 000000000..85748851a --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.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 +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedScaleTextProperties +{ +public: + static void addProperties( std::vector< css::beans::Property >& rOutProperties ); + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +/* 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 000000000..d3a883429 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx @@ -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 . + */ + +#include "WrappedSceneProperty.hxx" +#include "Chart2ModelContact.hxx" +#include +#include + +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 >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + rList.emplace_back( new WrappedD3DTransformMatrixProperty( spChart2ModelContact ) ); +} + +WrappedD3DTransformMatrixProperty::WrappedD3DTransformMatrixProperty( + const std::shared_ptr& spChart2ModelContact ) + : WrappedProperty("D3DTransformMatrix","D3DTransformMatrix") + , m_spChart2ModelContact( spChart2ModelContact ) +{ +} + +WrappedD3DTransformMatrixProperty::~WrappedD3DTransformMatrixProperty() +{ +} + +void WrappedD3DTransformMatrixProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const +{ + if( DiagramHelper::isPieOrDonutChart( m_spChart2ModelContact->getChart2Diagram() ) ) + { + 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( DiagramHelper::isPieOrDonutChart( m_spChart2ModelContact->getChart2Diagram() ) ) + { + 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 000000000..6b7ae6416 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCENEPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCENEPROPERTY_HXX + +#include + +#include +#include + +namespace chart::wrapper { class Chart2ModelContact; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedSceneProperty +{ +public: + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +class WrappedD3DTransformMatrixProperty : public WrappedProperty +{ +public: + explicit WrappedD3DTransformMatrixProperty( + const std::shared_ptr& 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 wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSCENEPROPERTY_HXX +#endif + +/* 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 000000000..88fa72696 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx @@ -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 . + */ + +#include "WrappedSeriesAreaOrLineProperty.hxx" +#include "DataSeriesPointWrapper.hxx" + +namespace chart::wrapper +{ + +WrappedSeriesAreaOrLineProperty::WrappedSeriesAreaOrLineProperty( + const OUString& rOuterName + , const OUString& rInnerAreaTypeName + , const OUString& rInnerLineTypeName + , DataSeriesPointWrapper* pDataSeriesPointWrapper ) + : WrappedProperty( rOuterName, OUString() ) + , m_pDataSeriesPointWrapper( pDataSeriesPointWrapper ) + , m_aInnerAreaTypeName( rInnerAreaTypeName ) + , m_aInnerLineTypeName( rInnerLineTypeName ) +{ +} +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 000000000..2c3eff9da --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESAREAORLINEPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESAREAORLINEPROPERTY_HXX + +#include + +namespace chart +{ +namespace wrapper +{ + +class DataSeriesPointWrapper; +class WrappedSeriesAreaOrLineProperty : public WrappedProperty +{ +public: + WrappedSeriesAreaOrLineProperty( const OUString& rOuterName + , const OUString& rInnerAreaTypeName, const OUString& rInnerLineTypeName + , DataSeriesPointWrapper* pDataSeriesPointWrapper ); + virtual ~WrappedSeriesAreaOrLineProperty() override; + + virtual OUString getInnerName() const override; + +private: + DataSeriesPointWrapper* m_pDataSeriesPointWrapper; + OUString m_aInnerAreaTypeName; + OUString m_aInnerLineTypeName; +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESAREAORLINEPROPERTY_HXX +#endif + +/* 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 000000000..26c260ffc --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESORDIAGRAMPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESORDIAGRAMPROPERTY_HXX + +#include +#include "Chart2ModelContact.hxx" +#include + +#include +#include + +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart +{ +namespace 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 + , const std::shared_ptr& spChart2ModelContact + , tSeriesOrDiagramPropertyType ePropertyType ) + : WrappedProperty(rName,OUString()) + , m_spChart2ModelContact(spChart2ModelContact) + , m_aOuterValue(rDefaulValue) + , m_aDefaultValue(rDefaulValue) + , m_ePropertyType( ePropertyType ) + { + } + + bool detectInnerValue( PROPERTYTYPE& rValue, bool& rHasAmbiguousValue ) const + { + bool bHasDetectableInnerValue = false; + rHasAmbiguousValue = false; + if( m_ePropertyType == DIAGRAM && + m_spChart2ModelContact ) + { + std::vector< css::uno::Reference< css::chart2::XDataSeries > > aSeriesVector( + ::chart::DiagramHelper::getDataSeriesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for (auto const& series : aSeriesVector) + { + PROPERTYTYPE aCurValue = getValueFromSeries( css::uno::Reference< css::beans::XPropertySet >::query(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< css::uno::Reference< css::chart2::XDataSeries > > aSeriesVector( + ::chart::DiagramHelper::getDataSeriesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for (auto const& series : aSeriesVector) + { + css::uno::Reference< css::beans::XPropertySet > xSeriesPropertySet(series, css::uno::UNO_QUERY); + if( xSeriesPropertySet.is() ) + { + setValueToSeries( xSeriesPropertySet, 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 wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSERIESORDIAGRAMPROPERTY_HXX +#endif + +/* 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 000000000..ad07a98bc --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +#include + +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +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, const OUString& rInnerName + , const css::uno::Any& rDefaulValue + , const std::shared_ptr& spChart2ModelContact ) + : WrappedProperty(rOuterName,OUString()) + , m_spChart2ModelContact(spChart2ModelContact) + , m_aOuterValue(rDefaulValue) + , m_aDefaultValue(rDefaulValue) + , m_aOwnInnerName(rInnerName) + { + } + + bool detectInnerValue( PROPERTYTYPE& rValue, bool& rHasAmbiguousValue ) const + { + bool bHasDetectableInnerValue = false; + rHasAmbiguousValue = false; + Sequence< css::uno::Reference< css::chart2::XChartType > > aChartTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for( sal_Int32 nN = aChartTypes.getLength(); nN--; ) + { + try + { + uno::Reference xChartTypePropertySet(aChartTypes[nN], uno::UNO_QUERY); + if (!xChartTypePropertySet.is()) + continue; + + Any aSingleValue = convertInnerToOuterValue( xChartTypePropertySet->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; + + Sequence< css::uno::Reference< css::chart2::XChartType > > aChartTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( m_spChart2ModelContact->getChart2Diagram() ) ); + for( sal_Int32 nN = aChartTypes.getLength(); nN--; ) + { + try + { + css::uno::Reference< css::beans::XPropertySet > xChartTypePropertySet( aChartTypes[nN], css::uno::UNO_QUERY ); + if( xChartTypePropertySet.is() ) + { + xChartTypePropertySet->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& 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER, + PROP_CHART_SPLINE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_RESOLUTION, + PROP_CHART_SPLINE_RESOLUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); +} + +void WrappedSplineProperties::addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + rList.emplace_back( new WrappedSplineTypeProperty( spChart2ModelContact ) ); + rList.emplace_back( + new WrappedSplineProperty( + CHART_UNONAME_SPLINE_ORDER, CHART_UNONAME_SPLINE_ORDER, + uno::Any(sal_Int32(3)), spChart2ModelContact)); + rList.emplace_back( + new WrappedSplineProperty( + CHART_UNONAME_SPLINE_RESOLUTION, CHART_UNONAME_CURVE_RESOLUTION, + uno::Any(sal_Int32(20)), spChart2ModelContact)); +} + +WrappedSplineTypeProperty::WrappedSplineTypeProperty(const std::shared_ptr& spChart2ModelContact) + : WrappedSplineProperty(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 000000000..d52c102c0 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSPLINEPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSPLINEPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedSplineProperties +{ +public: + static void addProperties( std::vector< css::beans::Property > & rOutProperties ); + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSPLINEPROPERTIES_HXX +#endif + +/* 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 000000000..6e12bea50 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx @@ -0,0 +1,1072 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) + { + uno::Reference< chart2::XChartDocument > xChartDoc( + spChart2ModelContact->getChart2Document()); + 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()) + { + OUString aResult = xConverter->convertRangeFromXML( rInOutRange ); + rInOutRange = aResult; + } + } +} + +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()) + { + OUString aResult = xConverter->convertRangeToXML( rInOutRange ); + rInOutRange = aResult; + } + } +} + +template< typename PROPERTYTYPE > +class WrappedStatisticProperty : public WrappedSeriesOrDiagramProperty< PROPERTYTYPE > +{ +public: + explicit WrappedStatisticProperty( + const OUString& rName, const Any& rDefaulValue, + const std::shared_ptr& spChart2ModelContact, + tSeriesOrDiagramPropertyType ePropertyType) + : WrappedSeriesOrDiagramProperty(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 ); + uno::Reference< chart2::XRegressionCurve > xRegressionCurve( xSeriesPropertySet, uno::UNO_QUERY ); + + if( xRegressionCurveContainer.is() && 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.set( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCnt ), uno::UNO_QUERY ); + 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.set( RegressionCurveHelper::getMeanValueLine( xRegCnt ), uno::UNO_QUERY ); + 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 >& 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ConstantErrorHigh", + PROP_CHART_STATISTIC_CONST_ERROR_HIGH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "MeanValue", + PROP_CHART_STATISTIC_MEAN_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorCategory", + PROP_CHART_STATISTIC_ERROR_CATEGORY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorBarStyle", + PROP_CHART_STATISTIC_ERROR_BAR_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "PercentageError", + PROP_CHART_STATISTIC_PERCENT_ERROR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorMargin", + PROP_CHART_STATISTIC_ERROR_MARGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorIndicator", + PROP_CHART_STATISTIC_ERROR_INDICATOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorBarRangePositive", + PROP_CHART_STATISTIC_ERROR_RANGE_POSITIVE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ErrorBarRangeNegative", + PROP_CHART_STATISTIC_ERROR_RANGE_NEGATIVE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "RegressionCurves", + PROP_CHART_STATISTIC_REGRESSION_CURVES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "DataRegressionProperties", + PROP_CHART_STATISTIC_REGRESSION_PROPERTIES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "DataErrorProperties", + PROP_CHART_STATISTIC_ERROR_PROPERTIES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "DataMeanValueProperties", + PROP_CHART_STATISTIC_MEAN_VALUE_PROPERTIES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + | beans::PropertyAttribute::MAYBEVOID ); +} + +void WrappedStatisticProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES ); +} + +void WrappedStatisticProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& 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 000000000..774d7a6da --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTATISTICPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTATISTICPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedStatisticProperties +{ +public: + static void addProperties( std::vector< css::beans::Property > & rOutProperties ); + static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); + static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTATISTICPROPERTIES_HXX +#endif + +/* 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 000000000..5e7a2808f --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx @@ -0,0 +1,281 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +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 + , const css::uno::Any& rDefaulValue + , const std::shared_ptr& 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 uno::Reference< chart2::XChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const Reference< lang::XMultiServiceFactory >& 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 + , const css::uno::Any& rDefaulValue + , const std::shared_ptr& spChart2ModelContact ) + : WrappedProperty(rOuterName,OUString()) + , m_spChart2ModelContact(spChart2ModelContact) + , m_aOuterValue() + , m_aDefaultValue(rDefaulValue) +{ +} + +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; + + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + sal_Int32 nDimension = ::chart::DiagramHelper::getDimension( xDiagram ); + if( !(xChartDoc.is() && xDiagram.is() && nDimension==2) ) + return; + + Reference< lang::XMultiServiceFactory > xFactory( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFactory ); + + uno::Reference< chart2::XChartTypeTemplate > xTemplate = + getNewTemplate( bNewValue, aTemplateAndService.second, xFactory ); + + if(!xTemplate.is()) + return; + + try + { + // locked controllers + ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getChartModel() ); + 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& spChart2ModelContact); + + css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override; + + uno::Reference< chart2::XChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const Reference< lang::XMultiServiceFactory >& xFactory ) const override; +}; + +} + +WrappedVolumeProperty::WrappedVolumeProperty(const std::shared_ptr& spChart2ModelContact) + : WrappedStockProperty( "Volume", uno::Any(false) , spChart2ModelContact ) +{ +} + +css::uno::Any WrappedVolumeProperty::getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() && xChartDoc.is() ) + { + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + if( !aSeriesVector.empty() ) + { + Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + + if( aTemplateAndService.second == "com.sun.star.chart2.template.StockVolumeLowHighClose" + || aTemplateAndService.second == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ) + m_aOuterValue <<= true; + else if( !aTemplateAndService.second.isEmpty() || !m_aOuterValue.hasValue() ) + m_aOuterValue <<= false; + } + else if(!m_aOuterValue.hasValue()) + m_aOuterValue <<= false; + } + return m_aOuterValue; +} + +uno::Reference< chart2::XChartTypeTemplate > WrappedVolumeProperty::getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const Reference< lang::XMultiServiceFactory >& xFactory ) const +{ + uno::Reference< chart2::XChartTypeTemplate > xTemplate; + + if(!xFactory.is()) + return xTemplate; + + if( bNewValue ) //add volume + { + if( rCurrentTemplate == "com.sun.star.chart2.template.StockLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockVolumeLowHighClose" ), uno::UNO_QUERY ); + else if( rCurrentTemplate == "com.sun.star.chart2.template.StockOpenLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ), uno::UNO_QUERY ); + } + else //remove volume + { + if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockLowHighClose" ), uno::UNO_QUERY ); + else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockOpenLowHighClose" ), uno::UNO_QUERY ); + } + return xTemplate; +} + +namespace { + +class WrappedUpDownProperty : public WrappedStockProperty +{ +public: + explicit WrappedUpDownProperty(const std::shared_ptr& spChart2ModelContact); + + css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override; + + uno::Reference< chart2::XChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const Reference< lang::XMultiServiceFactory >& xFactory ) const override; +}; + +} + +WrappedUpDownProperty::WrappedUpDownProperty(const std::shared_ptr& spChart2ModelContact) + : WrappedStockProperty( "UpDown", uno::Any(false) , spChart2ModelContact ) +{ +} + +css::uno::Any WrappedUpDownProperty::getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const +{ + Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + if( xDiagram.is() && xChartDoc.is() ) + { + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + if( !aSeriesVector.empty() ) + { + Reference< lang::XMultiServiceFactory > xFact( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + + if( aTemplateAndService.second == "com.sun.star.chart2.template.StockOpenLowHighClose" + || aTemplateAndService.second == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ) + m_aOuterValue <<= true; + else if( !aTemplateAndService.second.isEmpty() || !m_aOuterValue.hasValue() ) + m_aOuterValue <<= false; + } + else if(!m_aOuterValue.hasValue()) + m_aOuterValue <<= false; + } + return m_aOuterValue; +} +uno::Reference< chart2::XChartTypeTemplate > WrappedUpDownProperty::getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const Reference< lang::XMultiServiceFactory >& xFactory ) const +{ + uno::Reference< chart2::XChartTypeTemplate > xTemplate; + if( bNewValue ) //add open series + { + if( rCurrentTemplate == "com.sun.star.chart2.template.StockLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockOpenLowHighClose" ), uno::UNO_QUERY ); + else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ), uno::UNO_QUERY ); + } + else //remove open series + { + if( rCurrentTemplate == "com.sun.star.chart2.template.StockOpenLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockLowHighClose" ), uno::UNO_QUERY ); + else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ) + xTemplate.set( xFactory->createInstance( "com.sun.star.chart2.template.StockVolumeLowHighClose" ), uno::UNO_QUERY ); + } + 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "UpDown", + PROP_CHART_STOCK_UPDOWN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); +} + +void WrappedStockProperties::addWrappedProperties( std::vector< std::unique_ptr >& 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 000000000..1cc9d579b --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTOCKPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTOCKPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedStockProperties +{ +public: + static void addProperties( std::vector< css::beans::Property > & rOutProperties ); + static void addWrappedProperties( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSTOCKPROPERTIES_HXX +#endif + +/* 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 000000000..4dfabee48 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx @@ -0,0 +1,530 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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& spChart2ModelContact, + tSeriesOrDiagramPropertyType ePropertyType); +}; + +class WrappedSymbolBitmapURLProperty : public WrappedSeriesOrDiagramProperty +{ +public: + virtual OUString getValueFromSeries(const Reference& xSeriesPropertySet) const override; + virtual void setValueToSeries(const Reference & xSeriesPropertySet, OUString const & xNewGraphicURL) const override; + + explicit WrappedSymbolBitmapURLProperty(const std::shared_ptr& spChart2ModelContact, + tSeriesOrDiagramPropertyType ePropertyType); +}; + +class WrappedSymbolBitmapProperty : public WrappedSeriesOrDiagramProperty> +{ +public: + virtual uno::Reference getValueFromSeries(const Reference& xSeriesPropertySet) const override; + virtual void setValueToSeries(const Reference & xSeriesPropertySet, uno::Reference const & xNewGraphic) const override; + + explicit WrappedSymbolBitmapProperty(const std::shared_ptr& 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& 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& 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 >& 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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "SymbolBitmapURL", + PROP_CHART_SYMBOL_BITMAP_URL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "SymbolBitmap", + PROP_CHART_SYMBOL_BITMAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "SymbolSize", + PROP_CHART_SYMBOL_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Lines", + PROP_CHART_SYMBOL_AND_LINES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +void WrappedSymbolProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES ); +} + +void WrappedSymbolProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ) +{ + lcl_addWrappedProperties( rList, spChart2ModelContact, DIAGRAM ); +} + +WrappedSymbolTypeProperty::WrappedSymbolTypeProperty( + const std::shared_ptr& 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) + { + Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() ); + Reference< chart2::XDataSeries > xSeries( xInnerPropertyState, uno::UNO_QUERY ); + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + if( ChartTypeHelper::isSupportingSymbolProperties( xChartType, 2 ) ) + return beans::PropertyState_DIRECT_VALUE; + } + return WrappedProperty::getPropertyState( xInnerPropertyState ); +} + +WrappedSymbolBitmapURLProperty::WrappedSymbolBitmapURLProperty( + const std::shared_ptr& spChart2ModelContact, + tSeriesOrDiagramPropertyType ePropertyType ) + : WrappedSeriesOrDiagramProperty("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& spChart2ModelContact, + tSeriesOrDiagramPropertyType ePropertyType ) + : WrappedSeriesOrDiagramProperty>("SymbolBitmap", + uno::Any(uno::Reference()), spChart2ModelContact, ePropertyType) +{ +} + +uno::Reference WrappedSymbolBitmapProperty::getValueFromSeries(const Reference< beans::XPropertySet >& xSeriesPropertySet) const +{ + uno::Reference 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 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 = OutputDevice::LogicToLogic(aPixelSize, MapMode(MapUnit::MapPixel), MapMode(MapUnit::Map100thMM)); + 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& 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& 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 000000000..d8eca1a93 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSYMBOLPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSYMBOLPROPERTIES_HXX + +#include +#include +#include + +namespace chart { class WrappedProperty; } +namespace chart::wrapper { class Chart2ModelContact; } +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ +namespace wrapper +{ + +class WrappedSymbolProperties +{ +public: + static void addProperties( std::vector< css::beans::Property > & rOutProperties ); + static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); + static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr >& rList + , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact ); +}; + +} //namespace wrapper +} //namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDSYMBOLPROPERTIES_HXX +#endif + +/* 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 000000000..c35a75e31 --- /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 000000000..58392f0a7 --- /dev/null +++ b/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDTEXTROTATIONPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDTEXTROTATIONPROPERTY_HXX + +#include + +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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_CHARTAPIWRAPPER_WRAPPEDTEXTROTATIONPROPERTY_HXX +#endif + +/* 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 000000000..01201cbb2 --- /dev/null +++ b/chart2/source/controller/chartcontroller.component @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/source/controller/dialogs/ChangingResource.cxx b/chart2/source/controller/dialogs/ChangingResource.cxx new file mode 100644 index 000000000..c50f274da --- /dev/null +++ b/chart2/source/controller/dialogs/ChangingResource.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 + +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 000000000..91307afaa --- /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 +#include + +#include +#include + +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 000000000..199606abe --- /dev/null +++ b/chart2/source/controller/dialogs/ChartResourceGroups.cxx @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +Dim3DLookResourceGroup::Dim3DLookResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , 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); + + if (rParameter.eThreeDLookScheme == ThreeDLookScheme_Simple) + m_xLB_Scheme->set_active(POS_3DSCHEME_SIMPLE); + else if (rParameter.eThreeDLookScheme == ThreeDLookScheme_Realistic) + m_xLB_Scheme->set_active(POS_3DSCHEME_REALISTIC); + else + m_xLB_Scheme->set_active(-1); +} + +void Dim3DLookResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + rParameter.b3DLook = m_xCB_3DLook->get_active(); + const int nPos = m_xLB_Scheme->get_active(); + if (nPos == POS_3DSCHEME_SIMPLE) + rParameter.eThreeDLookScheme = ThreeDLookScheme_Simple; + else if (nPos == POS_3DSCHEME_REALISTIC) + rParameter.eThreeDLookScheme = ThreeDLookScheme_Realistic; + else + rParameter.eThreeDLookScheme = ThreeDLookScheme_Unknown; +} + +IMPL_LINK_NOARG(Dim3DLookResourceGroup, Dim3DLookCheckHdl, weld::ToggleButton&, 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) + : ChangingResource() + , 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::ToggleButton&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +StackingResourceGroup::StackingResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , 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::ToggleButton&, 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::ToggleButton&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +SplineResourceGroup::SplineResourceGroup(weld::Builder* pBuilder, weld::Window* pParent) + : ChangingResource() + , 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)); +} + +SplinePropertiesDialog& SplineResourceGroup::getSplinePropertiesDialog() +{ + if (!m_xSplinePropertiesDialog) + { + m_xSplinePropertiesDialog.reset(new SplinePropertiesDialog(m_pParent)); + } + return *m_xSplinePropertiesDialog; +} + +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; + getSplinePropertiesDialog().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); + if (getSplinePropertiesDialog().run() == RET_OK) + { + if (m_pChangeListener) + m_pChangeListener->stateChanged(); + } + else + { + //restore old state: + m_xLB_LineType->set_active(iOldLineTypePos); + getSplinePropertiesDialog().fillControls(aOldParameter); + } +} + +IMPL_LINK_NOARG(SplineResourceGroup, SteppedDetailsDialogHdl, weld::Button&, void) +{ + ChartTypeParameter aOldParameter; + getSteppedPropertiesDialog().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); + if (getSteppedPropertiesDialog().run() == RET_OK) + { + if (m_pChangeListener) + m_pChangeListener->stateChanged(); + } + else + { + //restore old state: + m_xLB_LineType->set_active(iOldLineTypePos); + getSteppedPropertiesDialog().fillControls(aOldParameter); + } +} + +GeometryResourceGroup::GeometryResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , 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(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 000000000..6153c03ed --- /dev/null +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx @@ -0,0 +1,1253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +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_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_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(); +} +uno::Reference< XChartTypeTemplate > ChartTypeDialogController::getCurrentTemplate( + const ChartTypeParameter& rParameter + , const uno::Reference< lang::XMultiServiceFactory >& xTemplateManager ) const +{ + uno::Reference< XChartTypeTemplate > xTemplate; + + OUString aServiceName( getServiceNameForParameter( rParameter ) ); + if(!aServiceName.isEmpty()) + { + xTemplate.set( xTemplateManager->createInstance( aServiceName ), uno::UNO_QUERY ); + if(xTemplate.is()) + { + uno::Reference< beans::XPropertySet > xTemplateProps( xTemplate, 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 uno::Reference< XChartDocument >& xChartModel ) +{ + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + uno::Reference< XChartTypeTemplate > xTemplate( getCurrentTemplate( rParameter, xTemplateManager ) ); + if(!xTemplate.is()) + return; + + // locked controllers + ControllerLockGuardUNO aCtrlLockGuard( xChartModel ); + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartModel ); + DiagramHelper::tTemplateWithServiceName aTemplateWithService( + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateManager )); + if( aTemplateWithService.first.is()) + aTemplateWithService.first->resetStyles( xDiagram ); + xTemplate->changeDiagram( xDiagram ); + if( AllSettings::GetMathLayoutRTL() ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + if( rParameter.b3DLook ) + ThreeDHelper::setScheme( xDiagram, rParameter.eThreeDLookScheme ); + + uno::Reference xDiaProp(xDiagram, uno::UNO_QUERY); + if (xDiaProp.is()) + { + xDiaProp->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 uno::Reference< XChartDocument >& /*xChartModel*/ + , const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const +{ +} +void ChartTypeDialogController::setTemplateProperties( const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const +{ +} + +ColumnOrBarChartDialogController_Base::ColumnOrBarChartDialogController_Base() + : ChartTypeDialogController() +{ +} +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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 OUStringLiteral(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 uno::Reference< XChartDocument >& xChartModel + , const uno::Reference< beans::XPropertySet >& xTemplateProps ) const +{ + if (!m_xMF_NumberOfLines) + return; + + uno::Reference< frame::XModel > xModel = xChartModel; + + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel ); + 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( xModel ).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 OUStringLiteral(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 000000000..d772905dc --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowser.cxx @@ -0,0 +1,1389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "DataBrowser.hxx" +#include "DataBrowserModel.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +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_getRowInData( long nRow ) +{ + return static_cast< sal_Int32 >( nRow ); +} + +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 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_left(int nLeft) { m_xControl->set_margin_left(nLeft); } + + void SetModifyHdl(const Link& rLink) { m_aModifyHdl = rLink; } + void SetGetFocusHdl(const Link& 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 m_xControl; + Link m_aModifyHdl; + Link m_aFocusInHdl; + sal_Int32 m_nStartColumn; + bool m_bShowWarningBox; +}; + +SeriesHeaderEdit::SeriesHeaderEdit(std::unique_ptr 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 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 Reference< chart2::XChartType > & 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& rLink); + + void SetEditChangedHdl( const Link & rLink ); + + bool HasFocus() const; + +private: + Timer m_aUpdateDataTimer; + + std::unique_ptr m_xBuilder1; + std::unique_ptr m_xBuilder2; + + weld::Container* m_pParent; + weld::Container* m_pColorParent; + + std::unique_ptr m_xContainer1; + std::unique_ptr m_xContainer2; + std::unique_ptr m_spSymbol; + std::unique_ptr m_spSeriesName; + std::unique_ptr m_spColorBar; + VclPtr< OutputDevice> m_xDevice; + Link m_aChangeLink; + Color m_aColor; + + void notifyChanges(); + DECL_LINK( ImplUpdateDataHdl, Timer*, void ); + DECL_LINK( SeriesNameEdited, SeriesHeaderEdit&, void ); + + static OUString GetChartTypeImage( + const Reference< chart2::XChartType > & 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("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.SetDebugName( "SeriesHeader UpdateDataTimer" ); + 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_left(2); + + aSize.setWidth(nSymbolHeight); + aSize.setHeight(12); + aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + aSize.setWidth(m_nWidth - aSize.Width() - 2); + m_spSeriesName->set_size_request(aSize.Width(), aSize.Height()); + + // color bar + aSize.setHeight(3); + aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + aSize.setWidth(m_nWidth); + m_spColorBar->set_size_request(aSize.Width(), aSize.Height()); + + auto xVirDev(m_spColorBar->create_virtual_device()); + xVirDev->SetOutputSizePixel(aSize); + 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 Reference< chart2::XChartType > & 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 & 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& rLink ) +{ + m_spSeriesName->SetGetFocusHdl( rLink ); +} + +bool SeriesHeader::HasFocus() const +{ + return m_spSeriesName->HasFocus(); +} + +OUString SeriesHeader::GetChartTypeImage( + const Reference< chart2::XChartType > & 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 &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::Create( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ) ), + m_aTextEditField( VclPtr::Create( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ) ), + m_pColumnsWin(pColumns), + m_pColorsWin(pColors), + m_rNumberEditController( new ::svt::FormattedFieldCellController( m_aNumberEditField.get() )), + m_rTextEditController( new ::svt::EditCellController( m_aTextEditField.get() )) +{ + double fNan; + ::rtl::math::setNan( & fNan ); + m_aNumberEditField->SetDefaultValue( fNan ); + m_aNumberEditField->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; + + long 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, "%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 aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus )); + Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged )); + + for (auto const& elemHeader : aHeaders) + { + auto spHeader = std::make_shared( m_pColumnsWin, m_pColorsWin ); + Reference< beans::XPropertySet > xSeriesProp( elemHeader.m_xDataSeries, uno::UNO_QUERY ); + sal_Int32 nColor = 0; + // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc. + if( xSeriesProp.is() && + ( xSeriesProp->getPropertyValue( "Color" ) >>= nColor )) + spHeader->SetColor( Color( nColor )); + spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis ); + spHeader->SetSeriesName( + DataSeriesHelper::getDataSeriesLabel( + elemHeader.m_xDataSeries, + (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( long nRow, sal_uInt16 nColumnId ) const +{ + OUString aResult; + + if( nColumnId == 0 ) + { + aResult = OUString::number(static_cast< sal_Int32 >( 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 )); + Color nLabelColor; + + if( ! std::isnan( fData ) && + m_spNumberFormatterWrapper ) + { + bool bColorChanged = false; + 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( + Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY), 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( long nRow, sal_uInt16 nColumnId ) const +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if(( nColumnId >= 1 ) && ( nRow >= 0 ) && m_apDataBrowserModel) + { + fResult = m_apDataBrowserModel->getCellNumber( + static_cast< sal_Int32 >( nColumnId ) - 1, nRow ); + } + + return fResult; +} + +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 xWarn(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + SchResId(STR_INVALID_NUMBER))); + xWarn->run(); +} + +bool DataBrowser::ShowQueryBox() +{ + std::unique_ptr 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->GetText()); + + 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 Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext ) +{ + m_xChartDoc.set( xChartDoc ); + + m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc, xContext )); + m_spNumberFormatterWrapper = + std::make_shared( + Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY )); + + m_aNumberEditField->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 = lcl_getRowInData( 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 = lcl_getRowInData( 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 = lcl_getRowInData( 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 = lcl_getRowInData( 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& 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( long 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 +{ + long nRow = GetCurRow(); + long nCol = GetCurColumnId(); + + // column 0 is header-column + long nBadCol = bForward + ? GetColumnCount() - 1 + : 1; + long nBadRow = bForward + ? GetRowCount() - 1 + : 0; + + if( !m_bDataValid ) + { + const_cast< DataBrowser* >( this )->ShowWarningBox(); + return false; + } + + return ( nRow != nBadRow || + nCol != nBadCol ); +} + +::svt::CellController* DataBrowser::GetController( long /*nRow*/, sal_uInt16 nCol ) +{ + if( m_bIsReadOnly ) + return nullptr; + + if( CellContainsNumbers( nCol )) + { + m_aNumberEditField->UseInputStringForFormatting(); + m_aNumberEditField->SetFormatKey( GetNumberFormatKey( nCol )); + return m_rNumberEditController.get(); + } + + return m_rTextEditController.get(); +} + +void DataBrowser::InitController( + ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) +{ + if( rController == m_rTextEditController ) + { + OUString aText( GetCellText( nRow, nCol ) ); + m_aTextEditField->SetText( aText ); + m_aTextEditField->SetSelection( ::Selection( 0, aText.getLength() )); + } + else if( rController == m_rNumberEditController ) + { + // treat invalid and empty text as Nan + m_aNumberEditField->EnableNotANumber( true ); + if( std::isnan( GetCellNumber( nRow, nCol ))) + m_aNumberEditField->SetTextValue( OUString()); + else + m_aNumberEditField->SetValue( GetCellNumber( nRow, nCol ) ); + OUString aText( m_aNumberEditField->GetText()); + m_aNumberEditField->SetSelection( ::Selection( 0, aText.getLength())); + } + 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 = lcl_getRowInData( 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->GetText()); + // 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 + { + double fData = m_aNumberEditField->GetValue(); + bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData ); + } + } + break; + case DataBrowserModel::TEXTORDATE: + { + OUString aText( m_aTextEditField->GetText() ); + 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: + { + OUString aText( m_aTextEditField->GetText()); + 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->ClearModified(); + } + + 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 aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus )); + Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged )); + + for (auto const& elemHeader : aHeaders) + { + auto spHeader = std::make_shared( m_pColumnsWin, m_pColorsWin ); + Reference< beans::XPropertySet > xSeriesProp(elemHeader.m_xDataSeries, uno::UNO_QUERY); + sal_Int32 nColor = 0; + if( xSeriesProp.is() && + ( xSeriesProp->getPropertyValue( "Color" ) >>= nColor )) + spHeader->SetColor( Color( nColor )); + spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis ); + spHeader->SetSeriesName( + DataSeriesHelper::getDataSeriesLabel( + elemHeader.m_xDataSeries, + (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_left(nCurrentPos); + pColorWin->set_margin_left(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_left(nStartPos); + pColorWin->set_margin_left(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 ) +{ + Reference< chart2::XDataSeries > xSeries( + m_apDataBrowserModel->getDataSeriesByColumn( rEdit.getStartColumn() - 1 )); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( !xSource.is()) + return; + + Reference< chart2::XChartType > xChartType( + m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType ); + if( xChartType.is()) + { + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + DataSeriesHelper::getDataSequenceByRole( xSource, 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 000000000..8e6372b0b --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowser.hxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX + +#include +#include +#include + +#include +#include + +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; + +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( long nRow ) override; + virtual bool IsTabAllowed( bool bForward ) const override; + virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) override; + virtual void InitController( ::svt::CellControllerRef& rController, long 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 &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(long 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( long 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 css::uno::Reference< css::chart2::XChartDocument > & xChartDoc, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + + // 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& 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: + css::uno::Reference< css::chart2::XChartDocument > 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 + long m_nSeekRow; + bool m_bIsReadOnly; + bool m_bDataValid; + + VclPtr m_aNumberEditField; + VclPtr 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 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 + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX + +/* 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 000000000..c8359f74a --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx @@ -0,0 +1,963 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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 Reference< chart2::XDataSeries > & 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()); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences()); + for( 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< Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec; + +lcl_tSharedSeqVec lcl_getSharedSequences( const Sequence< Reference< chart2::XDataSeries > > & 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.getLength() <= 1 ) + return aResult; + + Reference< chart2::data::XDataSource > xSource( rSeries[0], uno::UNO_QUERY ); + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences()); + for( Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aLSeq ) + { + Reference< chart2::data::XDataSequence > xValues( labeledDataSeq->getValues()); + bool bShared = true; + for( sal_Int32 nSeriesIdx=1; nSeriesIdx & 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 Reference< chart2::data::XLabeledDataSequence > & xLSeq ) : + m_aRole(DataSeriesHelper::getRole(xLSeq)) {} + + bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) + { + return DataSeriesHelper::getRole(xLSeq) == m_aRole; + } +private: + OUString m_aRole; +}; + +bool lcl_ShowCategoriesAsDataLabel( const Reference< chart2::XDiagram > & xDiagram ) +{ + return !DiagramHelper::isCategoryDiagram(xDiagram); +} + +} // anonymous namespace + +struct DataBrowserModel::tDataColumn +{ + uno::Reference m_xDataSeries; + OUString m_aUIRoleName; + uno::Reference m_xLabeledDataSequence; + eCellType m_eCellType; + sal_Int32 m_nNumberFormatKey; + + // default CTOR + tDataColumn() : m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {} + // "full" CTOR + tDataColumn( + const uno::Reference & xDataSeries, + const OUString& aUIRoleName, + const uno::Reference& xLabeledDataSequence, + eCellType aCellType, + sal_Int32 nNumberFormatKey ) : + m_xDataSeries( xDataSeries ), + m_aUIRoleName( aUIRoleName ), + m_xLabeledDataSequence( 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 Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext ) : + m_xChartDocument( xChartDoc ), + m_apDialogModel( new DialogModel( xChartDoc, xContext )) +{ + updateFromModel(); +} + +DataBrowserModel::~DataBrowserModel() +{} + +namespace +{ +struct lcl_DataSeriesOfHeaderMatches +{ + explicit lcl_DataSeriesOfHeaderMatches( + const Reference< chart2::XDataSeries > & xSeriesToCompareWith ) : + m_xSeries( xSeriesToCompareWith ) + {} + bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader ) + { + return (m_xSeries == rHeader.m_xDataSeries); + } +private: + Reference< chart2::XDataSeries > 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; + Reference xDiagram = ChartModelHelper::findDiagram(m_xChartDocument); + Reference xChartType; + Reference xSeries; + if (o3tl::make_unsigned(nAfterColumnIndex) < m_aColumns.size()) + // Get the data series at specific column position (if available). + xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries ); + + sal_Int32 nSeriesNumberFormat = 0; + if( xSeries.is()) + { + // Use the chart type of the currently selected data series. + xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, 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. + Reference< beans::XPropertySet > xSeriesProps( xSeries, uno::UNO_QUERY ); + if( xSeriesProps.is() ) + xSeriesProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nSeriesNumberFormat; + } + else + { + // No data series at specified column position. Use the first chart type. + xChartType.set( DiagramHelper::getChartTypeByIndex( xDiagram, 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). + Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY ); + lcl_tSharedSeqVec aSharedSequences; + if( xSeriesCnt.is()) + aSharedSequences = lcl_getSharedSequences( xSeriesCnt->getDataSeries()); + + Reference xNewSeries = + m_apDialogModel->insertSeriesAfter(xSeries, xChartType, true); + + if (!xNewSeries.is()) + // Failed to insert new data series to the model. Bail out. + return; + + Reference< chart2::data::XDataSource > xSource( xNewSeries, uno::UNO_QUERY ); + if (xSource.is()) + { + Sequence > aLSequences = xSource->getDataSequences(); + sal_Int32 nSeqIdx = 0; + sal_Int32 nSeqSize = aLSequences.getLength(); + 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 + Reference< beans::XPropertySet > xNewSeriesProps( xNewSeries, uno::UNO_QUERY ); + if( xNewSeriesProps.is() ) + xNewSeriesProps->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 Reference& 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 ); + Reference< chart2::data::XDataSource > xSourceOfDeleted( xSeries, uno::UNO_QUERY ); + if (!xDataProvider.is() || !xSourceOfDeleted.is()) + { + // Something went wrong. Bail out. + updateFromModel(); + return; + } + + Reference xSeriesCnt( + getHeaderForSeries(xSeries).m_xChartType, uno::UNO_QUERY); + 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 > aAllDataSeqs = + DataSeriesHelper::getAllDataSequences(xSeriesCnt->getDataSeries()); + + // 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 aSequenceIndexesToDelete; + const Sequence > aSequencesOfDeleted = xSourceOfDeleted->getDataSequences(); + 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 ) + { + Reference< chart2::XDataSeries > 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 +{ + for (auto const& elemHeader : m_aHeaders) + { + if( elemHeader.m_xDataSeries == xSeries ) + return elemHeader; + } + return tDataHeader(); +} + +Reference< chart2::XDataSeries > + 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 ) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + 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()) + fResult = aValues[nAtRow]; + } + } + return fResult; +} + +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#) + Reference< util::XModifiable > xModifiable( m_xChartDocument, uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->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(); + + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument )); + if( !xDiagram.is()) + return; + + // set template at DialogModel + uno::Reference< lang::XMultiServiceFactory > xFact( m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + if( aTemplateAndService.first.is()) + m_apDialogModel->setTemplate( aTemplateAndService.first ); + + sal_Int32 nHeaderStart = 0; + sal_Int32 nHeaderEnd = 0; + { + Reference< frame::XModel > xChartModel = m_xChartDocument; + ChartModel* pModel = dynamic_cast(xChartModel.get()); + if (!pModel) + return; + ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), *pModel ); + + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL xCategories( rSplitCategoriesList[nL] ); + if( !xCategories.is() ) + continue; + + tDataColumn aCategories; + aCategories.m_xLabeledDataSequence.set( 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; + } + } + + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( !xCooSysCnt.is()) + return; + const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + for( Reference< chart2::XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< chart2::XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); + sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( nullptr, coords, 0, 0 ); + + for( sal_Int32 nCTIdx=0; nCTIdx xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY ); + if( xSeriesCnt.is()) + { + OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( aChartTypes[nCTIdx] ); + + const Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); + 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( Reference< chart2::XDataSeries > const & dataSeries : aSeries ) + { + tDataColumnVector::size_type nStartColIndex = m_aColumns.size(); + Reference< chart2::XDataSeries > xSeries( dataSeries ); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( xSource.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences()); + if( !aLSeqs.hasElements() ) + 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( xSeries, uno::UNO_QUERY )); + } + 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 + { + Reference< beans::XPropertySet > xProp( coords, uno::UNO_QUERY ); + xProp->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, + aChartTypes[nCTIdx], + bSwapXAndYAxis, + nHeaderStart, + nHeaderEnd - 1 ); + + nHeaderStart = nHeaderEnd; + + std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() ); + } + } + } + } + } +} + +void DataBrowserModel::addErrorBarRanges( + const Reference< chart2::XDataSeries > & xDataSeries, + sal_Int32 nNumberFormatKey, + sal_Int32 & rInOutSequenceIndex, + sal_Int32 & rInOutHeaderEnd, bool bYError ) +{ + try + { + std::vector< Reference< chart2::data::XLabeledDataSequence > > aSequences; + + Reference< chart2::data::XDataSource > xErrorSource( + StatisticsHelper::getErrorBars( xDataSeries, bYError ), uno::UNO_QUERY ); + + Reference< chart2::data::XLabeledDataSequence > xErrorLSequence( + StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + xErrorSource, + /* bPositiveValue = */ true, + bYError )); + if( xErrorLSequence.is()) + aSequences.push_back( xErrorLSequence ); + + xErrorLSequence.set( + StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + xErrorSource, + /* bPositiveValue = */ false, + bYError )); + if( xErrorLSequence.is()) + aSequences.push_back( xErrorLSequence ); + + for (Reference 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 000000000..a4ba44987 --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowserModel.hxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX + +#include + +#include +#include + +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 DataBrowserModel final +{ +public: + explicit DataBrowserModel( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + ~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 if the number could successfully be set at the given position + bool setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue ); + /// returns 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 + { + css::uno::Reference< css::chart2::XDataSeries > m_xDataSeries; + css::uno::Reference< css::chart2::XChartType > 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( + css::uno::Reference< css::chart2::XDataSeries > const & xDataSeries, + css::uno::Reference< css::chart2::XChartType > const &xChartType, + bool bSwapXAndYAxis, + sal_Int32 nStartColumn, + sal_Int32 nEndColumn ) : + m_xDataSeries( xDataSeries ), + m_xChartType( 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; + + css::uno::Reference< css::chart2::XDataSeries > + getDataSeriesByColumn( sal_Int32 nColumn ) const; + +private: + void updateFromModel(); + + void removeComplexCategoryLevel( sal_Int32 nAtColumnIndex ); + + void addErrorBarRanges( + const css::uno::Reference & xDataSeries, + sal_Int32 nNumberFormatKey, + sal_Int32 & rInOutSequenceIndex, + sal_Int32 & rInOutHeaderEnd, bool bYError ); + + sal_Int32 getCategoryColumnCount(); + + css::uno::Reference< css::chart2::XChartDocument > 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX +#endif + +/* 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 000000000..b4bdbae65 --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -0,0 +1,860 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +const OUString lcl_aLabelRole( "label" ); + +struct lcl_ChartTypeToSeriesCnt +{ + Reference< XDataSeriesContainer > operator() ( + const Reference< XChartType > & xChartType ) + { + return Reference< XDataSeriesContainer >::query( xChartType ); + } +}; + +OUString lcl_ConvertRole( const OUString & rRoleString ) +{ + OUString aResult( rRoleString ); + + typedef std::map< OUString, OUString > tTranslationMap; + static 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_DataSeriesContainerAppend +{ + typedef Reference< XDataSeriesContainer > value_type; + typedef std::vector< ::chart::DialogModel::tSeriesWithChartTypeByName > tContainerType; + + explicit lcl_DataSeriesContainerAppend( tContainerType * rCnt ) + : m_rDestCnt( rCnt ) + {} + + lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal ) + { + try + { + if( xVal.is()) + { + const Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries()); + OUString aRole( "values-y" ); + Reference< XChartType > xCT( xVal, uno::UNO_QUERY ); + if( xCT.is()) + aRole = xCT->getRoleOfSequenceForSeriesLabel(); + for( Reference< XDataSeries > const & dataSeries : aSeq ) + { + m_rDestCnt->push_back( + ::chart::DialogModel::tSeriesWithChartTypeByName( + ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ), + std::make_pair( dataSeries, xCT ))); + } + } + } + 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_DataSeriesContainerAppend & operator* () { return *this; } + lcl_DataSeriesContainerAppend & operator++ () { return operator++(0); } + lcl_DataSeriesContainerAppend & operator++ (int) { return *this; } + +private: + tContainerType * m_rDestCnt; +}; + +struct lcl_RolesWithRangeAppend +{ + typedef Reference< data::XLabeledDataSequence > value_type; + typedef ::chart::DialogModel::tRolesWithRanges tContainerType; + + explicit lcl_RolesWithRangeAppend( tContainerType * rCnt, + const OUString & aLabelRole ) + : m_rDestCnt( rCnt ), + m_aRoleForLabelSeq( 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 + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< XDataSeriesContainer > value_type; + }; + + template<> struct iterator_traits + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< data::XLabeledDataSequence > value_type; + }; +} + +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 )); +} + +Reference< XDataSeries > lcl_CreateNewSeries( + const Reference< uno::XComponentContext > & xContext, + const Reference< XChartType > & xChartType, + sal_Int32 nNewSeriesIndex, + sal_Int32 nTotalNumberOfSeriesInCTGroup, + const Reference< XDiagram > & xDiagram, + const Reference< XChartTypeTemplate > & xTemplate, + bool bCreateDataCachedSequences ) +{ + // create plain series + Reference< XDataSeries > xResult( + xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.DataSeries" , + xContext ), uno::UNO_QUERY ); + if( xTemplate.is()) + { + Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY ); + if( xResultProp.is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + xResultProp->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex ))); + } + sal_Int32 nGroupIndex=0; + if( xChartType.is()) + { + Sequence< Reference< XChartType > > aCTs( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram )); + for( ; nGroupIndexapplyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup ); + } + + if( bCreateDataCachedSequences ) + { + // set chart type specific roles + Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY ); + if( xChartType.is() && xSink.is()) + { + std::vector< Reference< data::XLabeledDataSequence > > aNewSequences; + const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel(); + const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES)); + const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); + const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles()); + + 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 )); + } + + xSink->setData( comphelper::containerToSequence( 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( + const Reference< XChartDocument > & xChartDocument, + const Reference< uno::XComponentContext > & xContext ) : + m_xChartDocument( xChartDocument ), + m_xContext( xContext ), + m_aTimerTriggeredControllerLock( m_xChartDocument ) +{ +} + +DialogModel::~DialogModel() +{ + if(maTimeBasedInfo.bTimeBased) + { + getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd); + } +} + +void DialogModel::setTemplate( + const Reference< XChartTypeTemplate > & xTemplate ) +{ + m_xTemplate = xTemplate; +} + +std::shared_ptr< RangeSelectionHelper > const & + DialogModel::getRangeSelectionHelper() const +{ + if( ! m_spRangeSelectionHelper) + m_spRangeSelectionHelper = + std::make_shared( m_xChartDocument ); + + return m_spRangeSelectionHelper; +} + +Reference< frame::XModel > 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< Reference< XDataSeriesContainer > > + DialogModel::getAllDataSeriesContainers() const +{ + std::vector< Reference< XDataSeriesContainer > > aResult; + + try + { + Reference< XDiagram > xDiagram; + if( m_xChartDocument.is()) + xDiagram.set( m_xChartDocument->getFirstDiagram()); + if( xDiagram.is()) + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + std::transform( + aChartTypeSeq.begin(), aChartTypeSeq.end(), + std::back_inserter( aResult ), + lcl_ChartTypeToSeriesCnt() ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +std::vector< DialogModel::tSeriesWithChartTypeByName > + DialogModel::getAllDataSeriesWithLabel() const +{ + std::vector< tSeriesWithChartTypeByName > aResult; + std::vector< Reference< XDataSeriesContainer > > aContainers( + getAllDataSeriesContainers()); + + std::copy( aContainers.begin(), aContainers.end(), + lcl_DataSeriesContainerAppend( &aResult )); + return aResult; +} + +namespace { + +void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence& 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 Reference& xChartType, + const Reference& xSeries, + const Reference& xNewSeries ) +{ + Reference xSeriesCnt(xChartType, uno::UNO_QUERY_THROW); + auto aSeries = comphelper::sequenceToContainer >>(xSeriesCnt->getDataSeries()); + + std::vector >::iterator 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); + xSeriesCnt->setDataSeries(comphelper::containerToSequence(aSeries)); +} + +} + +DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( + const Reference< XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const Reference< chart2::XChartType > & 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 Reference< XDataSeries > & xSeries, + MoveDirection eDirection ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down ); +} + +Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter( + const Reference< XDataSeries > & xSeries, + const Reference< XChartType > & xChartType, + bool bCreateDataCachedSequences /* = false */ ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + Reference< XDataSeries > xNewSeries; + + try + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + sal_Int32 nSeriesInChartType = 0; + const sal_Int32 nTotalSeries = countSeries(); + if( xChartType.is()) + { + Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW ); + nSeriesInChartType = xCnt->getDataSeries().getLength(); + } + + // create new series + xNewSeries.set( + lcl_CreateNewSeries( + m_xContext, + xChartType, + nTotalSeries, // new series' index + nSeriesInChartType, + xDiagram, + m_xTemplate, + bCreateDataCachedSequences )); + + // add new series to container + if( xNewSeries.is()) + addNewSeriesToContainer(xChartType, xSeries, xNewSeries); + + ThreeDHelper::setScheme( xDiagram, e3DScheme ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xNewSeries; +} + +void DialogModel::deleteSeries( + const Reference< XDataSeries > & xSeries, + const Reference< XChartType > & xChartType ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + DataSeriesHelper::deleteSeries( xSeries, xChartType ); +} + +Reference< data::XLabeledDataSequence > DialogModel::getCategories() const +{ + Reference< data::XLabeledDataSequence > xResult; + try + { + if( m_xChartDocument.is()) + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xResult; +} + +void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) +{ + if( !m_xChartDocument.is()) + return; + + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + if( !xDiagram.is()) + return; + + // categories + bool bSupportsCategories = true; + + Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + if( xFirstChartType.is() ) + { + sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis + bSupportsCategories = (nAxisType == AxisType::CATEGORY); + } + DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories ); +} + +OUString DialogModel::getCategoriesRange() const +{ + Reference< data::XLabeledDataSequence > xLSeq( getCategories()); + OUString aRange; + if( xLSeq.is()) + { + Reference< data::XDataSequence > xSeq( xLSeq->getValues()); + if( xSeq.is()) + aRange = xSeq->getSourceRangeRepresentation(); + } + return aRange; +} + +bool DialogModel::isCategoryDiagram() const +{ + bool bRet = false; + if( m_xChartDocument.is()) + bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() ); + 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()) + DataSourceHelper::detectRangeSegmentation( + Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ), + 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 ) ); + + Reference< chart2::XDataInterpreter > xInterpreter( + m_xTemplate->getDataInterpreter()); + if( xInterpreter.is()) + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + std::vector< Reference< XDataSeries > > aSeriesToReUse( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + applyInterpretedData( + xInterpreter->interpretDataSource( + xDataSource, rArguments, + comphelper::containerToSequence( aSeriesToReUse )), + aSeriesToReUse); + + ThreeDHelper::setScheme( xDiagram, 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< Reference< XDataSeries > > & rSeriesToReUse ) +{ + if( ! m_xChartDocument.is()) + return; + + m_aTimerTriggeredControllerLock.startTimer(); + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + 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.getLength(); + + for(; nGroup < nOuterSize; ++nGroup) + { + Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] ); + const sal_Int32 nSeriesInGroup = aSeries.getLength(); + for( sal_Int32 nSeries=0; nSeries xSeriesProp( aSeries[nSeries], uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + xSeriesProp->setPropertyValue( "Color" , + uno::Any( xColorScheme->getColorByIndex( nSeriesCounter ))); + } + m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); + } + } + } + } + + // data series + std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers()); + auto aNewSeries( + comphelper::sequenceToContainer > >>( rNewData.Series )); + + OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size()); + + std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin()); + std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin()); + for(; aSrcIt != aNewSeries.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< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers()); + return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); +} + +ChartModel& DialogModel::getModel() const +{ + uno::Reference< frame::XModel > xModel = getChartModel(); + ChartModel* pModel = dynamic_cast(xModel.get()); + assert(pModel); + return *pModel; +} + +} // 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 000000000..8b3a2a5c0 --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX + +#include +#include + +#include +#include +#include + +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 Sequence; } + +namespace com::sun::star::chart2 { + class XDataSeriesContainer; + class XDataSeries; + class XChartType; + class XChartTypeTemplate; + struct InterpretedData; + namespace data { + class XDataProvider; + class XLabeledDataSequence; + } +} + +namespace chart +{ + +class RangeSelectionHelper; + +struct DialogModelTimeBasedInfo +{ + DialogModelTimeBasedInfo(); + + bool bTimeBased; + sal_Int32 nStart; + sal_Int32 nEnd; +}; + +class DialogModel +{ +public: + explicit DialogModel( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDocument, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + ~DialogModel(); + + typedef std::pair< + OUString, + std::pair< css::uno::Reference< css::chart2::XDataSeries >, + css::uno::Reference< css::chart2::XChartType > > > + tSeriesWithChartTypeByName; + + typedef std::map< OUString, OUString > + tRolesWithRanges; + + void setTemplate( + const css::uno::Reference< css::chart2::XChartTypeTemplate > & xTemplate ); + + std::shared_ptr< RangeSelectionHelper > const & + getRangeSelectionHelper() const; + + css::uno::Reference< css::frame::XModel > + getChartModel() const; + + css::uno::Reference< css::chart2::data::XDataProvider > + getDataProvider() const; + + std::vector< css::uno::Reference< css::chart2::XDataSeriesContainer > > + getAllDataSeriesContainers() const; + + std::vector< tSeriesWithChartTypeByName > + getAllDataSeriesWithLabel() const; + + static tRolesWithRanges getRolesWithRanges( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const css::uno::Reference< css::chart2::XChartType > & xChartType ); + + enum class MoveDirection + { + Down, Up + }; + + void moveSeries( const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + MoveDirection eDirection ); + + /// @return the newly inserted series + css::uno::Reference< + css::chart2::XDataSeries > insertSeriesAfter( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XChartType > & xChartType, + bool bCreateDataCachedSequences = false ); + + void deleteSeries( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XChartType > & 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: + css::uno::Reference< css::chart2::XChartDocument > + m_xChartDocument; + + css::uno::Reference< css::chart2::XChartTypeTemplate > + m_xTemplate; + + css::uno::Reference< css::uno::XComponentContext > + m_xContext; + + mutable std::shared_ptr< RangeSelectionHelper > + m_spRangeSelectionHelper; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + +private: + void applyInterpretedData( + const css::chart2::InterpretedData & rNewData, + const std::vector< css::uno::Reference< css::chart2::XDataSeries > > & rSeriesToReUse ); + + sal_Int32 countSeries() const; + + mutable DialogModelTimeBasedInfo maTimeBasedInfo; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX +#endif + +/* 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 000000000..2a3d954a6 --- /dev/null +++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx @@ -0,0 +1,865 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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( const OUString& rObjectCID, const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + if( xChartType.is() ) + { + aRet = ::chart::DataSeriesHelper::getDataSeriesLabel( + xSeries, xChartType->getRoleOfSequenceForSeriesLabel() ) ; + } + } + + return aRet; +} + +OUString lcl_getFullSeriesName( const OUString& rObjectCID, const Reference< frame::XModel >& 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, const OUString& rSeparator, const OUString& rNext ) +{ + if( !(rOut.isEmpty() || rNext.isEmpty()) ) + rOut+=rSeparator; + if( !rNext.isEmpty() ) + rOut+=rNext; +} + +OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal_Int32 nPointIndex, + const Reference< XCoordinateSystem >& xCooSys, + const Reference< frame::XModel >& xChartModel ) +{ + + OUString aRet; + + Reference xDataSource( + uno::Reference( xSeries, uno::UNO_QUERY ) ); + if(!xDataSource.is()) + return aRet; + + Sequence< Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + + 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.getLength();nN--;) + { + uno::Reference xDataSequence( aDataSequences[nN]->getValues()); + if( !xDataSequence.is() ) + continue; + Sequence< Any > aData( xDataSequence->getData() ); + if( nPointIndex >= aData.getLength() ) + continue; + uno::Reference xProp(xDataSequence, uno::UNO_QUERY ); + if( xProp.is()) + { + try + { + 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 uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + + if( aX.isEmpty() ) + { + ChartModel& rModel = dynamic_cast(*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; + default: //OBJECTTYPE_UNKNOWN + ; + } + return aRet; +} + +OUString ObjectNameProvider::getAxisName( const OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XAxis > xAxis( + ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY ); + + sal_Int32 nCooSysIndex = 0; + sal_Int32 nDimensionIndex = 0; + sal_Int32 nAxisIndex = 0; + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ), 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( const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XTitle > xTitle( + ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY ); + if( xTitle.is() ) + { + 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( const OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + sal_Int32 nCooSysIndex = -1; + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + Reference< XAxis > xAxis( ObjectIdentifier::getAxisForCID( rObjectCID , xChartModel ) ); + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ) + , 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( const OUString& rObjectCID, const Reference< chart2::XChartDocument >& xChartDocument ) +{ + return getHelpText( rObjectCID, Reference< frame::XModel >( xChartDocument ) ); +} + +OUString ObjectNameProvider::getHelpText( const OUString& rObjectCID, const Reference< frame::XModel >& 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); + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() ); + + //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< Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + 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 ); + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, nCurveIndex) ); + if( xCurve.is()) + { + try + { + Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW ); + sal_Int32 aDegree = 2; + sal_Int32 aPeriod = 2; + 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]; + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + if ( xProperties.is()) + { + xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree; + xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; + xProperties->getPropertyValue( "ForceIntercept") >>= bForceIntercept; + if (bForceIntercept) + xProperties->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, 2); + xCalculator->setXYNames ( aXName, aYName ); + RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel ); + + // change text for Moving Average + OUString aWildcard( "%PERIOD" ); + sal_Int32 nIndex = xCalculator->getRepresentation().indexOf( aWildcard ); + if( nIndex != -1 ) + { // replace period + aRet = xCalculator->getRepresentation(); + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(aPeriod) ); + } + + // replace formula + aWildcard = "%FORMULA"; + 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 + { + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(rObjectCID , xChartModel)); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + aRet += getName(eObjectType); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, 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); + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + if( xCurveCnt.is()) + { + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getMeanValueLine( xCurveCnt )); + 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( const OUString & rObjectCID, const css::uno::Reference< css::chart2::XChartDocument >& xChartDocument ) +{ + OUString aRet; + ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) ); + Reference< frame::XModel > xChartModel = xChartDocument; + + if( eObjectType == OBJECTTYPE_DATA_POINT ) + { + aRet = SchResId( STR_STATUS_DATAPOINT_MARKED ); + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() ); + + // replace data point index + replaceParamterInString( aRet, "%POINTNUMBER", OUString::number( nPointIndex + 1 )); + + // replace data series index + { + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesIndex = -1; + for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;) + { + if( aSeriesVector[nSeriesIndex] == xSeries ) + break; + } + replaceParamterInString( aRet, "%SERIESNUMBER", OUString::number( nSeriesIndex + 1 ) ); + } + + // replace point value + replaceParamterInString( aRet, "%POINTVALUES", lcl_getDataPointValueText( + xSeries, nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) ); + } + } + 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, xChartModel, bVerbose )); + if( !aHelpText.isEmpty()) + { + aRet = SchResId( STR_STATUS_OBJECT_MARKED ); + replaceParamterInString( aRet, "%OBJECTNAME", aHelpText ); + } + } + + return aRet; +} + +OUString ObjectNameProvider::getNameForCID( + const OUString& rObjectCID, + const uno::Reference< chart2::XChartDocument >& xChartDocument ) +{ + ObjectType eType( ObjectIdentifier::getObjectType( rObjectCID )); + Reference< frame::XModel > xModel = xChartDocument; + + switch( eType ) + { + case OBJECTTYPE_AXIS: + return getAxisName( rObjectCID, xModel ); + case OBJECTTYPE_TITLE: + return getTitleName( rObjectCID, xModel ); + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + return getGridName( rObjectCID, xModel ); + case OBJECTTYPE_DATA_SERIES: + return lcl_getFullSeriesName( rObjectCID, xModel ); + 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, xModel ) + " "; + 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) + { + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + + aRet += " " + getName(eType); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, 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, + const OUString& rSeriesCID, + const uno::Reference< chart2::XChartDocument >& xChartDocument ) +{ + uno::Reference< frame::XModel> xChartModel = xChartDocument; + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSeriesCID , xChartModel ); + if( xSeries.is() ) + { + OUString aRet = SchResId(STR_OBJECT_FOR_SERIES); + replaceParamterInString( aRet, "%OBJECTNAME", getName( eObjectType ) ); + replaceParamterInString( aRet, "%SERIESNAME", lcl_getDataSeriesName( rSeriesCID, xChartModel ) ); + return aRet; + } + else + return ObjectNameProvider::getName_ObjectForAllSeries( eObjectType ); +} + +OUString ObjectNameProvider::getName_ObjectForAllSeries( ObjectType eObjectType ) +{ + OUString aRet = SchResId(STR_OBJECT_FOR_ALL_SERIES); + replaceParamterInString( aRet, "%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 000000000..8cd8f64c8 --- /dev/null +++ b/chart2/source/controller/dialogs/RangeSelectionHelper.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 +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +RangeSelectionHelper::RangeSelectionHelper( + const Reference< chart2::XChartDocument > & xChartDocument ) : + m_xChartDocument( 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( 4 ); + aArgs[0] = beans::PropertyValue( + "InitialValue", -1, uno::Any( aCurrentRange ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + "Title", -1, + uno::Any( aUIString ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + "CloseOnMouseRelease", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = 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 000000000..ca0d9ae2c --- /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 + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +RangeSelectionListener::RangeSelectionListener( + RangeSelectionListenerParent & rParent, + const OUString & rInitialRange, + const Reference< frame::XModel >& xModelToLockController ) : + m_rParent( rParent ), + m_aRange( rInitialRange ), + 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 000000000..68181fdfc --- /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 +#include +#include + +namespace chart +{ +TextDirectionListBox::TextDirectionListBox(std::unique_ptr 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 000000000..166846da6 --- /dev/null +++ b/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx @@ -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 . + */ + +#include +#include +#include + +namespace chart +{ + +using namespace ::com::sun::star; + +TimerTriggeredControllerLock::TimerTriggeredControllerLock( const uno::Reference< frame::XModel >& xModel ) + : m_xModel( xModel ) + , m_apControllerLockGuard() + , m_aTimer() +{ + 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 000000000..e4e909901 --- /dev/null +++ b/chart2/source/controller/dialogs/TitleDialogData.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 + +#include + +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +TitleDialogData::TitleDialogData( std::unique_ptr pRefSizeProvider ) + : aPossibilityList(7) + , aExistenceList(7) + , aTextList(7) + , apReferenceSizeProvider( std::move(pRefSizeProvider) ) +{ + for (sal_Int32 i = 0; i < 7; i++) + { + aPossibilityList[i] = true; + aExistenceList[i] = false; + } +} + +void TitleDialogData::readFromModel( const uno::Reference< frame::XModel>& xChartModel ) +{ + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(xChartModel); + + //get possibilities + uno::Sequence< sal_Bool > aAxisPossibilityList; + AxisHelper::getAxisOrGridPossibilities( aAxisPossibilityList, xDiagram ); + aPossibilityList[2]=aAxisPossibilityList[0];//x axis title + aPossibilityList[3]=aAxisPossibilityList[1];//y axis title + aPossibilityList[4]=aAxisPossibilityList[2];//z axis title + aPossibilityList[5]=aAxisPossibilityList[3];//secondary x axis title + aPossibilityList[6]=aAxisPossibilityList[4];//secondary y axis title + + //find out which title exists and get their text + //main title: + for( sal_Int32 nTitleIndex = static_cast< sal_Int32 >( TitleHelper::TITLE_BEGIN); + nTitleIndex < static_cast< sal_Int32 >( TitleHelper::NORMAL_TITLE_END ); + nTitleIndex++) + { + uno::Reference< XTitle > xTitle = TitleHelper::getTitle( + static_cast< TitleHelper::eTitleType >( nTitleIndex ), xChartModel ); + aExistenceList[nTitleIndex] = xTitle.is(); + aTextList[nTitleIndex]=TitleHelper::getCompleteString( xTitle ); + } +} + +bool TitleDialogData::writeDifferenceToModel( + const uno::Reference< frame::XModel >& xChartModel + , const uno::Reference< uno::XComponentContext >& xContext + , TitleDialogData* pOldState ) +{ + bool bChanged = false; + for( sal_Int32 nN = static_cast< sal_Int32 >( TitleHelper::TITLE_BEGIN ); + nN < static_cast< sal_Int32 >( 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 + uno::Reference< XTitle > 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 000000000..d1c2acc3c --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ChartType.cxx @@ -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 . + */ + +#include +#include "tp_ChartType.hxx" +#include + + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +ChartTypeDialog::ChartTypeDialog(weld::Window* pParent, + const uno::Reference< frame::XModel >& xChartModel) + : GenericDialogController(pParent, "modules/schart/ui/charttypedialog.ui", "ChartTypeDialog") + , m_xChartModel(xChartModel) + , m_xContentArea(m_xDialog->weld_content_area()) +{ + m_xChartTypeTabPage = std::make_unique( + m_xContentArea.get(), this, + uno::Reference::query(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 000000000..1a34d47b4 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ChartType_UNO.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 +#include +#include +#include +#include +#include + +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 SAL_CALL ChartTypeUnoDlg::getSupportedServiceNames() +{ + return { CHART_TYPE_DIALOG_SERVICE_NAME }; +} +uno::Sequence< sal_Int8 > SAL_CALL ChartTypeUnoDlg::getImplementationId() +{ + return css::uno::Sequence(); +} +void ChartTypeUnoDlg::implInitialize(const uno::Any& _rValue) +{ + beans::PropertyValue aProperty; + if (_rValue >>= aProperty) + { + if (aProperty.Name == "ChartModel") + m_xChartModel.set(aProperty.Value,uno::UNO_QUERY); + else + ChartTypeUnoDlg_BASE::implInitialize(_rValue); + } + else + ChartTypeUnoDlg_BASE::implInitialize(_rValue); +} + +std::unique_ptr ChartTypeUnoDlg::createDialog(const css::uno::Reference& rParent) +{ + return std::make_unique(Application::GetFrameWeld(rParent), m_xChartModel); +} + +uno::Reference 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 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 000000000..da073c2f9 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include "tp_ChartType.hxx" +#include "tp_RangeChooser.hxx" +#include "tp_Wizard_TitlesAndObjects.hxx" +#include "tp_DataSource.hxx" +#include +#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 uno::Reference& xChartModel, + const uno::Reference& xContext) + : vcl::RoadmapWizardMachine(pParent) + , m_xChartModel(xChartModel,uno::UNO_QUERY) + , m_xComponentContext(xContext) + , m_pTemplateProvider(nullptr) + , m_aTimerTriggeredControllerLock(xChartModel) + , m_bCanTravel(true) +{ + m_pDialogModel.reset(new DialogModel(m_xChartModel, m_xComponentContext)); + defaultButton(WizardButtonFlags::FINISH); + + setTitleBase(SchResId(STR_DLG_CHART_WIZARD)); + + // tdf#134386 set m_pTemplateProvider before creating any other pages + m_pTemplateProvider = static_cast(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); + + SetRoadmapHelpId(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 CreationWizard::createPage(WizardState nState) +{ + std::unique_ptr xRet; + + OString sIdent(OString::number(nState)); + weld::Container* pPageContainer = m_xAssistant->append_page(sIdent); + + switch( nState ) + { + case STATE_CHARTTYPE: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique(pPageContainer, this, m_xChartModel); + break; + } + case STATE_SIMPLE_RANGE: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider); + break; + } + case STATE_DATA_SERIES: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider); + break; + } + case STATE_OBJECTS: + { + xRet = std::make_unique(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 +{ + const char* pResId = nullptr; + 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 000000000..5411277f8 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx @@ -0,0 +1,349 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +CreationWizardUnoDlg::CreationWizardUnoDlg(const uno::Reference& xContext) + : OComponentHelper(m_aMutex) + , m_xCC(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() throw () +{ + OComponentHelper::acquire(); +} +void SAL_CALL CreationWizardUnoDlg::release() throw () +{ + OComponentHelper::release(); +} +uno::Any SAL_CALL CreationWizardUnoDlg::queryAggregation( uno::Type const & rType ) +{ + if (rType == cppu::UnoType::get()) + { + void * p = static_cast< ui::dialogs::XAsynchronousExecutableDialog * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType::get()) + { + void * p = static_cast< lang::XServiceInfo * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType::get()) + { + void * p = static_cast< lang::XInitialization * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType::get()) + { + void * p = static_cast< frame::XTerminateListener * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType::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 aTypeList{ cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get() }; + return aTypeList; +} + +uno::Sequence< sal_Int8 > SAL_CALL CreationWizardUnoDlg::getImplementationId() +{ + return css::uno::Sequence(); +} + +// 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(); + } + } + uno::Reference< XComponent > xKeepAlive( this ); + if( m_xChartModel.is() ) + { + m_xDialog = std::make_shared(Application::GetFrameWeld(m_xParentWindow), 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& 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" ) + { + aProperty.Value >>= 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 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 000000000..3cb9598cb --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_DataEditor.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 +#include "DataBrowser.hxx" +#include + +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +DataEditor::DataEditor(weld::Window* pParent, + const Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext) + : GenericDialogController(pParent, "modules/schart/ui/chartdatadialog.ui", "ChartDataDialog") + , m_bReadOnly(false) + , m_xChartDoc(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::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_xContext ); + m_xBrwData->GrabFocus(); + + bool bReadOnly = true; + Reference< frame::XStorable > xStor( m_xChartDoc, uno::UNO_QUERY ); + if( xStor.is()) + bReadOnly = xStor->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 OString&, 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("MoveUpRow", bIsDataValid && m_xBrwData->MayMoveDownRows() ); + m_xTbxData->set_item_sensitive("MoveDownRow", 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 000000000..b196b24d9 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_DataSource.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 +#include + +#include +#include +#include +#include "DialogModel.hxx" + +#include "tp_RangeChooser.hxx" +#include "tp_DataSource.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::chart; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +namespace { + +class DocumentChartTypeTemplateProvider : public ChartTypeTemplateProvider +{ +public: + explicit DocumentChartTypeTemplateProvider( + const Reference< chart2::XChartDocument > & xDoc ); + + // ____ ChartTypeTemplateProvider ____ + virtual Reference< chart2::XChartTypeTemplate > getCurrentTemplate() const override; + +private: + Reference< chart2::XChartTypeTemplate > m_xTemplate; +}; + +} + +DocumentChartTypeTemplateProvider::DocumentChartTypeTemplateProvider( + const Reference< chart2::XChartDocument > & xDoc ) +{ + if( !xDoc.is()) + return; + + Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram()); + if( xDia.is()) + { + DiagramHelper::tTemplateWithServiceName aResult( + DiagramHelper::getTemplateForDiagram( + xDia, + Reference< lang::XMultiServiceFactory >( + xDoc->getChartTypeManager(), uno::UNO_QUERY ) )); + m_xTemplate.set( aResult.first ); + } +} + +Reference< chart2::XChartTypeTemplate > DocumentChartTypeTemplateProvider::getCurrentTemplate() const +{ + return m_xTemplate; +} + +sal_uInt16 DataSourceDialog::m_nLastPageId = 0; + +DataSourceDialog::DataSourceDialog(weld::Window * pParent, + const Reference< XChartDocument > & xChartDocument, + const Reference< uno::XComponentContext > & xContext) + : GenericDialogController(pParent, "modules/schart/ui/datarangedialog.ui", + "DataRangeDialog") + , m_apDocTemplateProvider(new DocumentChartTypeTemplateProvider(xChartDocument)) + , m_apDialogModel(new DialogModel(xChartDocument, xContext)) + , 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(m_xTabControl->get_page("range"), this, + *m_apDialogModel, + m_apDocTemplateProvider.get(), true /* bHideDescription */ ); + m_xDataSourceTabPage = std::make_unique(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 OString&, 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 OString&, 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 000000000..3843263ad --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx @@ -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 . + */ + +#include + +namespace chart +{ + +InsertAxisOrGridDialogData::InsertAxisOrGridDialogData() + : aPossibilityList(6) + , aExistenceList(6) +{ + sal_Int32 nN = 0; + for(nN=6;nN--;) + aPossibilityList[nN]=true; + for(nN=6;nN--;) + aExistenceList[nN]=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 ? + OString("InsertAxisDialog") : + OString("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 ) +{ + rOutput.aExistenceList[0]=m_xCbPrimaryX->get_active(); + rOutput.aExistenceList[1]=m_xCbPrimaryY->get_active(); + rOutput.aExistenceList[2]=m_xCbPrimaryZ->get_active(); + rOutput.aExistenceList[3]=m_xCbSecondaryX->get_active(); + rOutput.aExistenceList[4]=m_xCbSecondaryY->get_active(); + rOutput.aExistenceList[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 000000000..57817d883 --- /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 +#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_InsertErrorBars.cxx b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx new file mode 100644 index 000000000..a7aeb35d7 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using ::com::sun::star::uno::Reference; +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace chart +{ + +InsertErrorBarsDialog::InsertErrorBarsDialog( + weld::Window* pParent, const SfxItemSet& rMyAttrs, + const uno::Reference< chart2::XChartDocument > & 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 Reference< frame::XModel >& xChartModel, + const Reference< uno::XInterface >& xChartView, + const OUString& rSelectedObjectCID ) +{ + double fStepWidth = 0.001; + + ExplicitValueProvider* pExplicitValueProvider( comphelper::getUnoTunnelImplementation(xChartView) ); + if( pExplicitValueProvider ) + { + Reference< XAxis > xAxis; + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedObjectCID, xChartModel ); + xAxis = DiagramHelper::getAttachedAxis( xSeries, xDiagram ); + 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 000000000..65dc9010e --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertLegend.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 +#include + +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 uno::Reference< frame::XModel >& xChartModel ) +{ + m_xLegendPositionResources->writeToResources( xChartModel ); +} + +void SchLegendDlg::writeToModel( const uno::Reference< frame::XModel >& 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 000000000..f228e037d --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertTitle.cxx @@ -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 . + */ + +#include +#include +#include + +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 000000000..d91b545cd --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_NumberFormat.cxx @@ -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 . + */ + +#include "dlg_NumberFormat.hxx" + +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +NumberFormatDialog::NumberFormatDialog(weld::Window* pParent, SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet, "cui/ui/formatnumberdialog.ui", "FormatNumberDialog") +{ + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_NUMBERFORMAT ); + if (fnCreatePage) + { + std::unique_ptr xTabPage = (*fnCreatePage)(get_content_area(), this, &rSet); + xTabPage->PageCreated(rSet); + SetTabPage(std::move(xTabPage)); + } +} + +SfxItemSet NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( SfxItemPool& rItemPool ) +{ + static const sal_uInt16 nWhichPairs[] = + { + SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, + SID_ATTR_NUMBERFORMAT_NOLANGUAGE, SID_ATTR_NUMBERFORMAT_NOLANGUAGE, + SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA, + SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, + 0 + }; + return SfxItemSet( rItemPool, nWhichPairs ); +} + +} //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 000000000..f0c69702f --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_NumberFormat.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DLG_NUMBERFORMAT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DLG_NUMBERFORMAT_HXX + +#include + +namespace weld { class Window; } +class SfxItemSet; +class SfxItemPool; + +namespace chart +{ + +class NumberFormatDialog : public SfxSingleTabDialogController +{ +public: + NumberFormatDialog(weld::Window* pParent, SfxItemSet& rSet); + + static SfxItemSet CreateEmptyItemSetForNumberFormatDialog( SfxItemPool& rItemPool ); +}; + +} //namespace chart + +#endif + +/* 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 000000000..1add0435b --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx @@ -0,0 +1,624 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +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( const OUString& rObjectCID ) + : m_aObjectCID( rObjectCID ) + , m_eObjectType( ObjectIdentifier::getObjectType( m_aObjectCID ) ) + , m_bAffectsMultipleObjects(false) + , m_aLocalizedName() + , 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_aCategories() + , m_bComplexCategoriesAxis( false ) + , m_nNbPoints( 0 ) +{ + OUString aParticleID = ObjectIdentifier::getParticleID( m_aObjectCID ); + m_bAffectsMultipleObjects = (aParticleID == "ALLELEMENTS"); +} +ObjectPropertiesDialogParameter::~ObjectPropertiesDialogParameter() +{ +} + +void ObjectPropertiesDialogParameter::init( const uno::Reference< frame::XModel >& xChartModel ) +{ + m_xChartDocument.set( xChartModel, uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aObjectCID, xChartModel ); + uno::Reference< XChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + 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 ) + { + uno::Reference< XAxis > 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?: + uno::Reference< XCoordinateSystem > 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 ) + { + ChartModel* pModel = dynamic_cast(xChartModel.get()); + if (pModel) + m_aCategories = DiagramHelper::getExplicitSimpleCategories( *pModel ); + } + } + + 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 ) ) + { + ChartModel* pModel = dynamic_cast(xChartModel.get()); + if (pModel) + { + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, *pModel ); + 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 ) + { + uno::Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + Sequence< Reference< data::XLabeledDataSequence > > aDataSeqs( xSource->getDataSequences()); + Sequence< double > aXValues, aYValues; + bool bXValuesFound = false, bYValuesFound = false; + m_nNbPoints = 0; + sal_Int32 i = 0; + for( i=0; + ! (bXValuesFound && bYValuesFound) && i 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() ); + for( i=0; i pSymbolShapeProperties, + std::unique_ptr pAutoSymbolGraphic ) +{ + m_pSymbolShapeProperties = std::move(pSymbolShapeProperties); + m_pAutoSymbolGraphic = std::move(pAutoSymbolGraphic); +} + +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()); + + SvtCJKOptions aCJKOptions; + + 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( aCJKOptions.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 (aCJKOptions.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( aCJKOptions.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( aCJKOptions.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_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 (SvtLanguageOptions().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 OString& 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_pSymbolShapeProperties ) + aSet.Put(SfxTabDialogItem(SID_ATTR_SET,*m_pSymbolShapeProperties)); + if( m_pAutoSymbolGraphic ) + aSet.Put(SvxGraphicItem(*m_pAutoSymbolGraphic)); + } + 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(); + static_cast(rPage).ShowStaggeringControls( bShowStaggeringControls ); + dynamic_cast< SchAxisLabelTabPage& >( rPage ).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, static_cast(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 000000000..f5fc702a2 --- /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 +#include + +#include +#include +#include +#include +#include + +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 OString& 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 000000000..c990161cf --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ShapeParagraph.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 + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +ShapeParagraphDialog::ShapeParagraphDialog(weld::Window* pParent, + const SfxItemSet* pAttr) + : SfxTabDialogController(pParent, "modules/schart/ui/paradialog.ui", "ParagraphDialog", pAttr) +{ + SvtCJKOptions aCJKOptions; + + AddTabPage("labelTP_PARA_STD", RID_SVXPAGE_STD_PARAGRAPH); + AddTabPage("labelTP_PARA_ALIGN", RID_SVXPAGE_ALIGN_PARAGRAPH ); + if (aCJKOptions.IsAsianTypographyEnabled()) + { + AddTabPage("labelTP_PARA_ASIAN", RID_SVXPAGE_PARA_ASIAN); + } + else + { + RemoveTabPage("labelTP_PARA_ASIAN"); + } + AddTabPage("labelTP_TABULATOR", RID_SVXPAGE_TABULATOR); +} + +void ShapeParagraphDialog::PageCreated(const OString& 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(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 000000000..b81b7ecac --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_View3D.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 +#include +#include +#include "tp_3D_SceneGeometry.hxx" +#include "tp_3D_SceneAppearance.hxx" +#include "tp_3D_SceneIllumination.hxx" +#include +#include +#include +#include + +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 uno::Reference< frame::XModel > & xChartModel) + : GenericDialogController(pParent, "modules/schart/ui/3dviewdialog.ui", "3DViewDialog") + , m_aControllerLocker(xChartModel) + , m_xTabControl(m_xBuilder->weld_notebook("tabcontrol")) +{ + uno::Reference< beans::XPropertySet > xSceneProperties( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + + 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 OString&, 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 000000000..6b0a7eac2 --- /dev/null +++ b/chart2/source/controller/dialogs/res_BarGeometry.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 +#include +#include + +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 < SAL_N_ELEMENTS(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(4)); +} + +void BarGeometryResources::connect_changed(const Link& 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 000000000..ca1918c17 --- /dev/null +++ b/chart2/source/controller/dialogs/res_DataLabel.cxx @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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_DataLabel.hxx" + +#include +#include +#include "dlg_NumberFormat.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ + +namespace +{ + +const OUStringLiteral our_aLBEntryMap[] = {" ", ", ", "; ", "\n", ". "}; + +bool lcl_ReadNumberFormatFromItemSet( const SfxItemSet& rSet, sal_uInt16 nValueWhich, sal_uInt16 nSourceFormatWhich, sal_uLong& rnFormatKeyOut, bool& rbSourceFormatOut, bool& rbSourceFormatMixedStateOut ) +{ + bool bSet = false; + const SfxPoolItem *pItem1 = nullptr; + if( rSet.GetItemState( nValueWhich, true, &pItem1 ) == SfxItemState::SET ) + { + const SfxUInt32Item * pNumItem = dynamic_cast< const SfxUInt32Item * >( pItem1 ); + if( pNumItem ) + { + rnFormatKeyOut = pNumItem->GetValue(); + bSet = true; + } + } + + rbSourceFormatMixedStateOut=true; + const SfxPoolItem *pItem2 = nullptr; + if( rSet.GetItemState( nSourceFormatWhich, true, &pItem2 ) == SfxItemState::SET ) + { + const SfxBoolItem * pBoolItem = dynamic_cast< const SfxBoolItem * >( pItem2 ); + if( pBoolItem ) + { + rbSourceFormatOut = pBoolItem->GetValue(); + rbSourceFormatMixedStateOut=false; + } + } + return bSet; +} + +void lcl_setBoolItemToCheckBox(const SfxItemSet& rInAttrs, sal_uInt16 nWhichId, weld::CheckButton& rCheckbox) +{ + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(nWhichId, true, &pPoolItem) == SfxItemState::SET ) + rCheckbox.set_active(static_cast(pPoolItem)->GetValue()); + else + rCheckbox.set_state(TRISTATE_INDET); +} + +}//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_xCBWrapText(pBuilder->weld_check_button("CB_WRAP_TEXT")) + , m_xSeparatorResources(pBuilder->weld_widget("boxSEPARATOR")) + , m_xLB_Separator(pBuilder->weld_combo_box("LB_TEXT_SEPARATOR")) + , m_xBxLabelPlacement(pBuilder->weld_widget("boxPLACEMENT")) + , 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_xLB_TextDirection(new TextDirectionListBox(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_xDC_Dial->SetText(m_xFT_Dial->get_label()); + + //fill label placement list + std::map< sal_Int32, OUString > aPlacementToStringMap; + for( sal_Int32 nEnum=0; nEnumget_count(); ++nEnum ) + aPlacementToStringMap[nEnum] = m_xLB_LabelPlacement->get_text(static_cast(nEnum)); + + + std::vector< sal_Int32 > aAvailablePlacementList; + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, true, &pPoolItem) == SfxItemState::SET ) + aAvailablePlacementList = static_cast(pPoolItem)->GetList(); + + m_xLB_LabelPlacement->clear(); + for( size_t nN=0; nN( 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_xCBWrapText->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( rInAttrs.GetItemState(SCHATTR_DATADESCR_NO_PERCENTVALUE, true, &pPoolItem) == SfxItemState::SET ) + { + bool bForbidPercentValue = rInAttrs.Get( SCHATTR_DATADESCR_NO_PERCENTVALUE ).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); + else if (&rButton == m_xPB_NumberFormatForPercent.get() && !m_xCBPercent->get_active()) + m_xCBPercent->set_active(true); + + SfxItemSet aNumberSet = NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( *m_pPool ); + aNumberSet.Put (SvxNumberInfoItem( m_pNumberFormatter, static_cast(SID_ATTR_NUMBERFORMAT_INFO))); + + bool bPercent = (&rButton == m_xPB_NumberFormatForPercent.get()); + + sal_uLong& 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_uLong 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_NOARG(DataLabelResources, CheckHdl, weld::ToggleButton&, void) +{ + 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_xCBWrapText->set_sensitive( m_xCBNumber->get_active() || (m_xCBPercent->get_active() && m_xCBPercent->get_sensitive()) + || m_xCBCategory->get_active() ); + + // Enable or disable separator, placement and direction based on the check + // box states. Note that the check boxes are tri-state. + { + 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; + + m_xSeparatorResources->set_sensitive( nNumberOfCheckedLabelParts > 1 ); + + bool bEnableTextDir = nNumberOfCheckedLabelParts > 0; + m_xBxTextDirection->set_sensitive( bEnableTextDir ); + bool bEnablePlacement = nNumberOfCheckedLabelParts > 0 && m_xLB_LabelPlacement->get_count()>1; + m_xBxLabelPlacement->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_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_xCBWrapText->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_WRAP_TEXT, m_xCBWrapText->get_active()) ); + + OUString aSep = our_aLBEntryMap[m_xLB_Separator->get_active()]; + rOutAttrs->Put( SfxStringItem( SCHATTR_DATADESCR_SEPARATOR, 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_xLB_TextDirection->get_active() != -1) + rOutAttrs->Put( SvxFrameDirectionItem( m_xLB_TextDirection->get_active_id(), EE_PARA_WRITINGDIR ) ); + + if( m_xDC_Dial->IsVisible() ) + { + sal_Int32 nDegrees = m_xDC_Dial->GetRotation(); + rOutAttrs->Put(SfxInt32Item( 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 ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_PERCENTAGE, *m_xCBPercent ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_CATEGORY, *m_xCBCategory ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_SYMBOL, *m_xCBSymbol ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_WRAP_TEXT, *m_xCBWrapText ); + + 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); + + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_SEPARATOR, true, &pPoolItem) == SfxItemState::SET ) + for(size_t i=0; i < SAL_N_ELEMENTS(our_aLBEntryMap); ++i ) + { + if( our_aLBEntryMap[i] == static_cast(pPoolItem)->GetValue()) + m_xLB_Separator->set_active( i ); + } + else + m_xLB_Separator->set_active( 0 ); + + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_PLACEMENT, true, &pPoolItem) == SfxItemState::SET ) + { + sal_Int32 nPlacement = static_cast(pPoolItem)->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( rInAttrs.GetItemState(EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLB_TextDirection->set_active_id( static_cast(pPoolItem)->GetValue() ); + + if( rInAttrs.GetItemState( SCHATTR_TEXT_DEGREES, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nDegrees = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xDC_Dial->SetRotation( nDegrees ); + } + else + m_xDC_Dial->SetRotation( 0 ); + + 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 000000000..d21856cb4 --- /dev/null +++ b/chart2/source/controller/dialogs/res_DataLabel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_DATALABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_DATALABEL_HXX + +#include +#include + +#include + +class SvNumberFormatter; +namespace chart { class TextDirectionListBox; } + +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_uLong m_nNumberFormatForValue; + sal_uLong m_nNumberFormatForPercent; + + bool m_bSourceFormatMixedState; + bool m_bPercentSourceMixedState; + bool m_bSourceFormatForValue; + bool m_bSourceFormatForPercent; + + weld::Window* m_pWindow; + SfxItemPool* m_pPool; + + std::unique_ptr m_xCBNumber; + std::unique_ptr m_xPB_NumberFormatForValue; + std::unique_ptr m_xCBPercent; + std::unique_ptr m_xPB_NumberFormatForPercent; + std::unique_ptr m_xFT_NumberFormatForPercent; + std::unique_ptr m_xCBCategory; + std::unique_ptr m_xCBSymbol; + std::unique_ptr m_xCBWrapText; + + std::unique_ptr m_xSeparatorResources; + std::unique_ptr m_xLB_Separator; + + std::unique_ptr m_xBxLabelPlacement; + std::unique_ptr m_xLB_LabelPlacement; + + std::unique_ptr m_xBxOrientation; + std::unique_ptr m_xFT_Dial; + std::unique_ptr m_xNF_Degrees; + + std::unique_ptr m_xBxTextDirection; + + std::unique_ptr m_xLB_TextDirection; + std::unique_ptr m_xDC_Dial; + std::unique_ptr m_xDC_DialWin; + + DECL_LINK(NumberFormatDialogHdl, weld::Button&, void ); + DECL_LINK(CheckHdl, weld::ToggleButton&, void ); + void EnableControls(); +}; + +} //namespace chart + +#endif + +/* 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 000000000..aaa1c6eed --- /dev/null +++ b/chart2/source/controller/dialogs/res_ErrorBar.cxx @@ -0,0 +1,718 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 uno::Reference< chart2::XChartDocument > & xChartDocument ) +{ + if( xChartDocument.is()) + { + m_bHasInternalDataProvider = xChartDocument->hasInternalDataProvider(); + uno::Reference< beans::XPropertySet > xProps( xChartDocument, 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(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::ToggleButton&, 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::ToggleButton&, 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::ToggleButton&, 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(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 + aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTPLUS, true, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + m_fPlusValue = static_cast(pPoolItem)->GetValue(); + } + + aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTMINUS, true, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + m_fMinusValue = static_cast(pPoolItem)->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(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 000000000..50ac0602b --- /dev/null +++ b/chart2/source/controller/dialogs/res_LegendPosition.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include + +//itemset stuff +#include +#include +#include +#include +#include + +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, + const uno::Reference< uno::XComponentContext >& xCC) + : m_xCC(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 uno::Reference< frame::XModel >& xChartModel ) +{ + try + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartModel ); + uno::Reference< beans::XPropertySet > xProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xProp.is() ) + { + //show + bool bShowLegend = false; + xProp->getPropertyValue( "Show" ) >>= bShowLegend; + if (m_xCbxShow) + m_xCbxShow->set_active( bShowLegend ); + PositionEnableHdl(*m_xCbxShow); + + //position + chart2::LegendPosition ePos; + xProp->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 css::uno::Reference< frame::XModel >& xChartModel ) const +{ + try + { + bool bShowLegend = m_xCbxShow && m_xCbxShow->get_active(); + ChartModel& rModel = dynamic_cast(*xChartModel); + uno::Reference< beans::XPropertySet > xProp(LegendHelper::getLegend(rModel, m_xCC, bShowLegend), uno::UNO_QUERY); + 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::ToggleButton&, void) +{ + 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 ) +{ + const SfxPoolItem* pPoolItem = nullptr; + if( rInAttrs.GetItemState( SCHATTR_LEGEND_POS, true, &pPoolItem ) == SfxItemState::SET ) + { + chart2::LegendPosition nLegendPosition = static_cast(static_cast(pPoolItem)->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; + } + } + + if( m_xCbxShow && rInAttrs.GetItemState( SCHATTR_LEGEND_SHOW, true, &pPoolItem ) == SfxItemState::SET ) + { + bool bShow = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCbxShow->set_active(bShow); + } +} + +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(nLegendPosition) ) ); + + rOutAttrs.Put( SfxBoolItem(SCHATTR_LEGEND_SHOW, !m_xCbxShow || m_xCbxShow->get_active()) ); +} + +IMPL_LINK (LegendPositionResources, PositionChangeHdl, weld::ToggleButton&, 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& 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 000000000..e4cbe6d52 --- /dev/null +++ b/chart2/source/controller/dialogs/res_Titles.cxx @@ -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 . + */ + +#include +#include +#include + +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& 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 ) +{ + rOutput.aExistenceList[0] = !m_xEd_Main->get_text().isEmpty(); + rOutput.aExistenceList[1] = !m_xEd_Sub->get_text().isEmpty(); + rOutput.aExistenceList[2] = !m_xEd_XAxis->get_text().isEmpty(); + rOutput.aExistenceList[3] = !m_xEd_YAxis->get_text().isEmpty(); + rOutput.aExistenceList[4] = !m_xEd_ZAxis->get_text().isEmpty(); + rOutput.aExistenceList[5] = !m_xEd_SecondaryXAxis->get_text().isEmpty(); + rOutput.aExistenceList[6] = !m_xEd_SecondaryYAxis->get_text().isEmpty(); + + rOutput.aTextList[0] = m_xEd_Main->get_text(); + rOutput.aTextList[1] = m_xEd_Sub->get_text(); + rOutput.aTextList[2] = m_xEd_XAxis->get_text(); + rOutput.aTextList[3] = m_xEd_YAxis->get_text(); + rOutput.aTextList[4] = m_xEd_ZAxis->get_text(); + rOutput.aTextList[5] = m_xEd_SecondaryXAxis->get_text(); + rOutput.aTextList[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 000000000..0eaea7b4e --- /dev/null +++ b/chart2/source/controller/dialogs/res_Trendline.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 "res_Trendline.hxx" +#include +#include + +#include +#include +#include +#include + +namespace chart +{ + +static void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue ) +{ + rFmtField.set_value(fValue); +//TODO rFmtField.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")) +{ + FillValueSets(); + + Link 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 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::ToggleButton&, 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 ) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_CURVE_NAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_Name->set_text(aName); + } + else + { + m_xEE_Name->set_text(""); + } + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_XNAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_XName->set_text(aName); + } + else + { + m_xEE_XName->set_text("x"); + } + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_YNAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_YName->set_text(aName); + } + else + { + m_xEE_YName->set_text("f(x)"); + } + + 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( rInAttrs.GetItemState( SCHATTR_REGRESSION_DEGREE, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nDegree = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xNF_Degree->set_value( nDegree ); + } + else + { + m_xNF_Degree->set_value( 2 ); + } + + m_xNF_Degree->save_value(); + + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_PERIOD, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPeriod = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xNF_Period->set_value( nPeriod ); + } + else + { + m_xNF_Period->set_value( 2 ); + } + + m_xNF_Period->save_value(); + + double nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast(pPoolItem)->GetValue() ; + } + lcl_setValue(*m_xFmtFld_ExtrapolateForward, nValue); + + nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast(pPoolItem)->GetValue() ; + } + lcl_setValue(*m_xFmtFld_ExtrapolateBackward, nValue); + + nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_INTERCEPT_VALUE, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast(pPoolItem)->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( !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_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 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_ShowEquation->set_state(TRISTATE_FALSE); + m_xCB_ShowCorrelationCoeff->set_state(TRISTATE_FALSE); + } + m_xCB_ShowEquation->set_sensitive( !bMovingAverage ); + m_xCB_ShowCorrelationCoeff->set_sensitive( !bMovingAverage ); + 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->set_formatter( m_pNumFormatter ); + m_xFmtFld_ExtrapolateBackward->set_formatter( m_pNumFormatter ); + m_xFmtFld_InterceptValue->set_formatter( m_pNumFormatter ); +} + +void TrendlineResources::SetNbPoints( sal_Int32 nNbPoints ) +{ + m_nNbPoints = nNbPoints; + UpdateControlStates(); +} + +IMPL_LINK_NOARG(TrendlineResources, ShowEquation, weld::ToggleButton&, void) +{ + m_xEE_XName->set_sensitive(m_xCB_ShowEquation->get_active()); + m_xEE_YName->set_sensitive(m_xCB_ShowEquation->get_active()); + 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 000000000..91f70f241 --- /dev/null +++ b/chart2/source/controller/dialogs/res_Trendline.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX + +#include +#include +#include + +namespace weld { class Builder; } +namespace weld { class CheckButton; } +namespace weld { class Entry; } +namespace weld { class FormattedSpinButton; } +namespace weld { class Image; } +namespace weld { class RadioButton; } +namespace weld { class SpinButton; } +namespace weld { class ToggleButton; } + +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 m_xRB_Linear; + std::unique_ptr m_xRB_Logarithmic; + std::unique_ptr m_xRB_Exponential; + std::unique_ptr m_xRB_Power; + std::unique_ptr m_xRB_Polynomial; + std::unique_ptr m_xRB_MovingAverage; + + std::unique_ptr m_xFI_Linear; + std::unique_ptr m_xFI_Logarithmic; + std::unique_ptr m_xFI_Exponential; + std::unique_ptr m_xFI_Power; + std::unique_ptr m_xFI_Polynomial; + std::unique_ptr m_xFI_MovingAverage; + + std::unique_ptr m_xNF_Degree; + std::unique_ptr m_xNF_Period; + std::unique_ptr m_xEE_Name; + std::unique_ptr m_xFmtFld_ExtrapolateForward; + std::unique_ptr m_xFmtFld_ExtrapolateBackward; + std::unique_ptr m_xCB_SetIntercept; + std::unique_ptr m_xFmtFld_InterceptValue; + std::unique_ptr m_xCB_ShowEquation; + std::unique_ptr m_xEE_XName; + std::unique_ptr m_xEE_YName; + std::unique_ptr m_xCB_ShowCorrelationCoeff; + + void UpdateControlStates(); + DECL_LINK(SelectTrendLine, weld::ToggleButton&, void); + DECL_LINK(ChangeSpinValue, weld::SpinButton&, void); + DECL_LINK(ChangeFormattedValue, weld::FormattedSpinButton&, void); + DECL_LINK(ShowEquation, weld::ToggleButton&, void); +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX +#endif + +/* 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 000000000..c24cf6fab --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.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_3D_SceneAppearance.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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_Unknown) + {} +}; + +lcl_ModelProperties lcl_getPropertiesFromModel( uno::Reference< frame::XModel > const & xModel ) +{ + lcl_ModelProperties aProps; + try + { + uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW ); + xDiaProp->getPropertyValue( "D3DSceneShadeMode" ) >>= aProps.m_aShadeMode; + ::chart::ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, aProps.m_nRoundedEdges, aProps.m_nObjectLines ); + aProps.m_eScheme = ::chart::ThreeDHelper::detectScheme( xDiagram ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aProps; +} + +void lcl_setShadeModeAtModel( uno::Reference< frame::XModel > const & xModel, drawing::ShadeMode aShadeMode ) +{ + try + { + uno::Reference< beans::XPropertySet > xDiaProp( + ::chart::ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY_THROW ); + 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, + const uno::Reference& xChartModel, + ControllerLockHelper& rControllerLockHelper) + : m_xChartModel(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( + ::chart::ChartModelHelper::findDiagram( m_xChartModel ), 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_Simple: + m_xLB_Scheme->set_active( POS_3DSCHEME_SIMPLE ); + break; + case ThreeDLookScheme_Realistic: + m_xLB_Scheme->set_active( POS_3DSCHEME_REALISTIC ); + break; + case 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 ); + + uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( m_xChartModel ) ); + + if( m_xLB_Scheme->get_active() == POS_3DSCHEME_REALISTIC ) + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Realistic ); + else if( m_xLB_Scheme->get_active() == POS_3DSCHEME_SIMPLE ) + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Simple ); + else + { + OSL_FAIL( "Invalid Entry selected" ); + } + } + + // update other controls + initControlsFromModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneAppearance_TabPage, SelectShading, weld::ToggleButton&, void) +{ + if( !m_bUpdateOtherControls ) + return; + + applyShadeModeToModel(); + updateScheme(); +} + +IMPL_LINK(ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines, weld::ToggleButton&, 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 000000000..00bc4e3f4 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEAPPEARANCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEAPPEARANCE_HXX + +#include + +namespace chart { class ControllerLockHelper; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class ThreeD_SceneAppearance_TabPage +{ +public: + ThreeD_SceneAppearance_TabPage( + weld::Container* pParent, + const css::uno::Reference< css::frame::XModel > & xChartModel, + ControllerLockHelper & rControllerLockHelper ); + void ActivatePage(); + ~ThreeD_SceneAppearance_TabPage(); + +private: + DECL_LINK( SelectSchemeHdl, weld::ComboBox&, void ); + DECL_LINK( SelectShading, weld::ToggleButton&, void ); + DECL_LINK( SelectRoundedEdgeOrObjectLines, weld::ToggleButton&, void ); + + void initControlsFromModel(); + void applyShadeModeToModel(); + void applyRoundedEdgeAndObjectLinesToModel(); + void updateScheme(); + +private: + css::uno::Reference m_xChartModel; + + bool m_bUpdateOtherControls; + bool m_bCommitToModel; + OUString m_aCustom; + + ControllerLockHelper& m_rControllerLockHelper; + + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; + std::unique_ptr m_xLB_Scheme; + std::unique_ptr m_xCB_Shading; + std::unique_ptr m_xCB_ObjectLines; + std::unique_ptr m_xCB_RoundedEdge; +}; + +} //namespace chart + +#endif + +/* 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 000000000..238df9a00 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +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, + const uno::Reference< beans::XPropertySet > & xSceneProperties, + ControllerLockHelper & rControllerLockHelper) + : m_xSceneProperties( xSceneProperties ) + , 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; + ThreeDHelper::getRotationAngleFromDiagram( m_xSceneProperties, 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 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_xSceneProperties->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_xSceneProperties->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 + uno::Reference< chart2::XDiagram > xDiagram( m_xSceneProperties, uno::UNO_QUERY ); + if (ChartTypeHelper::isSupportingRightAngledAxes(DiagramHelper::getChartTypeByIndex(xDiagram, 0))) + { + bool bRightAngledAxes = false; + m_xSceneProperties->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); + + ThreeDHelper::setRotationAngleToDiagram( m_xSceneProperties, 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_xSceneProperties->setPropertyValue( "D3DScenePerspective" , uno::Any( aMode )); + m_xSceneProperties->setPropertyValue( "Perspective" , uno::Any( static_cast(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::ToggleButton&, void) +{ + m_xMFPerspective->set_sensitive(m_xCbxPerspective->get_active()); + applyPerspectiveToModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, RightAngledAxesToggled, weld::ToggleButton&, 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(ThreeDHelper::getValueClippedToRange(static_cast(m_nXRotation), ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE); + m_xMFYRotation->set_value(static_cast(ThreeDHelper::getValueClippedToRange(static_cast(m_nYRotation), ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE); + m_xMFZRotation->set_text(""); + + lcl_SetMetricFieldLimits( *m_xMFXRotation, static_cast(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes())); + lcl_SetMetricFieldLimits( *m_xMFYRotation, static_cast(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); + } + + ThreeDHelper::switchRightAngledAxes( m_xSceneProperties, 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 000000000..21597d382 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEGEOMETRY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEGEOMETRY_HXX + +#include +#include + +namespace com::sun::star::beans { class XPropertySet; } +namespace chart { class ControllerLockHelper; } + +namespace chart +{ + +class ThreeD_SceneGeometry_TabPage +{ +public: + ThreeD_SceneGeometry_TabPage(weld::Container* pWindow, + const css::uno::Reference< css::beans::XPropertySet > & xSceneProperties, + 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::ToggleButton&, void ); + DECL_LINK( RightAngledAxesToggled, weld::ToggleButton&, void ); + +private: + void applyAnglesToModel(); + void applyPerspectiveToModel(); + + css::uno::Reference< css::beans::XPropertySet > m_xSceneProperties; + + 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 m_xBuilder; + std::unique_ptr m_xContainer; + std::unique_ptr m_xCbxRightAngledAxes; + std::unique_ptr m_xMFXRotation; + std::unique_ptr m_xMFYRotation; + std::unique_ptr m_xFtZRotation; + std::unique_ptr m_xMFZRotation; + std::unique_ptr m_xCbxPerspective; + std::unique_ptr m_xMFPerspective; +}; + +} //namespace chart + +#endif + +/* 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 000000000..e656ef206 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx @@ -0,0 +1,529 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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() +{ + 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(std::make_pair(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::makeAny( 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 ) + { + sal_Int32 nResult = 0x000000; + try + { + xSceneProperties->getPropertyValue("D3DSceneAmbientColor") >>= nResult; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return Color( nResult ); + } + + void lcl_setAmbientColor( + const uno::Reference< beans::XPropertySet > & xSceneProperties, + const Color & rColor ) + { + try + { + xSceneProperties->setPropertyValue("D3DSceneAmbientColor", + uno::makeAny( rColor )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } +} + +ThreeD_SceneIllumination_TabPage::ThreeD_SceneIllumination_TabPage(weld::Container* pParent, + weld::Window* pTopLevel, + const uno::Reference< beans::XPropertySet > & xSceneProperties, + const uno::Reference< frame::XModel >& xChartModel) + : m_xSceneProperties( xSceneProperties ) + , m_aTimerTriggeredControllerLock( xChartModel ) + , m_bInCommitToModel( false ) + , 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_xBtn_Light1(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_1"))) + , m_xBtn_Light2(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_2"))) + , m_xBtn_Light3(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_3"))) + , m_xBtn_Light4(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_4"))) + , m_xBtn_Light5(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_5"))) + , m_xBtn_Light6(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_6"))) + , m_xBtn_Light7(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_7"))) + , m_xBtn_Light8(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_8"))) + , m_xLB_LightSource(new ColorListBox(m_xBuilder->weld_menu_button("LB_LIGHTSOURCE"), pTopLevel)) + , m_xBtn_LightSource_Color(m_xBuilder->weld_button("BTN_LIGHTSOURCE_COLOR")) + , m_xLB_AmbientLight(new ColorListBox(m_xBuilder->weld_menu_button("LB_AMBIENTLIGHT"), 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_xBtn_Light1.get(); + m_pLightSourceInfoList[1].pButton = m_xBtn_Light2.get(); + m_pLightSourceInfoList[2].pButton = m_xBtn_Light3.get(); + m_pLightSourceInfoList[3].pButton = m_xBtn_Light4.get(); + m_pLightSourceInfoList[4].pButton = m_xBtn_Light5.get(); + m_pLightSourceInfoList[5].pButton = m_xBtn_Light6.get(); + m_pLightSourceInfoList[6].pButton = m_xBtn_Light7.get(); + m_pLightSourceInfoList[7].pButton = m_xBtn_Light8.get(); + + fillControlsFromModel(nullptr); + + m_xBtn_Light1->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light2->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light3->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light4->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light5->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light6->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light7->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_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_xBtn_Light2->get_widget()); +} + +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( nL=0; nL<8; nL++) + { + LightButton* pLightButton = m_pLightSourceInfoList[nL].pButton; + if (pLightButton == pButton) + { + pLightButton->set_active(true); + if (!pLightButton->get_widget()->has_focus()) + pLightButton->get_widget()->grab_focus(); + m_pLightSourceInfoList[nL].pButton->set_prev_active(true); + } + else + { + pLightButton->set_active(false); + m_pLightSourceInfoList[nL].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 000000000..27606079e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEILLUMINATION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEILLUMINATION_HXX + +#include +#include +#include + +namespace com::sun::star::beans { class XPropertySet; } + +class ColorListBox; +class LightButton; + +namespace chart +{ + +struct LightSourceInfo; + +class ThreeD_SceneIllumination_TabPage +{ +public: + ThreeD_SceneIllumination_TabPage( + weld::Container* pParent, weld::Window* pTopLevel, + const css::uno::Reference< css::beans::XPropertySet > & xSceneProperties, + const css::uno::Reference< css::frame::XModel >& 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 m_pLightSourceInfoList; + + css::uno::Reference< css::beans::XPropertySet > m_xSceneProperties; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + bool m_bInCommitToModel; + + css::uno::Reference m_xChartModel; + + weld::Window* m_pTopLevel; + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; + std::unique_ptr m_xBtn_Light1; + std::unique_ptr m_xBtn_Light2; + std::unique_ptr m_xBtn_Light3; + std::unique_ptr m_xBtn_Light4; + std::unique_ptr m_xBtn_Light5; + std::unique_ptr m_xBtn_Light6; + std::unique_ptr m_xBtn_Light7; + std::unique_ptr m_xBtn_Light8; + std::unique_ptr m_xLB_LightSource; + std::unique_ptr m_xBtn_LightSource_Color; + std::unique_ptr m_xLB_AmbientLight; + std::unique_ptr m_xBtn_AmbientLight_Color; + std::unique_ptr m_xHoriScale; + std::unique_ptr m_xVertScale; + std::unique_ptr m_xBtn_Corner; + std::unique_ptr m_xPreview; + std::unique_ptr m_xPreviewWnd; + std::unique_ptr m_xCtl_Preview; +}; + +} //namespace chart + +#endif + +/* 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 000000000..1eaaa4063 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisLabel.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 "tp_AxisLabel.hxx" + +#include +#include + +#include +#include +#include +#include + +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_xFlOrient(m_xBuilder->weld_label("labelTextOrient")) + , 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_xLbTextDirection(new TextDirectionListBox(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(); + m_xLbTextDirection.reset(); +} + +std::unique_ptr SchAxisLabelTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique(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() ) + { + sal_Int32 nDegrees = bStacked ? 0 : m_xCtrlDial->GetRotation(); + if( !m_bHasInitialDegrees || (nDegrees != m_nInitialDegrees) ) + rOutAttrs->Put( SfxInt32Item( 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_xLbTextDirection->get_active() != -1) + rOutAttrs->Put( SvxFrameDirectionItem( m_xLbTextDirection->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; + aState = rInAttrs->GetItemState( SCHATTR_TEXT_DEGREES, false, &pPoolItem ); + if( aState == SfxItemState::SET ) + m_nInitialDegrees = static_cast< const SfxInt32Item * >( 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( rInAttrs->GetItemState( EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLbTextDirection->set_active_id( static_cast(pPoolItem)->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 ) + { + aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_ORDER, false, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + SvxChartTextOrder eOrder = static_cast< const SvxChartTextOrderItem * >( pPoolItem )->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::ToggleButton&, 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::ToggleButton&, 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_xLbTextDirection->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 000000000..0e7b9a097 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisLabel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISLABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISLABEL_HXX + +#include +#include + +namespace chart { class TextDirectionListBox; } +namespace weld { + class CheckButton; + class CustomWeld; + class Label; + class RadioButton; + class SpinButton; + class ToggleButton; +} + +namespace chart +{ + +class SchAxisLabelTabPage : public SfxTabPage +{ +private: + bool m_bShowStaggeringControls; + + sal_Int32 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 m_xCbShowDescription; + std::unique_ptr m_xFlOrder; + std::unique_ptr m_xRbSideBySide; + std::unique_ptr m_xRbUpDown; + std::unique_ptr m_xRbDownUp; + std::unique_ptr m_xRbAuto; + std::unique_ptr m_xFlTextFlow; + std::unique_ptr m_xCbTextOverlap; + std::unique_ptr m_xCbTextBreak; + std::unique_ptr m_xFtABCD; + std::unique_ptr m_xFlOrient; + std::unique_ptr m_xFtRotate; + std::unique_ptr m_xNfRotate; + std::unique_ptr m_xCbStacked; + std::unique_ptr m_xFtTextDirection; + std::unique_ptr m_xLbTextDirection; + std::unique_ptr m_xCtrlDial; + std::unique_ptr m_xCtrlDialWin; + + DECL_LINK(StackedToggleHdl, weld::ToggleButton&, void); + DECL_LINK(ToggleShowLabel, weld::ToggleButton&, void); + +public: + SchAxisLabelTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchAxisLabelTabPage() override; + + static std::unique_ptr 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 + +#endif + +/* 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 000000000..89b8c3899 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisPositions.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 "tp_AxisPositions.hxx" + +#include +#include + +#include +#include +#include + +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_aCategories() + , 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_xCB_AxisBetweenCategories(m_xBuilder->weld_check_button("CB_AXIS_BETWEEN_CATEGORIES")) + , 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_xED_LabelDistance(m_xBuilder->weld_formatted_spin_button("EDT_AXIS_LABEL_DISTANCE")) + , 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)); + + const double nMin = static_cast(SAL_MIN_INT64); + const double nMax = static_cast(SAL_MAX_INT64); + m_xED_CrossesAt->set_range(nMin, nMax); + m_xED_LabelDistance->set_range(nMin, nMax); +} + +AxisPositionsTabPage::~AxisPositionsTabPage() +{ +} + +std::unique_ptr AxisPositionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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 ) + { + double fCrossover = m_xED_CrossesAt->get_value(); + 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 + long nTicks=0; + long 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 + const SfxPoolItem *pPoolItem = nullptr; + + //axis line + if(rInAttrs->GetItemState(SCHATTR_AXIS_POSITION,true, &pPoolItem)== SfxItemState::SET) + { + bool bZero = false; + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->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 ); + + if( rInAttrs->GetItemState(SCHATTR_AXIS_POSITION_VALUE,true, &pPoolItem)== SfxItemState::SET || bZero ) + { + double fCrossover = 0.0; + if( !bZero ) + fCrossover = static_cast(pPoolItem)->GetValue(); + if( m_bCrossingAxisIsCategoryAxis ) + m_xED_CrossesAtCategory->set_active( static_cast(::rtl::math::round(fCrossover-1.0)) ); + else + m_xED_CrossesAt->set_value(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 + if (m_bSupportCategoryPositioning && rInAttrs->GetItemState(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION, true, &pPoolItem) == SfxItemState::SET) + { + if (static_cast(pPoolItem)->GetValue()) + m_xRB_Between->set_active(true); + else + m_xRB_On->set_active(true); + } + else + m_xFL_Position->hide(); + + // Labels + if( rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_POSITION, false, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->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 + long nTicks = 0, nMinorTicks = 0; + if (rInAttrs->GetItemState(SCHATTR_AXIS_TICKS,true, &pPoolItem)== SfxItemState::SET) + nTicks = static_cast(pPoolItem)->GetValue(); + if (rInAttrs->GetItemState(SCHATTR_AXIS_HELPTICKS,true, &pPoolItem)== SfxItemState::SET) + nMinorTicks = static_cast(pPoolItem)->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( rInAttrs->GetItemState( SCHATTR_AXIS_MARK_POSITION, false, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->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; + m_xED_CrossesAt->set_formatter(m_pNumFormatter); + + const SfxPoolItem *pPoolItem = nullptr; + if( GetItemSet().GetItemState( SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_uLong nFmt = static_cast(pPoolItem)->GetValue(); + m_xED_CrossesAt->set_format_key( 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->set_value(0.0); + if (m_xED_CrossesAtCategory->get_active() == -1) + 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 000000000..6be65c9de --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisPositions.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISPOSITIONS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISPOSITIONS_HXX + +#include + +namespace chart +{ + +class AxisPositionsTabPage : public SfxTabPage +{ +public: + AxisPositionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~AxisPositionsTabPage() override; + + static std::unique_ptr 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 m_xFL_AxisLine; + std::unique_ptr m_xLB_CrossesAt; + std::unique_ptr m_xED_CrossesAt; + std::unique_ptr m_xED_CrossesAtCategory; + std::unique_ptr m_xCB_AxisBetweenCategories; + + std::unique_ptr m_xFL_Position; + std::unique_ptr m_xRB_On; + std::unique_ptr m_xRB_Between; + + std::unique_ptr m_xFL_Labels; + std::unique_ptr m_xLB_PlaceLabels; + std::unique_ptr m_xED_LabelDistance; + + std::unique_ptr m_xCB_TicksInner; + std::unique_ptr m_xCB_TicksOuter; + + std::unique_ptr m_xCB_MinorInner; + std::unique_ptr m_xCB_MinorOuter; + + std::unique_ptr m_xBxPlaceTicks; + std::unique_ptr m_xLB_PlaceTicks; +}; + +} //namespace chart + +#endif + +/* 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 000000000..271d4721c --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ChartType.cxx @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogController* pController, const uno::Reference< XChartDocument >& 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( 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"))) + , 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( m_xChartModel, 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()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back( + std::make_unique()); + } + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + } + m_aChartTypeDialogControllerList.push_back( + std::make_unique()); + + 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(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 + uno::Reference xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme(xDiagram); + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->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( nMadjustParameterToSubType( 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 = ThreeDHelper::detectScheme( ChartModelHelper::findDiagram( m_xChartModel ) ); + if(!aParameter.b3DLook && aParameter.eThreeDLookScheme!=ThreeDLookScheme_Realistic ) + aParameter.eThreeDLookScheme=ThreeDLookScheme_Realistic; + + uno::Reference xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + } + catch ( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + fillAllControls( aParameter ); + uno::Reference< beans::XPropertySet > xTemplateProps( getCurrentTemplate(), 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( 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; + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( m_xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + DiagramHelper::tTemplateWithServiceName aTemplate = + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateManager ); + OUString aServiceName( aTemplate.second ); + + 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( aTemplate.first, uno::UNO_QUERY ); + ChartTypeParameter aParameter = elem->getChartTypeParameterForService( aServiceName, xTemplateProps ); + m_pCurrentMainType = getSelectedMainType(); + + //set ThreeDLookScheme + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme( xDiagram ); + if(!aParameter.b3DLook && aParameter.eThreeDLookScheme!=ThreeDLookScheme_Realistic ) + aParameter.eThreeDLookScheme=ThreeDLookScheme_Realistic; + + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->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 ); + } +} + +bool ChartTypeTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ ) +{ + return true; // return false if this page should not be left +} + +uno::Reference< XChartTypeTemplate > ChartTypeTabPage::getCurrentTemplate() const +{ + if( m_pCurrentMainType && m_xChartModel.is() ) + { + ChartTypeParameter aParameter( getCurrentParamter() ); + m_pCurrentMainType->adjustParameterToSubType( aParameter ); + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( m_xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + return m_pCurrentMainType->getCurrentTemplate( aParameter, xTemplateManager ); + } + 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 000000000..405c3c9ed --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ChartType.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_CHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_CHARTTYPE_HXX + +#include + +#include +#include +#include + +#include + +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 + , const css::uno::Reference< css::chart2::XChartDocument >& xChartModel + , bool bShowDescription = true ); + virtual ~ChartTypeTabPage() override; + + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override; + + virtual css::uno::Reference< css::chart2::XChartTypeTemplate > 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 m_pDim3DLookResourceGroup; + std::unique_ptr m_pStackingResourceGroup; + std::unique_ptr m_pSplineResourceGroup; + std::unique_ptr m_pGeometryResourceGroup; + std::unique_ptr m_pSortByXValuesResourceGroup; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartModel; + + std::vector< std::unique_ptr > m_aChartTypeDialogControllerList; + ChartTypeDialogController* m_pCurrentMainType; + + sal_Int32 m_nChangingCalls; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + std::unique_ptr m_xFT_ChooseType; + std::unique_ptr m_xMainTypeList; + std::unique_ptr m_xSubTypeList; + std::unique_ptr m_xSubTypeListWin; +}; + +} //namespace chart +#endif + +/* 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 000000000..3594e3e8f --- /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 DataLabelsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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 000000000..e7d052728 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataLabel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATALABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATALABEL_HXX + +#include "res_DataLabel.hxx" +#include + +class SvNumberFormatter; + +namespace chart +{ + +class DataLabelsTabPage : public SfxTabPage +{ +public: + DataLabelsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + + static std::unique_ptr 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 +#endif + +/* 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 000000000..7fb9f230e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataPointOption.cxx @@ -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 . + */ + +#include "tp_DataPointOption.hxx" + +#include +#include + +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 DataPointOptionTabPage::Create(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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) +{ + const SfxPoolItem* pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, true, &pPoolItem) + == SfxItemState::SET) + { + bool bVal = static_cast(pPoolItem)->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 000000000..5473d93c8 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataPointOption.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATAPOINTOPTION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATAPOINTOPTION_HXX + +#include + +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 + 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 m_xCBHideLegendEntry; +}; + +} //namespace chart + +#endif + +/* 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 000000000..b6ebe98d0 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataSource.cxx @@ -0,0 +1,928 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include "DialogModel.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +const OUString lcl_aLabelRole( "label" ); + +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 = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64()); + 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 = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64()); + if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is()) + { + OUString aLabel(::chart::DataSeriesHelper::getDataSeriesLabel( + pEntry->m_xDataSeries, + 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 = reinterpret_cast<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry).toInt64()); + 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 Reference< chart2::data::XLabeledDataSequence > & xLSequence, + const Reference< chart2::data::XDataSource > & xSource ) +{ + Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY ); + if( xSink.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences()); + aData.realloc( aData.getLength() + 1 ); + aData[ aData.getLength() - 1 ] = xLSequence; + xSink->setData( aData ); + } +} + +Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( + const Reference< chart2::data::XDataSource > & xDataSource ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + + for( Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aSequences ) + { + // no values are set but a label exists + if( ! labeledDataSeq->getValues().is() && + labeledDataSeq->getLabel().is()) + { + xResult.set( 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(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 aWidths; + aWidths.push_back(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(OUString::number(reinterpret_cast(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() +{ + Reference< XDataSeries > xSelected; + SeriesEntry* pEntry = nullptr; + int nEntry = m_xLB_SERIES->get_selected_index(); + if (nEntry != -1) + { + pEntry = reinterpret_cast(m_xLB_SERIES->get_id(nEntry).toInt64()); + xSelected.set(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 + const OUString aReplacementStr( "%NUMBER" ); + 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.set(series.second.first); + pEntry->m_xChartType.set(series.second.second); + m_xLB_SERIES->append(OUString::number(reinterpret_cast(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 = reinterpret_cast(m_xLB_SERIES->get_id(nSeriesEntry).toInt64()); + 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 + const OUString aReplacementStr( "%VALUETYPE" ); + 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(); + Reference< XDataSeries > xSeriesToInsertAfter; + Reference< XChartType > xChartTypeForNewSeries; + if( m_pTemplateProvider ) + m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate()); + + if (nEntry != -1) + { + ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + xSeriesToInsertAfter.set(pEntry->m_xDataSeries); + xChartTypeForNewSeries.set(pEntry->m_xChartType); + } + else + { + std::vector< Reference< XDataSeriesContainer > > aCntVec( + m_rDialogModel.getAllDataSeriesContainers()); + if( ! aCntVec.empty()) + xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY ); + } + 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 = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + Reference< XDataSeries > xNewSelSeries; + SeriesEntry * pNewSelEntry = nullptr; + if (nEntry + 1 < m_xLB_SERIES->n_children()) + pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1).toInt64()); + else if (nEntry > 0) + pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1).toInt64()); + if (pNewSelEntry) + xNewSelSeries.set(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 = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i).toInt64()); + 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 = reinterpret_cast(m_xLB_SERIES->get_id(nEntry).toInt64()); + + 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 = reinterpret_cast(m_xLB_SERIES->get_id(nEntry).toInt64()); + + 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())) + { + Reference< 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.set( 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.set(nullptr); + m_rDialogModel.setCategories( xLabeledSeq ); + } + } + } + + int nSeriesEntry = m_xLB_SERIES->get_selected_index(); + SeriesEntry* pSeriesEntry = nullptr; + if (nSeriesEntry != -1) + pSeriesEntry = reinterpret_cast(m_xLB_SERIES->get_id(nSeriesEntry).toInt64()); + 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; + + Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW ); + Reference< data::XLabeledDataSequence > xLabeledSeq( + DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole )); + + if( xDataProvider.is()) + { + if( bIsLabel ) + { + if( ! xLabeledSeq.is()) + { + // check if there is already an "orphan" label sequence + xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); + if( ! xLabeledSeq.is()) + { + // no corresponding labeled data sequence for label found + xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() ); + lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); + } + } + 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 )); + 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.set( lcl_findLSequenceWithOnlyLabel( xSource )); + if( ! xLabeledSeq.is()) + { + xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() ); + lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); + } + } + 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 + { + Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->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 000000000..3ba36a1cf --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX + +#include + +#include + +namespace com::sun::star::chart2 { class XChartType; } +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart { class TabPageNotifiable; } + +namespace chart +{ + +class ChartTypeTemplateProvider; +class DialogModel; + +class SeriesEntry +{ +public: + OUString m_sRole; + + /// the corresponding data series + css::uno::Reference< css::chart2::XDataSeries > m_xDataSeries; + + /// the chart type that contains the series (via XDataSeriesContainer) + css::uno::Reference< css::chart2::XChartType > 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 + if the text from the field is a valid format to the internal + data was valid + */ + bool updateModelFromControl(const weld::Entry* pField = nullptr); + + /** @return , if the edit field contains a valid range entry. If no + XCellRangesAccess can be obtained, is returned. + */ + bool isRangeFieldContentValid(weld::Entry& rEdit); + + /** @return , if the tab-page is in a consistent (committable) state + */ + bool isValid(); + void setDirty(); + + void updateControlsFromDialogModel(); + + void fillSeriesListBox(); + void fillRoleListBox(); + + std::vector> m_aEntries; + + OUString m_aFixedTextRange; + + ChartTypeTemplateProvider * m_pTemplateProvider; + DialogModel & m_rDialogModel; + weld::Entry* m_pCurrentRangeChoosingField; + bool m_bIsDirty; + + TabPageNotifiable * m_pTabPageNotifiable; + + std::unique_ptr m_xFT_CAPTION; + std::unique_ptr m_xFT_SERIES; + std::unique_ptr m_xLB_SERIES; + std::unique_ptr m_xBTN_ADD; + std::unique_ptr m_xBTN_REMOVE; + std::unique_ptr m_xBTN_UP; + std::unique_ptr m_xBTN_DOWN; + std::unique_ptr m_xFT_ROLE; + std::unique_ptr m_xLB_ROLE; + std::unique_ptr m_xFT_RANGE; + std::unique_ptr m_xEDT_RANGE; + std::unique_ptr m_xIMB_RANGE_MAIN; + std::unique_ptr m_xFT_CATEGORIES; + std::unique_ptr m_xFT_DATALABELS;//used for xy charts + std::unique_ptr m_xEDT_CATEGORIES; + std::unique_ptr m_xIMB_RANGE_CAT; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX +#endif + +/* 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 000000000..94a3d6c77 --- /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 ErrorBarsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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 uno::Reference< chart2::XChartDocument > & 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 000000000..2ce941a1d --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ErrorBars.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_ERRORBARS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_ERRORBARS_HXX + +#include + +#include + +namespace chart +{ + +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 css::uno::Reference< css::chart2::XChartDocument > & xChartDocument ); + + static std::unique_ptr 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 + +#endif + +/* 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 000000000..04697e75e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_LegendPosition.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_LegendPosition.hxx" +#include +#include +#include +#include +#include + +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_xLbTextDirection(new TextDirectionListBox(m_xBuilder->weld_combo_box("LB_LEGEND_TEXTDIR"))) + , m_xCBLegendNoOverlay(m_xBuilder->weld_check_button("CB_NO_OVERLAY")) +{ +} + +SchLegendPosTabPage::~SchLegendPosTabPage() +{ + m_xLbTextDirection.reset(); +} + +std::unique_ptr SchLegendPosTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +bool SchLegendPosTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + m_aLegendPositionResources.writeToItemSet(*rOutAttrs); + + if (m_xLbTextDirection->get_active() != -1) + rOutAttrs->Put(SvxFrameDirectionItem(m_xLbTextDirection->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); + + const SfxPoolItem* pPoolItem = nullptr; + if( rInAttrs->GetItemState( EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLbTextDirection->set_active_id( static_cast(pPoolItem)->GetValue() ); + + if (rInAttrs->GetItemState(SCHATTR_LEGEND_NO_OVERLAY, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast(pPoolItem)->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 000000000..61e4c8929 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_LegendPosition.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_LEGENDPOSITION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_LEGENDPOSITION_HXX + +#include + +#include + +namespace chart { class TextDirectionListBox; } + +namespace chart +{ + +class SchLegendPosTabPage : public SfxTabPage +{ +private: + + LegendPositionResources m_aLegendPositionResources; + std::unique_ptr m_xLbTextDirection; + std::unique_ptr m_xCBLegendNoOverlay; + +public: + SchLegendPosTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchLegendPosTabPage() override; + + static std::unique_ptr 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 + +#endif + +/* 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 000000000..6d2ac1b45 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PointGeometry.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 "tp_PointGeometry.hxx" +#include + +#include + +#include +#include + +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 SchLayoutTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +bool SchLayoutTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + int nShape = m_pGeometryResources ? m_pGeometryResources->get_selected_index() : -1; + if (nShape != -1) + { + 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) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_STYLE_SHAPE,true, &pPoolItem) == SfxItemState::SET) + { + long nVal = static_cast(pPoolItem)->GetValue(); + if(m_pGeometryResources) + { + m_pGeometryResources->select(static_cast(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 000000000..2438ce898 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PointGeometry.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POINTGEOMETRY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POINTGEOMETRY_HXX + +#include + +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 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 m_pGeometryResources; +}; + +} //namespace chart + +#endif + +/* 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 000000000..804c42212 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PolarOptions.cxx @@ -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 . + */ + +#include "tp_PolarOptions.hxx" +#include + +#include +#include + +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 PolarOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +bool PolarOptionsTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + if (m_xAngleDialWin->get_visible()) + { + rOutAttrs->Put(SfxInt32Item(SCHATTR_STARTING_ANGLE, + static_cast< sal_Int32 >(m_xAngleDial->GetRotation()/100))); + } + + 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) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_STARTING_ANGLE, true, &pPoolItem) == SfxItemState::SET) + { + long nTmp = static_cast(static_cast(pPoolItem)->GetValue()); + m_xAngleDial->SetRotation( nTmp*100 ); + } + else + { + m_xFL_StartingAngle->hide(); + } + if (rInAttrs->GetItemState(SCHATTR_CLOCKWISE, true, &pPoolItem) == SfxItemState::SET) + { + bool bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCB_Clockwise->set_active(bCheck); + } + else + { + m_xCB_Clockwise->hide(); + } + if (rInAttrs->GetItemState(SCHATTR_INCLUDE_HIDDEN_CELLS, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast(pPoolItem)->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 000000000..e5d4287cb --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PolarOptions.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POLAROPTIONS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POLAROPTIONS_HXX + +#include +#include + +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 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 m_xCB_Clockwise; + std::unique_ptr m_xFL_StartingAngle; + std::unique_ptr m_xNF_StartingAngle; + std::unique_ptr m_xFL_PlotOptions; + std::unique_ptr m_xCB_IncludeHiddenCells; + std::unique_ptr m_xAngleDial; + std::unique_ptr m_xAngleDialWin; +}; + +} //namespace chart + +#endif + +/* 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 000000000..c11c9eee8 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_RangeChooser.cxx @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include "DialogModel.hxx" +#include +#include +#include +#include +#include +#include + +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_aLastValidRangeString() + , m_pTemplateProvider(pTemplateProvider) + , m_rDialogModel( rDialogModel ) + , m_pTabPageNotifiable(dynamic_cast(pController)) + , m_xFT_Caption(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD")) + , m_xFT_Range(m_xBuilder->weld_label("FT_RANGE")) + , 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 ) ); + + SvtMiscOptions aOpts; + if ( !aOpts.IsExperimentalMode() ) + { + 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.set( 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[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[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::ToggleButton&, void) +{ + ControlChangedHdl(*m_xED_Range); +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedCheckBoxHdl, weld::ToggleButton&, 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 000000000..b337910cc --- /dev/null +++ b/chart2/source/controller/dialogs/tp_RangeChooser.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_RANGECHOOSER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_RANGECHOOSER_HXX + +#include + +#include + +namespace chart { class TabPageNotifiable; } +namespace com::sun::star::chart2 { class XChartTypeTemplate; } + +namespace chart +{ + +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::ToggleButton&, void ); + DECL_LINK( ControlChangedRadioHdl, weld::ToggleButton&, void ); + DECL_LINK( ControlEditedHdl, weld::Entry&, void ); + + sal_Int32 m_nChangingControlCalls; + bool m_bIsDirty; + + OUString m_aLastValidRangeString; + css::uno::Reference< css::chart2::XChartTypeTemplate > m_xCurrentChartTypeTemplate; + ChartTypeTemplateProvider* m_pTemplateProvider; + + DialogModel & m_rDialogModel; + TabPageNotifiable * m_pTabPageNotifiable; + + std::unique_ptr m_xFT_Caption; + std::unique_ptr m_xFT_Range; + std::unique_ptr m_xED_Range; + std::unique_ptr m_xIB_Range; + std::unique_ptr m_xRB_Rows; + std::unique_ptr m_xRB_Columns; + std::unique_ptr m_xCB_FirstRowAsLabel; + std::unique_ptr m_xCB_FirstColumnAsLabel; + std::unique_ptr m_xFTTitle; + std::unique_ptr m_xFL_TimeBased; + std::unique_ptr m_xCB_TimeBased; + std::unique_ptr m_xFT_TimeStart; + std::unique_ptr m_xEd_TimeStart; + std::unique_ptr m_xFT_TimeEnd; + std::unique_ptr m_xEd_TimeEnd; +}; + +} //namespace chart +#endif + +/* 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 000000000..0c6266677 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Scale.cxx @@ -0,0 +1,604 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +namespace +{ + +void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue) +{ + rFmtField.set_value(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)); + + const double nMin = static_cast(SAL_MIN_INT64); + const double nMax = static_cast(SAL_MAX_INT64); + m_xFmtFldMin->set_range(nMin, nMax); + m_xFmtFldMax->set_range(nMin, nMax); + m_xFmtFldStepMain->set_range(nMin, nMax); + m_xFmtFldOrigin->set_range(nMin, nMax); + + 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->get_value()); + } + + 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::ToggleButton&, 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 ScaleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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; + + const SfxPoolItem *pPoolItem = nullptr; + if (rInAttrs->GetItemState(SCHATTR_AXIS_ALLOW_DATEAXIS, true, &pPoolItem) == SfxItemState::SET) + m_bAllowDateAxis = static_cast(pPoolItem)->GetValue(); + m_nAxisType=chart2::AxisType::REALNUMBER; + if (rInAttrs->GetItemState(SCHATTR_AXISTYPE, true, &pPoolItem) == SfxItemState::SET) + m_nAxisType = static_cast(static_cast(pPoolItem)->GetValue()); + if( m_nAxisType==chart2::AxisType::DATE && !m_bAllowDateAxis ) + m_nAxisType=chart2::AxisType::CATEGORY; + if( m_bAllowDateAxis ) + { + bool bAutoDateAxis = false; + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_DATEAXIS, true, &pPoolItem) == SfxItemState::SET) + bAutoDateAxis = static_cast(pPoolItem)->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 (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_MIN,true,&pPoolItem) == SfxItemState::SET) + m_xCbxAutoMin->set_active(static_cast(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MIN,true, &pPoolItem) == SfxItemState::SET) + { + fMin = static_cast(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldMin, fMin ); + m_xFmtFldMin->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_MAX,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoMax->set_active(static_cast(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MAX,true, &pPoolItem) == SfxItemState::SET) + { + fMax = static_cast(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldMax, fMax ); + m_xFmtFldMax->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_STEP_MAIN,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoStepMain->set_active(static_cast(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_STEP_MAIN,true, &pPoolItem) == SfxItemState::SET) + { + fStepMain = static_cast(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldStepMain, fStepMain ); + m_xFmtFldStepMain->save_value(); + m_xMt_MainDateStep->set_value( static_cast(fStepMain) ); + m_xMt_MainDateStep->save_value(); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_STEP_HELP,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoStepHelp->set_active(static_cast(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_LOGARITHM,true, &pPoolItem) == SfxItemState::SET) + m_xCbxLogarithm->set_active(static_cast(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_REVERSE,true, &pPoolItem) == SfxItemState::SET) + m_xCbxReverse->set_active(static_cast(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_STEP_HELP,true, &pPoolItem) == SfxItemState::SET) + { + nStepHelp = static_cast(pPoolItem)->GetValue(); + m_xMtStepHelp->set_value( nStepHelp ); + m_xMtStepHelp->save_value(); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_ORIGIN,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoOrigin->set_active(static_cast(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_ORIGIN,true, &pPoolItem) == SfxItemState::SET) + { + fOrigin = static_cast(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldOrigin, fOrigin ); + m_xFmtFldOrigin->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_TIME_RESOLUTION,true, &pPoolItem) == SfxItemState::SET) + m_xCbx_AutoTimeResolution->set_active(static_cast(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_TIME_RESOLUTION,true, &pPoolItem) == SfxItemState::SET) + { + m_nTimeResolution = static_cast(pPoolItem)->GetValue(); + m_xLB_TimeResolution->set_active( m_nTimeResolution ); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MAIN_TIME_UNIT,true, &pPoolItem) == SfxItemState::SET) + { + m_nMainTimeUnit = static_cast(pPoolItem)->GetValue(); + m_xLB_MainTimeUnit->set_active( m_nMainTimeUnit ); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_HELP_TIME_UNIT,true, &pPoolItem) == SfxItemState::SET) + { + m_nHelpTimeUnit = static_cast(pPoolItem)->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->get_format_key(); + 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->get_format_key(); + if (pNumFormatter->GetType(nStepFmt) == SvNumFormatType::TEXT) + nStepFmt = 0; + + weld::Widget* pControl = nullptr; + const char* pErrStrId = nullptr; + double fDummy; + + fMax = m_xFmtFldMax->get_value(); + fMin = m_xFmtFldMin->get_value(); + fOrigin = m_xFmtFldOrigin->get_value(); + fStepMain = bDateAxis ? m_xMt_MainDateStep->get_value() : m_xFmtFldStepMain->get_value(); + 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; + m_xFmtFldMax->set_formatter( pNumFormatter ); + m_xFmtFldMin->set_formatter( pNumFormatter ); + m_xFmtFldStepMain->set_formatter( pNumFormatter ); + m_xFmtFldOrigin->set_formatter( pNumFormatter ); + SetNumFormat(); +} + +void ScaleTabPage::SetNumFormat() +{ + const SfxPoolItem *pPoolItem = nullptr; + + if( GetItemSet().GetItemState( SID_ATTR_NUMBERFORMAT_VALUE, true, &pPoolItem ) != SfxItemState::SET ) + return; + + sal_uLong nFmt = static_cast(pPoolItem)->GetValue(); + + m_xFmtFldMax->set_format_key(nFmt); + m_xFmtFldMin->set_format_key(nFmt); + m_xFmtFldOrigin->set_format_key(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 ); + } + + 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 ); + + m_xFmtFldMax->set_format_key(nFmt); + m_xFmtFldMin->set_format_key(nFmt); + m_xFmtFldOrigin->set_format_key(nFmt); + } + } + + m_xFmtFldStepMain->set_format_key(nFmt); +} + +void ScaleTabPage::ShowAxisOrigin( bool bShowOrigin ) +{ + m_bShowAxisOrigin = bShowOrigin; + if( !AxisHelper::isAxisPositioningEnabled() ) + m_bShowAxisOrigin = true; +} + +bool ScaleTabPage::ShowWarning(const char* pResIdMessage, weld::Widget* pControl /* = nullptr */) +{ + if (pResIdMessage == nullptr) + return false; + + std::unique_ptr xWarn(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + SchResId(pResIdMessage))); + xWarn->run(); + if (pControl) + { + pControl->grab_focus(); + weld::Entry* pEdit = dynamic_cast(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 000000000..b0e308845 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Scale.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SCALE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SCALE_HXX + +#include + +namespace chart +{ + +class ScaleTabPage : public SfxTabPage +{ +public: + ScaleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~ScaleTabPage() override; + + static std::unique_ptr 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 m_xCbxReverse; + std::unique_ptr m_xCbxLogarithm; + std::unique_ptr m_xBxType; + std::unique_ptr m_xLB_AxisType; + std::unique_ptr m_xBxMinMax; + std::unique_ptr m_xFmtFldMin; + std::unique_ptr m_xCbxAutoMin; + std::unique_ptr m_xFmtFldMax; + std::unique_ptr m_xCbxAutoMax; + std::unique_ptr m_xBxResolution; + std::unique_ptr m_xLB_TimeResolution; + std::unique_ptr m_xCbx_AutoTimeResolution; + std::unique_ptr m_xTxtMain; + std::unique_ptr m_xFmtFldStepMain; + std::unique_ptr m_xMt_MainDateStep; + std::unique_ptr m_xLB_MainTimeUnit; + std::unique_ptr m_xCbxAutoStepMain; + std::unique_ptr m_xTxtHelpCount; + std::unique_ptr m_xTxtHelp; + std::unique_ptr m_xMtStepHelp; + std::unique_ptr m_xLB_HelpTimeUnit; + std::unique_ptr m_xCbxAutoStepHelp; + std::unique_ptr m_xFmtFldOrigin; + std::unique_ptr m_xCbxAutoOrigin; + std::unique_ptr m_xBxOrigin; + + void EnableControls(); + + DECL_LINK(SelectAxisTypeHdl, weld::ComboBox&, void); + DECL_LINK(EnableValueHdl, weld::ToggleButton&, 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(const char* pResIdMessage, weld::Widget* pControl); + + void HideAllControls(); +}; + +} //namespace chart + +#endif + +/* 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 000000000..82bd80ab6 --- /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 + +#include +#include +#include + +#include + +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::ToggleButton&, 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 SchOptionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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) +{ + const SfxPoolItem *pPoolItem = nullptr; + + m_xRbtAxis1->set_active(true); + m_xRbtAxis2->set_active(false); + if (rInAttrs->GetItemState(SCHATTR_AXIS,true, &pPoolItem) == SfxItemState::SET) + { + long nVal=static_cast(pPoolItem)->GetValue(); + if(nVal==CHART_AXIS_SECONDARY_Y) + { + m_xRbtAxis2->set_active(true); + m_xRbtAxis1->set_active(false); + } + } + + long nTmp; + if (rInAttrs->GetItemState(SCHATTR_BAR_GAPWIDTH, true, &pPoolItem) == SfxItemState::SET) + { + nTmp = static_cast(static_cast(pPoolItem)->GetValue()); + m_xMTGap->set_value(nTmp, FieldUnit::PERCENT); + } + + if (rInAttrs->GetItemState(SCHATTR_BAR_OVERLAP, true, &pPoolItem) == SfxItemState::SET) + { + nTmp = static_cast(static_cast(pPoolItem)->GetValue()); + m_xMTOverlap->set_value(nTmp, FieldUnit::PERCENT); + } + + if (rInAttrs->GetItemState(SCHATTR_BAR_CONNECT, true, &pPoolItem) == SfxItemState::SET) + { + bool bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCBConnect->set_active(bCheck); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_FOR_ALL_SERIES, true, &pPoolItem) == SfxItemState::SET) + { + m_nAllSeriesAxisIndex = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xCBAxisSideBySide->set_sensitive(false); + } + if (rInAttrs->GetItemState(SCHATTR_GROUP_BARS_PER_AXIS, true, &pPoolItem) == SfxItemState::SET) + { + // model property is "group bars per axis", UI feature is the other way + // round: "show bars side by side" + bool bCheck = ! static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCBAxisSideBySide->set_active( bCheck ); + } + else + { + m_xCBAxisSideBySide->hide(); + } + + //missing value treatment + { + std::vector< sal_Int32 > aMissingValueTreatments; + if( rInAttrs->GetItemState(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, true, &pPoolItem) == SfxItemState::SET ) + aMissingValueTreatments = static_cast(pPoolItem)->GetList(); + + if ( aMissingValueTreatments.size()>1 && rInAttrs->GetItemState(SCHATTR_MISSING_VALUE_TREATMENT,true, &pPoolItem) == SfxItemState::SET) + { + 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); + } + + long nVal=static_cast(pPoolItem)->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 (rInAttrs->GetItemState(SCHATTR_INCLUDE_HIDDEN_CELLS, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast(pPoolItem)->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 (rInAttrs->GetItemState(SCHATTR_HIDE_LEGEND_ENTRY, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast(pPoolItem)->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 000000000..8580e5722 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SERIESTOAXIS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SERIESTOAXIS_HXX + +#include + +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 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::ToggleButton&, void ); + + sal_Int32 m_nAllSeriesAxisIndex; + + bool m_bProvidesSecondaryYAxis; + bool m_bProvidesOverlapAndGapWidth; + bool m_bProvidesBarConnectors; + + std::unique_ptr m_xGrpAxis; + std::unique_ptr m_xRbtAxis1; + std::unique_ptr m_xRbtAxis2; + std::unique_ptr m_xGrpBar; + std::unique_ptr m_xMTGap; + std::unique_ptr m_xMTOverlap; + std::unique_ptr m_xCBConnect; + std::unique_ptr m_xCBAxisSideBySide; + std::unique_ptr m_xGrpPlotOptions; + std::unique_ptr m_xGridPlotOptions; + std::unique_ptr m_xRB_DontPaint; + std::unique_ptr m_xRB_AssumeZero; + std::unique_ptr m_xRB_ContinueLine; + std::unique_ptr m_xCBIncludeHiddenCells; + std::unique_ptr m_xCBHideLegendEntry; +}; + +} //namespace chart + +#endif + +/* 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 000000000..d23e393d5 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_TitleRotation.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 "tp_TitleRotation.hxx" + +#include +#include + +#include +#include +#include + +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_xFtTextDirection(m_xBuilder->weld_label("textdirL")) + , m_xFtABCD(m_xBuilder->weld_label("labelABCD")) + , m_xLbTextDirection(new TextDirectionListBox(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::ToggleButton&, 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(); + m_xLbTextDirection.reset(); +} + +std::unique_ptr SchAlignmentTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rInAttrs) +{ + return std::make_unique(pPage, pController, *rInAttrs); +} + +std::unique_ptr SchAlignmentTabPage::CreateWithoutRotation(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rInAttrs) +{ + return std::make_unique(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 ) ); + + sal_Int32 nDegrees = bStacked ? 0 : m_xCtrlDial->GetRotation(); + rOutAttrs->Put( SfxInt32Item( SCHATTR_TEXT_DEGREES, nDegrees ) ); + + SvxFrameDirection aDirection( m_xLbTextDirection->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 ); + + sal_Int32 nDegrees = pItem ? static_cast(pItem)->GetValue() : 0; + m_xCtrlDial->SetRotation( nDegrees ); + + pItem = GetItem( *rInAttrs, SCHATTR_TEXT_STACKED ); + bool bStacked = pItem && static_cast(pItem)->GetValue(); + m_xCbStacked->set_active(bStacked); + StackedToggleHdl(*m_xCbStacked); + + if( rInAttrs->GetItemState(EE_PARA_WRITINGDIR, true, &pItem) == SfxItemState::SET) + m_xLbTextDirection->set_active_id(static_cast(pItem)->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 000000000..b6b184eea --- /dev/null +++ b/chart2/source/controller/dialogs/tp_TitleRotation.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TITLEROTATION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TITLEROTATION_HXX + +#include +#include + +namespace chart { class TextDirectionListBox; } +namespace weld { + class CheckButton; + class CustomWeld; + class Label; + class SpinButton; + class ToggleButton; +} + +namespace chart +{ + +class SchAlignmentTabPage : public SfxTabPage +{ +private: + std::unique_ptr m_xFtRotate; + std::unique_ptr m_xNfRotate; + std::unique_ptr m_xCbStacked; + std::unique_ptr m_xFtTextDirection; + std::unique_ptr m_xFtABCD; + std::unique_ptr m_xLbTextDirection; + std::unique_ptr m_xCtrlDial; + std::unique_ptr m_xCtrlDialWin; + + DECL_LINK(StackedToggleHdl, weld::ToggleButton&, void); + +public: + SchAlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs, bool bWithRotation = true); + virtual ~SchAlignmentTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + static std::unique_ptr 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 + +#endif + +/* 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 000000000..fe25959bd --- /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 TrendlineTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(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 000000000..596ff339b --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Trendline.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TRENDLINE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TRENDLINE_HXX + +#include "res_Trendline.hxx" + +#include + +namespace chart +{ + +class TrendlineTabPage : public SfxTabPage +{ +public: + TrendlineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + + static std::unique_ptr 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 + +#endif + +/* 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 000000000..b191f2a42 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.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 "tp_Wizard_TitlesAndObjects.hxx" +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +TitlesAndObjectsTabPage::TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController, + const uno::Reference< XChartDocument >& 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(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 + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( m_xChartModel ); + uno::Sequence< sal_Bool > aPossibilityList; + uno::Sequence< sal_Bool > aExistenceList; + AxisHelper::getAxisOrGridPossibilities( aPossibilityList, xDiagram, false ); + AxisHelper::getAxisOrGridExcistence( 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(); + uno::Reference< frame::XModel > 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 + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel ); + uno::Sequence< sal_Bool > aOldExistenceList; + AxisHelper::getAxisOrGridExcistence( aOldExistenceList, xDiagram, false ); + uno::Sequence< sal_Bool > aNewExistenceList(aOldExistenceList); + aNewExistenceList[0] = m_xCB_Grid_X->get_active(); + aNewExistenceList[1] = m_xCB_Grid_Y->get_active(); + aNewExistenceList[2] = m_xCB_Grid_Z->get_active(); + AxisHelper::changeVisibilityOfGrids( xDiagram + , aOldExistenceList, aNewExistenceList ); + } +} + +IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeCheckBoxHdl, weld::ToggleButton&, 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 000000000..f6c5bbc4b --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_WIZARD_TITLESANDOBJECTS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_WIZARD_TITLESANDOBJECTS_HXX + +#include + +#include + +#include + +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 TitlesAndObjectsTabPage final : public vcl::OWizardPage +{ +public: + TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController, + const css::uno::Reference< css::chart2::XChartDocument >& 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::ToggleButton&, void ); + + std::unique_ptr< TitleResources > m_xTitleResources; + std::unique_ptr< LegendPositionResources > m_xLegendPositionResources; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartModel; + css::uno::Reference< css::uno::XComponentContext> m_xCC; + + bool m_bCommitToModel; + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + std::unique_ptr m_xCB_Grid_X; + std::unique_ptr m_xCB_Grid_Y; + std::unique_ptr m_xCB_Grid_Z; +}; + +} //namespace chart +#endif + +/* 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 000000000..d60b259da --- /dev/null +++ b/chart2/source/controller/drawinglayer/DrawViewWrapper.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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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(pOutDev->PixelToLogic(Size(HITPIX,0)).Width()); + return nHitTolerance; + } + +// this code is copied from sfx2/source/doc/objembed.cxx +SfxObjectShell * lcl_GetParentObjectShell( const uno::Reference< frame::XModel > & xModel ) +{ + SfxObjectShell* pResult = nullptr; + + try + { + uno::Reference< container::XChild > xChildModel( xModel, uno::UNO_QUERY ); + if ( xChildModel.is() ) + { + uno::Reference< lang::XUnoTunnel > xParentTunnel( xChildModel->getParent(), uno::UNO_QUERY ); + if ( xParentTunnel.is() ) + { + SvGlobalName aSfxIdent( SFX_GLOBAL_CLASSID ); + pResult = reinterpret_cast< SfxObjectShell * >( + xParentTunnel->getSomething( aSfxIdent.GetByteSequence() ) ); + } + } + } + catch( const uno::Exception& ) + { + // TODO: error handling + } + + return pResult; +} + +// 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 = lcl_GetParentObjectShell( 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); + SetPagePaintingAllowed(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 = dynamic_cast< E3dObject* >(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 +{ + SfxItemSet aFullSet( + GetModel()->GetItemPool(), + svl::Items< + SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS, + 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,static_cast< sal_uInt16 >( ConfigurationAccess::getFieldUnit()))); + 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.IsInside(rPnt); + } + return false; +} + +void DrawViewWrapper::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + //prevent wrong reselection of objects + SdrModel* pSdrModel( GetModel() ); + if( pSdrModel && pSdrModel->isLocked() ) + return; + + const SdrHint* pSdrHint = ( rHint.GetId() == SfxHintId::ThisIsAnSdrHint ? static_cast(&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()) + { + SvxShape* pSvxShape = comphelper::getUnoTunnelImplementation(xShape); + if(pSvxShape) + pRet = pSvxShape->GetSdrObject(); + } + 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 000000000..9259ce921 --- /dev/null +++ b/chart2/source/controller/drawinglayer/ViewElementListProvider.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 shape factory + uno::Reference xShapeFactory( + m_pDrawModelWrapper->getShapeFactory()); + + //get hidden draw page (target): + uno::Reference 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 ?? + uno::Reference xSymbols + = DataPointSymbolSupplier::create2DSymbolList(xShapeFactory, xTarget, aSymbolSize); + + SdrObject* pSdrObject = DrawViewWrapper::getSdrObject( + uno::Reference(xSymbols, 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(); + SdrObject* pObj = pSymbolList->GetObj(nStandardSymbol); + + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + + std::unique_ptr pModel( + new SdrModel()); + + pModel->GetItemPool().FreezeIdRanges(); + SdrPage* pPage = new SdrPage( *pModel, false ); + pPage->SetSize(Size(1000,1000)); + pModel->InsertPage( pPage, 0 ); + std::unique_ptr pView(new SdrView(*pModel, pVDev)); + pView->hideMarkHandles(); + SdrPageView* pPageView = pView->ShowSdrPage(pPage); + + // directly clone to target SdrModel + pObj = pObj->CloneSdrObject(*pModel); + + pPage->NbcInsertObject(pObj); + pView->MarkObj(pObj,pPageView); + if( pSymbolShapeProperties ) + pObj->SetMergedItemSet(*pSymbolShapeProperties); + + GDIMetaFile aMeta(pView->GetMarkedObjMetaFile()); + + Graphic aGraph(aMeta); + Size aSize = pObj->GetSnapRect().GetSize(); + aGraph.SetPrefSize(aSize); + aGraph.SetPrefMapMode(MapMode(MapUnit::Map100thMM)); + + pView->UnmarkAll(); + pObj=pPage->RemoveObject(0); + SdrObject::Free( pObj ); + + 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 000000000..ef1eab329 --- /dev/null +++ b/chart2/source/controller/inc/AccessibleBase.hxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLEBASE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLEBASE_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::view { class XSelectionSupplier; } +namespace utl { class AccessibleStateSetHelper; } + + +class SdrView; + +namespace accessibility +{ +class IAccessibleViewForwarder; +} + +namespace chart +{ + +class AccessibleBase; +class ObjectHierarchy; + +typedef ObjectIdentifier AccessibleUniqueId; + +struct AccessibleElementInfo +{ + AccessibleUniqueId m_aOID; + + css::uno::WeakReference< css::chart2::XChartDocument > m_xChartDocument; + css::uno::WeakReference< css::view::XSelectionSupplier > m_xSelectionSupplier; + css::uno::WeakReference< css::uno::XInterface > 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 MutexContainer, + public impl::AccessibleBase_Base +{ +public: + enum class EventType + { + GOT_SELECTION, + LOST_SELECTION + }; + + AccessibleBase( const AccessibleElementInfo & rAccInfo, + 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_Int16 aState ); + + /** Removes a state from the set if the set contains the state, otherwise + nothing is done. + + @throws css::uno::RuntimeException + */ + void RemoveState( sal_Int16 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 + + If bSendGlobally is true, the event is also broadcast via + vcl::unohelper::NotifyAccessibleStateEventGlobally() + */ + void BroadcastAccEvent( sal_Int16 nId, + const css::uno::Any & rNew, + const css::uno::Any & rOld, + bool bSendGlobally = false ) 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_Int32 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_Int32 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_Int32 SAL_CALL getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleChild( sal_Int32 i ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleParent() override; + virtual sal_Int32 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 css::uno::Reference< css::accessibility::XAccessibleStateSet > 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; + + /** Implementation helper for getAccessibleStateSet() + + Note: This member must come before m_aStateSet! + */ + rtl::Reference<::utl::AccessibleStateSetHelper> m_xStateSetHelper; + + 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 + +#endif + +/* 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 000000000..f6e174b53 --- /dev/null +++ b/chart2/source/controller/inc/AccessibleChartView.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLECHARTVIEW_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLECHARTVIEW_HXX + +#include "AccessibleBase.hxx" +#include +#include +#include +#include + +#include + +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 +{ + +namespace impl +{ +typedef ::cppu::ImplInheritanceHelper< + ::chart::AccessibleBase, + css::lang::XInitialization, + css::view::XSelectionChangeListener > + AccessibleChartView_Base; +} + +class AccessibleChartView : + public impl::AccessibleChartView_Base +{ +public: + AccessibleChartView(SdrView* pView ); + virtual ~AccessibleChartView() override; + + AccessibleChartView() = delete; + + // ____ WeakComponentHelper (called from XComponent::dispose()) ____ + using AccessibleBase::disposing; + + // ____ lang::XInitialization ____ + // 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 + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // ____ 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_Int32 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 + css::uno::WeakReference< css::view::XSelectionSupplier > m_xSelectionSupplier; + css::uno::WeakReference< css::frame::XModel > m_xChartModel; + css::uno::WeakReference< css::uno::XInterface > 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 +#endif + +/* 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 000000000..30b4123b9 --- /dev/null +++ b/chart2/source/controller/inc/AccessibleTextHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLETEXTHELPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLETEXTHELPER_HXX + +#include +#include +#include +#include +#include + +// forward declaration of helper class from svx +namespace accessibility +{ +class AccessibleTextHelper; +} + +namespace chart +{ + +class DrawViewWrapper; + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper< + css::lang::XInitialization, + css::accessibility::XAccessibleContext > + AccessibleTextHelper_Base; +} + +class AccessibleTextHelper : + public MutexContainer, + public impl::AccessibleTextHelper_Base +{ +public: + explicit AccessibleTextHelper( DrawViewWrapper * pDrawViewWrapper ); + virtual ~AccessibleTextHelper() override; + + // ____ XInitialization ____ + /** 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. + */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // ____ XAccessibleContext ____ + virtual ::sal_Int32 SAL_CALL getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( + ::sal_Int32 i ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override; + virtual ::sal_Int32 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 css::uno::Reference< css::accessibility::XAccessibleStateSet > 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ACCESSIBLETEXTHELPER_HXX +#endif + +/* 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 000000000..5bd230bd6 --- /dev/null +++ b/chart2/source/controller/inc/AxisItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_AXISITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_AXISITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +#include + +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 { struct ExplicitIncrementData; } +namespace chart { struct ExplicitScaleData; } + +class SdrModel; + +namespace chart::wrapper { + +class AxisItemConverter : public ItemConverter +{ +public: + AxisItemConverter( + const css::uno::Reference& rPropertySet, + SfxItemPool& rItemPool, SdrModel& rDrawModel, + const css::uno::Reference & 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 sal_uInt16 * 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 > m_aConverters; + css::uno::Reference< + css::chart2::XAxis > m_xAxis; + + css::uno::Reference< + css::chart2::XChartDocument > m_xChartDoc; + + std::unique_ptr m_pExplicitScale; + std::unique_ptr m_pExplicitIncrement; +}; + +} + +#endif + +/* 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 000000000..0cf947d0e --- /dev/null +++ b/chart2/source/controller/inc/CharacterPropertyItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARACTERPROPERTYITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARACTERPROPERTYITEMCONVERTER_HXX + +#include "ItemConverter.hxx" +#include + +#include + +namespace chart::wrapper { + +class CharacterPropertyItemConverter final : public ItemConverter +{ +public: + CharacterPropertyItemConverter( + const css::uno::Reference& rPropertySet, + SfxItemPool& rItemPool ); + + CharacterPropertyItemConverter( + const css::uno::Reference& rPropertySet, + SfxItemPool& rItemPool, + const css::awt::Size* pRefSize, + const OUString & rRefSizePropertyName, + const css::uno::Reference& rRefSizePropSet = css::uno::Reference() ); + + virtual ~CharacterPropertyItemConverter() override; + +private: + virtual const sal_uInt16* 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& GetRefSizePropertySet() const; + + OUString m_aRefSizePropertyName; + css::uno::Reference m_xRefSizePropSet; + std::optional m_pRefSize; +}; + +} + +#endif + +/* 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 000000000..1977e8e16 --- /dev/null +++ b/chart2/source/controller/inc/ChartController.hxx @@ -0,0 +1,559 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTCONTROLLER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTCONTROLLER_HXX + +#include +#include "CommandDispatchContainer.hxx" +#include "SelectionHelper.hxx" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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::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; +} + +class DropTargetHelper; + +namespace com::sun::star { + namespace graphic { + class XGraphic; + } +} + +namespace chart +{ + +class UndoGuard; +class ChartWindow; +class DrawModelWrapper; +class DrawViewWrapper; +class ReferenceSizeProvider; +class ViewElementListProvider; + +enum ChartDrawMode { CHARTDRAW_INSERT, CHARTDRAW_SELECT }; + + +class ChartController : public ::cppu::WeakImplHelper < + css::frame::XController //comprehends XComponent (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::lang::XServiceInfo + ,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::lang::XMultiServiceFactory + ,css::util::XModifyListener + ,css::util::XModeChangeListener + ,css::frame::XLayoutManagerListener + > +{ +public: + ChartController() = delete; + explicit ChartController(css::uno::Reference< css::uno::XComponentContext > const & xContext); + virtual ~ChartController() override; + + OUString GetContextName(); + + // 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::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::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::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; + + // 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 , 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(); + + static bool isObjectDeleteable( const css::uno::Any& rSelection ); + + void setDrawMode( ChartDrawMode eMode ) { m_eDrawMode = eMode; } + + bool isShapeContext() const; + + ViewElementListProvider getViewElementListProvider(); + DrawModelWrapper* GetDrawModelWrapper(); + DrawViewWrapper* GetDrawViewWrapper(); + VclPtr GetChartWindow() const; + weld::Window* GetChartFrame(); + bool isAdditionalShapeSelected() const; + void SetAndApplySelection(const css::uno::Reference& rxShape); + void StartTextEdit( const Point* pMousePixel = nullptr ); + + void NotifyUndoActionHdl( std::unique_ptr ); + + css::uno::Reference const & getChartView() const; + +private: + class TheModel : public salhelper::SimpleReferenceObject + { + public: + explicit TheModel( const css::uno::Reference< + css::frame::XModel > & xModel ); + + virtual ~TheModel() override; + + void addListener( ChartController* pController ); + void removeListener( ChartController* pController ); + void tryTermination(); + const css::uno::Reference< css::frame::XModel >& + getModel() const { return m_xModel;} + + private: + css::uno::Reference< css::frame::XModel > m_xModel; + css::uno::Reference< css::util::XCloseable > m_xCloseable; + + //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 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 m_xViewWindow; + css::uno::Reference m_xChartView; + std::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper; + std::unique_ptr 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 mpSelectionChangeHandler; + + bool impl_isDisposedOrSuspended() const; + std::unique_ptr impl_createReferenceSizeProvider(); + void impl_adaptDataSeriesAutoResize(); + + void impl_createDrawViewController(); + void impl_deleteDrawViewController(); + + //executeDispatch methods + void executeDispatch_ObjectProperties(); + void executeDispatch_FormatObject( const OUString& 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_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 sendPopupRequest(OUString const & 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( const css::uno::Reference< css::lang::XInitialization >& 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 , if resize/move was successful + bool impl_moveOrResizeObject( + const OUString & rCID, eMoveOrResizeType eType, double fAmountLogicX, double fAmountLogicY ); + bool impl_DragDataPoint( const OUString & rCID, double fOffset ); + + static const o3tl::sorted_vector< OUString >& impl_getAvailableCommands(); + + /** Creates a helper accessibility class that must be initialized via XInitialization. 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. + */ + css::uno::Reference< css::accessibility::XAccessibleContext > + impl_createAccessibleTextContext(); + + 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 + +#endif + +/* 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 000000000..9f36c42b3 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARTDOCUMENTWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARTDOCUMENTWRAPPER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XRefreshable; } + +namespace chart +{ + +namespace 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 : 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 + css::uno::Reference< css::drawing::XDrawPage > 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 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 > createWrappedProperties() override; + virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() 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; + + css::uno::Reference< css::uno::XInterface > m_xChartView; + css::uno::Reference< css::lang::XMultiServiceFactory> + m_xShapeFactory; + + bool m_bIsDisposed; +}; + +} // namespace wrapper +} // namespace chart + +// CHART_CHARTDOCUMENT_HXX +#endif + +/* 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 000000000..140a62b60 --- /dev/null +++ b/chart2/source/controller/inc/ChartToolbarController.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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARTTOOLBARCONTROLLER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CHARTTOOLBARCONTROLLER_HXX + +#include +#include + +#include +#include +#include +#include +#include + +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::frame { class XFramesSupplier; } + +namespace chart { + +typedef cppu::WeakComponentImplHelper< + css::frame::XToolbarController, css::frame::XStatusListener, + css::util::XUpdatable, css::lang::XInitialization, + css::lang::XServiceInfo> ChartToolbarControllerBase; + +class ChartToolbarController : private cppu::BaseMutex, + public ChartToolbarControllerBase +{ +public: + ChartToolbarController(const css::uno::Sequence& 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 SAL_CALL createPopupWindow() override; + + virtual css::uno::Reference SAL_CALL + createItemWindow(const css::uno::Reference& rParent) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; + + virtual css::uno::Sequence 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& rAny) override; + + // XUpdatable + virtual void SAL_CALL update() override; + + using cppu::WeakComponentImplHelperBase::disposing; + +private: + + css::uno::Reference mxFramesSupplier; +}; + +} + +#endif + +/* 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 000000000..a05db545b --- /dev/null +++ b/chart2/source/controller/inc/ChartWindow.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTWINDOW_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTWINDOW_HXX + +#include + +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 : 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; + + /// For LibreOfficeKit, we need to route these to the mouse events. + virtual void LogicMouseButtonDown(const MouseEvent&) override; + virtual void LogicMouseButtonUp(const MouseEvent&) override; + virtual void LogicMouseMove(const MouseEvent&) override; + + void ForceInvalidate(); + virtual void Invalidate( InvalidateFlags nFlags = InvalidateFlags::NONE ) override; + virtual void Invalidate( const tools::Rectangle& rRect, InvalidateFlags nFlags = InvalidateFlags::NONE ) override; + virtual void Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags = InvalidateFlags::NONE ) 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 m_pViewShellWindow; + + void adjustHighContrastMode(); +}; + +} //namespace chart + +#endif + +/* 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 000000000..8e6aa4c49 --- /dev/null +++ b/chart2/source/controller/inc/CommandDispatchContainer.hxx @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCHCONTAINER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCHCONTAINER_HXX + +#include +#include + +#include +#include + +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 DrawCommandDispatch; +class ShapeController; + +/** @HTML + + Helper class for implementing the XDispatchProvider interface + of the ChartController. This class handles all commands to queryDispatch and + queryDispatches in the following way: + +
    +
  • Check if there is a cached XDispatch for a given command. + If so, use it.
  • +
  • Check if the command is handled by this class, e.g. Undo. If so, + return a corresponding XDispatch implementation, and cache + this implementation for later use
  • +
  • Otherwise send the command to the chart dispatch provider, if it + can handle this dispatch (determined by the list of commands given in + setChartDispatch()).
  • +
+ +

The XDispatchProvider is designed to return different + XDispatch implementations for each command. This class here + decides which implementation to use for which command.

+ +

As most commands need much information of the controller and are + implemented there, the controller handles most of the commands itself (it + also implements XDispatch). Therefore it is set here as + chart dispatch.

+ */ +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 css::uno::Reference< css::frame::XModel > & xModel ); + + /** Set a chart dispatcher that is used for all commands contained in + rChartCommands + */ + void setChartDispatch( + const css::uno::Reference< css::frame::XDispatch >& rChartDispatch, + const 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. + +

If all this fails, return an empty dispatch.

+ */ + 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 ); + + css::uno::Reference< css::frame::XDispatch > getChartDispatcher() { 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; + css::uno::WeakReference< css::frame::XModel > m_xModel; + + css::uno::Reference< css::frame::XDispatch > m_xChartDispatcher; + o3tl::sorted_vector< OUString > m_aChartCommands; + + DrawCommandDispatch* m_pDrawCommandDispatch; + ShapeController* m_pShapeController; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCHCONTAINER_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/inc/ConfigurationAccess.hxx b/chart2/source/controller/inc/ConfigurationAccess.hxx new file mode 100644 index 000000000..416ae72fe --- /dev/null +++ b/chart2/source/controller/inc/ConfigurationAccess.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CONFIGURATIONACCESS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_CONFIGURATIONACCESS_HXX + +#include + +namespace chart +{ + +namespace ConfigurationAccess +{ + /** @descr Retrieve the FieldUnit to be used for the UI. This unit is retrieved + from the registry settings of the Calc application. + + If this setting can not be found there is a fallback to cm which is the most + common setting worldwide (or not?) + + @return the FieldUnit enum. See for definition + */ + FieldUnit getFieldUnit(); +} + +} //namespace chart +#endif + +/* 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 000000000..88c2b3a27 --- /dev/null +++ b/chart2/source/controller/inc/DataPointItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DATAPOINTITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DATAPOINTITEMCONVERTER_HXX + +#include "ItemConverter.hxx" +#include "GraphicPropertyItemConverter.hxx" +#include + +#include + +#include + +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; } + +class SdrModel; + +namespace chart::wrapper { + +class DataPointItemConverter : public ItemConverter +{ +public: + DataPointItemConverter( + const css::uno::Reference& xChartModel, + const css::uno::Reference& xContext, + const css::uno::Reference& rPropertySet, + const css::uno::Reference& xSeries, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const css::uno::Reference& 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 sal_uInt16 * 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 > 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 m_aAvailableLabelPlacements; + bool m_bForbidPercentValue; + bool m_bHideLegendEntry; + sal_Int32 m_nPointIndex; + css::uno::Reference m_xSeries; +}; + +} + +#endif + +/* 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 000000000..8bad64410 --- /dev/null +++ b/chart2/source/controller/inc/DrawViewWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DRAWVIEWWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DRAWVIEWWRAPPER_HXX + +#include +#include + +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 : 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 +#endif + +/* 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 000000000..691ca508a --- /dev/null +++ b/chart2/source/controller/inc/ErrorBarItemConverter.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ERRORBARITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ERRORBARITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart +{ +namespace wrapper +{ + +class ErrorBarItemConverter : public ItemConverter +{ +public: + ErrorBarItemConverter( + const 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 sal_uInt16 * 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 wrapper +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ERRORBARITEMCONVERTER_HXX + +/* 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 000000000..1fcc4f224 --- /dev/null +++ b/chart2/source/controller/inc/GraphicPropertyItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_GRAPHICPROPERTYITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_GRAPHICPROPERTYITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart +{ +namespace wrapper +{ + +enum class GraphicObjectType +{ + FilledDataPoint, + LineDataPoint, + LineProperties, + LineAndFillProperties +}; + +class GraphicPropertyItemConverter : public ItemConverter +{ +public: + GraphicPropertyItemConverter( + const css::uno::Reference< css::beans::XPropertySet > & rPropertySet, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const css::uno::Reference< css::lang::XMultiServiceFactory > & xNamedPropertyContainerFactory, + GraphicObjectType eObjectType ); + virtual ~GraphicPropertyItemConverter() override; + +protected: + virtual const sal_uInt16 * 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 wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_GRAPHICPROPERTYITEMCONVERTER_HXX +#endif + +/* 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 000000000..8d00d9042 --- /dev/null +++ b/chart2/source/controller/inc/ItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ITEMCONVERTER_HXX + +#include +#include + +#include + +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( + const css::uno::Reference< css::beans::XPropertySet > & rPropertySet , + 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 of the form: + + const sal_uInt16 aMyPairs[] = + { + from_1, to_1, + from_2, to_2, + ... + from_n, to_n, + 0 + }; + */ + virtual const sal_uInt16 * 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; +}; + +} + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ITEMCONVERTER_HXX +#endif + +/* 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 000000000..26cd4e88c --- /dev/null +++ b/chart2/source/controller/inc/ItemPropertyMap.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ITEMPROPERTYMAP_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_ITEMPROPERTYMAP_HXX + +#include + +#include "ItemConverter.hxx" + +#include + +namespace chart::wrapper { + +typedef std::map< ItemConverter::tWhichIdType, std::pair< ItemConverter::tPropertyNameType, ItemConverter::tMemberIdType > > + ItemPropertyMapType; + +} + +#endif + +/* 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 000000000..74de6cd62 --- /dev/null +++ b/chart2/source/controller/inc/LegendItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_LEGENDITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_LEGENDITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +#include + +namespace com::sun::star::awt { struct Size; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart +{ +namespace wrapper +{ + +class LegendItemConverter : 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 sal_uInt16 * 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 > m_aConverters; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_LEGENDITEMCONVERTER_HXX +#endif + +/* 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 000000000..9f5fd399d --- /dev/null +++ b/chart2/source/controller/inc/MultipleChartConverters.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_MULTIPLECHARTCONVERTERS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_MULTIPLECHARTCONVERTERS_HXX + +#include "MultipleItemConverter.hxx" + +namespace com::sun::star::awt { struct Size; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart::wrapper { + +class AllAxisItemConverter : public MultipleItemConverter +{ +public: + AllAxisItemConverter( + const css::uno::Reference & xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const css::awt::Size* pRefSize ); + + virtual ~AllAxisItemConverter() override; + +protected: + virtual const sal_uInt16 * GetWhichPairs() const override; +}; + +class AllGridItemConverter : public MultipleItemConverter +{ +public: + AllGridItemConverter( + const css::uno::Reference& xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const css::uno::Reference & xNamedPropertyContainerFactory ); + virtual ~AllGridItemConverter() override; + +protected: + virtual const sal_uInt16 * GetWhichPairs() const override; +}; + +class AllDataLabelItemConverter : public MultipleItemConverter +{ +public: + AllDataLabelItemConverter( + const css::uno::Reference& xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const css::uno::Reference& xNamedPropertyContainerFactory ); + + virtual ~AllDataLabelItemConverter() override; + +protected: + virtual const sal_uInt16 * GetWhichPairs() const override; +}; + +class AllTitleItemConverter : public MultipleItemConverter +{ +public: + AllTitleItemConverter( + const css::uno::Reference& xChartModel, + SfxItemPool& rItemPool, SdrModel& rDrawModel, + const css::uno::Reference& xNamedPropertyContainerFactory ); + + virtual ~AllTitleItemConverter() override; + +protected: + virtual const sal_uInt16 * GetWhichPairs() const override; +}; + +class AllSeriesStatisticsConverter : public MultipleItemConverter +{ +public: + AllSeriesStatisticsConverter( + const css::uno::Reference& xChartModel, SfxItemPool& rItemPool ); + virtual ~AllSeriesStatisticsConverter() override; + +protected: + virtual const sal_uInt16 * GetWhichPairs() const override; +}; + +} // namespace chart::wrapper + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_MULTIPLECHARTCONVERTERS_HXX +#endif + +/* 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 000000000..e2e8f0775 --- /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 + +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 > 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 000000000..a765275c4 --- /dev/null +++ b/chart2/source/controller/inc/ObjectHierarchy.hxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_INC_OBJECTHIERARCHY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_OBJECTHIERARCHY_HXX + +#include + +namespace com::sun::star::awt { struct KeyEvent; } +namespace com::sun::star::chart2 { class XChartDocument; } + +#include +#include + +namespace chart +{ + +class ExplicitValueProvider; + +namespace impl +{ +class ImplObjectHierarchy; +} + +class ObjectHierarchy +{ +public: + typedef std::vector< ObjectIdentifier > tChildContainer; + + /** @param bFlattenDiagram + If , 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 css::uno::Reference< css::chart2::XChartDocument > & xChartDocument, + ExplicitValueProvider * pExplicitValueProvider, + bool bFlattenDiagram = false, + bool bOrderingForElementSelector = false ); + ~ObjectHierarchy(); + + static ObjectIdentifier getRootNodeOID(); + static bool isRootNode( const ObjectIdentifier& rOID ); + + /// equal to getChildren( getRootNodeOID()) + tChildContainer getTopLevelChildren() const; + bool hasChildren( const ObjectIdentifier& rParent ) const; + tChildContainer getChildren( const ObjectIdentifier& rParent ) 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: + + std::unique_ptr< impl::ImplObjectHierarchy > m_apImpl; +}; + +class ObjectKeyNavigation +{ +public: + explicit ObjectKeyNavigation( const ObjectIdentifier & rCurrentOID, + const css::uno::Reference< css::chart2::XChartDocument > & 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; + css::uno::Reference< css::chart2::XChartDocument > m_xChartDocument; + ExplicitValueProvider * m_pExplicitValueProvider; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_OBJECTHIERARCHY_HXX +#endif + +/* 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 000000000..ea0f7c4a7 --- /dev/null +++ b/chart2/source/controller/inc/ObjectNameProvider.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_OBJECTNAMEPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_OBJECTNAMEPROVIDER_HXX + +#include +#include + +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( const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + static OUString getGridName( const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + static OUString getTitleName( const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + static OUString getTitleNameByType( TitleHelper::eTitleType eType ); + + static OUString getNameForCID( + const OUString& rObjectCID, + const css::uno::Reference< css::chart2::XChartDocument >& xChartDocument ); + + static OUString getName_ObjectForSeries( + ObjectType eObjectType, + const OUString& rSeriesCID, + const css::uno::Reference< css::chart2::XChartDocument >& 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( const OUString& rObjectCID, const css::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel, bool bVerbose=false ); + static OUString getHelpText( const OUString& rObjectCID, const css::uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDocument ); + + /** This is used for showing the currently selected object in the status bar + (command "Context") + */ + static OUString getSelectedObjectText( const OUString & rObjectCID, const css::uno::Reference< css::chart2::XChartDocument >& xChartDocument ); +}; + +} //namespace chart +#endif + +/* 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 000000000..efe94648a --- /dev/null +++ b/chart2/source/controller/inc/PositionAndSizeHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_POSITIONANDSIZEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_POSITIONANDSIZEHELPER_HXX + +#include + +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( const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel + , const css::awt::Rectangle& rNewPositionAndSize + , const css::awt::Rectangle& rOldPositionAndSize + , const css::awt::Rectangle& rPageRectangle ); +}; + +} //namespace chart +#endif + +/* 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 000000000..e4669a044 --- /dev/null +++ b/chart2/source/controller/inc/RangeSelectionHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONHELPER_HXX + +#include +#include +#include + +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 RangeSelectionListenerParent; + +class RangeSelectionHelper +{ +public: + explicit RangeSelectionHelper( + const css::uno::Reference< css::chart2::XChartDocument > & 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; + + css::uno::Reference< css::chart2::XChartDocument > + m_xChartDocument; + + css::uno::Reference< css::sheet::XRangeSelectionListener > + m_xRangeSelectionListener; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONHELPER_HXX +#endif + +/* 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 000000000..6f6239a0e --- /dev/null +++ b/chart2/source/controller/inc/RangeSelectionListener.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONLISTENER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONLISTENER_HXX + +#include +#include +#include + +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class RangeSelectionListenerParent +{ +public: + virtual void listeningFinished( const OUString & rNewRange ) = 0; + virtual void disposingRangeSelection() = 0; + +protected: + ~RangeSelectionListenerParent() {} +}; + +class RangeSelectionListener : public + ::cppu::WeakImplHelper< + css::sheet::XRangeSelectionListener > +{ +public: + explicit RangeSelectionListener( + RangeSelectionListenerParent & rParent, + const OUString & rInitialRange, + const css::uno::Reference< css::frame::XModel >& 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RANGESELECTIONLISTENER_HXX +#endif + +/* 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 000000000..73e67900e --- /dev/null +++ b/chart2/source/controller/inc/RegressionCurveItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_REGRESSIONCURVEITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_REGRESSIONCURVEITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +namespace com::sun::star::chart2 { class XRegressionCurveContainer; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart +{ +namespace wrapper +{ + +class RegressionCurveItemConverter : public ItemConverter +{ +public: + RegressionCurveItemConverter( + const css::uno::Reference< css::beans::XPropertySet > & rPropertySet, + const css::uno::Reference< css::chart2::XRegressionCurveContainer > & 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 sal_uInt16 * 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::chart2::XRegressionCurveContainer > m_xCurveContainer; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_REGRESSIONCURVEITEMCONVERTER_HXX +#endif + +/* 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 000000000..237452f6f --- /dev/null +++ b/chart2/source/controller/inc/RegressionEquationItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_REGRESSIONEQUATIONITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_REGRESSIONEQUATIONITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +#include + +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 : 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 sal_uInt16 * 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 > m_aConverters; +}; + +} + +#endif + +/* 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 000000000..570fc60a5 --- /dev/null +++ b/chart2/source/controller/inc/SelectionHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_SELECTIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_SELECTIONHELPER_HXX + +#include "DrawViewWrapper.hxx" +#include + +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 css::uno::Reference< css::frame::XModel >& 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 : 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( const OUString& rCID + , const css::uno::Reference< css::frame::XModel >& 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 +#endif + +/* 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 000000000..2be1490ee --- /dev/null +++ b/chart2/source/controller/inc/SeriesOptionsItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_SERIESOPTIONSITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_SERIESOPTIONSITEMCONVERTER_HXX + +#include "ItemConverter.hxx" +#include + +namespace com::sun::star::chart2 { class XCoordinateSystem; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ +namespace wrapper +{ + +class SeriesOptionsItemConverter : public ItemConverter +{ +public: + SeriesOptionsItemConverter( + const css::uno::Reference< css::frame::XModel > & xChartModel, + const css::uno::Reference< css::uno::XComponentContext > & xContext, + const css::uno::Reference< css::beans::XPropertySet > & rPropertySet, + SfxItemPool& rItemPool ); + virtual ~SeriesOptionsItemConverter() override; + +protected: + virtual const sal_uInt16 * 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: + css::uno::Reference< css::frame::XModel > 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; + css::uno::Reference< css::chart2::XCoordinateSystem > m_xCooSys; + + css::uno::Sequence< sal_Int32 > m_aSupportedMissingValueTreatments; + sal_Int32 m_nMissingValueTreatment; + + bool m_bSupportingPlottingOfHiddenCells; + bool m_bIncludeHiddenCells; + + bool m_bHideLegendEntry; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_SERIESOPTIONSITEMCONVERTER_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/inc/ShapeController.h b/chart2/source/controller/inc/ShapeController.h new file mode 100644 index 000000000..392c28d2f --- /dev/null +++ b/chart2/source/controller/inc/ShapeController.h @@ -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 . + */ +#ifndef CHART_SHAPECONTROLLER_H +#define CHART_SHAPECONTROLLER_H + +//Command Ids: +#define COMMAND_ID_FORMAT_LINE 1 +#define COMMAND_ID_FORMAT_AREA 2 +#define COMMAND_ID_TEXT_ATTRIBUTES 3 +#define COMMAND_ID_TRANSFORM_DIALOG 4 +#define COMMAND_ID_OBJECT_TITLE_DESCRIPTION 5 +#define COMMAND_ID_RENAME_OBJECT 6 +#define COMMAND_ID_BRING_TO_FRONT 8 +#define COMMAND_ID_FORWARD 9 +#define COMMAND_ID_BACKWARD 10 +#define COMMAND_ID_SEND_TO_BACK 11 +#define COMMAND_ID_FONT_DIALOG 15 +#define COMMAND_ID_PARAGRAPH_DIALOG 16 + +#endif + +/* 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 000000000..00760488f --- /dev/null +++ b/chart2/source/controller/inc/StatisticsItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_STATISTICSITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_STATISTICSITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ +namespace wrapper +{ + +class StatisticsItemConverter : public ItemConverter +{ +public: + StatisticsItemConverter( + const css::uno::Reference< css::frame::XModel > & xChartModel, + const css::uno::Reference< css::beans::XPropertySet > & rPropertySet, + SfxItemPool& rItemPool ); + virtual ~StatisticsItemConverter() override; + +protected: + virtual const sal_uInt16 * 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: + css::uno::Reference< css::frame::XModel > m_xModel; +}; + +} // namespace wrapper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_STATISTICSITEMCONVERTER_HXX +#endif + +/* 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 000000000..d9ba55588 --- /dev/null +++ b/chart2/source/controller/inc/TabPageNotifiable.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TABPAGENOTIFIABLE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TABPAGENOTIFIABLE_HXX + +// 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 TabPageNotifiable +{ +public: + virtual void setInvalidPage( BuilderPage * pTabPage ) = 0; + virtual void setValidPage( BuilderPage * pTabPage ) = 0; + +protected: + ~TabPageNotifiable() {} +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TABPAGENOTIFIABLE_HXX +#endif + +/* 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 000000000..7db7d674e --- /dev/null +++ b/chart2/source/controller/inc/TextDirectionListBox.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TEXTDIRECTIONLISTBOX_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TEXTDIRECTIONLISTBOX_HXX + +#include + +namespace chart +{ + +class TextDirectionListBox : public svx::FrameDirectionListBox +{ +public: + explicit TextDirectionListBox(std::unique_ptr pControl); +}; + + +} //namespace chart + +#endif + +/* 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 000000000..9647793a8 --- /dev/null +++ b/chart2/source/controller/inc/TextLabelItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TEXTLABELITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TEXTLABELITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +#include + +#include + +namespace com::sun::star::awt { struct Size; } +namespace com::sun::star::chart2 { class XDataSeries; } +namespace com::sun::star::frame { class XModel; } + +namespace chart::wrapper { + +class TextLabelItemConverter : public ItemConverter +{ +public: + TextLabelItemConverter( + const css::uno::Reference& xChartModel, + const css::uno::Reference& rPropertySet, + const css::uno::Reference& 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 sal_uInt16* 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> maConverters; + sal_Int32 mnNumberFormat; + sal_Int32 mnPercentNumberFormat; + css::uno::Sequence maAvailableLabelPlacements; + + bool mbDataSeries:1; + bool mbForbidPercentValue:1; +}; + +} + +#endif + +/* 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 000000000..e8018ae43 --- /dev/null +++ b/chart2/source/controller/inc/TimerTriggeredControllerLock.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 +#include + +#include + +namespace com::sun::star::frame { class XModel; } +namespace chart { class ControllerLockGuardUNO; } + +namespace chart +{ + +class TimerTriggeredControllerLock final +{ +public: + TimerTriggeredControllerLock( const css::uno::Reference< css::frame::XModel >& xModel ); + ~TimerTriggeredControllerLock(); + + void startTimer(); + +private: + css::uno::Reference< css::frame::XModel > 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 000000000..d589dc65d --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TITLEDIALOGDATA_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TITLEDIALOGDATA_HXX + +#include +#include +#include + +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +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 pReferenzeSizeProvider = nullptr); + + void readFromModel( const css::uno::Reference< css::frame::XModel >& xChartModel ); + /* return true if anything has changed; + when pOldState is NULL then all data are written to the model + */ + bool writeDifferenceToModel( const css::uno::Reference< css::frame::XModel >& xChartModel + , const css::uno::Reference< css::uno::XComponentContext >& xContext + , TitleDialogData* pOldState=nullptr ); +}; + +} //namespace chart +#endif + +/* 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 000000000..59078b5e9 --- /dev/null +++ b/chart2/source/controller/inc/TitleItemConverter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TITLEITEMCONVERTER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_TITLEITEMCONVERTER_HXX + +#include "ItemConverter.hxx" + +#include + +namespace com::sun::star::awt { struct Size; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +class SdrModel; + +namespace chart::wrapper { + +class TitleItemConverter : public ItemConverter +{ +public: + TitleItemConverter( + const css::uno::Reference& rPropertySet, + SfxItemPool& rItemPool, SdrModel& rDrawModel, + const css::uno::Reference& 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 sal_uInt16 * 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 > m_aConverters; +}; + +} + +#endif + +/* 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 000000000..d8b8ffc42 --- /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 +#include + +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 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 000000000..64cab54b8 --- /dev/null +++ b/chart2/source/controller/inc/dlg_ChartType.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CHARTTYPE_HXX + +#include + +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class ChartTypeTabPage; +class ChartTypeDialog : public weld::GenericDialogController +{ +public: + ChartTypeDialog(weld::Window* pWindow, + const css::uno::Reference< css::frame::XModel >& xChartModel); + virtual ~ChartTypeDialog() override; + +private: + css::uno::Reference m_xChartModel; + std::unique_ptr m_xContentArea; + std::unique_ptr m_xChartTypeTabPage; +}; + +} //namespace chart + +#endif + +/* 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 000000000..bfa1ce433 --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CHARTTYPE_UNO_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CHARTTYPE_UNO_HXX + +#include +#include + +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::beans { class XPropertySetInfo; } + +namespace chart +{ +typedef ::svt::OGenericUnoDialog ChartTypeUnoDlg_BASE; +class ChartTypeUnoDlg : 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 createDialog(const css::uno::Reference& rParent) override; + + // XTypeProvider + virtual css::uno::Sequence SAL_CALL getImplementationId( ) override; + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence 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; + + css::uno::Reference< css::frame::XModel > m_xChartModel; +}; + +} //namespace chart +#endif + +/* 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 000000000..b44050eef --- /dev/null +++ b/chart2/source/controller/inc/dlg_CreationWizard.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CREATIONWIZARD_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CREATIONWIZARD_HXX + +#include "TimerTriggeredControllerLock.hxx" +#include "TabPageNotifiable.hxx" + +#include + +#include + +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::uno { class XComponentContext; } + +using vcl::WizardTypes::WizardState; +using vcl::WizardTypes::CommitPageReason; + +namespace chart +{ + +class DialogModel; +class ChartTypeTemplateProvider; + +class CreationWizard : public vcl::RoadmapWizardMachine, public TabPageNotifiable +{ +public: + CreationWizard(weld::Window* pParent, + const css::uno::Reference& xChartModel, + const css::uno::Reference& 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 createPage(WizardState nState) override; + + css::uno::Reference m_xChartModel; + css::uno::Reference m_xComponentContext; + ChartTypeTemplateProvider* m_pTemplateProvider; + std::unique_ptr m_pDialogModel; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + bool m_bCanTravel; +}; + +} //namespace chart + +#endif + +/* 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 000000000..2e27418de --- /dev/null +++ b/chart2/source/controller/inc/dlg_CreationWizard_UNO.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CREATIONWIZARD_UNO_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_CREATIONWIZARD_UNO_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlg_CreationWizard.hxx" +#include +#include +#include + +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 CreationWizardUnoDlg : public MutexContainer + , 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( const 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() throw () override; + virtual void SAL_CALL release() throw () 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& 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: + css::uno::Reference< css::frame::XModel > m_xChartModel; + css::uno::Reference< css::uno::XComponentContext> m_xCC; + css::uno::Reference< css::awt::XWindow > m_xParentWindow; + + std::shared_ptr m_xDialog; + bool m_bUnlockControllersOnExecute; +}; + +} //namespace chart +#endif + +/* 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 000000000..878dc9d9c --- /dev/null +++ b/chart2/source/controller/inc/dlg_DataEditor.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATAEDITOR_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATAEDITOR_HXX + +#include + +namespace com::sun::star::uno { class XComponentContext; } +namespace comphelper { template class mem_fun1_t; } + +namespace com::sun::star { + namespace chart2 { + class XChartDocument; + } +} + +namespace chart +{ + +class DataBrowser; + +class DataEditor : public weld::GenericDialogController +{ +public: + DataEditor(weld::Window* pParent, + const css::uno::Reference & xChartDoc, + const css::uno::Reference & xContext); + virtual ~DataEditor() override; + + DECL_LINK(CloseHdl, weld::Button&, void); + + void SetReadOnly( bool bReadOnly ); + +private: + bool m_bReadOnly; + + css::uno::Reference m_xChartDoc; + css::uno::Reference m_xContext; + + std::unique_ptr m_xTbxData; + std::unique_ptr m_xCloseBtn; + std::unique_ptr m_xTable; + std::unique_ptr m_xColumns; + std::unique_ptr m_xColors; + css::uno::Reference m_xTableCtrlParent; + VclPtr m_xBrwData; + + /// handles actions of the toolbox + DECL_LINK( ToolboxHdl, const OString&, void ); + /// is called, if the cursor of the table has moved + DECL_LINK( BrowserCursorMovedHdl, DataBrowser*, void); +}; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATAEDITOR_HXX + +/* 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 000000000..272fe1a81 --- /dev/null +++ b/chart2/source/controller/inc/dlg_DataSource.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATASOURCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATASOURCE_HXX + +#include + +#include "TabPageNotifiable.hxx" + +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::uno { class XComponentContext; } + +#include + +class BuilderPage; + +namespace chart +{ + +class RangeChooserTabPage; +class DataSourceTabPage; +class ChartTypeTemplateProvider; +class DialogModel; + +class DataSourceDialog final : + public weld::GenericDialogController, + public TabPageNotifiable +{ +public: + explicit DataSourceDialog( + weld::Window * pParent, + const css::uno::Reference< css::chart2::XChartDocument > & xChartDocument, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + 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 OString&, void); + DECL_LINK(DeactivatePageHdl, const OString&, bool); + + std::unique_ptr< ChartTypeTemplateProvider > m_apDocTemplateProvider; + std::unique_ptr< DialogModel > m_apDialogModel; + + std::unique_ptr m_xRangeChooserTabPage; + std::unique_ptr m_xDataSourceTabPage; + bool m_bRangeChooserTabIsValid; + bool m_bDataSourceTabIsValid; + bool m_bTogglingEnabled; + + std::unique_ptr m_xTabControl; + std::unique_ptr m_xBtnOK; + + static sal_uInt16 m_nLastPageId; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_DATASOURCE_HXX +#endif + +/* 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 000000000..14e3c6669 --- /dev/null +++ b/chart2/source/controller/inc/dlg_InsertAxis_Grid.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTAXIS_GRID_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTAXIS_GRID_HXX + +#include +#include + +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 +{ +protected: + std::unique_ptr m_xCbPrimaryX; + std::unique_ptr m_xCbPrimaryY; + std::unique_ptr m_xCbPrimaryZ; + std::unique_ptr m_xCbSecondaryX; + std::unique_ptr m_xCbSecondaryY; + std::unique_ptr m_xCbSecondaryZ; + +public: + SchAxisDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput, bool bAxisDlg = true); + void getResult( InsertAxisOrGridDialogData& rOutput ); +}; + +/************************************************************************* +|* +|* Grid dialog +|* +\************************************************************************/ +class SchGridDlg : public SchAxisDlg +{ +public: + SchGridDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput); +}; + +} //namespace chart + +#endif + +/* 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 000000000..c39d608d1 --- /dev/null +++ b/chart2/source/controller/inc/dlg_InsertDataLabel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTDATALABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTDATALABEL_HXX + +#include +#include +#include + +class SvNumberFormatter; + +namespace chart +{ +class DataLabelResources; + +class DataLabelsDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_apDataLabelResources; + +public: + DataLabelsDialog(weld::Window* pParent, const SfxItemSet& rInAttrs, + SvNumberFormatter* pFormatter); + virtual ~DataLabelsDialog() override; + + void FillItemSet(SfxItemSet& rOutAttrs); +}; + +} //namespace chart + +#endif + +/* 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 000000000..60cbaac65 --- /dev/null +++ b/chart2/source/controller/inc/dlg_InsertErrorBars.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTERRORBARS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTERRORBARS_HXX + +#include +#include +#include + +#include "res_ErrorBar.hxx" + +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class InsertErrorBarsDialog : public weld::GenericDialogController +{ +public: + InsertErrorBarsDialog(weld::Window* pParent, const SfxItemSet& rMyAttrs, + const css::uno::Reference< css::chart2::XChartDocument > & xChartDocument, + ErrorBarResources::tErrorBarType eType); + + void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ); + + static double getAxisMinorStepWidthForErrorBarDecimals( + const css::uno::Reference< css::frame::XModel >& xChartModel, + const css::uno::Reference< css::uno::XInterface >& xChartView, + const OUString& rSelectedObjectCID ); + + void FillItemSet( SfxItemSet& rOutAttrs ); + +private: + std::unique_ptr< ErrorBarResources > m_apErrorBarResources; +}; + +} //namespace chart + +#endif + +/* 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 000000000..41605db73 --- /dev/null +++ b/chart2/source/controller/inc/dlg_InsertLegend.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTLEGEND_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTLEGEND_HXX + +#include + +#include + +#include "res_LegendPosition.hxx" + +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +class SchLegendDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xLegendPositionResources; + +public: + SchLegendDlg(weld::Window* pParent, const css::uno::Reference< css::uno::XComponentContext>& xCC); + + void init( const css::uno::Reference< css::frame::XModel >& xChartModel ); + void writeToModel( const css::uno::Reference< css::frame::XModel >& xChartModel ) const; +}; + +} //namespace chart + +#endif + +/* 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 000000000..7eea6f2bb --- /dev/null +++ b/chart2/source/controller/inc/dlg_InsertTitle.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTTITLE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_INSERTTITLE_HXX + +#include "res_Titles.hxx" +#include +#include + +namespace chart +{ +class SchTitleDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xTitleResources; + +public: + SchTitleDlg(weld::Window* pParent, const TitleDialogData& rInput); + + void getResult(TitleDialogData& rOutput); +}; + +} //namespace chart + +#endif + +/* 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 000000000..78a13838b --- /dev/null +++ b/chart2/source/controller/inc/dlg_ObjectProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_OBJECTPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_OBJECTPROPERTIES_HXX + +#include +#include + +namespace com::sun::star::util { class XNumberFormatsSupplier; } +class Graphic; + +namespace chart +{ + +class ObjectPropertiesDialogParameter final +{ +public: + ObjectPropertiesDialogParameter( const OUString& rObjectCID ); + ~ObjectPropertiesDialogParameter(); + + void init( const css::uno::Reference< css::frame::XModel >& 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 css::uno::Reference< css::chart2::XChartDocument >& + 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; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartDocument; + + bool m_bComplexCategoriesAxis; + + sal_Int32 m_nNbPoints; +}; + +/************************************************************************* +|* +|* dialog for properties of different chart object +|* +\************************************************************************/ + +class ViewElementListProvider; + +class SchAttribTabDlg : public SfxTabDialogController +{ +private: + const ObjectPropertiesDialogParameter * const m_pParameter; + const ViewElementListProvider* const m_pViewElementListProvider; + SvNumberFormatter* m_pNumberFormatter; + + std::unique_ptr m_pSymbolShapeProperties; + std::unique_ptr m_pAutoSymbolGraphic; + + double m_fAxisMinorStepWidthForErrorBarDecimals; + bool m_bOKPressed; + + DECL_LINK(OKPressed, weld::Button&, void); + + virtual void PageCreated(const OString& 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( std::unique_ptr pSymbolShapeProperties, std::unique_ptr pAutoSymbolGraphic ); + + void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ); + + bool DialogWasClosedWithOK() const { return m_bOKPressed;} +}; + +} //namespace chart + +#endif + +/* 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 000000000..5429b8449 --- /dev/null +++ b/chart2/source/controller/inc/dlg_ShapeFont.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEFONT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEFONT_HXX + +#include + +namespace chart +{ +class ViewElementListProvider; + +/** dialog for font properties of shapes + */ +class ShapeFontDialog : public SfxTabDialogController +{ +public: + ShapeFontDialog(weld::Window* pParent, const SfxItemSet* pAttr, + const ViewElementListProvider* pViewElementListProvider); + +private: + virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override; + + const ViewElementListProvider* m_pViewElementListProvider; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEFONT_HXX +#endif + +/* 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 000000000..6e214dfbc --- /dev/null +++ b/chart2/source/controller/inc/dlg_ShapeParagraph.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEPARAGRAPH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEPARAGRAPH_HXX + +#include + +namespace chart +{ +/** dialog for paragraph properties of shapes + */ +class ShapeParagraphDialog : public SfxTabDialogController +{ +public: + ShapeParagraphDialog(weld::Window* pParent, const SfxItemSet* pAttr); + +private: + virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_SHAPEPARAGRAPH_HXX +#endif + +/* 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 000000000..ad5466e49 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_VIEW3D_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_DLG_VIEW3D_HXX + +#include +#include + +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ +class ThreeD_SceneGeometry_TabPage; +class ThreeD_SceneAppearance_TabPage; +class ThreeD_SceneIllumination_TabPage; + +class View3DDialog : public weld::GenericDialogController +{ +public: + View3DDialog(weld::Window* pWindow, const css::uno::Reference & xChartModel); + virtual ~View3DDialog() override; + + virtual short run() override; + +private: + DECL_LINK(ActivatePageHdl, const OString&, void); + + ControllerLockHelper m_aControllerLocker; + + static sal_uInt16 m_nLastPageId; + + std::unique_ptr m_xTabControl; + std::unique_ptr m_xGeometry; + std::unique_ptr m_xAppearance; + std::unique_ptr m_xIllumination; +}; + +} //namespace chart + +#endif + +/* 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 000000000..2867867d6 --- /dev/null +++ b/chart2/source/controller/inc/helpids.h @@ -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 . + */ + +#ifndef CHART_HELPIDS_H +#define CHART_HELPIDS_H + +#define HID_SCH_WIN_DOCUMENT "CHART2_HID_SCH_WIN_DOCUMENT" +#define HID_SCH_ERROR_BARS_FROM_DATA "CHART2_SCH_ERROR_BARS_FROM_DATA" + + + +#define HID_SCH_WIZARD_ROADMAP "CHART2_HID_SCH_WIZARD_ROADMAP" +#define HID_SCH_DATA_SERIES_LABEL "CHART2_HID_SCH_DATA_SERIES_LABEL" + + +#endif + +/* 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 000000000..0514855a2 --- /dev/null +++ b/chart2/source/controller/inc/res_ErrorBar.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_ERRORBAR_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_ERRORBAR_HXX + +#include +#include +#include +#include +#include "RangeSelectionListener.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 ToggleButton; } +namespace weld { class Widget; } + +namespace chart +{ + +class RangeSelectionHelper; + +class ErrorBarResources : 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 css::uno::Reference< css::chart2::XChartDocument > & 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 m_xRbNone; + std::unique_ptr m_xRbConst; + std::unique_ptr m_xRbPercent; + std::unique_ptr m_xRbFunction; + std::unique_ptr m_xRbRange; + std::unique_ptr m_xLbFunction; + + // parameters + std::unique_ptr m_xFlParameters; + std::unique_ptr m_xBxPositive; + std::unique_ptr m_xMfPositive; + std::unique_ptr m_xEdRangePositive; + std::unique_ptr m_xIbRangePositive; + std::unique_ptr m_xBxNegative; + std::unique_ptr m_xMfNegative; + std::unique_ptr m_xEdRangeNegative; + std::unique_ptr m_xIbRangeNegative; + std::unique_ptr m_xCbSyncPosNeg; + + // indicator + std::unique_ptr m_xRbBoth; + std::unique_ptr m_xRbPositive; + std::unique_ptr m_xRbNegative; + std::unique_ptr m_xFiBoth; + std::unique_ptr m_xFiPositive; + std::unique_ptr m_xFiNegative; + + std::unique_ptr m_xUIStringPos; + std::unique_ptr m_xUIStringNeg; + std::unique_ptr m_xUIStringRbRange; + + DECL_LINK( CategoryChosen, weld::ToggleButton&, void ); + DECL_LINK( CategoryChosen2, weld::ComboBox&, void ); + DECL_LINK( SynchronizePosAndNeg, weld::ToggleButton&, void ); + DECL_LINK( PosValueChanged, weld::MetricSpinButton&, void ); + DECL_LINK( IndicatorChanged, weld::ToggleButton&, void ); + DECL_LINK( ChooseRange, weld::Button&, void ); + DECL_LINK( RangeChanged, weld::Entry&, void ); + + void UpdateControlStates(); + void isRangeFieldContentValid(weld::Entry& rEdit); +}; + +} //namespace chart + +#endif + +/* 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 000000000..3701225b6 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_LEGENDPOSITION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_LEGENDPOSITION_HXX + +#include +#include + +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 ToggleButton; } + +namespace chart +{ + +class LegendPositionResources final +{ + +public: + //constructor without Display checkbox + LegendPositionResources(weld::Builder& rBuilder); + //constructor inclusive Display checkbox + LegendPositionResources(weld::Builder& rBuilder, const css::uno::Reference< + css::uno::XComponentContext>& xCC ); + ~LegendPositionResources(); + + void writeToResources( const css::uno::Reference< css::frame::XModel >& xChartModel ); + void writeToModel( const css::uno::Reference< css::frame::XModel >& xChartModel ) const; + + void initFromItemSet( const SfxItemSet& rInAttrs ); + void writeToItemSet( SfxItemSet& rOutAttrs ) const; + + void SetChangeHdl( const Link& rLink ); + + DECL_LINK( PositionEnableHdl, weld::ToggleButton&, void ); + DECL_LINK( PositionChangeHdl, weld::ToggleButton&, void ); + +private: + void impl_setRadioButtonToggleHdl(); + +private: + css::uno::Reference< css::uno::XComponentContext> m_xCC; + Link m_aChangeLink; + + std::unique_ptr m_xCbxShow; + std::unique_ptr m_xRbtLeft; + std::unique_ptr m_xRbtRight; + std::unique_ptr m_xRbtTop; + std::unique_ptr m_xRbtBottom; +}; + +} //namespace chart + +#endif + +/* 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 000000000..f18c99b5b --- /dev/null +++ b/chart2/source/controller/inc/res_Titles.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_TITLES_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_INC_RES_TITLES_HXX + +#include "TitleDialogData.hxx" + +template 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& rLink ); + bool get_value_changed_from_saved() const; + void save_value(); + +private: + std::unique_ptr m_xFT_Main; + std::unique_ptr m_xFT_Sub; + std::unique_ptr m_xEd_Main; + std::unique_ptr m_xEd_Sub; + + std::unique_ptr m_xFT_XAxis; + std::unique_ptr m_xFT_YAxis; + std::unique_ptr m_xFT_ZAxis; + std::unique_ptr m_xEd_XAxis; + std::unique_ptr m_xEd_YAxis; + std::unique_ptr m_xEd_ZAxis; + + std::unique_ptr m_xFT_SecondaryXAxis; + std::unique_ptr m_xFT_SecondaryYAxis; + std::unique_ptr m_xEd_SecondaryXAxis; + std::unique_ptr m_xEd_SecondaryYAxis; +}; + +} //namespace chart + +#endif + +/* 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 000000000..01dc8b500 --- /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 +#include + +#include "ChartWindow.hxx" + +class ChartUIObject : public UIObject +{ +public: + + ChartUIObject(const VclPtr& xChartWindow, + const OUString& rCID); + + StringMap get_state() override; + + virtual void execute(const OUString& rAction, + const StringMap& rParameters) override; + + virtual std::unique_ptr get_child(const OUString& rID) override; + + virtual std::set get_children() const override; + + virtual OUString get_type() const override; + +private: + + OUString maCID; + VclPtr mxChartWindow; + std::vector> maCommands; + + DECL_LINK(PostCommand, void*, void); +}; + +class ChartWindowUIObject : public WindowUIObject +{ + VclPtr mxChartWindow; + +public: + + ChartWindowUIObject(const VclPtr& xChartWindow); + + virtual StringMap get_state() override; + + virtual void execute(const OUString& rAction, + const StringMap& rParameters) override; + + virtual std::unique_ptr get_child(const OUString& rID) override; + + virtual std::set get_children() const override; + + static std::unique_ptr 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 000000000..62078d4a8 --- /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 +#include +#include +#include +#include +#include +#include +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 Reference< chart2::XChartDocument > & xChartDoc, + ::chart::ExplicitScaleData const * pScale /* = NULL */, + ::chart::ExplicitIncrementData const * pIncrement /* = NULL */, + const awt::Size* pRefSize ) : + ItemConverter( rPropertySet, rItemPool ), + m_xChartDoc( xChartDoc ) +{ + Reference< lang::XMultiServiceFactory > xNamedPropertyContainerFactory( xChartDoc, uno::UNO_QUERY ); + + 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, + xNamedPropertyContainerFactory, + GraphicObjectType::LineProperties )); + m_aConverters.emplace_back( + new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize")); + + m_xAxis.set( Reference< chart2::XAxis >( rPropertySet, uno::UNO_QUERY ) ); + OSL_ASSERT( m_xAxis.is()); +} + +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 sal_uInt16 * 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, nWhichId ) ); + else + { + if( m_pExplicitScale ) + fMax = m_pExplicitScale->Maximum; + rOutItemSet.Put( SvxDoubleItem( fMax, nWhichId ) ); + } + } + 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, nWhichId ) ); + else if( m_pExplicitScale ) + rOutItemSet.Put( SvxDoubleItem( m_pExplicitScale->Minimum, nWhichId )); + } + 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, nWhichId )); + else if( m_pExplicitIncrement ) + rOutItemSet.Put( SvxDoubleItem( m_pExplicitIncrement->MajorTimeInterval.Number, nWhichId )); + } + else + { + double fDistance = 1.0; + if( rIncrement.Distance >>= fDistance ) + rOutItemSet.Put( SvxDoubleItem(fDistance, nWhichId )); + else if( m_pExplicitIncrement ) + rOutItemSet.Put( SvxDoubleItem( m_pExplicitIncrement->Distance, nWhichId )); + } + 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( + 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: + { + long 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, nWhichId )); + } + break; + + case SCHATTR_AXIS_POSITION: + { + css::chart::ChartAxisPosition eAxisPos( css::chart::ChartAxisPosition_ZERO ); + GetPropertySet()->getPropertyValue( "CrossoverPosition" ) >>= eAxisPos; + rOutItemSet.Put( SfxInt32Item( nWhichId, static_cast(eAxisPos) ) ); + } + break; + + case SCHATTR_AXIS_POSITION_VALUE: + { + double fValue = 0.0; + if( GetPropertySet()->getPropertyValue( "CrossoverValue" ) >>= fValue ) + rOutItemSet.Put( SvxDoubleItem( fValue, nWhichId ) ); + } + break; + + case SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT: + { + //read only item + //necessary tp display the crossing value with an appropriate format + + Reference< chart2::XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( + m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + + Reference< chart2::XAxis > 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(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(ePos) ) ); + } + break; + + case SCHATTR_TEXT_DEGREES: + { + // convert double to int (times 100) + double fVal = 0; + + if( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fVal ) + { + rOutItemSet.Put( SfxInt32Item( nWhichId, static_cast< sal_Int32 >( + ::rtl::math::round( fVal * 100.0 ) ) )); + } + } + break; + + case SID_ATTR_NUMBERFORMAT_VALUE: + { + if( m_pExplicitScale ) + { + Reference< chart2::XCoordinateSystem > xCooSys( + AxisHelper::getCoordinateSystemOfAxis( + m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + + 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: + { + Reference< chart2::XCoordinateSystem > xCooSys( + AxisHelper::getCoordinateSystemOfAxis( m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + 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(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[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[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 + Reference< chart2::XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( + m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + + sal_Int32 nDimensionIndex=0; + sal_Int32 nAxisIndex=0; + if( AxisHelper::getIndicesForAxis( m_xAxis, xCooSys, nDimensionIndex, nAxisIndex ) && nAxisIndex==0 ) + { + Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( m_xAxis, xCooSys ), uno::UNO_QUERY ); + 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(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 ) + { + Reference< beans::XPropertySet > xParallelAxis( AxisHelper::getParallelAxis( m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ), uno::UNO_QUERY ); + 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 + { + Reference< chart2::XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( + m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + + 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 (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(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 ) + { + Reference< beans::XPropertySet > xParallelAxis( AxisHelper::getParallelAxis( m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ), uno::UNO_QUERY ); + 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(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: + { + // convert int to double (divided by 100) + double fVal = static_cast< double >( + static_cast< const SfxInt32Item & >( + rItemSet.Get( nWhichId )).GetValue()) / 100.0; + 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 = + static_cast< const SfxBoolItem & >( + 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 + { + Reference< chart2::XCoordinateSystem > xCooSys( + AxisHelper::getCoordinateSystemOfAxis( + m_xAxis, ChartModelHelper::findDiagram( m_xChartDoc ) ) ); + + 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 000000000..49945b2f5 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx @@ -0,0 +1,556 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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, + const OUString & rRefSizePropertyName, + const uno::Reference< beans::XPropertySet > & rRefSizePropSet ) : + ItemConverter( rPropertySet, rItemPool ), + m_aRefSizePropertyName( rRefSizePropertyName ), + m_xRefSizePropSet( rRefSizePropSet.is() ? rRefSizePropSet : rPropertySet ) +{ + if (pRefSize) + m_pRefSize = *pRefSize; +} + +CharacterPropertyItemConverter::~CharacterPropertyItemConverter() +{} + +const sal_uInt16 * 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(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(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& 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 000000000..4920d2b72 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx @@ -0,0 +1,782 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "SchWhichPairs.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +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) ? OUString(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 ) + { + Reference< chart2::XDataSeries > xSeries( xPropertySet, uno::UNO_QUERY); + 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) ? OUString(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 ) + { + Reference< chart2::XDataSeries > xSeries( xPropertySet, uno::UNO_QUERY); + 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 uno::Reference< frame::XModel > & xChartModel, + const uno::Reference< uno::XComponentContext > & xContext, + const uno::Reference< beans::XPropertySet > & rPropertySet, + const uno::Reference< XDataSeries > & xSeries, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const uno::Reference& 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(nSpecialFillColor), + m_nNumberFormat(nNumberFormat), + m_nPercentNumberFormat(nPercentNumberFormat), + m_aAvailableLabelPlacements(), + 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 ) + { + m_aConverters.emplace_back( new StatisticsItemConverter( xChartModel, rPropertySet, rItemPool )); + m_aConverters.emplace_back( new SeriesOptionsItemConverter( xChartModel, xContext, rPropertySet, rItemPool )); + } + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram(xChartModel) ); + uno::Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram , xSeries ) ); + bool bFound = false; + bool bAmbiguous = false; + bool bSwapXAndY = DiagramHelper::getVertical( xDiagram, bFound, bAmbiguous ); + m_aAvailableLabelPlacements = ChartTypeHelper::getSupportedLabelPlacements( xChartType, bSwapXAndY, xSeries ); + + m_bForbidPercentValue = ChartTypeHelper::getAxisType( xChartType, 0 ) != AxisType::CATEGORY; + + if (bDataSeries) + return; + + uno::Reference xSeriesProp(xSeries, uno::UNO_QUERY); + uno::Sequence deletedLegendEntriesSeq; + xSeriesProp->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq; + for (auto& deletedLegendEntry : 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 sal_uInt16 * 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_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 : aLabel.ShowLegendSymbol )); + bool bOldValue = rValue; + rValue = rItem.GetValue(); + if( m_bOverwriteLabelsForAttributedDataPointsAlso ) + { + Reference< chart2::XDataSeries > xSeries( GetPropertySet(), uno::UNO_QUERY); + if( bOldValue != bool(rValue) || + DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, CHART_UNONAME_LABEL , aOldValue ) ) + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_LABEL , uno::Any( aLabel ) ); + 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(); + OUString aOldValue; + try + { + GetPropertySet()->getPropertyValue( "LabelSeparator" ) >>= aOldValue; + if( m_bOverwriteLabelsForAttributedDataPointsAlso ) + { + Reference< chart2::XDataSeries > xSeries( GetPropertySet(), uno::UNO_QUERY); + 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 ) + { + Reference< chart2::XDataSeries > xSeries( GetPropertySet(), uno::UNO_QUERY); + 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 ) + { + Reference< chart2::XDataSeries > xSeries( GetPropertySet(), uno::UNO_QUERY); + 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 = static_cast< double >( + static_cast< const SfxInt32Item & >( + rItemSet.Get( nWhichId )).GetValue()) / 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_HIDE_DATA_POINT_LEGEND_ENTRY: + { + bool bHideLegendEntry = static_cast(rItemSet.Get(nWhichId)).GetValue(); + if (bHideLegendEntry != m_bHideLegendEntry) + { + uno::Sequence deletedLegendEntriesSeq; + Reference xSeriesProp(m_xSeries, uno::UNO_QUERY); + xSeriesProp->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq; + std::vector deletedLegendEntries; + for (auto& deletedLegendEntry : deletedLegendEntriesSeq) + { + if (bHideLegendEntry || m_nPointIndex != deletedLegendEntry) + deletedLegendEntries.push_back(deletedLegendEntry); + } + if (bHideLegendEntry) + deletedLegendEntries.push_back(m_nPointIndex); + xSeriesProp->setPropertyValue("DeletedLegendEntries", uno::makeAny(oox::ContainerHelper::vectorToSequence(deletedLegendEntries))); + } + } + 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_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 : aLabel.ShowLegendSymbol )); + + rOutItemSet.Put( SfxBoolItem( nWhichId, bValue )); + + if( m_bOverwriteLabelsForAttributedDataPointsAlso ) + { + if( DataSeriesHelper::hasAttributedDataPointDifferentValue( + Reference< chart2::XDataSeries >( GetPropertySet(), uno::UNO_QUERY), 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: + { + OUString aValue; + try + { + 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_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( SfxInt32Item( nWhichId, 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/ErrorBarItemConverter.cxx b/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx new file mode 100644 index 000000000..5a8114c21 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx @@ -0,0 +1,433 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "SchWhichPairs.hxx" +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +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( + const 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( + rPropertySet, rItemPool, rDrawModel, + xNamedPropertyContainerFactory, + GraphicObjectType::LineProperties )), + m_xModel( 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 sal_uInt16 * 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, nWhichId )); + } + break; + + case SCHATTR_STAT_BIGERROR: + { + double fPos(0.0), fNeg(0.0); + lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); + rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId )); + } + break; + + case SCHATTR_STAT_CONSTPLUS: + { + double fPos(0.0), fNeg(0.0); + lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); + rOutItemSet.Put( SvxDoubleItem( fPos, nWhichId )); + } + break; + + case SCHATTR_STAT_CONSTMINUS: + { + double fPos(0.0), fNeg(0.0); + lcl_getErrorValues( GetPropertySet(), fPos, fNeg ); + rOutItemSet.Put( SvxDoubleItem( fNeg, nWhichId )); + } + 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 000000000..55e954e94 --- /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 +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, + const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory, + GraphicObjectType eObjectType /* = FILL_PROPERTIES */ ) : + ItemConverter( rPropertySet, rItemPool ), + m_GraphicObjectType( eObjectType ), + m_rDrawModel( rDrawModel ), + m_xNamedPropertyTableFactory( xNamedPropertyContainerFactory ) +{} + +GraphicPropertyItemConverter::~GraphicPropertyItemConverter() +{} + +const sal_uInt16 * GraphicPropertyItemConverter::GetWhichPairs() const +{ + const sal_uInt16 * pResult = nullptr; + + switch( m_GraphicObjectType ) + { + case GraphicObjectType::LineDataPoint: + case GraphicObjectType::FilledDataPoint: + pResult = nRowWhichPairs; break; + case GraphicObjectType::LineProperties: + pResult = nLinePropertyWhichPairs; break; + case GraphicObjectType::LineAndFillProperties: + pResult = nLineAndFillPropertyWhichPairs; break; + } + + return pResult; +} + +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 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 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 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 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 )) + { + const OUString aModePropName("FillBitmapMode"); + 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 )) + { + const OUString aModePropName("FillBitmapMode"); + 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::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::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 000000000..a99d848d0 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace chart::wrapper { + +ItemConverter::ItemConverter( + const uno::Reference< beans::XPropertySet > & rPropertySet, + SfxItemPool& rItemPool ) : + m_xPropertySet( rPropertySet ), + 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 sal_uInt16 * pRanges = rOutItemSet.GetRanges(); + tPropertyNameWithMemberId aProperty; + SfxItemPool & rPool = GetItemPool(); + + assert(pRanges != nullptr); + OSL_ASSERT( m_xPropertySetInfo.is()); + OSL_ASSERT( m_xPropertySet.is()); + + while( (*pRanges) != 0) + { + sal_uInt16 nBeg = *pRanges; + ++pRanges; + sal_uInt16 nEnd = *pRanges; + ++pRanges; + + 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 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( rItemSet.GetItemState( pItem->Which(), 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) + { + if ((rSourceSet.GetItemState(nWhich, true, &pPoolItem) == 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( rSourceSet.GetItemState(nWhich, true, &pPoolItem) == 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 000000000..9ae14be68 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/LegendItemConverter.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 +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +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 sal_uInt16 * 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: + { + const SfxPoolItem* pPoolItem = nullptr; + if( rInItemSet.GetItemState( SCHATTR_LEGEND_SHOW, true, &pPoolItem ) == SfxItemState::SET ) + { + bool bShow = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + bool bWasShown = true; + if( ! (GetPropertySet()->getPropertyValue( "Show" ) >>= bWasShown) || + ( bWasShown != bShow )) + { + GetPropertySet()->setPropertyValue( "Show" , uno::Any( bShow )); + bChanged = true; + } + } + + } + break; + case SCHATTR_LEGEND_POS: + { + const SfxPoolItem* pPoolItem = nullptr; + if( rInItemSet.GetItemState( SCHATTR_LEGEND_POS, true, &pPoolItem ) == SfxItemState::SET ) + { + chart2::LegendPosition eNewPos = static_cast(static_cast(pPoolItem)->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: + { + const SfxPoolItem* pPoolItem = nullptr; + if(rInItemSet.GetItemState(SCHATTR_LEGEND_NO_OVERLAY, true, &pPoolItem) == SfxItemState::SET) + { + bool bOverlay = !static_cast(pPoolItem)->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(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 000000000..8351e5bf0 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 uno::Reference< frame::XModel > & xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const awt::Size* pRefSize ) + : MultipleItemConverter( rItemPool ) +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + const Sequence< Reference< XAxis > > aElementList( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( Reference< XAxis > const & axis : aElementList ) + { + uno::Reference< beans::XPropertySet > xObjectProperties(axis, uno::UNO_QUERY); + m_aConverters.emplace_back( new ::chart::wrapper::AxisItemConverter( + xObjectProperties, rItemPool, rDrawModel, + uno::Reference< chart2::XChartDocument >( xChartModel, uno::UNO_QUERY ), nullptr, nullptr, + pRefSize)); + } +} + +AllAxisItemConverter::~AllAxisItemConverter() +{ +} + +const sal_uInt16 * AllAxisItemConverter::GetWhichPairs() const +{ + // must span all used items! + return nAllAxisWhichPairs; +} + +AllGridItemConverter::AllGridItemConverter( + const uno::Reference< frame::XModel > & xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) + : MultipleItemConverter( rItemPool ) +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + const Sequence< Reference< beans::XPropertySet > > aElementList( AxisHelper::getAllGrids( xDiagram ) ); + for( Reference< beans::XPropertySet > const & xObjectProperties : aElementList ) + { + m_aConverters.emplace_back( new ::chart::wrapper::GraphicPropertyItemConverter( + xObjectProperties, rItemPool, rDrawModel, xNamedPropertyContainerFactory, + ::chart::wrapper::GraphicObjectType::LineProperties ) ); + } +} + +AllGridItemConverter::~AllGridItemConverter() +{ +} + +const sal_uInt16 * AllGridItemConverter::GetWhichPairs() const +{ + // must span all used items! + return nGridWhichPairs; +} + +AllDataLabelItemConverter::AllDataLabelItemConverter( + const uno::Reference< frame::XModel > & xChartModel, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) + : MultipleItemConverter( rItemPool ) +{ + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesList( + ::chart::ChartModelHelper::getDataSeries( xChartModel )); + + for (auto const& series : aSeriesList) + { + uno::Reference< beans::XPropertySet > xObjectProperties(series, uno::UNO_QUERY); + uno::Reference< uno::XComponentContext> xContext;//do not need Context for label properties + + sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties ); + sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( + xObjectProperties,uno::Reference< util::XNumberFormatsSupplier >(xChartModel, uno::UNO_QUERY)); + + m_aConverters.emplace_back( + new ::chart::wrapper::DataPointItemConverter( + xChartModel, xContext, xObjectProperties, series, rItemPool, rDrawModel, + xNamedPropertyContainerFactory, GraphicObjectType::FilledDataPoint, + nullptr, true, false, 0, true, nNumberFormat, nPercentNumberFormat)); + } +} + +AllDataLabelItemConverter::~AllDataLabelItemConverter() +{ +} + +const sal_uInt16 * AllDataLabelItemConverter::GetWhichPairs() const +{ + // must span all used items! + return nDataLabelWhichPairs; +} + +AllTitleItemConverter::AllTitleItemConverter( + const uno::Reference< frame::XModel > & 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++ ) + { + uno::Reference< chart2::XTitle > xTitle( TitleHelper::getTitle( TitleHelper::eTitleType(nTitle), xChartModel ) ); + if(!xTitle.is()) + continue; + uno::Reference< beans::XPropertySet > xObjectProperties( xTitle, uno::UNO_QUERY); + m_aConverters.emplace_back( + new ::chart::wrapper::TitleItemConverter( + xObjectProperties, rItemPool, rDrawModel, xNamedPropertyContainerFactory, nullptr)); + } +} + +AllTitleItemConverter::~AllTitleItemConverter() +{ +} + +const sal_uInt16 * AllTitleItemConverter::GetWhichPairs() const +{ + // must span all used items! + return nTitleWhichPairs; +} + +AllSeriesStatisticsConverter::AllSeriesStatisticsConverter( + const uno::Reference< frame::XModel > & xChartModel, + SfxItemPool& rItemPool ) + : MultipleItemConverter( rItemPool ) +{ + std::vector< uno::Reference< chart2::XDataSeries > > aSeriesList( + ::chart::ChartModelHelper::getDataSeries( xChartModel )); + + for (auto const& series : aSeriesList) + { + uno::Reference< beans::XPropertySet > xObjectProperties(series, uno::UNO_QUERY); + m_aConverters.emplace_back( new ::chart::wrapper::StatisticsItemConverter( + xChartModel, xObjectProperties, rItemPool )); + } +} + +AllSeriesStatisticsConverter::~AllSeriesStatisticsConverter() +{} + +const sal_uInt16 * 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 000000000..5937575cc --- /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 + +#include + +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 000000000..8859158ac --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "SchWhichPairs.hxx" +#include + +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +template +bool lclConvertToPropertySet(const SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + T aValue = static_cast(static_cast(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 +void lclConvertToItemSet(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + T aValue = static_cast(static_cast(rItemSet.Get( nWhichId )).GetValue()); + if(xProperties->getPropertyValue( aPropertyID ) >>= aValue) + { + rItemSet.Put(D( nWhichId, aValue )); + } + } +} + +void lclConvertToItemSetDouble(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + double aValue = static_cast(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, + const uno::Reference< chart2::XRegressionCurveContainer >& xContainer, + SfxItemPool& rItemPool, + SdrModel& rDrawModel, + const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) : + ItemConverter( rPropertySet, rItemPool ), + m_spGraphicConverter( std::make_shared( + rPropertySet, rItemPool, rDrawModel, + xNamedPropertyContainerFactory, + GraphicObjectType::LineProperties )), + m_xCurveContainer( 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 sal_uInt16 * 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 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(rItemSet, nWhichId, xProperties, "PolynomialDegree"); + } + break; + + case SCHATTR_REGRESSION_PERIOD: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "MovingAveragePeriod"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ExtrapolateForward"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ExtrapolateBackward"); + } + break; + + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ForceIntercept"); + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "InterceptValue"); + } + break; + + case SCHATTR_REGRESSION_CURVE_NAME: + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "CurveName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_EQUATION: + { + uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "ShowEquation"); + } + break; + + case SCHATTR_REGRESSION_XNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "XName"); + } + break; + + case SCHATTR_REGRESSION_YNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "YName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_COEFF: + { + uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "ShowCorrelationCoefficient"); + } + break; + + } + return bChanged; +} + +void RegressionCurveItemConverter::FillSpecialItem(sal_uInt16 nWhichId, SfxItemSet& rOutItemSet ) const +{ + uno::Reference 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(rOutItemSet, nWhichId, xProperties, "PolynomialDegree"); + } + break; + + case SCHATTR_REGRESSION_PERIOD: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "MovingAveragePeriod"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD: + { + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "ExtrapolateForward"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD: + { + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "ExtrapolateBackward"); + } + break; + + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "ForceIntercept"); + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "InterceptValue"); + } + break; + + case SCHATTR_REGRESSION_CURVE_NAME: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "CurveName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_EQUATION: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "ShowEquation"); + } + break; + + case SCHATTR_REGRESSION_XNAME: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "XName"); + } + break; + + case SCHATTR_REGRESSION_YNAME: + { + lclConvertToItemSet(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "YName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_COEFF: + { + lclConvertToItemSet(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 000000000..234d2b5ba --- /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 +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include + +#include + +#include + +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 sal_uInt16 * 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 000000000..49ad33871 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ITEMSETWRAPPER_SCHWHICHPAIRS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ITEMSETWRAPPER_SCHWHICHPAIRS_HXX + +#include +#include +#include +#include + +#include + +#define CHARACTER_WHICHPAIRS \ + EE_ITEMS_START, EE_ITEMS_END, \ + SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING + +const sal_uInt16 nTitleWhichPairs[] = +{ + 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 + CHARACTER_WHICHPAIRS, + 0 +}; + +const sal_uInt16 nAxisWhichPairs[] = +{ + XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx + CHARACTER_WHICHPAIRS, + 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 + SCHATTR_AXIS_START, SCHATTR_AXIS_END, + SCHATTR_TEXT_START, SCHATTR_TEXT_END, + 0 +}; + +const sal_uInt16 nAllAxisWhichPairs[] = +{ + XATTR_LINE_FIRST, XATTR_LINE_LAST, + CHARACTER_WHICHPAIRS, + SCHATTR_AXIS_LABEL_START, SCHATTR_AXIS_LABEL_END, + SCHATTR_TEXT_START, SCHATTR_TEXT_END, + 0 +}; + +const sal_uInt16 nGridWhichPairs[] = +{ + XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx + 0 +}; + +const sal_uInt16 nLegendWhichPairs[] = +{ + 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 + CHARACTER_WHICHPAIRS, + SCHATTR_LEGEND_START, SCHATTR_LEGEND_END, // 3 - 3 sch/schattr.hxx + 0 +}; + +const sal_uInt16 nDataLabelWhichPairs[] = +{ + SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END, + 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 */ + SCHATTR_TEXT_DEGREES,SCHATTR_TEXT_DEGREES, + EE_PARA_WRITINGDIR,EE_PARA_WRITINGDIR, + 0 +}; + +#define CHART_POINT_WHICHPAIRS \ + 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, /* 3994 - 4037 editeng/eeitem.hxx */ \ + SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING, \ + SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END, /* 1 - 2 sch/schattr.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 */ \ + 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*/ \ + SDRATTR_3D_FIRST, SDRATTR_3D_LAST, /* 1244 - 1334 svx/svddef.hxx */ \ + SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY + +const sal_uInt16 nDataPointWhichPairs[] = +{ + CHART_POINT_WHICHPAIRS, + 0 +}; + +const sal_uInt16 nTextLabelWhichPairs[] = +{ + XATTR_LINESTYLE, XATTR_LINECOLOR, + XATTR_LINETRANSPARENCE, XATTR_LINETRANSPARENCE, + EE_ITEMS_START, EE_ITEMS_END, + SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING, + SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END, + SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, + SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, + SCHATTR_TEXT_DEGREES, SCHATTR_TEXT_DEGREES, + SCHATTR_STYLE_SYMBOL, SCHATTR_STYLE_SYMBOL, + SCHATTR_SYMBOL_BRUSH, SCHATTR_SYMBOL_BRUSH, + SCHATTR_SYMBOL_SIZE, SCHATTR_SYMBOL_SIZE, + 0 +}; + +#define CHART_SERIES_OPTIONS_WHICHPAIRS \ + 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, \ + SCHATTR_STARTING_ANGLE,SCHATTR_STARTING_ANGLE, \ + SCHATTR_CLOCKWISE,SCHATTR_CLOCKWISE, \ + SCHATTR_MISSING_VALUE_TREATMENT,SCHATTR_MISSING_VALUE_TREATMENT, \ + SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS,SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, \ + SCHATTR_INCLUDE_HIDDEN_CELLS,SCHATTR_INCLUDE_HIDDEN_CELLS, \ + SCHATTR_HIDE_LEGEND_ENTRY,SCHATTR_HIDE_LEGEND_ENTRY + +const sal_uInt16 nSeriesOptionsWhichPairs[] = +{ + CHART_SERIES_OPTIONS_WHICHPAIRS, + 0 +}; + +const sal_uInt16 nRowWhichPairs[] = +{ + CHART_POINT_WHICHPAIRS, + CHART_SERIES_OPTIONS_WHICHPAIRS, + 0 +}; + +const sal_uInt16 nAreaWhichPairs[] = +{ + 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 + 0 +}; + +const sal_uInt16 nTextWhichPairs[] = +{ + CHARACTER_WHICHPAIRS, + SCHATTR_TEXT_START, SCHATTR_TEXT_END, + 0 +}; + +const sal_uInt16 nTextOrientWhichPairs[] = +{ + CHARACTER_WHICHPAIRS, + SCHATTR_TEXT_START, SCHATTR_TEXT_END, + 0 +}; + +const sal_uInt16 nStatWhichPairs[]= +{ + SCHATTR_STAT_START, SCHATTR_STAT_END, // 45 - 52 sch/schattr.hxx + SCHATTR_REGRESSION_START, SCHATTR_REGRESSION_END, // 108 - 109 + 0 +}; + +const sal_uInt16 nErrorBarWhichPairs[]= +{ + SCHATTR_STAT_START, SCHATTR_STAT_END, // 45 - 52 sch/schattr.hxx + XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx + 0 +}; + +// for CharacterProperties + +const sal_uInt16 nCharacterPropertyWhichPairs[] = +{ + CHARACTER_WHICHPAIRS, + 0 +}; + +const sal_uInt16 nLinePropertyWhichPairs[] = +{ + XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx + 0 +}; + +const sal_uInt16 nFillPropertyWhichPairs[] = +{ + XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1000 - 1016 svx/xdef.hxx + SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, // 1067 - 1078 svx/svddef.hxx + 0 +}; + +const sal_uInt16 nLineAndFillPropertyWhichPairs[] = +{ + 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 + 0 +}; + +const sal_uInt16 nChartStyleWhichPairs[] = +{ + SCHATTR_STYLE_SHAPE, SCHATTR_STYLE_SHAPE, + SCHATTR_NUM_OF_LINES_FOR_BAR, SCHATTR_NUM_OF_LINES_FOR_BAR, + SCHATTR_SPLINE_ORDER, SCHATTR_SPLINE_ORDER, + SCHATTR_SPLINE_RESOLUTION, SCHATTR_SPLINE_RESOLUTION, + 0 +}; + +const sal_uInt16 nRegressionCurveWhichPairs[] = +{ + SCHATTR_REGRESSION_START, SCHATTR_REGRESSION_END, // 108 - 109 + XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx + 0 +}; + +const sal_uInt16 nRegEquationWhichPairs[] = +{ + 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 + CHARACTER_WHICHPAIRS, + SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_VALUE, // 10585 - 10585 svx/svxids.hrc + 0 +}; + +// INCLUDED_CHART2_SOURCE_CONTROLLER_ITEMSETWRAPPER_SCHWHICHPAIRS_HXX +#endif + +/* 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 000000000..d50f39abc --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.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 +#include "SchWhichPairs.hxx" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace chart::wrapper +{ + +SeriesOptionsItemConverter::SeriesOptionsItemConverter( + const uno::Reference< frame::XModel >& xChartModel + , const uno::Reference< uno::XComponentContext > & xContext + , const uno::Reference< beans::XPropertySet >& xPropertySet + , SfxItemPool& rItemPool ) + : ItemConverter( xPropertySet, rItemPool ) + , m_xChartModel(xChartModel) + , m_xCC(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_aSupportedMissingValueTreatments() + , m_nMissingValueTreatment(0) + , m_bSupportingPlottingOfHiddenCells(false) + , m_bIncludeHiddenCells(true) + , m_bHideLegendEntry(false) +{ + try + { + uno::Reference< XDataSeries > xDataSeries( xPropertySet, uno::UNO_QUERY ); + + m_bAttachToMainAxis = DiagramHelper::isSeriesAttachedToMainAxis( xDataSeries ); + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram(xChartModel) ); + uno::Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + uno::Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram , xDataSeries ) ); + + m_xCooSys = DataSeriesHelper::getCoordinateSystemOfSeries( xDataSeries, xDiagram ); + if( m_xCooSys.is() ) + { + uno::Reference< chart2::XAxis > xAxis( AxisHelper::getAxis( 1, 0, m_xCooSys ) ); + chart2::ScaleData aScale( xAxis->getScaleData() ); + m_bClockwise = (aScale.Orientation == chart2::AxisOrientation_REVERSE); + } + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + m_bSupportingOverlapAndGapWidthProperties = ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( xChartType, nDimensionCount ); + + if( m_bSupportingOverlapAndGapWidthProperties ) + { + + sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + + uno::Sequence< sal_Int32 > aBarPositionSequence; + uno::Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); + if( xChartTypeProps.is() ) + { + if( xChartTypeProps->getPropertyValue( "OverlapSequence" ) >>= aBarPositionSequence ) + { + if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() ) + m_nBarOverlap = aBarPositionSequence[nAxisIndex]; + } + if( xChartTypeProps->getPropertyValue( "GapwidthSequence" ) >>= aBarPositionSequence ) + { + if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() ) + m_nGapWidth = aBarPositionSequence[nAxisIndex]; + } + } + } + + m_bSupportingBarConnectors = ChartTypeHelper::isSupportingBarConnectors( xChartType, nDimensionCount ); + if( m_bSupportingBarConnectors && xDiagramProperties.is() ) + { + xDiagramProperties->getPropertyValue( "ConnectBars" ) >>= m_bConnectBars; + } + + m_bSupportingAxisSideBySide = ChartTypeHelper::isSupportingAxisSideBySide( xChartType, nDimensionCount ); + if( m_bSupportingAxisSideBySide && xDiagramProperties.is() ) + { + xDiagramProperties->getPropertyValue( "GroupBarsPerAxis" ) >>= m_bGroupBarsPerAxis; + } + + m_bSupportingStartingAngle = ChartTypeHelper::isSupportingStartingAngle( xChartType ); + if( m_bSupportingStartingAngle ) + { + xDiagramProperties->getPropertyValue( "StartingAngle" ) >>= m_nStartingAngle; + } + + m_aSupportedMissingValueTreatments = ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ); + m_nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( + ChartModelHelper::findDiagram(m_xChartModel), xChartType ); + + uno::Reference< XChartDocument > xChartDoc( m_xChartModel, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xProp( xChartDoc->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; + xDiagramProperties->getPropertyValue( "IncludeHiddenCells" ) >>= m_bIncludeHiddenCells; + } + catch( const beans::UnknownPropertyException& ) + { + } + } + + m_bHideLegendEntry = !xPropertySet->getPropertyValue("ShowLegendEntry").get(); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +SeriesOptionsItemConverter::~SeriesOptionsItemConverter() +{ +} + +const sal_uInt16 * 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: + bChanged = DiagramHelper::attachSeriesToAxis( bAttachToMainAxis, uno::Reference< XDataSeries >::query( GetPropertySet() ) + , ChartModelHelper::findDiagram(m_xChartModel), 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"; + + uno::Reference< XDataSeries > xDataSeries( GetPropertySet(), uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram(m_xChartModel) ); + uno::Reference< beans::XPropertySet > xChartTypeProps( DiagramHelper::getChartTypeOfSeries( xDiagram , xDataSeries ), uno::UNO_QUERY ); + if( xChartTypeProps.is() ) + { + sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + uno::Sequence< sal_Int32 > aBarPositionSequence; + if( xChartTypeProps.is() ) + { + if( xChartTypeProps->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 : aBarPositionSequence ) + pos = rBarPosition; + } + else if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() ) + aBarPositionSequence[nAxisIndex] = rBarPosition; + + xChartTypeProps->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; + uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); + 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; + uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); + 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 SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue(); + uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); + 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() ) + { + uno::Reference< chart2::XAxis > 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 + { + uno::Reference< beans::XPropertySet > xDiagramProperties( ChartModelHelper::findDiagram(m_xChartModel), uno::UNO_QUERY ); + 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(rItemSet.Get(nWhichId)).GetValue(); + if (bIncludeHiddenCells != m_bIncludeHiddenCells) + { + ChartModel* pModel = dynamic_cast(m_xChartModel.get()); + if (pModel) + bChanged = ChartModelHelper::setIncludeHiddenCells( bIncludeHiddenCells, *pModel ); + } + } + } + break; + case SCHATTR_HIDE_LEGEND_ENTRY: + { + bool bHideLegendEntry = static_cast(rItemSet.Get(nWhichId)).GetValue(); + if (bHideLegendEntry != m_bHideLegendEntry) + { + GetPropertySet()->setPropertyValue("ShowLegendEntry", css::uno::makeAny(!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( SfxInt32Item(nWhichId,m_nStartingAngle)); + 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 000000000..b4c4405ff --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.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 +#include "SchWhichPairs.hxx" +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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 ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(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 ) + { + SvxChartRegress eRegress = SvxChartRegress::NONE; + const SfxPoolItem *pPoolItem = nullptr; + if( pItemSet->GetItemState( SCHATTR_REGRESSION_TYPE, true, &pPoolItem ) == SfxItemState::SET ) + { + eRegress = static_cast< const SvxChartRegressItem * >( pPoolItem )->GetValue(); + bEquationExists = ( eRegress != SvxChartRegress::NONE ); + } + } + + if( bEquationExists ) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropSet, uno::UNO_QUERY ); + uno::Reference< chart2::XRegressionCurve > 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 ) + { + SvxChartRegress eRegress = SvxChartRegress::NONE; + const SfxPoolItem *pPoolItem = nullptr; + if( pItemSet->GetItemState( SCHATTR_REGRESSION_TYPE, true, &pPoolItem ) == SfxItemState::SET ) + { + eRegress = static_cast< const SvxChartRegressItem * >( pPoolItem )->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 +bool lclConvertToPropertySet(const SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + T aValue = static_cast(static_cast(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 +void lclConvertToItemSet(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + T aValue = static_cast(static_cast(rItemSet.Get( nWhichId )).GetValue()); + if(xProperties->getPropertyValue( aPropertyID ) >>= aValue) + { + rItemSet.Put(D( nWhichId, aValue )); + } + } +} + +void lclConvertToItemSetDouble(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference& xProperties, const OUString& aPropertyID) +{ + OSL_ASSERT(xProperties.is()); + if( xProperties.is() ) + { + double aValue = static_cast(rItemSet.Get( nWhichId )).GetValue(); + if(xProperties->getPropertyValue( aPropertyID ) >>= aValue) + { + rItemSet.Put(SvxDoubleItem( aValue, nWhichId )); + } + } +} + +} // anonymous namespace + +namespace chart::wrapper +{ + +StatisticsItemConverter::StatisticsItemConverter( + const uno::Reference< frame::XModel > & xModel, + const uno::Reference< beans::XPropertySet > & rPropertySet, + SfxItemPool& rItemPool ) : + ItemConverter( rPropertySet, rItemPool ), + m_xModel( xModel ) +{ +} + +StatisticsItemConverter::~StatisticsItemConverter() +{ +} + +const sal_uInt16 * 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 ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(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(rItemSet, nWhichId, xProperties, "PolynomialDegree"); + } + break; + + case SCHATTR_REGRESSION_PERIOD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "MovingAveragePeriod"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ExtrapolateForward"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ExtrapolateBackward"); + } + break; + + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "ForceIntercept"); + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "InterceptValue"); + } + break; + + case SCHATTR_REGRESSION_CURVE_NAME: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xProperties, "CurveName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_EQUATION: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "ShowEquation"); + } + break; + + case SCHATTR_REGRESSION_XNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "XName"); + } + break; + + case SCHATTR_REGRESSION_YNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(rItemSet, nWhichId, xEqProp, "YName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_COEFF: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet )); + bChanged = lclConvertToPropertySet(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::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 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, nWhichId )); + } + } + 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, nWhichId )); + } + } + 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, nWhichId )); + } + } + 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, nWhichId )); + } + } + 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 xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "PolynomialDegree"); + } + break; + + case SCHATTR_REGRESSION_PERIOD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "MovingAveragePeriod"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "ExtrapolateForward"); + } + break; + + case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "ExtrapolateBackward"); + } + break; + + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "ForceIntercept"); + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSetDouble(rOutItemSet, nWhichId, xProperties, "InterceptValue"); + } + break; + + case SCHATTR_REGRESSION_CURVE_NAME: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xProperties, "CurveName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_EQUATION: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xEqProp, "ShowEquation"); + } + break; + + case SCHATTR_REGRESSION_XNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xEqProp, "XName"); + } + break; + + case SCHATTR_REGRESSION_YNAME: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(rOutItemSet, nWhichId, xEqProp, "YName"); + } + break; + + case SCHATTR_REGRESSION_SHOW_COEFF: + { + uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr )); + lclConvertToItemSet(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 000000000..496b25e26 --- /dev/null +++ b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.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 +#include +#include +#include +#include +#include +#include +#include "SchWhichPairs.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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& xPropertySet, + bool bOverwriteDataPoints ) +{ + bool bChanged = false; + if (!xPropertySet.is()) + return bChanged; + + OUString aPropertyName = (nWhichId == SID_ATTR_NUMBERFORMAT_VALUE) ? OUString(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(rItemSet.Get(nSourceWhich)).GetValue(); + if (!bUseSourceFormat) + { + SfxItemState aState = rItemSet.GetItemState(nWhichId); + if (aState == SfxItemState::SET) + { + sal_Int32 nFmt = static_cast( + static_cast( + rItemSet.Get(nWhichId)).GetValue()); + aValue <<= nFmt; + } + else + return bChanged; + } + + uno::Any aOldValue = xPropertySet->getPropertyValue(aPropertyName); + if (bOverwriteDataPoints) + { + Reference xSeries(xPropertySet, uno::UNO_QUERY); + 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& xPropertySet, + bool bOverwriteDataPoints ) +{ + bool bChanged = false; + if (!xPropertySet.is()) + return bChanged; + OUString aPropertyName = (nWhichId == SID_ATTR_NUMBERFORMAT_SOURCE) ? OUString(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( + 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( + static_cast( + rItemSet.Get(nFormatWhich)).GetValue()); + aNewValue <<= nFormatKey; + } + else + return bChanged; + } + + uno::Any aOldValue(xPropertySet->getPropertyValue(aPropertyName)); + if (bOverwriteDataPoints) + { + Reference xSeries(xPropertySet, uno::UNO_QUERY); + 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 uno::Reference& xChartModel, + const uno::Reference& rPropertySet, + const uno::Reference& 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) +{ + maConverters.emplace_back(new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize")); + + uno::Reference xDiagram(ChartModelHelper::findDiagram(xChartModel)); + uno::Reference xChartType(DiagramHelper::getChartTypeOfSeries(xDiagram, xSeries)); + bool bFound = false; + bool bAmbiguous = false; + bool bSwapXAndY = DiagramHelper::getVertical(xDiagram, 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 sal_uInt16* 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_SYMBOL: + { + const SfxBoolItem& rItem = static_cast(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 : aLabel.ShowLegendSymbol)); + bool bOldValue = rValue; + rValue = rItem.GetValue(); + if (mbDataSeries) + { + Reference xSeries(GetPropertySet(), uno::UNO_QUERY); + if (bOldValue != bool(rValue) || + DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, CHART_UNONAME_LABEL, aOldValue)) + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, CHART_UNONAME_LABEL, uno::Any(aLabel)); + 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(rItemSet.Get(nWhichId)).GetValue(); + OUString aOldValue; + try + { + GetPropertySet()->getPropertyValue("LabelSeparator") >>= aOldValue; + if (mbDataSeries) + { + Reference xSeries(GetPropertySet(), uno::UNO_QUERY); + 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 ) + { + Reference< chart2::XDataSeries > xSeries( GetPropertySet(), uno::UNO_QUERY); + 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(rItemSet.Get(nWhichId)).GetValue(); + sal_Int32 nOld = -1; + RelativePosition aCustomLabelPosition; + GetPropertySet()->getPropertyValue("LabelPlacement") >>= nOld; + if (mbDataSeries) + { + Reference xSeries(GetPropertySet(), uno::UNO_QUERY); + 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( + 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( + 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( + rItemSet.Get(nWhichId))); + uno::Any aXGraphicAny; + const Graphic* pGraphic(rBrshItem.GetGraphic()); + if (pGraphic) + { + uno::Reference 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( + static_cast( + rItemSet.Get(nWhichId)).GetValue()) / 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; + } + + 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_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 : aLabel.ShowLegendSymbol)); + + rOutItemSet.Put(SfxBoolItem(nWhichId, bValue)); + + if (mbDataSeries) + { + if (DataSeriesHelper::hasAttributedDataPointDifferentValue( + Reference(GetPropertySet(), uno::UNO_QUERY), 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: + { + OUString aValue; + try + { + 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_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( + SfxInt32Item(nWhichId, static_cast(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 000000000..dfc57623b --- /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 +#include "SchWhichPairs.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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 sal_uInt16 * 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 sal_uInt16 * FormattedStringsConverter::GetWhichPairs() const +{ + return nCharacterPropertyWhichPairs; +} + +TitleItemConverter::TitleItemConverter( + const uno::Reference & 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 sal_uInt16 * 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 SfxInt32Item & >( + rItemSet.Get( nWhichId )).GetValue()) / 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( SfxInt32Item( nWhichId, 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 000000000..f81b26118 --- /dev/null +++ b/chart2/source/controller/main/ChartController.cxx @@ -0,0 +1,1659 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include "ControllerCommandDispatch.hxx" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include "ChartDropTargetHelper.hxx" + +#include +#include +#include "DrawCommandDispatch.hxx" +#include "ShapeController.hxx" +#include "UndoActions.hxx" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +// this is needed to properly destroy the unique_ptr to the AcceleratorExecute +// object in the DTOR +#include +#include +#include + +// 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 const & xContext) : + m_aLifeTimeManager( nullptr ), + m_bSuspended( false ), + m_xCC(xContext), //@todo is it allowed to hold this context?? + m_aModelMutex(), + m_aModel( nullptr, m_aModelMutex ), + m_xViewWindow(), + m_xChartView(), + m_pDrawModelWrapper(), + m_eDragMode(SdrDragMode::Move), + 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( const uno::Reference< frame::XModel > & xModel ) : + m_xModel( xModel ), + m_bOwnership( true ) +{ + m_xCloseable = + uno::Reference< util::XCloseable >( xModel, uno::UNO_QUERY ); +} + +ChartController::TheModel::~TheModel() +{ +} + +void ChartController::TheModel::addListener( ChartController* pController ) +{ + if(m_xCloseable.is()) + { + //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_xCloseable->addCloseListener( + static_cast(pController) ); + } + else if( m_xModel.is() ) + { + //we need to add as dispose event listener + m_xModel->addEventListener( + static_cast(pController) ); + } + +} + +void ChartController::TheModel::removeListener( ChartController* pController ) +{ + if(m_xCloseable.is()) + m_xCloseable->removeCloseListener( + static_cast(pController) ); + + else if( m_xModel.is() ) + m_xModel->removeEventListener( + static_cast(pController) ); +} + +void ChartController::TheModel::tryTermination() +{ + if(!m_bOwnership) + return; + + try + { + if(m_xCloseable.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_xCloseable->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; + } + + } + else if( m_xModel.is() ) + { + //@todo correct?? + m_xModel->dispose(); + 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 { + +css::uno::Reference getChartType( + const css::uno::Reference& xChartDoc) +{ + Reference xDiagram = xChartDoc->getFirstDiagram(); + if (!xDiagram.is()) { + return css::uno::Reference(); + } + + Reference< chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW ); + + Sequence< Reference< chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems()); + if (!xCooSysSequence.hasElements()) { + return css::uno::Reference(); + } + + Reference< chart2::XChartTypeContainer > xChartTypeContainer( xCooSysSequence[0], uno::UNO_QUERY_THROW ); + + Sequence< Reference< chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() ); + + return xChartTypeSequence[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"; + break; + 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: + { + css::uno::Reference xChartType = getChartType(css::uno::Reference(getModel(), uno::UNO_QUERY)); + 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; +} + +// lang::XServiceInfo + +OUString SAL_CALL ChartController::getImplementationName() +{ + return CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME; +} + +sal_Bool SAL_CALL ChartController::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ChartController::getSupportedServiceNames() +{ + return { + CHART_CONTROLLER_SERVICE_NAME, + "com.sun.star.frame.Controller" + //// @todo : add additional services if you support any further + }; +} + +namespace { + +uno::Reference getSidebarFromModel(const uno::Reference& xModel) +{ + uno::Reference xChild(xModel, uno::UNO_QUERY); + if (!xChild.is()) + return nullptr; + + uno::Reference xParent (xChild->getParent(), uno::UNO_QUERY); + if (!xParent.is()) + return nullptr; + + uno::Reference xController(xParent->getCurrentController(), uno::UNO_QUERY); + if (!xController.is()) + return nullptr; + + uno::Reference xSidebarProvider = xController->getSidebar(); + if (!xSidebarProvider.is()) + return nullptr; + + return xSidebarProvider->getSidebar(); +} + +} + +// XController + +void SAL_CALL ChartController::attachFrame( + const uno::Reference& xFrame ) +{ + SolarMutexGuard aGuard; + + if( impl_isDisposedOrSuspended() ) //@todo? allow attaching the frame while suspended? + return; //behave passive if already disposed or suspended + + mpSelectionChangeHandler->Connect(); + + uno::Reference xSidebar = getSidebarFromModel(getModel()); + if (xSidebar.is()) + { + auto pSidebar = dynamic_cast(xSidebar.get()); + assert(pSidebar); + sfx2::sidebar::SidebarController::registerSidebarForFrame(pSidebar, this); + pSidebar->updateModel(getModel()); + css::lang::EventObject aEvent; + mpSelectionChangeHandler->selectionChanged(aEvent); + } + + 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 + + //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(); + VCLXWindow* pParentComponent = comphelper::getUnoTunnelImplementation(xContainerWindow); + assert(pParentComponent); + if (pParentComponent) + pParentComponent->setVisible(true); + + pParent = VCLUnoHelper::GetWindow( xContainerWindow ).get(); + } + + { + // calls to VCL + SolarMutexGuard aSolarGuard; + auto pChartWindow = VclPtr::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(), + uno::Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY ))); + + 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( getModel() ); + + 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(); + + TheModelRef aNewModelRef( new TheModel( xModel), m_aModelMutex); + TheModelRef aOldModelRef(m_aModel,m_aModelMutex); + m_aModel = aNewModelRef; + + //--handle relations to the old model if any + if( aOldModelRef.is() ) + { + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->removeModeChangeListener(this); + m_pDrawModelWrapper.reset(); + + aOldModelRef->removeListener( this ); + #ifdef TEST_ENABLE_MODIFY_LISTENER + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aOldModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->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()); + 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, impl_getAvailableCommands() ); + + DrawCommandDispatch* pDrawDispatch = new DrawCommandDispatch( m_xCC, this ); + pDrawDispatch->initialize(); + m_aDispatchContainer.setDrawCommandDispatch( pDrawDispatch ); + + ShapeController* pShapeController = new ShapeController( m_xCC, this ); + pShapeController->initialize(); + m_aDispatchContainer.setShapeController( pShapeController ); + aGuard.clear(); + +#ifdef TEST_ENABLE_MODIFY_LISTENER + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aNewModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->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() ) ) ); + + uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY ); + if( xFact.is()) + { + m_xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME ); + GetDrawModelWrapper(); + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->addModeChangeListener(this); + } + + //the frameloader is responsible to call xModel->connectController + { + SolarMutexGuard aGuard2; + auto pChartWindow(GetChartWindow()); + if( pChartWindow ) + pChartWindow->Invalidate(); + } + + uno::Reference< document::XUndoManagerSupplier > xSuppUndo( getModel(), uno::UNO_QUERY_THROW ); + m_xUndoManager.set( xSuppUndo->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() +{ + //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 uno::Reference< frame::XModel > (); +} + +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; +} + +void ChartController::impl_createDrawViewController() +{ + SolarMutexGuard aGuard; + if(!m_pDrawViewWrapper) + { + if( m_pDrawModelWrapper ) + { + m_pDrawViewWrapper.reset( new DrawViewWrapper(m_pDrawModelWrapper->getSdrModel(),GetChartWindow()) ); + m_pDrawViewWrapper->attachParentReferenceDevice( getModel() ); + } + } +} + +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; + + if (getModel().is()) + { + uno::Reference xSidebar = getSidebarFromModel(getModel()); + if (sfx2::sidebar::SidebarController* pSidebar = dynamic_cast(xSidebar.get())) + { + sfx2::sidebar::SidebarController::unregisterSidebarForFrame(pSidebar, this); + } + } + mpSelectionChangeHandler->selectionChanged(css::lang::EventObject()); + mpSelectionChangeHandler->Disconnect(); + + try + { + //This object should release all resources and references in the + //easiest possible manner + //This object must notify all registered listeners using the method + //XEventListener::disposing + + //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; + uno::Reference< chart2::data::XDataReceiver > xDataReceiver( getModel(), uno::UNO_QUERY ); + 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 + { + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->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.set( nullptr ); + } + + 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 + { + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->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& xListener ) +{ + SolarMutexGuard aGuard; + if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode? + return; //behave passive if already disposed or suspended + + //--add listener + m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType::get(), xListener ); +} + +void SAL_CALL ChartController::removeEventListener( + const uno::Reference& xListener ) +{ + SolarMutexGuard aGuard; + if( m_aLifeTimeManager.impl_isDisposed(false) ) + return; //behave passive if already disposed or suspended + + //--remove listener + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType::get(), 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( aModelRef->getModel() != 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() && m_aModel->getModel() == 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.set( nullptr ); + } +} + +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( const OUString& aCommand ) +{ + return aCommand == "MainTitle" + || aCommand == "SubTitle" + || aCommand == "XTitle" + || aCommand == "YTitle" + || aCommand == "ZTitle" + || aCommand == "SecondaryXTitle" + || aCommand == "SecondaryYTitle" + || aCommand == "AllTitles" + || aCommand == "DiagramAxisX" + || aCommand == "DiagramAxisY" + || aCommand == "DiagramAxisZ" + || aCommand == "DiagramAxisA" + || aCommand == "DiagramAxisB" + || aCommand == "DiagramAxisAll" + || aCommand == "DiagramGridXMain" + || aCommand == "DiagramGridYMain" + || aCommand == "DiagramGridZMain" + || aCommand == "DiagramGridXHelp" + || aCommand == "DiagramGridYHelp" + || aCommand == "DiagramGridZHelp" + || aCommand == "DiagramGridAll" + + || aCommand == "DiagramWall" + || aCommand == "DiagramFloor" + || aCommand == "DiagramArea" + || aCommand == "Legend" + + || aCommand == "FormatWall" + || aCommand == "FormatFloor" + || aCommand == "FormatChartArea" + || aCommand == "FormatLegend" + + || aCommand == "FormatTitle" + || aCommand == "FormatAxis" + || aCommand == "FormatDataSeries" + || aCommand == "FormatDataPoint" + || aCommand == "FormatDataLabels" + || aCommand == "FormatDataLabel" + || aCommand == "FormatXErrorBars" + || aCommand == "FormatYErrorBars" + || aCommand == "FormatMeanValue" + || aCommand == "FormatTrendline" + || aCommand == "FormatTrendlineEquation" + || aCommand == "FormatStockLoss" + || aCommand == "FormatStockGain" + || aCommand == "FormatMajorGrid" + || aCommand == "FormatMinorGrid"; +} + +} // anonymous namespace + +uno::Reference 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 > + ChartController::queryDispatches( + const uno::Sequence& xDescripts ) +{ + SolarMutexGuard g; + + if ( !m_aLifeTimeManager.impl_isDisposed() ) + { + return m_aDispatchContainer.getDispatchesForURLs( xDescripts ); + } + return uno::Sequence > (); +} + +// 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 == "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( getModel() ); + 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 == "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(); + //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& /* xControl */, + const util::URL& /* aURL */ ) +{ + //@todo +} + +void SAL_CALL ChartController::removeStatusListener( + const uno::Reference& /* 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(), getModel()); + if (aDlg.run() == RET_OK) + { + impl_adaptDataSeriesAutoResize(); + aUndoGuard.commit(); + } +} + +void ChartController::executeDispatch_SourceData() +{ + //convert properties to ItemSet + uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + 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 = dynamic_cast(*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 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, m_xCC); + if (aDlg.run() == RET_OK) + { + impl_adaptDataSeriesAutoResize(); + aUndoGuard.commit(); + } +} + +void ChartController::executeDispatch_MoveSeries( bool bForward ) +{ + ControllerLockGuardUNO aCLGuard( getModel() ); + + //get selected series + OUString aObjectCID(m_aSelection.getSelectedCID()); + uno::Reference< XDataSeries > xGivenDataSeries( ObjectIdentifier::getDataSeriesForCID( //yyy todo also legend entries and labels? + aObjectCID, getModel() ) ); + + UndoGuardWithSelection aUndoGuard( + ActionDescriptionProvider::createDescription( + (bForward ? ActionDescriptionProvider::ActionType::MoveToTop : ActionDescriptionProvider::ActionType::MoveToBottom), + SchResId(STR_OBJECT_DATASERIES)), + m_xUndoManager ); + + bool bChanged = DiagramHelper::moveSeries( ChartModelHelper::findDiagram( getModel() ), xGivenDataSeries, bForward ); + if( bChanged ) + { + m_aSelection.setSelection( ObjectIdentifier::getMovedSeriesCID( aObjectCID, bForward ) ); + aUndoGuard.commit(); + } +} + +// ____ XMultiServiceFactory ____ +uno::Reference< uno::XInterface > SAL_CALL + ChartController::createInstance( const OUString& aServiceSpecifier ) +{ + uno::Reference< uno::XInterface > xResult; + + if( aServiceSpecifier == CHART_ACCESSIBLE_TEXT_SERVICE_NAME ) + xResult.set( impl_createAccessibleTextContext()); + return xResult; +} + +uno::Reference< uno::XInterface > SAL_CALL + ChartController::createInstanceWithArguments( + const OUString& ServiceSpecifier, + const uno::Sequence< uno::Any >& /* Arguments */ ) +{ + // ignore Arguments + return createInstance( ServiceSpecifier ); +} + +uno::Sequence< OUString > SAL_CALL + ChartController::getAvailableServiceNames() +{ + uno::Sequence< OUString > aServiceNames { CHART_ACCESSIBLE_TEXT_SERVICE_NAME }; + return aServiceNames; +} + +// ____ 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 pUndoAction ) +{ + ENSURE_OR_RETURN_VOID( pUndoAction, "invalid Undo action" ); + + OUString aObjectCID = m_aSelection.getSelectedCID(); + if ( !aObjectCID.isEmpty() ) + return; + + try + { + const Reference< document::XUndoManagerSupplier > xSuppUndo( getModel(), uno::UNO_QUERY_THROW ); + 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 ) + { + ExplicitValueProvider* pProvider = comphelper::getUnoTunnelImplementation( m_xChartView ); + if( pProvider ) + m_pDrawModelWrapper = pProvider->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(); +} + + +VclPtr 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(VCLUnoHelper::GetWindow(m_xViewWindow).get()); +} + +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& rxShape) +{ + if(rxShape.is()) + { + m_aSelection.setSelection(rxShape); + m_aSelection.applySelection(GetDrawViewWrapper()); + } +} + + + +uno::Reference< XAccessible > ChartController::CreateAccessible() +{ + uno::Reference< XAccessible > xResult = new AccessibleChartView( GetDrawViewWrapper() ); + impl_initializeAccessible( uno::Reference< lang::XInitialization >( xResult, uno::UNO_QUERY ) ); + return xResult; +} + +void ChartController::impl_invalidateAccessible() +{ + SolarMutexGuard aGuard; + auto pChartWindow(GetChartWindow()); + if( pChartWindow ) + { + Reference< lang::XInitialization > xInit( pChartWindow->GetAccessible(false), uno::UNO_QUERY ); + if(xInit.is()) + { + uno::Sequence< uno::Any > aArguments(3);//empty arguments -> invalid accessible + xInit->initialize(aArguments); + } + } +} +void ChartController::impl_initializeAccessible() +{ + SolarMutexGuard aGuard; + auto pChartWindow(GetChartWindow()); + if( pChartWindow ) + this->impl_initializeAccessible( Reference< lang::XInitialization >( pChartWindow->GetAccessible(false), uno::UNO_QUERY ) ); +} +void ChartController::impl_initializeAccessible( const uno::Reference< lang::XInitialization >& xInit ) +{ + if(!xInit.is()) + return; + + uno::Sequence< uno::Any > aArguments(5); + aArguments[0] <<= uno::Reference(this); + aArguments[1] <<= getModel(); + aArguments[2] <<= m_xChartView; + uno::Reference< XAccessible > xParent; + { + SolarMutexGuard aGuard; + auto pChartWindow(GetChartWindow()); + if( pChartWindow ) + { + vcl::Window* pParentWin( pChartWindow->GetAccessibleParentWindow()); + if( pParentWin ) + xParent.set( pParentWin->GetAccessible()); + } + } + aArguments[3] <<= xParent; + aArguments[4] <<= m_xViewWindow; + + xInit->initialize(aArguments); +} + +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", + //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 + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_ChartController_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence const &) +{ + return cppu::acquire(new chart::ChartController(context)); +} + +/* 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 000000000..e9820cab3 --- /dev/null +++ b/chart2/source/controller/main/ChartController_EditData.cxx @@ -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 . + */ + +#include +#include + +#include +#include "UndoGuard.hxx" +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +void ChartController::executeDispatch_EditData() +{ + Reference< chart2::XChartDocument > xChartDoc( getModel(), 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 000000000..85f7ea5c3 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Insert.cxx @@ -0,0 +1,877 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +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 uno::Reference< chart2::XDataSeries > & xSeries ) +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + xSeries, uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + ::chart::RegressionCurveHelper::addMeanValueLine( + xRegCurveCnt, uno::Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY )); + } +} + +} // anonymous namespace + +namespace chart +{ + +void ChartController::executeDispatch_InsertAxes() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AXES )), + m_xUndoManager ); + + try + { + InsertAxisOrGridDialogData aDialogInput; + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(getModel()); + AxisHelper::getAxisOrGridExcistence( 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( getModel() ); + + 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; + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(getModel()); + AxisHelper::getAxisOrGridExcistence( 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( getModel() ); + 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_InsertTitles() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_TITLES )), + m_xUndoManager ); + + try + { + TitleDialogData aDialogInput; + aDialogInput.readFromModel( getModel() ); + + SolarMutexGuard aGuard; + SchTitleDlg aDlg(GetChartFrame(), aDialogInput); + if (aDlg.run() == RET_OK) + { + // lock controllers till end of block + ControllerLockGuardUNO aCLGuard( getModel() ); + TitleDialogData aDialogOutput(impl_createReferenceSizeProvider()); + aDlg.getResult(aDialogOutput); + bool bChanged = aDialogOutput.writeDifferenceToModel( getModel(), 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 ); + + ChartModel& rModel = dynamic_cast(*getModel()); + LegendHelper::hideLegend(rModel); + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_InsertLegend() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_LEGEND )), + m_xUndoManager ); + + ChartModel& rModel = dynamic_cast(*getModel()); + LegendHelper::showLegend(rModel, 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( getModel() ); + if (aDlg.run() == RET_OK) + { + // lock controllers till end of block + ControllerLockGuardUNO aCLGuard( getModel() ); + aDlg.writeToModel( getModel() ); + 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: + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel()); + 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( + getModel(), + m_pDrawModelWrapper->GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + + //prepare and open dialog + SolarMutexGuard aGuard; + + //get number formatter + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( getModel(), uno::UNO_QUERY ); + NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier ); + 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( getModel() ); + 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(), + getModel() ) ); + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_InsertMenu_MeanValues() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AVERAGE_LINE )), + m_xUndoManager ); + + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xSeries.is() ) + { + //if a series is selected insert mean value only for that series: + lcl_InsertMeanValueLine( xSeries ); + } + else + { + std::vector< uno::Reference< chart2::XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( ChartModelHelper::findDiagram( getModel() ))); + + for( const auto& xSrs : aSeries ) + lcl_InsertMeanValueLine( xSrs ); + } + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_InsertMenu_Trendlines() +{ + OUString aCID = m_aSelection.getSelectedCID(); + + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( aCID, getModel() ); + + if( !xSeries.is() ) + return; + + executeDispatch_InsertTrendline(); +} + +void ChartController::executeDispatch_InsertTrendline() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel()), uno::UNO_QUERY ); + + if( !xRegressionCurveContainer.is() ) + return; + + UndoLiveUpdateGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_CURVE )), + m_xUndoManager ); + + uno::Reference< chart2::XRegressionCurve > xCurve = + RegressionCurveHelper::addRegressionCurve( + SvxChartRegress::Linear, + xRegressionCurveContainer ); + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + + if( !xProperties.is()) + return; + + wrapper::RegressionCurveItemConverter aItemConverter( + xProperties, xRegressionCurveContainer, m_pDrawModelWrapper->getSdrModel().GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + + // 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( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get()); + SolarMutexGuard aGuard; + SchAttribTabDlg aDialog( + GetChartFrame(), &aItemSet, &aDialogParameter, + &aViewElementListProvider, + uno::Reference< util::XNumberFormatsSupplier >( + getModel(), uno::UNO_QUERY ) ); + + // 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( getModel() ); + 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: + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + + 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( + getModel(), xErrorBarProp, m_pDrawModelWrapper->getSdrModel().GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + + // open dialog + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemSet.Put(SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE,bYError)); + aItemConverter.FillItemSet( aItemSet ); + ObjectPropertiesDialogParameter aDialogParameter( + ObjectIdentifier::createClassifiedIdentifierWithParent( + objType, OUString(), m_aSelection.getSelectedCID())); + aDialogParameter.init( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get()); + SolarMutexGuard aGuard; + SchAttribTabDlg aDlg( + GetChartFrame(), &aItemSet, &aDialogParameter, + &aViewElementListProvider, + uno::Reference< util::XNumberFormatsSupplier >( + getModel(), uno::UNO_QUERY ) ); + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), + 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( getModel() ); + 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( + getModel(), m_pDrawModelWrapper->GetItemPool() ); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + + //prepare and open dialog + SolarMutexGuard aGuard; + InsertErrorBarsDialog aDlg( + GetChartFrame(), aItemSet, + uno::Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY ), + bYError ? ErrorBarResources::ERROR_BAR_Y : ErrorBarResources::ERROR_BAR_X); + + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), m_xChartView, OUString() ) ); + + if (aDlg.run() == RET_OK) + { + SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet(); + aDlg.FillItemSet( aOutItemSet ); + + // lock controllers till end of block + ControllerLockGuardUNO aCLGuard( getModel() ); + 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(), getModel() ), uno::UNO_QUERY ); + if( !xRegCurve.is() ) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + 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(), getModel() ); + 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(), getModel() ); + 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() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + 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() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + 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() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + 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 ) +{ + uno::Reference< chart2::XDataSeries > xDataSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() )); + 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() +{ + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + 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(), getModel() ) ); + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_DeleteDataLabels() +{ + uno::Reference< chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + 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(), getModel() ) ); + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_ResetAllDataPoints() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Format, + SchResId( STR_OBJECT_DATAPOINTS )), + m_xUndoManager ); + uno::Reference< chart2::XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xSeries.is() ) + xSeries->resetAllDataPoints(); + aUndoGuard.commit(); +} +void ChartController::executeDispatch_ResetDataPoint() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Format, + SchResId( STR_OBJECT_DATAPOINT )), + m_xUndoManager ); + uno::Reference< chart2::XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xSeries.is() ) + { + sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() ); + xSeries->resetDataPoint( nPointIndex ); + } + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_InsertAxisTitle() +{ + try + { + uno::Reference< XTitle > xTitle; + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_TITLE )), + m_xUndoManager ); + + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + sal_Int32 nDimensionIndex = -1; + sal_Int32 nCooSysIndex = -1; + sal_Int32 nAxisIndex = -1; + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram(getModel()), 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), getModel(), 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeGridVisible( xAxis->getGridProperties() ); + 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeGridInvisible( xAxis->getGridProperties() ); + 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + const Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( Reference< beans::XPropertySet > 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + const Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( Reference< beans::XPropertySet > 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 000000000..52664c356 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Position.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 + +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 ) +{ + long nPosX(0); + long nPosY(0); + long nSizX(0); + long nSizY(0); + + RectPoint eRP = RectPoint::LT; + + const SfxPoolItem* pPoolItem=nullptr; + //read position + if (rItemSet.GetItemState(SID_ATTR_TRANSFORM_POS_X,true,&pPoolItem)==SfxItemState::SET) + nPosX= static_cast(pPoolItem)->GetValue(); + if (rItemSet.GetItemState(SID_ATTR_TRANSFORM_POS_Y,true,&pPoolItem)==SfxItemState::SET) + nPosY=static_cast(pPoolItem)->GetValue(); + //read size + if (rItemSet.GetItemState(SID_ATTR_TRANSFORM_WIDTH,true,&pPoolItem)==SfxItemState::SET) + nSizX=static_cast(pPoolItem)->GetValue(); + if (rItemSet.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,true,&pPoolItem)==SfxItemState::SET) + nSizY=static_cast(pPoolItem)->GetValue(); + if (rItemSet.GetItemState(SID_ATTR_TRANSFORM_SIZE_POINT,true,&pPoolItem)==SfxItemState::SET) + eRP=static_cast(static_cast(pPoolItem)->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 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; + + sal_uInt16 nWhich; + for (const auto& aProp: *pArgs) + { + sal_Int32 nValue = 0; + aProp.Value >>= nValue; + if (aProp.Name == "TransformPosX") { + nWhich = pPool->GetWhich(SID_ATTR_TRANSFORM_POS_X); + aItemSet.Put(SfxInt32Item(nWhich, nValue)); + } + else if (aProp.Name == "TransformPosY") { + nWhich = pPool->GetWhich(SID_ATTR_TRANSFORM_POS_Y); + aItemSet.Put(SfxInt32Item(nWhich, nValue)); + } + else if (aProp.Name == "TransformWidth") { + nWhich = pPool->GetWhich(SID_ATTR_TRANSFORM_WIDTH); + aItemSet.Put(SfxUInt32Item(nWhich, static_cast(nValue))); + } + else if (aProp.Name == "TransformHeight") { + nWhich = pPool->GetWhich(SID_ATTR_TRANSFORM_HEIGHT); + aItemSet.Put(SfxUInt32Item(nWhich, static_cast(nValue))); + } + } + } + + if(pOutItemSet || pArgs) + { + awt::Rectangle aOldObjectRect; + ExplicitValueProvider* pProvider(comphelper::getUnoTunnelImplementation( m_xChartView )); + if( pProvider ) + aOldObjectRect = pProvider->getRectangleOfObject(aCID); + + awt::Rectangle aNewObjectRect; + lcl_getPositionAndSizeFromItemSet( aItemSet, aNewObjectRect, ToSize(aOldObjectRect) ); + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + awt::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height ); + + bool bChanged = false; + if ( eObjectType == OBJECTTYPE_LEGEND ) + { + ChartModel& rModel = dynamic_cast(*getModel()); + bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning(rModel, false , true); + } + + bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID(), getModel() + , 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 000000000..587cbbfc0 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Properties.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; + +namespace +{ + +wrapper::ItemConverter* createItemConverter( + const OUString & aObjectCID, const uno::Reference& xChartModel, + const uno::Reference& 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; + } + + OUString aParticleID = ObjectIdentifier::getParticleID( aObjectCID ); + bool bAffectsMultipleObjects = aParticleID == "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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicObjectType::LineAndFillProperties ); + break; + case OBJECTTYPE_TITLE: + { + std::unique_ptr pRefSize; + if (pRefSizeProvider) + pRefSize.reset(new awt::Size(pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::TitleItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), rDrawModel, + uno::Reference(xChartModel, uno::UNO_QUERY), + pRefSize.get()); + } + break; + case OBJECTTYPE_LEGEND: + { + std::unique_ptr pRefSize; + if (pRefSizeProvider) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::LegendItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), rDrawModel, + uno::Reference(xChartModel, uno::UNO_QUERY), + 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicObjectType::LineAndFillProperties ); + break; + case OBJECTTYPE_AXIS: + { + std::unique_ptr pRefSize; + if (pRefSizeProvider) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + uno::Reference< beans::XPropertySet > xDiaProp; + xDiaProp.set( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + + // 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( + uno::Reference< XAxis >( xObjectProperties, uno::UNO_QUERY ), + aExplicitScale, aExplicitIncrement ); + + pItemConverter = new wrapper::AxisItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, + uno::Reference< chart2::XChartDocument >( xChartModel, uno::UNO_QUERY ), + &aExplicitScale, &aExplicitIncrement, + pRefSize.get() ); + } + break; + case OBJECTTYPE_AXIS_UNITLABEL: + break; + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_LABEL: + { + std::unique_ptr pRefSize; + if (pRefSizeProvider) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + uno::Reference xSeries = ObjectIdentifier::getDataSeriesForCID(aObjectCID, xChartModel); + + bool bDataSeries = eObjectType == OBJECTTYPE_DATA_LABELS; + + sal_Int32 nNumberFormat = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties ); + sal_Int32 nPercentNumberFormat = ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( + xObjectProperties,uno::Reference(xChartModel, uno::UNO_QUERY)); + + 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 pRefSize; + if (pRefSizeProvider) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + wrapper::GraphicObjectType eMapTo = + wrapper::GraphicObjectType::FilledDataPoint; + + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel ); + uno::Reference< XChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries ); + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + 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 = aParticleID.toInt32(); + uno::Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + bool bVaryColorsByPoint = false; + if( xSeriesProp.is() && + (xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint) && + bVaryColorsByPoint ) + { + if( !ColorPerPointHelper::hasPointOwnColor( xSeriesProp, 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,uno::Reference< util::XNumberFormatsSupplier >(xChartModel, uno::UNO_QUERY)); + + pItemConverter = new wrapper::DataPointItemConverter( xChartModel, xContext, + xObjectProperties, xSeries, rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + + case OBJECTTYPE_DATA_CURVE: + pItemConverter = new wrapper::RegressionCurveItemConverter( + xObjectProperties, uno::Reference< chart2::XRegressionCurveContainer >( + ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel ), uno::UNO_QUERY ), + rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + std::unique_ptr pRefSize; + if (pRefSizeProvider) + pRefSize.reset(new awt::Size(pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::RegressionEquationItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicObjectType::LineAndFillProperties ); + 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + case OBJECTTYPE_AXIS: + { + std::unique_ptr 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, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + default: //for this type it is not supported to change all elements at once + break; + } + + } + return pItemConverter; +} + +OUString lcl_getTitleCIDForCommand( const OString& rDispatchCommand, const uno::Reference< frame::XModel > & xChartModel ) +{ + if( rDispatchCommand == "AllTitles") + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_TITLE, "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; + + uno::Reference< XTitle > xTitle( TitleHelper::getTitle( nTitleType, xChartModel ) ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ); +} + +OUString lcl_getAxisCIDForCommand( const OString& rDispatchCommand, const uno::Reference< frame::XModel >& xChartModel ) +{ + if( rDispatchCommand == "DiagramAxisAll") + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_AXIS, "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; + } + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ); +} + +OUString lcl_getGridCIDForCommand( const OString& rDispatchCommand, const uno::Reference< frame::XModel >& xChartModel ) +{ + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + + if( rDispatchCommand == "DiagramGridAll") + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_GRID, "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; + } + + uno::Reference< XAxis > 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, OUString(), rSelectedCID ); +} + +OUString lcl_getObjectCIDForCommand( const OString& rDispatchCommand, const uno::Reference< XChartDocument > & xChartDocument, const OUString& rSelectedCID ) +{ + ObjectType eObjectType = OBJECTTYPE_UNKNOWN; + + uno::Reference< frame::XModel > xChartModel = xChartDocument; + const ObjectType eSelectedType = ObjectIdentifier::getObjectType( rSelectedCID ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedCID, xChartModel ); + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xSeries, uno::UNO_QUERY ); + + //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, xChartModel ); + } + //axis + else if( rDispatchCommand == "DiagramAxisX" + || rDispatchCommand == "DiagramAxisY" + || rDispatchCommand == "DiagramAxisZ" + || rDispatchCommand == "DiagramAxisA" + || rDispatchCommand == "DiagramAxisB" + || rDispatchCommand == "DiagramAxisAll" + ) + { + return lcl_getAxisCIDForCommand( rDispatchCommand, xChartModel ); + } + //grid + else if( rDispatchCommand == "DiagramGridYMain" + || rDispatchCommand == "DiagramGridXMain" + || rDispatchCommand == "DiagramGridZMain" + || rDispatchCommand == "DiagramGridYHelp" + || rDispatchCommand == "DiagramGridXHelp" + || rDispatchCommand == "DiagramGridZHelp" + || rDispatchCommand == "DiagramGridAll" + ) + { + return lcl_getGridCIDForCommand( rDispatchCommand, xChartModel ); + } + //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, OUString(), rSelectedCID ); + } + //data labels + else if( rDispatchCommand == "FormatDataLabel" ) + { + if( eSelectedType == OBJECTTYPE_DATA_LABEL ) + return rSelectedCID; + else + { + sal_Int32 nPointIndex = ObjectIdentifier::getParticleID( rSelectedCID ).toInt32(); + 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, OUString(), 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( xRegCurveCnt, + RegressionCurveHelper::getMeanValueLine( xRegCurveCnt ) ), true ); + } + //trend line + else if( rDispatchCommand == "FormatTrendline" ) + { + if( eSelectedType == OBJECTTYPE_DATA_CURVE ) + return rSelectedCID; + else + return ObjectIdentifier::createDataCurveCID( + ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ), + RegressionCurveHelper::getRegressionCurveIndex( xRegCurveCnt, + RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ), 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( xRegCurveCnt, + RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ) ); + } + // 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 + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis , xChartModel ); + } + } + // major grid + else if( rDispatchCommand == "FormatMajorGrid" ) + { + if( eSelectedType == OBJECTTYPE_GRID ) + return rSelectedCID; + else + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ); + } + + } + // minor grid + else if( rDispatchCommand == "FormatMinorGrid" ) + { + if( eSelectedType == OBJECTTYPE_SUBGRID ) + return rSelectedCID; + else + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, 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, OUString()); + } + // stock gain + else if( rDispatchCommand == "FormatStockGain" ) + { + if( eSelectedType == OBJECTTYPE_DATA_STOCK_GAIN ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DATA_STOCK_GAIN, OUString() ); + } + + return ObjectIdentifier::createClassifiedIdentifier( + eObjectType, + OUString() ); // aParticleID +} + +} +// anonymous namespace + +void ChartController::executeDispatch_FormatObject(const OUString& rDispatchCommand) +{ + uno::Reference< XChartDocument > xChartDocument( getModel(), uno::UNO_QUERY ); + 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 ) + { + OUString aParentParticle( ObjectIdentifier::getFullParentParticle( rSelectedCID ) ); + aFormatCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); + } + + // treat diagram as wall + if( eObjectType==OBJECTTYPE_DIAGRAM ) + aFormatCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ); + + 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( !DiagramHelper::isSupportingFloorAndWall( ChartModelHelper::findDiagram( getModel() ) ) ) + return bRet; + } + + //convert properties to ItemSet + + std::unique_ptr pRefSizeProv(impl_createReferenceSizeProvider()); + + std::unique_ptr pItemConverter( + createItemConverter( rObjectCID, getModel(), m_xCC, + m_pDrawModelWrapper->getSdrModel(), + comphelper::getUnoTunnelImplementation(m_xChartView), + 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( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get() ); + + SolarMutexGuard aGuard; + SchAttribTabDlg aDlg( + GetChartFrame(), &aItemSet, &aDialogParameter, + &aViewElementListProvider, + uno::Reference< util::XNumberFormatsSupplier >( + getModel(), uno::UNO_QUERY ) ); + + if(aDialogParameter.HasSymbolProperties()) + { + uno::Reference< beans::XPropertySet > xObjectProperties = + ObjectIdentifier::getObjectPropertySet( rObjectCID, getModel() ); + wrapper::DataPointItemConverter aSymbolItemConverter( getModel(), m_xCC + , xObjectProperties, ObjectIdentifier::getDataSeriesForCID( rObjectCID, getModel() ) + , m_pDrawModelWrapper->getSdrModel().GetItemPool() + , m_pDrawModelWrapper->getSdrModel() + , uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY ) + , wrapper::GraphicObjectType::FilledDataPoint ); + + std::unique_ptr pSymbolShapeProperties(new SfxItemSet( aSymbolItemConverter.CreateEmptyItemSet() )); + aSymbolItemConverter.FillItemSet( *pSymbolShapeProperties ); + + sal_Int32 const nStandardSymbol=0;//@todo get from somewhere + std::unique_ptr pAutoSymbolGraphic(new Graphic( aViewElementListProvider.GetSymbolGraphic( nStandardSymbol, pSymbolShapeProperties.get() ) )); + // note: the dialog takes the ownership of pSymbolShapeProperties and pAutoSymbolGraphic + aDlg.setSymbolInformation( std::move(pSymbolShapeProperties), std::move(pAutoSymbolGraphic) ); + } + if( aDialogParameter.HasStatisticProperties() ) + { + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), m_xChartView, rObjectCID ) ); + } + + //open the dialog + if (aDlg.run() == RET_OK || (bSuccessOnUnchanged && aDlg.DialogWasClosedWithOK())) + { + const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet(); + if(pOutItemSet) + { + ControllerLockGuardUNO aCLGuard( getModel()); + (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(), getModel()); + 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 000000000..ae18162d8 --- /dev/null +++ b/chart2/source/controller/main/ChartController_TextEdit.cxx @@ -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 . + */ + +#include + +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + uno::Reference< beans::XPropertySet > xChartViewProps( m_xChartView, uno::UNO_QUERY ); + if( xChartViewProps.is() ) + xChartViewProps->setPropertyValue( "SdrViewIsInEditMode", uno::Any(true) ); + + bool bEdit = m_pDrawViewWrapper->SdrBeginTextEdit( pTextObj + , m_pDrawViewWrapper->GetPageView() + , GetChartWindow() + , 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 ); + } + } + + //we invalidate the outliner region because the outliner has some + //paint problems (some characters are painted twice a little bit shifted) + GetChartWindow()->Invalidate( m_pDrawViewWrapper->GetMarkedObjBoundRect() ); +} + +bool ChartController::EndTextEdit() +{ + m_pDrawViewWrapper->SdrEndTextEdit(); + + //#i77362 change notification for changes on additional shapes are missing + uno::Reference< beans::XPropertySet > xChartViewProps( m_xChartView, uno::UNO_QUERY ); + if( xChartViewProps.is() ) + xChartViewProps->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 ) + { + 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, getModel() ); + + // lock controllers till end of block + ControllerLockGuardUNO aCLGuard( getModel() ); + + TitleHelper::setCompleteString( aString, uno::Reference< + css::chart2::XTitle >::query( xPropSet ), 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 pDlg(pFact->CreateCharMapDialog(GetChartFrame(), aSet, nullptr)); + if( pDlg->Execute() != RET_OK ) + return; + + const SfxItemSet* pSet = pDlg->GetOutputItemSet(); + const SfxPoolItem* pItem=nullptr; + OUString aString; + if (pSet && pSet->GetItemState(SID_CHARMAP, true, &pItem) == SfxItemState::SET) + if (auto pStringItem = dynamic_cast(pItem)) + aString = pStringItem->GetValue(); + + OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView(); + SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner(); + + if(!pOutliner || !pOutlinerView) + return; + + // insert string to outliner + + // prevent flicker + pOutlinerView->HideCursor(); + pOutliner->SetUpdateMode(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->SetUpdateMode(true); + pOutlinerView->ShowCursor(); +} + +uno::Reference< css::accessibility::XAccessibleContext > + ChartController::impl_createAccessibleTextContext() +{ + uno::Reference< css::accessibility::XAccessibleContext > xResult( + new AccessibleTextHelper( m_pDrawViewWrapper.get() )); + + return xResult; +} + +} //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 000000000..c60243504 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Tools.cxx @@ -0,0 +1,990 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include +#include +#include +#include "ChartTransferable.hxx" +#include +#include +#include +#include +#include "ShapeController.hxx" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +namespace +{ + +bool lcl_deleteDataSeries( + const OUString & rCID, + const Reference< frame::XModel > & xModel, + const Reference< document::XUndoManager > & xUndoManager ) +{ + bool bResult = false; + uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rCID, xModel )); + uno::Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + if( xSeries.is() && xChartDoc.is()) + { + uno::Reference< chart2::XChartType > xChartType( + DataSeriesHelper::getChartTypeOfSeries( xSeries, xChartDoc->getFirstDiagram())); + if( xChartType.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_DATASERIES )), + xUndoManager ); + + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< chart2::XAxis > xAxis( DiagramHelper::getAttachedAxis( xSeries, xDiagram ) ); + + DataSeriesHelper::deleteSeries( xSeries, xChartType ); + + AxisHelper::hideAxisIfNoDataIsAttached( xAxis, xDiagram ); + + bResult = true; + aUndoGuard.commit(); + } + } + return bResult; +} + +bool lcl_deleteDataCurve( + const OUString & rCID, + const Reference< frame::XModel > & 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 ChartController::impl_createReferenceSizeProvider() +{ + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + + return std::make_unique( + aPageSize, Reference(getModel(), uno::UNO_QUERY)); +} + +void ChartController::impl_adaptDataSeriesAutoResize() +{ + std::unique_ptr 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 + { + Reference< frame::XModel > xModel( getModel() ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + if( xDiagram.is()) + { + UndoGuard aUndoGuard( + SchResId( STR_ACTION_REARRANGE_CHART ), + m_xUndoManager ); + ControllerLockGuardUNO aCtlLockGuard( xModel ); + + // diagram + Reference< beans::XPropertyState > xState( xDiagram, uno::UNO_QUERY_THROW ); + xState->setPropertyToDefault( "RelativeSize"); + xState->setPropertyToDefault( "RelativePosition"); + xState->setPropertyToDefault( "PosSizeExcludeAxes"); + + // 3d rotation + ThreeDHelper::set3DSettingsToDefault( uno::Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ) ); + + // legend + Reference< beans::XPropertyState > xLegendState( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendState.is()) + { + xLegendState->setPropertyToDefault( "RelativePosition"); + xLegendState->setPropertyToDefault( "RelativeSize"); + xLegendState->setPropertyToDefault( "AnchorPosition"); + } + + // titles + for( sal_Int32 eType = TitleHelper::TITLE_BEGIN; + eType < TitleHelper::NORMAL_TITLE_END; + ++eType ) + { + Reference< beans::XPropertyState > xTitleState( + TitleHelper::getTitle( + static_cast< TitleHelper::eTitleType >( eType ), xModel ), uno::UNO_QUERY ); + if( xTitleState.is()) + xTitleState->setPropertyToDefault( "RelativePosition"); + } + + // regression curve equations + std::vector< Reference< chart2::XRegressionCurve > > aRegressionCurves( + RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine( xDiagram )); + + // 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( getModel() ); + + std::unique_ptr 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( {}, pChartWindow->GetSizePixel()).Center()); + + // handle different formats + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pChartWindow )); + if( aDataHelper.GetTransferable().is()) + { + if ( aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ) ) + { + tools::SvRef 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 xStm; + if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm )) + ReadGraphic( *xStm, 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. + uno::Reference< beans::XPropertySet > xModelProp( getModel(), uno::UNO_QUERY ); + DrawModelWrapper * pDrawModelWrapper( GetDrawModelWrapper()); + if( ! (xGraphic.is() && xModelProp.is())) + return; + uno::Reference< lang::XMultiServiceFactory > xFact( pDrawModelWrapper->getShapeFactory()); + uno::Reference< drawing::XShape > xGraphicShape( + xFact->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xGraphicShapeProp( xGraphicShape, uno::UNO_QUERY ); + if( !(xGraphicShapeProp.is() && xGraphicShape.is())) + return; + + uno::Reference< drawing::XShapes > xPage = pDrawModelWrapper->getMainDrawPage(); + if( xPage.is()) + { + xPage->add( xGraphicShape ); + //need to change the model state manually + { + uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->setModified( true ); + } + //select new shape + m_aSelection.setSelection( xGraphicShape ); + m_aSelection.applySelection( m_pDrawViewWrapper.get() ); + } + xGraphicShapeProp->setPropertyValue( "Graphic", uno::Any( xGraphic )); + uno::Reference< beans::XPropertySet > xGraphicProp( xGraphic, uno::UNO_QUERY ); + + awt::Size aGraphicSize( 1000, 1000 ); + auto pChartWindow(GetChartWindow()); + // first try size in 100th mm, then pixel size + if( ! ( xGraphicProp->getPropertyValue( "Size100thMM") >>= aGraphicSize ) && + ( ( xGraphicProp->getPropertyValue( "SizePixel") >>= aGraphicSize ) && 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 + SdrObject* pNewObj(pObj ? pObj->CloneSdrObject(pDrawModelWrapper->getSdrModel()) : nullptr); + + 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 ); + m_pDrawViewWrapper->AddUndo( std::make_unique( *pNewObj ) ); + xSelShape = xShape; + } + } + } + + Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY ); + 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< lang::XMultiServiceFactory >& xShapeFactory( pDrawModelWrapper->getShapeFactory() ); + const Reference< drawing::XDrawPage >& xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + OSL_ASSERT( xShapeFactory.is() && xDrawPage.is() ); + + if ( !(xShapeFactory.is() && xDrawPage.is()) ) + return; + + try + { + Reference< drawing::XShape > xTextShape( + xShapeFactory->createInstance( "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY_THROW ); + xDrawPage->add( xTextShape ); + + Reference< text::XTextRange > xRange( xTextShape, uno::UNO_QUERY_THROW ); + xRange->setString( rString ); + + float fCharHeight = 10.0; + Reference< beans::XPropertySet > xProperties( xTextShape, uno::UNO_QUERY_THROW ); + xProperties->setPropertyValue( "TextAutoGrowHeight", uno::Any( true ) ); + xProperties->setPropertyValue( "TextAutoGrowWidth", uno::Any( true ) ); + xProperties->setPropertyValue( "CharHeight", uno::Any( fCharHeight ) ); + xProperties->setPropertyValue( "CharHeightAsian", uno::Any( fCharHeight ) ); + xProperties->setPropertyValue( "CharHeightComplex", uno::Any( fCharHeight ) ); + xProperties->setPropertyValue( "TextVerticalAdjust", uno::Any( drawing::TextVerticalAdjust_CENTER ) ); + xProperties->setPropertyValue( "TextHorizontalAdjust", uno::Any( drawing::TextHorizontalAdjust_CENTER ) ); + xProperties->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( *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 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() == OBJ_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 + uno::Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + 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 ), getModel() ); + bReturn = true; + aUndoGuard.commit(); + break; + } + case OBJECTTYPE_LEGEND: + { + uno::Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); + if( xDiagram.is()) + { + uno::Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_LEGEND )), + m_xUndoManager ); + xLegendProp->setPropertyValue( "Show", uno::Any( false )); + bReturn = true; + aUndoGuard.commit(); + } + } + break; + } + + case OBJECTTYPE_DATA_SERIES: + bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager ); + break; + + case OBJECTTYPE_LEGEND_ENTRY: + { + ObjectType eParentObjectType = ObjectIdentifier::getObjectType( + ObjectIdentifier::getFullParentParticle( aCID )); + if( eParentObjectType == OBJECTTYPE_DATA_SERIES ) + { + bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager ); + } + else if( eParentObjectType == OBJECTTYPE_DATA_CURVE ) + { + sal_Int32 nEndPos = aCID.lastIndexOf(':'); + OUString aParentCID = aCID.copy(0, nEndPos); + + bReturn = lcl_deleteDataCurve(aParentCID, getModel(), 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 ), getModel()), 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, getModel(), m_xUndoManager ); + } + break; + + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + uno::Reference< beans::XPropertySet > xEqProp( + ObjectIdentifier::getObjectPropertySet( aCID, getModel())); + + if( xEqProp.is()) + { + uno::Reference< frame::XModel > xModel( getModel() ); + 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, getModel() )); + if( xErrorBarProp.is()) + { + const char* 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; + + uno::Reference< frame::XModel > xModel( getModel() ); + 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, getModel() ); + 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; + if( aObjectType == OBJECTTYPE_DATA_LABELS ) + { + uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( aCID, getModel() )); + ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_LABEL, uno::Any(aLabel) ); + } + else + xObjectProperties->setPropertyValue( CHART_UNONAME_LABEL, uno::Any(aLabel) ); + 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() +{ + Reference< frame::XModel > xModel( getModel() ); + UndoGuard aUndoGuard( + SchResId( STR_ACTION_TOGGLE_LEGEND ), m_xUndoManager ); + ChartModel& rModel = dynamic_cast(*xModel); + Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(rModel), uno::UNO_QUERY ); + 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.set( LegendHelper::getLegend(rModel, m_xCC, true), uno::UNO_QUERY ); + if( xLegendProp.is()) + bChanged = true; + } + + if( bChanged ) + aUndoGuard.commit(); +} + +void ChartController::executeDispatch_ToggleGridHorizontal() +{ + UndoGuard aUndoGuard( + SchResId( STR_ACTION_TOGGLE_GRID_HORZ ), m_xUndoManager ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( getModel() )); + 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 ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( getModel() )); + 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_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() ); + const uno::Reference< frame::XModel >& xChartModel = getModel(); + 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 ); + ChartModel& rModel = dynamic_cast(*m_aModel->getModel()); + if (DiagramHelper::switchDiagramPositioningToExcludingPositioning(rModel, 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 000000000..cdf7e02aa --- /dev/null +++ b/chart2/source/controller/main/ChartController_Window.cxx @@ -0,0 +1,2121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "UndoGuard.hxx" +#include +#include +#include +#include "DragMethod_PieSegment.hxx" +#include "DragMethod_RotateDiagram.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DrawCommandDispatch.hxx" +#include +#include "ControllerCommandDispatch.hxx" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRGPIX 2 // Drag MinMove in Pixel + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +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( const OUString& 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 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( getModel() ); + 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(Flags) ); + + //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% + uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY ); + if( xProp.is() ) + { + auto aZoomFactors(::comphelper::InitPropertySequence({ + { "ScaleXNumerator", uno::Any( nScaleXNumerator ) }, + { "ScaleXDenominator", uno::Any( nScaleXDenominator ) }, + { "ScaleYNumerator", uno::Any( nScaleYNumerator ) }, + { "ScaleYDenominator", uno::Any( nScaleYDenominator ) } + })); + xProp->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->GetOutputSize()); + m_pDrawViewWrapper->SetWorkArea( aRect ); + } + pChartWindow->Invalidate(); +} + +awt::Rectangle SAL_CALL ChartController::getPosSize() +{ + //@todo + awt::Rectangle aRet(0, 0, 0, 0); + + uno::Reference xWindow = m_xViewWindow; + if(xWindow.is()) + aRet = xWindow->getPosSize(); + + return aRet; +} + +void SAL_CALL ChartController::setVisible( sal_Bool Visible ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setVisible( Visible ); +} + +void SAL_CALL ChartController::setEnable( sal_Bool Enable ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setEnable( Enable ); +} + +void SAL_CALL ChartController::setFocus() +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setFocus(); +} + +void SAL_CALL ChartController::addWindowListener( + const uno::Reference< awt::XWindowListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addWindowListener( xListener ); +} + +void SAL_CALL ChartController::removeWindowListener( + const uno::Reference< awt::XWindowListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeWindowListener( xListener ); +} + +void SAL_CALL ChartController::addFocusListener( + const uno::Reference< awt::XFocusListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addFocusListener( xListener ); +} + +void SAL_CALL ChartController::removeFocusListener( + const uno::Reference< awt::XFocusListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeFocusListener( xListener ); +} + +void SAL_CALL ChartController::addKeyListener( + const uno::Reference< awt::XKeyListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addKeyListener( xListener ); +} + +void SAL_CALL ChartController::removeKeyListener( + const uno::Reference< awt::XKeyListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeKeyListener( xListener ); +} + +void SAL_CALL ChartController::addMouseListener( + const uno::Reference< awt::XMouseListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addMouseListener( xListener ); +} + +void SAL_CALL ChartController::removeMouseListener( + const uno::Reference< awt::XMouseListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeMouseListener( xListener ); +} + +void SAL_CALL ChartController::addMouseMotionListener( + const uno::Reference< awt::XMouseMotionListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addMouseMotionListener( xListener ); +} + +void SAL_CALL ChartController::removeMouseMotionListener( + const uno::Reference< awt::XMouseMotionListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeMouseMotionListener( xListener ); +} + +void SAL_CALL ChartController::addPaintListener( + const uno::Reference< awt::XPaintListener >& xListener ) +{ + //@todo + uno::Reference xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addPaintListener( xListener ); +} + +void SAL_CALL ChartController::removePaintListener( + const uno::Reference< awt::XPaintListener >& xListener ) +{ + //@todo + uno::Reference 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 + { + uno::Reference xModel(getModel()); + //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint"); + if (!xModel.is()) + return; + + //better performance for big data + uno::Reference xProp(m_xChartView, uno::UNO_QUERY); + if (xProp.is()) + { + awt::Size aResolution(1000, 1000); + { + SolarMutexGuard aGuard; + auto pChartWindow(GetChartWindow()); + if (pChartWindow) + { + aResolution.Width = pChartWindow->GetSizePixel().Width(); + aResolution.Height = pChartWindow->GetSizePixel().Height(); + } + } + xProp->setPropertyValue( "Resolution", uno::Any( aResolution )); + } + + uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY ); + if (xUpdatable.is()) + xUpdatable->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); + 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() == OBJ_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( getModel() ) ) + { + 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(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(), getModel(), eRotationDirection ); + } + } + else + { + OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ); + if( aDragMethodServiceName == ObjectIdentifier::getPieSegmentDragMethodServiceName() ) + pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() ); + } + 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) ) + return; + } + + if(pDrawViewWrapper->IsAction()) + { + pDrawViewWrapper->MovAction( pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + } + + impl_SetMousePointer( rMEvt ); +} + +void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt ) +{ + ControllerLockGuardUNO aCLGuard( getModel() ); + 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) ) + 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() == OBJ_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( getModel() ) ); + tools::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height ); + + const E3dObject* pE3dObject(dynamic_cast< const E3dObject*>(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; + ChartModel* pModel = dynamic_cast(getModel().get()); + assert(pModel); + if ( eObjectType == OBJECTTYPE_LEGEND ) + bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( *pModel, false , true ); + + bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID() + , getModel() + , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight()) + , awt::Rectangle(aOldObjectRect.getX(), aOldObjectRect.getY(), 0, 0) + , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) ); + + 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( getModel() ); + + //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 ( dynamic_cast< const SdrTextObj* >(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(); + + css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( m_xCC->getServiceManager()->createInstanceWithContext( + "com.sun.star.awt.PopupMenu", m_xCC ), css::uno::UNO_QUERY ); + + 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() ? OUStringLiteral( "drawtext" ) : OUStringLiteral( "draw" ); + else + { + // todo: the context menu should be specified by an xml file in uiconfig + if( xPopupMenu.is()) + { + sal_Int16 nUniqueId = 1; + lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Cut" ); + lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Copy" ); + lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Paste" ); + xPopupMenu->insertSeparator( -1 ); + + ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); + Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() ); + + 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 ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) ); + bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline ); + Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) ); + 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; + + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + { + if( aAttributedDataPointIndexList.hasElements() ) + { + if( bIsPoint ) + { + auto aIndices( comphelper::sequenceToContainer>( aAttributedDataPointIndexList ) ); + std::vector< sal_Int32 >::iterator aIt = std::find( aIndices.begin(), aIndices.end(), nPointIndex ); + if( aIt != aIndices.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" ); + } + + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + if( xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + try + { + Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY ); + if( xChartTypeProp.is() ) + { + bool bJapaneseStyle = false; + xChartTypeProp->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" ); + uno::Reference< awt::XPopupMenu > xArrangePopupMenu( + m_xCC->getServiceManager()->createInstanceWithContext( + "com.sun.star.awt.PopupMenu", m_xCC ), uno::UNO_QUERY ); + if( xArrangePopupMenu.is() ) + { + 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 ) + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + 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 = false; + uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY ); + if( xTitled.is()) + bHasTitle = !TitleHelper::getCompleteString( xTitled->getTitleObject() ).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( 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( 3 ); + aArgs[0] <<= comphelper::makePropertyValue( "IsContextMenu", true ); + aArgs[1] <<= comphelper::makePropertyValue( "Frame", m_xFrame ); + aArgs[2] <<= 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()) + { + PopupMenu* pPopupMenu = static_cast(comphelper::getUnoTunnelImplementation(xPopupMenu)->GetMenu()); + ControllerCommandDispatch* pCommandDispatch = dynamic_cast(m_aDispatchContainer.getChartDispatcher().get()); + if(pCommandDispatch) + { + for (sal_uInt16 nPos = 0; nPos < pPopupMenu->GetItemCount(); nPos++) + { + const sal_uInt16 nItemId = pPopupMenu->GetItemId(nPos); + OUString aCommandURL = pPopupMenu->GetItemCommand(nItemId); + if(!pCommandDispatch->commandAvailable(aCommandURL)) + pPopupMenu->EnableItem(nItemId, false); + } + } + + boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(pPopupMenu); + 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, aStream.str().c_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 + if( m_pDrawViewWrapper ) + 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) + uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, comphelper::getUnoTunnelImplementation( m_xChartView )); + 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(), getModel() ) ) + { + 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; + OUString 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(getModel())); + if ((fShiftAmountX > 0.0 && (aRect.getX() + fShiftAmountX + aRect.getWidth() > aPageSize.Width)) || + (fShiftAmountX < 0.0 && (aRect.getX() + fShiftAmountX < 0)) || + (fShiftAmountY > 0.0 && (aRect.getY() + fShiftAmountY + aRect.getHeight() > aPageSize.Height)) || + (fShiftAmountY < 0.0 && (aRect.getY() + fShiftAmountY < 0))) + bReturn = false; + else + bReturn = PositionAndSizeHelper::moveObject( + m_aSelection.getSelectedCID(), getModel(), + awt::Rectangle(aRect.getX() + fShiftAmountX, aRect.getY() + fShiftAmountY, aRect.getWidth(), aRect.getHeight()), + awt::Rectangle(aRect.getX(), aRect.getY(), 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( getModel() ) ); + aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX ); + aPos.Y = static_cast< 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) + { + uno::Reference< qa::XDumper > xChartModel( getModel(), uno::UNO_QUERY ); + if(xChartModel.is()) + { + OUString aDump = xChartModel->dump(); + 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 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 ) +{ + uno::Reference< frame::XModel > xChartModel; + if( m_aModel.is()) + xChartModel.set( getModel() ); + 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 + ExplicitValueProvider * pValueProvider( + comphelper::getUnoTunnelImplementation( m_xChartView )); + if( pValueProvider ) + rOutEqualRect = pValueProvider->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::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 & xListener ) +{ + SolarMutexGuard aGuard; + if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode? + return; //behave passive if already disposed or suspended + + //--add listener + m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType::get(), xListener ); +} + +void SAL_CALL ChartController::removeSelectionChangeListener( const uno::Reference & xListener ) +{ + SolarMutexGuard aGuard; + if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode? + return; //behave passive if already disposed or suspended + + //--remove listener + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType::get(), xListener ); +} + +void ChartController::impl_notifySelectionChangeListeners() +{ + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType::get() ); + if( pIC ) + { + uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this); + lang::EventObject aEvent( xSelectionSupplier ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->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 ); + + uno::Reference< frame::XModel > xChartModel( getModel() ); + 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( + comphelper::getUnoTunnelImplementation( m_xChartView )); + 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( const OUString & rCID, double fAdditionalOffset ) +{ + bool bResult = false; + if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 ) + return bResult; + + sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID ); + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( rCID, getModel() )); + 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, 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, 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 = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() ); + switch ( eKind ) + { + case OBJ_LINE: + { + ePointerStyle = PointerStyle::DrawLine; + } + break; + case OBJ_RECT: + case OBJ_CUSTOMSHAPE: + { + ePointerStyle = PointerStyle::DrawRect; + } + break; + case OBJ_CIRC: + { + ePointerStyle = PointerStyle::DrawEllipse; + } + break; + case OBJ_FREELINE: + { + ePointerStyle = PointerStyle::DrawPolygon; + } + break; + case OBJ_TEXT: + { + ePointerStyle = PointerStyle::DrawText; + } + break; + case OBJ_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 + , getModel() ) ) + 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 ); +} + +css::uno::Reference const & ChartController::getChartView() const +{ + return m_xChartView; +} + +void ChartController::sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle) +{ + ChartModel* pChartModel = dynamic_cast(m_aModel->getModel().get()); + if (!pChartModel) + return; + + uno::Reference xPivotTableDataProvider; + xPivotTableDataProvider.set(pChartModel->getDataProvider(), uno::UNO_QUERY); + if (!xPivotTableDataProvider.is()) + return; + + OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName(); + + PopupRequest* pPopupRequest = dynamic_cast(pChartModel->getPopupRequest().get()); + if (!pPopupRequest) + return; + + // Get dimension index from CID + sal_Int32 nStartPos = rCID.lastIndexOf('.'); + nStartPos++; + sal_Int32 nEndPos = rCID.getLength(); + OUString sDimensionIndex = rCID.copy(nStartPos, nEndPos - nStartPos); + sal_Int32 nDimensionIndex = sDimensionIndex.toInt32(); + + awt::Rectangle xRectangle { + sal_Int32(aRectangle.Left()), + sal_Int32(aRectangle.Top()), + sal_Int32(aRectangle.GetWidth()), + sal_Int32(aRectangle.GetHeight()) + }; + + uno::Sequence aCallbackData = comphelper::InitPropertySequence( + { + {"Rectangle", uno::makeAny(xRectangle)}, + {"DimensionIndex", uno::makeAny(nDimensionIndex)}, + {"PivotTableName", uno::makeAny(sPivotTableName)}, + }); + + pPopupRequest->getCallback()->notify(uno::makeAny(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 000000000..15272dfc5 --- /dev/null +++ b/chart2/source/controller/main/ChartDropTargetHelper.cxx @@ -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 . + */ + +#include "ChartDropTargetHelper.hxx" +#include + +#include +#include +#include + +#include +#include + +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& rxDropTarget, + const Reference< chart2::XChartDocument > & xChartDocument ) : + DropTargetHelper( rxDropTarget ), + m_xChartDocument( 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 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] ); + Reference< container::XChild > xChild( m_xChartDocument, uno::UNO_QUERY ); + if( xChild.is()) + { + Reference< frame::XModel > xParentModel( xChild->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) + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); + if( xDataProvider.is() && xDiagram.is() && + DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument )) + { + Reference< chart2::data::XDataSource > xDataSource( + DataSourceHelper::pressUsedDataIntoRectangularFormat( m_xChartDocument )); + Sequence< beans::PropertyValue > aArguments( + xDataProvider->detectArguments( xDataSource )); + + OUString aOldRange; + beans::PropertyValue * pCellRange = nullptr; + for( sal_Int32 i=0; i>= 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; + } + + xDataSource.set( xDataProvider->createDataSource( aArguments )); + xDiagram->setDiagramData( xDataSource, 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 000000000..04c390a00 --- /dev/null +++ b/chart2/source/controller/main/ChartDropTargetHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTDROPTARGETHELPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTDROPTARGETHELPER_HXX + +#include + +namespace com::sun::star { + namespace chart2 { + class XChartDocument; + } +} + +namespace chart +{ + +class ChartDropTargetHelper : public DropTargetHelper +{ +public: + ChartDropTargetHelper() = delete; + explicit ChartDropTargetHelper( + const css::uno::Reference< css::datatransfer::dnd::XDropTarget >& rxDropTarget, + const css::uno::Reference< css::chart2::XChartDocument > & 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; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartDocument; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTDROPTARGETHELPER_HXX +#endif + +/* 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 000000000..c03a3f6b6 --- /dev/null +++ b/chart2/source/controller/main/ChartFrameloader.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 "ChartFrameloader.hxx" +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ + +using namespace ::com::sun::star; + +ChartFrameLoader::ChartFrameLoader( + uno::Reference 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& 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.set( + m_xCC->getServiceManager()->createInstanceWithContext( + CHART_MODEL_SERVICE_IMPLEMENTATION_NAME, m_xCC ) + , uno::UNO_QUERY ); + + if( impl_checkCancel() ) + return false; + } + + //create the controller(+XWindow) + uno::Reference< frame::XController > xController; + uno::Reference< awt::XWindow > xComponentWindow; + { + xController.set( + m_xCC->getServiceManager()->createInstanceWithContext( + CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME,m_xCC ) + , uno::UNO_QUERY ); + + //!!!it is a special characteristic of the example application + //that the controller simultaneously provides the XWindow controller functionality + xComponentWindow = + uno::Reference< awt::XWindow >( xController, uno::UNO_QUERY ); + + if( impl_checkCancel() ) + return false; + } + + //connect frame, controller and model one to each other: + if(xController.is()&&xModel.is()) + { + xModel->connectController(xController); + xModel->setCurrentController(xController); + xController->attachModel(xModel); + if(xFrame.is()) + xFrame->setComponent(xComponentWindow,xController); + //creates the view and menu + //for correct menu creation the initialized component must be already set into the frame + xController->attachFrame(xFrame); + } + + // call initNew() or load() at XLoadable + if(!bHaveLoadedModel) + 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( xComponentWindow.is() && aMDHelper.ISSET_FilterName && aMDHelper.FilterName == "StarChart 5.0" ) + { + 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 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 000000000..d1564b46e --- /dev/null +++ b/chart2/source/controller/main/ChartFrameloader.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTFRAMELOADER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTFRAMELOADER_HXX + +#include +#include +#include +#include + +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 + +#endif + +/* 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 000000000..6348aee6e --- /dev/null +++ b/chart2/source/controller/main/ChartModelClone.cxx @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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::lang::XComponent; + using ::com::sun::star::chart2::XTitled; + using ::com::sun::star::util::XModifiable; + using ::com::sun::star::chart2::data::XDataSource; + using ::com::sun::star::chart2::data::XLabeledDataSequence; + + // = helper + namespace + { + Reference< XModel > lcl_cloneModel( const Reference< XModel > & xModel ) + { + Reference< XModel > xResult; + try + { + const Reference< XCloneable > xCloneable( xModel, UNO_QUERY_THROW ); + xResult.set( xCloneable->createClone(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xResult; + } + + } + + // = ChartModelClone + ChartModelClone::ChartModelClone( const Reference< XModel >& i_model, const ModelFacet i_facet ) + { + m_xModelClone.set( lcl_cloneModel( i_model ) ); + + try + { + if ( i_facet == E_MODEL_WITH_DATA ) + { + const Reference< XChartDocument > xChartDoc( m_xModelClone, UNO_QUERY_THROW ); + ENSURE_OR_THROW( xChartDoc->hasInternalDataProvider(), "invalid chart model" ); + + const Reference< XCloneable > xCloneable( xChartDoc->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; + + try + { + Reference< XComponent > xComp( m_xModelClone, UNO_QUERY_THROW ); + xComp->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + 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 Reference< XModel >& 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 Reference< XModel >& i_model, + const Reference< XModel >& 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 ); + Reference< XChartDocument > xSource( i_modelToCopyFrom, UNO_QUERY_THROW ); + Reference< XChartDocument > xDestination( i_model, UNO_QUERY_THROW ); + + // propagate the correct flag for plotting of hidden values to the data provider and all used sequences + ChartModel& rModel = dynamic_cast(*i_model); + ChartModelHelper::setIncludeHiddenCells(ChartModelHelper::isIncludeHiddenCells( i_modelToCopyFrom ), rModel); + + // diagram + xDestination->setFirstDiagram( xSource->getFirstDiagram() ); + + // main title + Reference< XTitled > xDestinationTitled( xDestination, UNO_QUERY_THROW ); + Reference< XTitled > xSourceTitled( xSource, UNO_QUERY_THROW ); + xDestinationTitled->setTitleObject( xSourceTitled->getTitleObject() ); + + // page background + ::comphelper::copyProperties( + xSource->getPageBackground(), + xDestination->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 ( xDestination->hasInternalDataProvider() ) + { + Reference< XInternalDataProvider > xNewDataProvider( xDestination->getDataProvider(), UNO_QUERY ); + Reference< XDataSource > 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 + Reference< XModifiable > xSourceMod( xSource, UNO_QUERY ); + Reference< XModifiable > xDestMod( xDestination, UNO_QUERY ); + if ( xSourceMod.is() && xDestMod.is() && !xSourceMod->isModified() ) + { + xDestMod->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 000000000..eb5a9b027 --- /dev/null +++ b/chart2/source/controller/main/ChartModelClone.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTMODELCLONE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTMODELCLONE_HXX + +#include +#include + +namespace com::sun::star::chart2 { class XInternalDataProvider; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + + enum ModelFacet + { + E_MODEL, + E_MODEL_WITH_DATA, + E_MODEL_WITH_SELECTION + }; + + class ChartModelClone + { + public: + ChartModelClone( + const css::uno::Reference< css::frame::XModel >& i_model, + const ModelFacet i_facet + ); + + ~ChartModelClone(); + + ChartModelClone(const ChartModelClone&) = delete; + const ChartModelClone& operator=(const ChartModelClone&) = delete; + + ModelFacet getFacet() const; + + void applyToModel( const css::uno::Reference< css::frame::XModel >& i_model ) const; + + static void applyModelContentToModel( + const css::uno::Reference< css::frame::XModel > & i_model, + const css::uno::Reference< css::frame::XModel > & i_modelToCopyFrom, + const css::uno::Reference< css::chart2::XInternalDataProvider > & i_data ); + + void dispose(); + + private: + bool impl_isDisposed() const { return !m_xModelClone.is(); } + + private: + css::uno::Reference< css::frame::XModel > m_xModelClone; + css::uno::Reference< css::chart2::XInternalDataProvider > m_xDataClone; + css::uno::Any m_aSelection; + }; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTMODELCLONE_HXX + +/* 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 000000000..67db8d3e4 --- /dev/null +++ b/chart2/source/controller/main/ChartTransferable.cxx @@ -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 . + */ + +#include + +#include + +#include "ChartTransferable.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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_pMarkedObjModel( nullptr ) + ,m_bDrawing( bDrawing ) +{ + std::unique_ptr pExchgView(std::make_unique( 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_pMarkedObjModel = pExchgView->CreateMarkedObjModel().release(); + } +} + +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_pMarkedObjModel, 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& 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 ) ); + if ( SvxDrawingLayerExport( pMarkedObjModel, xDocOut ) ) + { + rxOStm->Commit(); + } + + 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 000000000..ebe6df966 --- /dev/null +++ b/chart2/source/controller/main/ChartTransferable.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTTRANSFERABLE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTTRANSFERABLE_HXX + +#include + +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& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, + const css::datatransfer::DataFlavor& rFlavor ) override; + +private: + css::uno::Reference< css::graphic::XGraphic > m_xMetaFileGraphic; + SdrModel* m_pMarkedObjModel; + bool m_bDrawing; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CHARTTRANSFERABLE_HXX +#endif + +/* 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 000000000..0971fd079 --- /dev/null +++ b/chart2/source/controller/main/ChartWindow.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 +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define TWIPS_PER_PIXEL 15 + +using namespace ::com::sun::star; + +namespace +{ +::tools::Rectangle lcl_AWTRectToVCLRect( const css::awt::Rectangle & rAWTRect ) +{ + ::tools::Rectangle aResult; + aResult.setX( rAWTRect.X ); + aResult.setY( 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 + SetAntialiasing( AntialiasingFlags::EnableB2dDraw | 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( m_pWindowController ) + return m_pWindowController->CreateAccessible(); + else + return Window::CreateAccessible(); +} + +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( rHEvt.GetMousePosPixel()); // old chart: GetPointerPosPixel() + Point aLogicHitPos = PixelToLogic( GetPointerPosPixel()); + OUString aQuickHelpText; + awt::Rectangle aHelpRect; + bool bIsBalloonHelp( Help::IsBalloonHelpEnabled() ); + bHelpHandled = m_pWindowController->requestQuickHelp( aLogicHitPos, bIsBalloonHelp, aQuickHelpText, aHelpRect ); + + if( bHelpHandled ) + { + if( bIsBalloonHelp ) + Help::ShowBalloon( + this, rHEvt.GetMousePosPixel(), lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText ); + else + Help::ShowQuickHelp( + this, lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText ); + } + } + + if( !bHelpHandled ) + vcl::Window::RequestHelp( rHEvt ); +} + +void ChartWindow::LogicMouseButtonDown(const MouseEvent& rEvent) +{ + MouseButtonDown(rEvent); +} + +void ChartWindow::LogicMouseButtonUp(const MouseEvent& rEvent) +{ + MouseButtonUp(rEvent); +} + +void ChartWindow::LogicMouseMove(const MouseEvent& rEvent) +{ + MouseMove(rEvent); +} + +void ChartWindow::adjustHighContrastMode() +{ + static const DrawModeFlags nContrastMode = + DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | + DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient; + + bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode(); + SetDrawMode( bUseContrast ? nContrastMode : DrawModeFlags::Default ); +} + +void ChartWindow::ForceInvalidate() +{ + vcl::Window::Invalidate(); +} +void ChartWindow::Invalidate( InvalidateFlags nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + vcl::Window::Invalidate( nFlags ); +} +void ChartWindow::Invalidate( const tools::Rectangle& rRect, InvalidateFlags nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + vcl::Window::Invalidate( rRect, nFlags ); +} +void ChartWindow::Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + vcl::Window::Invalidate( rRegion, nFlags ); +} + +void ChartWindow::LogicInvalidate(const tools::Rectangle* pRectangle) +{ + SfxViewShell* pCurrentShell = SfxViewShell::Current(); + if ( nullptr == pCurrentShell ) + return; + OString sRectangle; + if (!pRectangle) + { + // we have to invalidate the whole chart area not the whole document + sRectangle = GetBoundingBox().toString(); + } + else + { + tools::Rectangle aRectangle(*pRectangle); + // When dragging shapes the map mode is disabled. + if (IsMapModeEnabled()) + { + if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM) + aRectangle = OutputDevice::LogicToLogic(aRectangle, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); + } + else + { + aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip)); + } + + vcl::Window* pEditWin = GetParentEditWin(); + if (pEditWin) + { + MapMode aCWMapMode = GetMapMode(); + double fXScale( aCWMapMode.GetScaleX() ); + double fYScale( aCWMapMode.GetScaleY() ); + + if (!IsMapModeEnabled()) + { + aRectangle.SetLeft( aRectangle.Left() / fXScale ); + aRectangle.SetRight( aRectangle.Right() / fXScale ); + aRectangle.SetTop( aRectangle.Top() / fYScale ); + aRectangle.SetBottom( aRectangle.Bottom() / fYScale ); + } + + Point aOffset = this->GetOffsetPixelFrom(*pEditWin); + aOffset.setX( aOffset.X() * (TWIPS_PER_PIXEL / fXScale) ); + aOffset.setY( aOffset.Y() * (TWIPS_PER_PIXEL / fYScale) ); + + aRectangle = tools::Rectangle(aRectangle.TopLeft() + aOffset, aRectangle.GetSize()); + } + + sRectangle = aRectangle.toString(); + } + SfxLokHelper::notifyInvalidation(pCurrentShell, sRectangle); +} + +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(); + double fXScale( aCWMapMode.GetScaleX() ); + double fYScale( aCWMapMode.GetScaleY() ); + Point aOffset = GetOffsetPixelFrom(*pRootWin); + aOffset.setX( aOffset.X() * (TWIPS_PER_PIXEL / fXScale) ); + aOffset.setY( aOffset.Y() * (TWIPS_PER_PIXEL / fYScale) ); + Size aSize = GetSizePixel(); + aSize.setWidth( aSize.Width() * (TWIPS_PER_PIXEL / fXScale) ); + aSize.setHeight( aSize.Height() * (TWIPS_PER_PIXEL / fYScale) ); + 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 000000000..22e0a52c2 --- /dev/null +++ b/chart2/source/controller/main/CommandDispatch.cxx @@ -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 . + */ + +#include "CommandDispatch.hxx" +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +template< class Map > + void lcl_DisposeAndClearAndDeleteAllMapElements( + Map & rMap, + const Reference< uno::XInterface > & xEventSource ) +{ + for( const auto& rElement : rMap ) + { + if( rElement.second ) + { + rElement.second->disposeAndClear( xEventSource ); + delete rElement.second; + } + } +} + +} // anonymous namespace + +namespace chart +{ + +CommandDispatch::CommandDispatch( + const Reference< uno::XComponentContext > & xContext ) : + impl::CommandDispatch_Base( m_aMutex ), + m_xContext( xContext ) +{ +} + +CommandDispatch::~CommandDispatch() +{} + +void CommandDispatch::initialize() +{} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL CommandDispatch::disposing() +{ + lcl_DisposeAndClearAndDeleteAllMapElements( m_aListeners, static_cast< cppu::OWeakObject* >( this )); + 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 ) +{ + tListenerMap::iterator aIt( m_aListeners.find( URL.Complete )); + if( aIt == m_aListeners.end()) + { + aIt = m_aListeners.insert( + m_aListeners.begin(), + tListenerMap::value_type( URL.Complete, new ::comphelper::OInterfaceContainerHelper2( m_aMutex ))); + } + OSL_ASSERT( aIt != m_aListeners.end()); + + aIt->second->addInterface( Control ); + fireStatusEvent( URL.Complete, Control ); +} + +void SAL_CALL CommandDispatch::removeStatusListener( const Reference< frame::XStatusListener >& Control, const util::URL& URL ) +{ + tListenerMap::iterator aIt( m_aListeners.find( URL.Complete )); + if( aIt != m_aListeners.end()) + (*aIt).second->removeInterface( 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()) + { + if( aIt->second ) + { + ::comphelper::OInterfaceIteratorHelper2 aIntfIt( *((*aIt).second) ); + + while( aIntfIt.hasMoreElements()) + { + Reference< frame::XStatusListener > xListener( aIntfIt.next(), uno::UNO_QUERY ); + try + { + if( xListener.is()) + xListener->statusChanged( aEventToSend ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + } +} + +} // 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 000000000..00638a6c0 --- /dev/null +++ b/chart2/source/controller/main/CommandDispatch.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCH_HXX + +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XURLTransformer; } + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper< + css::frame::XDispatch, + css::util::XModifyListener > + CommandDispatch_Base; +} + +/** This is the base class for an XDispatch. + */ +class CommandDispatch : + public MutexContainer, + 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 SAL_CALL disposing() 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::OInterfaceContainerHelper2* > + tListenerMap; + + tListenerMap m_aListeners; + +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_COMMANDDISPATCH_HXX +#endif + +/* 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 000000000..b007ebe5c --- /dev/null +++ b/chart2/source/controller/main/CommandDispatchContainer.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 +#include "UndoCommandDispatch.hxx" +#include "StatusBarCommandDispatch.hxx" +#include +#include "DrawCommandDispatch.hxx" +#include "ShapeController.hxx" + +#include +#include +#include + +#include + +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 Reference< frame::XModel > & xModel ) +{ + // remove all existing dispatcher that base on the old model + m_aCachedDispatches.clear(); + DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches ); + m_aToBeDisposedDispatches.clear(); + m_xModel = xModel; +} + +void CommandDispatchContainer::setChartDispatch( + const Reference< frame::XDispatch >& rChartDispatch, + const o3tl::sorted_vector< OUString > & rChartCommands ) +{ + OSL_ENSURE(rChartDispatch.is(),"Invalid fall back dispatcher!"); + m_xChartDispatcher.set( rChartDispatch ); + m_aChartCommands = 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 + { + uno::Reference< frame::XModel > xModel( m_xModel ); + + if( xModel.is() && ( rURL.Path == "Undo" || rURL.Path == "Redo" || + rURL.Path == "GetUndoStrings" || rURL.Path == "GetRedoStrings" ) ) + { + 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 ); + 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 ); + + for( sal_Int32 nPos = 0; nPos < nCount; ++nPos ) + { + if ( aDescriptors[ nPos ].FrameName == "_self" ) + aRet[ 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/ConfigurationAccess.cxx b/chart2/source/controller/main/ConfigurationAccess.cxx new file mode 100644 index 000000000..2d1dcfcf9 --- /dev/null +++ b/chart2/source/controller/main/ConfigurationAccess.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 + +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +namespace +{ +bool lcl_IsMetric() +{ + SvtSysLocale aSysLocale; + const LocaleDataWrapper* pLocWrapper = aSysLocale.GetLocaleDataPtr(); + MeasurementSystem eSys = pLocWrapper->getMeasurementSystemEnum(); + + return ( eSys == MeasurementSystem::Metric ); +} + +class CalcConfigItem : public ::utl::ConfigItem +{ +private: + virtual void ImplCommit() override; + +public: + CalcConfigItem(); + + FieldUnit getFieldUnit(); + virtual void Notify( const uno::Sequence& aPropertyNames) override; +}; + +}//end anonymous namespace + +CalcConfigItem::CalcConfigItem() + : ConfigItem( "Office.Calc/Layout" ) +{ +} + +void CalcConfigItem::ImplCommit() {} +void CalcConfigItem::Notify( const uno::Sequence& ) {} + +FieldUnit CalcConfigItem::getFieldUnit() +{ + FieldUnit eResult( FieldUnit::CM ); + + uno::Sequence< OUString > aNames( 1 ); + if( lcl_IsMetric() ) + aNames[ 0 ] = "Other/MeasureUnit/Metric"; + else + aNames[ 0 ] = "Other/MeasureUnit/NonMetric"; + + uno::Sequence< uno::Any > aResult( GetProperties( aNames )); + sal_Int32 nValue = 0; + if( aResult[ 0 ] >>= nValue ) + eResult = static_cast< FieldUnit >( nValue ); + + return eResult; +} + +namespace +{ + //a CalcConfigItem Singleton + struct theCalcConfigItem : public rtl::Static< CalcConfigItem, theCalcConfigItem > {}; +} + +namespace ConfigurationAccess +{ + FieldUnit getFieldUnit() + { + FieldUnit aUnit( theCalcConfigItem::get().getFieldUnit() ); + return aUnit; + } +} //namespace ConfigurationAccess + +} //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 000000000..aa21b77fb --- /dev/null +++ b/chart2/source/controller/main/ControllerCommandDispatch.cxx @@ -0,0 +1,837 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ShapeController.hxx" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// only needed until #i68864# is fixed +#include + +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 { + static bool const MOVE_SERIES_FORWARD = true; + static 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 Reference< frame::XModel > & 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 Reference< frame::XModel > & 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; + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + bIsFormateableObjectSelected = bHasSelectedObject && aSelOID.isAutoGeneratedObject(); + if( aObjectType==OBJECTTYPE_DIAGRAM || aObjectType==OBJECTTYPE_DIAGRAM_WALL || aObjectType==OBJECTTYPE_DIAGRAM_FLOOR ) + bIsFormateableObjectSelected = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + + uno::Reference< chart2::XDataSeries > xGivenDataSeries( + ObjectIdentifier::getDataSeriesForCID( + aSelObjCID, xModel ) ); + + bIsDeleteableObjectSelected = ChartController::isObjectDeleteable( aSelObj ); + + bMayMoveSeriesForward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + xGivenDataSeries, + MOVE_SERIES_FORWARD ); + + bMayMoveSeriesBackward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + 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 = DiagramHelper::getDimension( xDiagram ); + uno::Reference< chart2::XChartType > xFirstChartType( + DataSeriesHelper::getChartTypeOfSeries( xGivenDataSeries, xDiagram )); + + // trend lines/mean value line + if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT) + && ChartTypeHelper::isSupportingRegressionProperties( xFirstChartType, nDimensionCount )) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xGivenDataSeries, uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + // Trendline + bMayAddTrendline = true; + + // Mean Value + bMayFormatMeanValue = bMayDeleteMeanValue = RegressionCurveHelper::hasMeanValueLine( xRegCurveCnt ); + 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; + } + else if( aObjectType == OBJECTTYPE_DATA_CURVE_EQUATION ) + { + bMayFormatTrendlineEquation = true; + bool bHasR2Value = false; + try + { + uno::Reference< beans::XPropertySet > xEquationProperties = + ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ); + if( xEquationProperties.is() ) + xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient" ) >>= bHasR2Value; + } + catch(const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + bMayAddR2Value = !bHasR2Value; + 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 Reference< frame::XModel > & 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; +}; + +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 Reference< frame::XModel > & xModel ) +{ + Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + + bIsReadOnly = true; + Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY ); + if( xStorable.is()) + bIsReadOnly = xStorable->isReadonly(); + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + uno::Reference< chart2::XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + bSupportsStatistics = ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount ); + bSupportsAxes = ChartTypeHelper::isSupportingMainAxis( xFirstChartType, nDimensionCount, 0 ); + + bIsThreeD = (nDimensionCount == 3); + if (xChartDoc.is()) + { + ChartModel& rModel = dynamic_cast(*xChartDoc); + bHasOwnData = rModel.hasInternalDataProvider(); + bHasDataFromPivotTable = !bHasOwnData && rModel.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( xChartDoc ) == + ReferenceSizeProvider::AUTO_RESIZE_YES); + + bHasLegend = LegendHelper::hasLegend( xDiagram ); + bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + bHasFloor = bHasWall && bIsThreeD; +} + +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; + + Reference< frame::XModel > xModel( m_xChartController->getModel()); + Reference< util::XModifyBroadcaster > xModifyBroadcaster( xModel, uno::UNO_QUERY ); + OSL_ASSERT( xModifyBroadcaster.is()); + if( xModifyBroadcaster.is()) + xModifyBroadcaster->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.get(), 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", "" ); + } + } + + Reference< chart2::XChartDocument > xChartDoc(m_xChartController->getModel(), uno::UNO_QUERY); + OSL_ENSURE(xChartDoc.is(), "Invalid XChartDocument"); + if ( xChartDoc.is() ) + { + ChartModel& rModel = dynamic_cast(*xChartDoc); + css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(rModel.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" ] <<= m_apModelState->bHasMainYGrid; + m_aCommandAvailability[ ".uno:ToggleGridVertical" ] = bIsWritable; + m_aCommandArguments[ ".uno:ToggleGridVertical" ] <<= m_apModelState->bHasMainXGrid; + + m_aCommandAvailability[ ".uno:ToggleLegend" ] = bIsWritable; + m_aCommandArguments[ ".uno:ToggleLegend" ] <<= 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 && 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 && m_apControllerState->bIsTextObject; + + // 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" ] <<= 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; + m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendlineEquation; + m_aCommandAvailability[ ".uno:InsertTrendlineEquationAndR2" ] = m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ]; + m_aCommandAvailability[ ".uno:InsertR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddR2Value; + 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; +} + +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.get()); + 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.get() )); + 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 SAL_CALL ControllerCommandDispatch::disposing() +{ + 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->getModel()); + bUpdateCommandAvailability = true; + } + + // Update the "ControllerState" Struct. + if( m_apControllerState && m_xChartController.is()) + { + m_apControllerState->update( m_xChartController.get(), m_xChartController->getModel()); + 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.get(), m_xChartController->getModel()); + 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 000000000..67a07514e --- /dev/null +++ b/chart2/source/controller/main/ControllerCommandDispatch.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CONTROLLERCOMMANDDISPATCH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CONTROLLERCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" +#include +#include +#include + +#include + +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 SAL_CALL disposing() 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 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_CONTROLLERCOMMANDDISPATCH_HXX +#endif + +/* 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 000000000..9e01d5c3b --- /dev/null +++ b/chart2/source/controller/main/DragMethod_Base.cxx @@ -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 . + */ + +#include "DragMethod_Base.hxx" +#include + +#include +#include + +#include +#include +#include + +namespace chart +{ + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::WeakReference; + +DragMethod_Base::DragMethod_Base( DrawViewWrapper& rDrawViewWrapper + , const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel + , ActionDescriptionProvider::ActionType eActionType ) + : SdrDragMethod( rDrawViewWrapper ) + , m_rDrawViewWrapper(rDrawViewWrapper) + , m_aObjectCID(rObjectCID) + , m_eActionType( eActionType ) + , m_xChartModel( WeakReference< frame::XModel >(xChartModel) ) +{ + setMoveOnly(true); +} +DragMethod_Base::~DragMethod_Base() +{ +} + +Reference< frame::XModel > DragMethod_Base::getChartModel() const +{ + return Reference< frame::XModel >( m_xChartModel ); +} + +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 000000000..9ae8090fc --- /dev/null +++ b/chart2/source/controller/main/DragMethod_Base.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_BASE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_BASE_HXX + +#include +#include +#include + +namespace chart { class DrawViewWrapper; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class DragMethod_Base : public SdrDragMethod +{ +public: + DragMethod_Base( DrawViewWrapper& rDrawViewWrapper, const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& 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: + css::uno::Reference< css::frame::XModel > getChartModel() const; + +protected: + DrawViewWrapper& m_rDrawViewWrapper; + OUString m_aObjectCID; + ActionDescriptionProvider::ActionType m_eActionType; + +private: + css::uno::WeakReference< css::frame::XModel > m_xChartModel; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_BASE_HXX +#endif + +/* 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 000000000..9814a5db6 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_PieSegment.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 "DragMethod_PieSegment.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 Reference< frame::XModel >& 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 ) +{ + OUString 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((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(aNewPosVector.getX()), static_cast(aNewPosVector.getY()) ); + if( aNewPos != DragStat().GetNow() ) + { + Hide(); + DragStat().NextMove( aNewPos ); + Show(); + } +} +bool DragMethod_PieSegment::EndSdrDrag(bool /*bCopy*/) +{ + Hide(); + + try + { + Reference< frame::XModel > 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() +{ + 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 ) + { + const basegfx::B2DPolyPolygon aNewPolyPolygon(pObj->TakeXorPoly()); + addSdrDragEntry(std::unique_ptr(new SdrDragEntryPolyPolygon(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 000000000..4a1264a01 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_PieSegment.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_PIESEGMENT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_PIESEGMENT_HXX + +#include "DragMethod_Base.hxx" +#include + +namespace chart +{ + +class DragMethod_PieSegment : public DragMethod_Base +{ +public: + DragMethod_PieSegment( DrawViewWrapper& rDrawViewWrapper, const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& 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() 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_PIESEGMENT_HXX +#endif + +/* 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 000000000..7501f0bf7 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.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 "DragMethod_RotateDiagram.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +DragMethod_RotateDiagram::DragMethod_RotateDiagram( DrawViewWrapper& rDrawViewWrapper + , const OUString& rObjectCID + , const Reference< frame::XModel >& 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_aWireframePolyPolygon() + , 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(); + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram(getChartModel()) ); + uno::Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + if( !xDiagramProperties.is() ) + return; + + ThreeDHelper::getRotationFromDiagram( xDiagramProperties + , m_nInitialHorizontalAngleDegree, m_nInitialVerticalAngleDegree ); + + ThreeDHelper::getRotationAngleFromDiagram( xDiagramProperties + , m_fInitialXAngleRad, m_fInitialYAngleRad, m_fInitialZAngleRad ); + + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + xDiagramProperties->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 = F_PI2 * static_cast(rPnt.Y() - m_aStartPos.Y()) + / (m_aReferenceRect.GetHeight() > 0 ? static_cast(m_aReferenceRect.GetHeight()) : 1.0); + double fY = F_PI * static_cast(rPnt.X() - m_aStartPos.X()) + / (m_aReferenceRect.GetWidth() > 0 ? static_cast(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(basegfx::rad2deg(m_fAdditionalXAngleRad)); + m_nAdditionalVerticalAngleDegree = -static_cast(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 ); + + ThreeDHelper::setRotationAngleToDiagram( uno::Reference< beans::XPropertySet >( ChartModelHelper::findDiagram( getChartModel() ), uno::UNO_QUERY ) + , fResultX, fResultY, fResultZ ); + } + else + { + ThreeDHelper::setRotationToDiagram( ( uno::Reference< beans::XPropertySet >( ChartModelHelper::findDiagram( getChartModel() ), uno::UNO_QUERY ) ) + , 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 pNew( + new sdr::overlay::OverlayPolyPolygonStripedAndFilled( + 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 000000000..a9401c923 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_ROTATEDIAGRAM_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_ROTATEDIAGRAM_HXX + +#include "DragMethod_Base.hxx" + +#include + +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 css::uno::Reference< css::frame::XModel >& 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 + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAGMETHOD_ROTATEDIAGRAM_HXX +#endif + +/* 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 000000000..24ed70957 --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.cxx @@ -0,0 +1,619 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 "DrawCommandDispatch.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 ) +{ + sal_uInt16 nFeatureId = 0; + OUString aBaseCommand; + OUString aCustomShapeType; + return parseCommandURL( rCommandURL, &nFeatureId, &aBaseCommand, &aCustomShapeType ); +} + +static ::basegfx::B2DPolyPolygon getPolygon(const char* pResId, const SdrModel& rModel) +{ + ::basegfx::B2DPolyPolygon aReturn; + XLineEndListRef pLineEndList = rModel.GetLineEndList(); + if ( pLineEndList.is() ) + { + OUString aName(SvxResId(pResId)); + long nCount = pLineEndList->Count(); + for ( 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() == OBJ_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(); + SfxItemSet aDest( + pObj->getSdrModelFromSdrObject().GetItemPool(), + svl::Items< + // 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.Set( rSource ); + pObj->SetMergedItemSet( aDest ); + sal_Int32 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + { + double a = nAngle * F_PI18000; + pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) ); + } + 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 == COMMAND_ID_LINE_ARROW_END && 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 ); + + long nWidth = 300; // (1/100th mm) + if ( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE ) + { + 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() +{ +} + +// XEventListener +void DrawCommandDispatch::disposing( const lang::EventObject& /* Source */ ) +{ +} + +FeatureState DrawCommandDispatch::getState( const OUString& rCommand ) +{ + FeatureState aReturn; + aReturn.bEnabled = false; + aReturn.aState <<= false; + + sal_uInt16 nFeatureId = 0; + OUString aBaseCommand; + OUString aCustomShapeType; + if ( parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) ) + { + switch ( nFeatureId ) + { + case COMMAND_ID_OBJECT_SELECT: + case COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + case COMMAND_ID_DRAW_RECT: + case COMMAND_ID_DRAW_ELLIPSE: + case COMMAND_ID_DRAW_FREELINE_NOFILL: + case COMMAND_ID_DRAW_TEXT: + case COMMAND_ID_DRAW_CAPTION: + case COMMAND_ID_DRAWTBX_CS_BASIC: + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + case COMMAND_ID_DRAWTBX_CS_ARROW: + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + case COMMAND_ID_DRAWTBX_CS_STAR: + { + 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 = OBJ_NONE; + + sal_uInt16 nFeatureId = 0; + OUString aBaseCommand; + OUString aCustomShapeType; + if ( !parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) ) + return; + + bool bCreate = false; + m_nFeatureId = nFeatureId; + m_aCustomShapeType = aCustomShapeType; + + switch ( nFeatureId ) + { + case COMMAND_ID_OBJECT_SELECT: + { + eDrawMode = CHARTDRAW_SELECT; + eKind = OBJ_NONE; + } + break; + case COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_LINE; + } + break; + case COMMAND_ID_DRAW_RECT: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_RECT; + } + break; + case COMMAND_ID_DRAW_ELLIPSE: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CIRC; + } + break; + case COMMAND_ID_DRAW_FREELINE_NOFILL: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_FREELINE; + } + break; + case COMMAND_ID_DRAW_TEXT: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_TEXT; + bCreate = true; + } + break; + case COMMAND_ID_DRAW_CAPTION: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CAPTION; + } + break; + case COMMAND_ID_DRAWTBX_CS_BASIC: + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + case COMMAND_ID_DRAWTBX_CS_ARROW: + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + case COMMAND_ID_DRAWTBX_CS_STAR: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CUSTOMSHAPE; + } + break; + default: + { + eDrawMode = CHARTDRAW_SELECT; + eKind = OBJ_NONE; + } + break; + } + + if ( !m_pChartController ) + return; + + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( !pDrawViewWrapper ) + return; + + SolarMutexGuard aGuard; + m_pChartController->setDrawMode( eDrawMode ); + setInsertObj( sal::static_int_cast< sal_uInt16 >( eKind ) ); + if ( bCreate ) + { + pDrawViewWrapper->SetCreateMode(); + } + + const OUString sKeyModifier( "KeyModifier" ); + const beans::PropertyValue* pIter = rArgs.getConstArray(); + const beans::PropertyValue* pEnd = pIter + rArgs.getLength(); + const beans::PropertyValue* pKeyModifier = std::find_if(pIter, pEnd, + [&sKeyModifier](const beans::PropertyValue& lhs) + {return lhs.Name == sKeyModifier;} ); + sal_Int16 nKeyModifier = 0; + if ( !(pKeyModifier != pEnd && ( pKeyModifier->Value >>= nKeyModifier ) && nKeyModifier == KEY_MOD1) ) + return; + + if ( eDrawMode != CHARTDRAW_INSERT ) + return; + + SdrObject* pObj = createDefaultObject( nFeatureId ); + if ( pObj ) + { + SdrPageView* pPageView = pDrawViewWrapper->GetSdrPageView(); + if (pDrawViewWrapper->InsertObjectAtView(pObj, *pPageView)) + m_pChartController->SetAndApplySelection(Reference(pObj->getUnoShape(), uno::UNO_QUERY)); + if ( nFeatureId == COMMAND_ID_DRAW_TEXT ) + { + m_pChartController->StartTextEdit(); + } + } +} + +void DrawCommandDispatch::describeSupportedFeatures() +{ + implDescribeSupportedFeature( ".uno:SelectObject", COMMAND_ID_OBJECT_SELECT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Line", COMMAND_ID_DRAW_LINE, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:LineArrowEnd", COMMAND_ID_LINE_ARROW_END, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Rect", COMMAND_ID_DRAW_RECT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Ellipse", COMMAND_ID_DRAW_ELLIPSE, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Freeline_Unfilled", COMMAND_ID_DRAW_FREELINE_NOFILL, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:DrawText", COMMAND_ID_DRAW_TEXT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:DrawCaption", COMMAND_ID_DRAW_CAPTION, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes", COMMAND_ID_DRAWTBX_CS_BASIC, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes", COMMAND_ID_DRAWTBX_CS_SYMBOL, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes", COMMAND_ID_DRAWTBX_CS_ARROW, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes", COMMAND_ID_DRAWTBX_CS_FLOWCHART, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes", COMMAND_ID_DRAWTBX_CS_CALLOUT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes", COMMAND_ID_DRAWTBX_CS_STAR, CommandGroup::INSERT ); +} + +void DrawCommandDispatch::setInsertObj( sal_uInt16 eObj ) +{ + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr ); + if ( pDrawViewWrapper ) + { + pDrawViewWrapper->SetCurrentObj( eObj /*, Inventor */); + } +} + +SdrObject* DrawCommandDispatch::createDefaultObject( const sal_uInt16 nID ) +{ + SdrObject* pObj = nullptr; + 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 COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + { + if ( auto const pathObj = dynamic_cast( pObj) ) + { + 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 COMMAND_ID_DRAW_FREELINE_NOFILL: + { + if ( auto const pathObj = dynamic_cast( pObj) ) + { + 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 COMMAND_ID_DRAW_TEXT: + case COMMAND_ID_DRAW_TEXT_VERTICAL: + { + if ( SdrTextObj* pTextObj = dynamic_cast( pObj) ) + { + pTextObj->SetLogicRect( aRect ); + bool bVertical = ( nID == COMMAND_ID_DRAW_TEXT_VERTICAL ); + 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 COMMAND_ID_DRAW_CAPTION: + case COMMAND_ID_DRAW_CAPTION_VERTICAL: + { + if ( SdrCaptionObj* pCaptionObj = dynamic_cast( pObj) ) + { + bool bIsVertical( nID == COMMAND_ID_DRAW_CAPTION_VERTICAL ); + 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 ); + pObj->SetMergedItemSet( aSet ); + } + break; + } + } + } + } + + return pObj; +} + +bool DrawCommandDispatch::parseCommandURL( const OUString& rCommandURL, sal_uInt16* pnFeatureId, + OUString* pBaseCommand, OUString* pCustomShapeType ) +{ + bool bFound = true; + sal_uInt16 nFeatureId = 0; + OUString aBaseCommand; + OUString aType; + + sal_Int32 nIndex = 1; + OUString aToken = rCommandURL.getToken( 0, '.', nIndex ); + if ( nIndex == -1 || aToken.isEmpty() ) + { + aBaseCommand = rCommandURL; + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( aBaseCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + nFeatureId = aIter->second.nFeatureId; + + switch ( nFeatureId ) + { + case COMMAND_ID_DRAWTBX_CS_BASIC: + { + aType = "diamond"; + } + break; + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + { + aType = "smiley"; + } + break; + case COMMAND_ID_DRAWTBX_CS_ARROW: + { + aType = "left-right-arrow"; + } + break; + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + { + aType = "flowchart-internal-storage"; + } + break; + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + { + aType = "round-rectangular-callout"; + } + break; + case COMMAND_ID_DRAWTBX_CS_STAR: + { + 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.h b/chart2/source/controller/main/DrawCommandDispatch.h new file mode 100644 index 000000000..faf70bde1 --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.h @@ -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 . + */ +#ifndef CHART_DRAWCOMMANDDISPATCH_HRC +#define CHART_DRAWCOMMANDDISPATCH_HRC + +//Command Ids: +#define COMMAND_ID_OBJECT_SELECT 1 +#define COMMAND_ID_DRAW_LINE 2 +#define COMMAND_ID_LINE_ARROW_END 3 +#define COMMAND_ID_DRAW_RECT 4 +#define COMMAND_ID_DRAW_ELLIPSE 5 +#define COMMAND_ID_DRAW_FREELINE_NOFILL 6 +#define COMMAND_ID_DRAW_TEXT 7 +#define COMMAND_ID_DRAW_TEXT_VERTICAL 8 +#define COMMAND_ID_DRAW_CAPTION 9 +#define COMMAND_ID_DRAW_CAPTION_VERTICAL 10 +#define COMMAND_ID_DRAWTBX_CS_BASIC 11 +#define COMMAND_ID_DRAWTBX_CS_SYMBOL 12 +#define COMMAND_ID_DRAWTBX_CS_ARROW 13 +#define COMMAND_ID_DRAWTBX_CS_FLOWCHART 14 +#define COMMAND_ID_DRAWTBX_CS_CALLOUT 15 +#define COMMAND_ID_DRAWTBX_CS_STAR 16 + +#endif + +/* 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 000000000..7df47171a --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAWCOMMANDDISPATCH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAWCOMMANDDISPATCH_HXX + +#include "FeatureCommandDispatchBase.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 SAL_CALL disposing() 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( sal_uInt16 eObj ); + SdrObject* createDefaultObject( const sal_uInt16 nID ); + + bool parseCommandURL( const OUString& rCommandURL, sal_uInt16* pnFeatureId, OUString* pBaseCommand, OUString* pCustomShapeType ); + + ChartController* m_pChartController; + OUString m_aCustomShapeType; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_DRAWCOMMANDDISPATCH_HXX +#endif + +/* 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 000000000..46e601954 --- /dev/null +++ b/chart2/source/controller/main/ElementSelector.cxx @@ -0,0 +1,328 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +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 +{ +static const char lcl_aServiceName[] = "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) +{ + 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(); +} + +void SelectorListBox::GetFocus() +{ + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); +} + +SelectorListBox::~SelectorListBox() +{ + disposeOnce(); +} + +static void lcl_addObjectsToList( const ObjectHierarchy& rHierarchy, const ObjectIdentifier & rParent, std::vector< ListBoxEntryData >& rEntries + , const sal_Int32 nHierarchyDepth, const Reference< chart2::XChartDocument >& 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 Reference< frame::XController >& xChartController ) +{ + m_xChartController = xChartController; +} + +void SelectorListBox::UpdateChartElementsListAndSelection() +{ + m_xWidget->clear(); + m_aEntries.clear(); + + Reference< frame::XController > xChartController( m_xChartController ); + if( xChartController.is() ) + { + Reference< view::XSelectionSupplier > xSelectionSupplier( xChartController, uno::UNO_QUERY); + ObjectIdentifier aSelectedOID; + OUString aSelectedCID; + if( xSelectionSupplier.is() ) + { + aSelectedOID = ObjectIdentifier( xSelectionSupplier->getSelection() ); + aSelectedCID = aSelectedOID.getObjectCID(); + } + + Reference< chart2::XChartDocument > xChartDoc( xChartController->getModel(), uno::UNO_QUERY ); + 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; + Reference< lang::XMultiServiceFactory > xFact( xChartController->getModel(), uno::UNO_QUERY ); + 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) + { + m_xWidget->append_text(entry.UIName); + 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; + } + + Reference< frame::XController > xController( m_xChartController ); + 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; + Reference< view::XSelectionSupplier > xSelectionSupplier( m_xChartController.get(), uno::UNO_QUERY ); + if( xSelectionSupplier.is() ) + xSelectionSupplier->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() throw () +{ + ToolboxController::acquire(); +} +void SAL_CALL ElementSelectorToolbarController::release() throw () +{ + 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; + m_apSelectorListBox->SetChartController( xChartController ); + 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 pParent = VCLUnoHelper::GetWindow( xParent ); + if( pParent ) + { + m_apSelectorListBox.reset(VclPtr::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 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 000000000..01cfd273c --- /dev/null +++ b/chart2/source/controller/main/ElementSelector.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_ELEMENTSELECTOR_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_ELEMENTSELECTOR_HXX + +#include +#include +#include +#include +#include + +#include +#include + +namespace chart +{ + +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; + + virtual void GetFocus() override; + + void ReleaseFocus_Impl(); + + void SetChartController( const css::uno::Reference< css::frame::XController >& xChartController ); + void UpdateChartElementsListAndSelection(); + +private: + css::uno::WeakReference m_xChartController; + std::unique_ptr m_xWidget; + + std::vector 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() throw () override; + virtual void SAL_CALL release() throw () 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 + +#endif + +/* 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 000000000..90dcf77b2 --- /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( 0 ) +{ +} + +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, + sal_uInt16 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 000000000..e1125cd8e --- /dev/null +++ b/chart2/source/controller/main/FeatureCommandDispatchBase.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_FEATURECOMMANDDISPATCHBASE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_FEATURECOMMANDDISPATCHBASE_HXX + +#include "CommandDispatch.hxx" + +#include + +namespace chart +{ + +struct ControllerFeature: public css::frame::DispatchInformation +{ + sal_uInt16 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 describeSupportedFeatures. + + @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 CommandGroup. + */ + void implDescribeSupportedFeature( const char* pAsciiCommandURL, sal_uInt16 nId, + sal_Int16 nGroup ); + + mutable SupportedFeatures m_aSupportedFeatures; + + sal_uInt16 m_nFeatureId; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_FEATURECOMMANDDISPATCHBASE_HXX +#endif + +/* 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 000000000..32762762e --- /dev/null +++ b/chart2/source/controller/main/ObjectHierarchy.cxx @@ -0,0 +1,845 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 lcl_ObjectToOID +{ + explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) : + m_xModel( xChartDoc ) + {} + + ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj ) + { + return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) ); + } + +private: + Reference< frame::XModel > m_xModel; +}; + +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 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 Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel ) +{ + Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY ); + if( xAxisTitled.is()) + { + Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject()); + if( xAxisTitle.is()) + rContainer.emplace_back( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) ); + } +} + +} // anonymous namespace + +namespace chart +{ + +namespace impl +{ + +class ImplObjectHierarchy +{ +public: + explicit ImplObjectHierarchy( + const Reference< XChartDocument >& xChartDocument, + ExplicitValueProvider* pExplicitValueProvider, + bool bFlattenDiagram, bool bOrderingForElementSelector ); + + bool hasChildren( const ObjectIdentifier& rParent ); + ObjectHierarchy::tChildContainer getChildren( const ObjectIdentifier& rParent ); + ObjectHierarchy::tChildContainer getSiblings( const ObjectIdentifier& rNode ); + + ObjectIdentifier getParent( const ObjectIdentifier& rOID ); + +private: + void createTree( const Reference< XChartDocument > & xChartDocument ); + void createAxesTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ); + void createDiagramTree( + ObjectHierarchy::tChildContainer& rContainer, + const Reference< XChartDocument >& xChartDoc, + const Reference< XDiagram >& xDiagram ); + void createDataSeriesTree( + ObjectHierarchy::tChildContainer & rOutDiagramSubContainer, + const Reference< XDiagram > & xDiagram ); + static void createWallAndFloor( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XDiagram > & xDiagram ); + void createLegendTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ); + void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ); + + ObjectIdentifier getParentImpl( + const ObjectIdentifier& rParentOID, + const ObjectIdentifier& rOID ); + + typedef std::map< ObjectIdentifier, ObjectHierarchy::tChildContainer > + tChildMap; + tChildMap m_aChildMap; + ExplicitValueProvider* m_pExplicitValueProvider; + bool m_bFlattenDiagram; + bool m_bOrderingForElementSelector; +}; + +ImplObjectHierarchy::ImplObjectHierarchy( + const Reference< XChartDocument >& xChartDocument, + ExplicitValueProvider* pExplicitValueProvider, + bool bFlattenDiagram, + bool bOrderingForElementSelector ) : + m_pExplicitValueProvider( pExplicitValueProvider ), + m_bFlattenDiagram( bFlattenDiagram ), + m_bOrderingForElementSelector( bOrderingForElementSelector ) +{ + createTree( xChartDocument ); + // don't remember this helper to avoid access after lifetime + m_pExplicitValueProvider = nullptr; +} + +void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument ) +{ + m_aChildMap = tChildMap();//clear tree + + if( !xChartDocument.is() ) + return; + + //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel + Reference< frame::XModel > xModel = xChartDocument; + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) ); + ObjectIdentifier aDiaOID; + if( xDiagram.is() ) + aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) ); + ObjectHierarchy::tChildContainer aTopLevelContainer; + + // First Level + + // Chart Area + if( m_bOrderingForElementSelector ) + { + aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ); + if( xDiagram.is() ) + { + aTopLevelContainer.push_back( aDiaOID ); + createWallAndFloor( aTopLevelContainer, xDiagram ); + createLegendTree( aTopLevelContainer, xChartDocument, xDiagram ); + } + } + + // Main Title + Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY ); + if( xDocTitled.is()) + { + Reference< XTitle > xMainTitle( xDocTitled->getTitleObject()); + if( xMainTitle.is()) + aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ); + } + + if( xDiagram.is()) + { + // Sub Title. Note: This is interpreted of being top level + Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY ); + if( xDiaTitled.is()) + { + Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject()); + if( xSubTitle.is()) + aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ); + } + + if( !m_bOrderingForElementSelector ) + { + // Axis Titles. Note: These are interpreted of being top level + const Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( Reference< XAxis > const & axis : aAxes ) + lcl_addAxisTitle( axis, aTopLevelContainer, xModel ); + + // Diagram + aTopLevelContainer.push_back( aDiaOID ); + } + + if( m_bFlattenDiagram ) + createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram ); + else + { + ObjectHierarchy::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, OUString() ) ); + + if( ! aTopLevelContainer.empty()) + m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer; +} + +void ImplObjectHierarchy::createLegendTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & 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 ) + { + Reference< container::XIndexAccess > xLegendShapeContainer( + m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY ); + ObjectHierarchy::tChildContainer aLegendEntryOIDs; + lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer ); + + m_aChildMap[ aLegendOID ] = aLegendEntryOIDs; + } +} + +void ImplObjectHierarchy::createAxesTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ) +{ + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 ); + if( !bSupportsAxesGrids ) + return; + + Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) ); + if( !m_bOrderingForElementSelector ) + std::transform( aAxes.begin(), aAxes.end(), + std::back_inserter( rContainer ), + lcl_ObjectToOID( xChartDoc )); + + // get all axes, also invisible ones + aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram ); + // Grids + Reference< frame::XModel > xChartModel = xChartDoc; + for( Reference< XAxis > const & xAxis : std::as_const(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, xChartModel ) ); + + // axis title + lcl_addAxisTitle( xAxis, rContainer, xChartModel ); + } + + Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() ); + if( AxisHelper::isGridVisible( xGridProperties ) ) + { + //main grid + rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ); + } + + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + sal_Int32 nSubGrid = 0; + for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid ) + { + Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] ); + if( AxisHelper::isGridVisible( xSubGridProperties ) ) + { + //sub grid + rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ); + } + } + } +} + +void ImplObjectHierarchy::createWallAndFloor( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XDiagram > & xDiagram ) +{ + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + bool bIsThreeD = ( nDimensionCount == 3 ); + bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + if( bHasWall && bIsThreeD ) + { + rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) ); + + Reference< beans::XPropertySet > xFloor( xDiagram->getFloor()); + if( xFloor.is()) + rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) ); + } + +} + +void ImplObjectHierarchy::createDiagramTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ) +{ + if( !m_bOrderingForElementSelector ) + { + createDataSeriesTree( rContainer, xDiagram ); + createAxesTree( rContainer, xChartDoc, xDiagram ); + createWallAndFloor( rContainer, xDiagram ); + } + else + { + createAxesTree( rContainer, xChartDoc, xDiagram ); + createDataSeriesTree( rContainer, xDiagram ); + } +} + +void ImplObjectHierarchy::createDataSeriesTree( + ObjectHierarchy::tChildContainer & rOutDiagramSubContainer, + const Reference< XDiagram > & xDiagram ) +{ + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + + try + { + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 nCooSysIdx=0; nCooSysIdx xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( sal_Int32 nCTIdx=0; nCTIdx xChartType( aChartTypeSeq[nCTIdx] ); + Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() ); + const sal_Int32 nNumberOfSeries = + ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength()); + + for( sal_Int32 nSeriesIdx=0; nSeriesIdx 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 ) ) + { + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + if( xCurveCnt.is()) + { + Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves()); + for( sal_Int32 nCurveIdx=0; nCurveIdx xSeriesProp( xSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBarProp; + if( xSeriesProp.is() && + (xSeriesProp->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, OUString(), aSeriesParticle ) ); + } + } + + if( xSeriesProp.is() && + (xSeriesProp->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, OUString(), aSeriesParticle ) ); + } + } + } + } + + // Data Points + // iterate over child shapes of legend and search for matching CIDs + if( m_pExplicitValueProvider ) + { + Reference< container::XIndexAccess > xSeriesShapeContainer( + m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY ); + lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer ); + } + + if( ! aSeriesSubContainer.empty()) + m_aChildMap[ aSeriesOID ] = aSeriesSubContainer; + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ) +{ + try + { + if ( m_pExplicitValueProvider ) + { + Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->getByIndex( i ) >>= xShape ) + { + if ( xShape.is() && xShape != xChartRoot ) + { + rContainer.emplace_back( xShape ); + } + } + } + } + } + catch ( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool ImplObjectHierarchy::hasChildren( const ObjectIdentifier& rParent ) +{ + if ( rParent.isValid() ) + { + tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); + if( aIt != m_aChildMap.end()) + return ! (aIt->second.empty()); + } + return false; +} + +ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectIdentifier& rParent ) +{ + if ( rParent.isValid() ) + { + tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); + if( aIt != m_aChildMap.end()) + return aIt->second; + } + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectIdentifier& rNode ) +{ + if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) ) + { + for (auto const& child : m_aChildMap) + { + ObjectHierarchy::tChildContainer::const_iterator aElemIt( + std::find( child.second.begin(), child.second.end(), rNode )); + if( aElemIt != child.second.end()) + return child.second; + } + } + return ObjectHierarchy::tChildContainer(); +} + +ObjectIdentifier ImplObjectHierarchy::getParentImpl( + const ObjectIdentifier & rParentOID, + const ObjectIdentifier & rOID ) +{ + // search children + ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID )); + ObjectHierarchy::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 ImplObjectHierarchy::getParent( + const ObjectIdentifier & rOID ) +{ + return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID ); +} + +} // namespace impl + +ObjectHierarchy::ObjectHierarchy( + const Reference< XChartDocument > & xChartDocument, + ExplicitValueProvider * pExplicitValueProvider /* = 0 */, + bool bFlattenDiagram /* = false */, + bool bOrderingForElementSelector /* = false */) : + m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector )) +{} + +ObjectHierarchy::~ObjectHierarchy() +{} + +ObjectIdentifier ObjectHierarchy::getRootNodeOID() +{ + return ObjectIdentifier( "ROOT" ); +} + +bool ObjectHierarchy::isRootNode( const ObjectIdentifier& rOID ) +{ + return ( rOID == ObjectHierarchy::getRootNodeOID() ); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const +{ + return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID()); +} + +bool ObjectHierarchy::hasChildren( const ObjectIdentifier& rParent ) const +{ + return m_apImpl->hasChildren( rParent ); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren( + const ObjectIdentifier& rParent ) const +{ + if ( rParent.isValid() ) + return m_apImpl->getChildren( rParent ); + + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings( + const ObjectIdentifier& rNode ) const +{ + if ( rNode.isValid() && !isRootNode( rNode ) ) + return m_apImpl->getSiblings( rNode ); + + return ObjectHierarchy::tChildContainer(); +} + +ObjectIdentifier ObjectHierarchy::getParent( + const ObjectIdentifier& rNode ) const +{ + return m_apImpl->getParent( rNode ); +} + +sal_Int32 ObjectHierarchy::getIndexInParent( + const ObjectIdentifier& rNode ) const +{ + ObjectIdentifier aParentOID( m_apImpl->getParent( rNode )); + tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) ); + sal_Int32 nIndex = 0; + for (auto const& child : aChildren) + { + if ( child == rNode ) + return nIndex; + ++nIndex; + } + return -1; +} + +ObjectKeyNavigation::ObjectKeyNavigation( + const ObjectIdentifier & rCurrentOID, + const Reference< chart2::XChartDocument > & xChartDocument, + ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) : + m_aCurrentOID( rCurrentOID ), + m_xChartDocument( 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 000000000..84e4325e3 --- /dev/null +++ b/chart2/source/controller/main/PositionAndSizeHelper.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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.getWidth() == 0 || aPageRect.getHeight() == 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.getWidth())/2.0)/double(aPageRect.getWidth()); + aRelativePosition.Secondary = (double(aPos.Y())+double(aObjectRect.getHeight())/2.0)/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) ); + } + else if( eObjectType == OBJECTTYPE_DATA_LABEL ) + { + RelativePosition aAbsolutePosition; + RelativePosition aCustomLabelPosition; + aAbsolutePosition.Primary = double(rOldPositionAndSize.X) / double(aPageRect.getWidth()); + aAbsolutePosition.Secondary = double(rOldPositionAndSize.Y) / double(aPageRect.getHeight()); + + 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.getWidth()) - aAbsolutePosition.Primary; + aCustomLabelPosition.Secondary = double(aPos.Y()) / double(aPageRect.getHeight()) - 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.getWidth()); + aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight()); + 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.getWidth() ); + aRelativePosition.Secondary = + static_cast< double >( aAnchor.Y()) / + static_cast< double >( aPageRect.getHeight()); + + xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) ); + + aRelativeSize.Primary = + static_cast< double >( aObjectRect.getWidth()) / + static_cast< double >( aPageRect.getWidth() ); + if (aRelativeSize.Primary > 1.0) + aRelativeSize.Primary = 1.0; + aRelativeSize.Secondary = + static_cast< double >( aObjectRect.getHeight()) / + static_cast< double >( aPageRect.getHeight()); + 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.getWidth()); + aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight()); + 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.getWidth())/double(aPageRect.getWidth()); + aRelativeSize.Secondary = double(aObjectRect.getHeight())/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( "RelativeSize", uno::Any(aRelativeSize) ); + } + else + return false; + return true; +} + +bool PositionAndSizeHelper::moveObject( const OUString& rObjectCID + , const uno::Reference< frame::XModel >& 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.set( ObjectIdentifier::getDiagramForCID( rObjectCID, xChartModel ), uno::UNO_QUERY ); + 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 000000000..5475be204 --- /dev/null +++ b/chart2/source/controller/main/SelectionHelper.cxx @@ -0,0 +1,650 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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, OUString() ) );//@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, OUString() ) );//@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 uno::Reference< frame::XModel >& 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, OUString() ) );//@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, OUString() ) );//@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( const OUString& rCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + if( !ObjectIdentifier::isRotateableObject( rCID ) ) + return false; + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( ChartModelHelper::findDiagram( xChartModel ) ); + + return nDimensionCount == 3; +} + +SelectionHelper::SelectionHelper( SdrObject* pSelectedObj ) + : m_pSelectedObj( pSelectedObj ), m_pMarkObj(nullptr) +{ + +} +SelectionHelper::~SelectionHelper() +{ +} + +bool SelectionHelper::getFrameDragSingles() +{ + //true == green == surrounding handles + return dynamic_cast( 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 = dynamic_cast(pObj); + if( !pRotateable ) + { + SolarMutexGuard aSolarGuard; + SdrObjList* pSubList = pObj->GetSubList(); + if(pSubList) + { + SdrObjListIter aIterator(pSubList, SdrIterMode::DeepWithGroups); + while( aIterator.IsMore() && !pRotateable ) + { + SdrObject* pSubObj = aIterator.Next(); + pRotateable = dynamic_cast(pSubObj); + } + } + } + } + + 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( dynamic_cast( m_pMarkObj) != nullptr ) + { + //if th object is a polygon + //from each point a handle is generated + const ::basegfx::B2DPolyPolygon& rPolyPolygon = static_cast(m_pMarkObj)->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(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(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 000000000..8161717fe --- /dev/null +++ b/chart2/source/controller/main/ShapeController.cxx @@ -0,0 +1,676 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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() +{ +} + +// 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 ) + { + Reference< frame::XStorable > xStorable( m_pChartController->getModel(), uno::UNO_QUERY ); + if ( xStorable.is() ) + { + bWritable = !xStorable->isReadonly(); + } + } + + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + sal_uInt16 nFeatureId = aIter->second.nFeatureId; + switch ( nFeatureId ) + { + case COMMAND_ID_FORMAT_LINE: + case COMMAND_ID_FORMAT_AREA: + case COMMAND_ID_TEXT_ATTRIBUTES: + case COMMAND_ID_TRANSFORM_DIALOG: + case COMMAND_ID_OBJECT_TITLE_DESCRIPTION: + case COMMAND_ID_RENAME_OBJECT: + { + aReturn.bEnabled = bWritable; + aReturn.aState <<= false; + } + break; + case COMMAND_ID_BRING_TO_FRONT: + case COMMAND_ID_FORWARD: + { + aReturn.bEnabled = ( bWritable && isForwardPossible() ); + aReturn.aState <<= false; + } + break; + case COMMAND_ID_BACKWARD: + case COMMAND_ID_SEND_TO_BACK: + { + + aReturn.bEnabled = ( bWritable && isBackwardPossible() ); + aReturn.aState <<= false; + } + break; + case COMMAND_ID_FONT_DIALOG: + case COMMAND_ID_PARAGRAPH_DIALOG: + { + 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; + + sal_uInt16 nFeatureId = aIter->second.nFeatureId; + switch ( nFeatureId ) + { + case COMMAND_ID_FORMAT_LINE: + { + executeDispatch_FormatLine(); + } + break; + case COMMAND_ID_FORMAT_AREA: + { + executeDispatch_FormatArea(); + } + break; + case COMMAND_ID_TEXT_ATTRIBUTES: + { + executeDispatch_TextAttributes(); + } + break; + case COMMAND_ID_TRANSFORM_DIALOG: + { + executeDispatch_TransformDialog(); + } + break; + case COMMAND_ID_OBJECT_TITLE_DESCRIPTION: + { + executeDispatch_ObjectTitleDescription(); + } + break; + case COMMAND_ID_RENAME_OBJECT: + { + executeDispatch_RenameObject(); + } + break; + case COMMAND_ID_BRING_TO_FRONT: + case COMMAND_ID_FORWARD: + case COMMAND_ID_BACKWARD: + case COMMAND_ID_SEND_TO_BACK: + { + executeDispatch_ChangeZOrder( nFeatureId ); + } + break; + case COMMAND_ID_FONT_DIALOG: + { + executeDispatch_FontDialog(); + } + break; + case COMMAND_ID_PARAGRAPH_DIALOG: + { + executeDispatch_ParagraphDialog(); + } + break; + default: + { + } + break; + } +} + +void ShapeController::describeSupportedFeatures() +{ + implDescribeSupportedFeature( ".uno:FormatLine", COMMAND_ID_FORMAT_LINE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:FormatArea", COMMAND_ID_FORMAT_AREA, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:TextAttributes", COMMAND_ID_TEXT_ATTRIBUTES, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:TransformDialog", COMMAND_ID_TRANSFORM_DIALOG, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectTitleDescription", COMMAND_ID_OBJECT_TITLE_DESCRIPTION, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:RenameObject", COMMAND_ID_RENAME_OBJECT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:BringToFront", COMMAND_ID_BRING_TO_FRONT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Forward", COMMAND_ID_FORWARD, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Backward", COMMAND_ID_BACKWARD, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SendToBack", COMMAND_ID_SEND_TO_BACK, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:FontDialog", COMMAND_ID_FONT_DIALOG, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:ParagraphDialog", COMMAND_ID_PARAGRAPH_DIALOG, 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)); + 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() == OBJ_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 sal_uInt16* 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() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + weld::Window* pChartWindow(m_pChartController->GetChartFrame()); + ScopedVclPtr< AbstractSvxObjectTitleDescDialog > pDlg( + pFact->CreateSvxObjectTitleDescDialog(pChartWindow, aTitle, aDescription)); + if ( pDlg->Execute() == RET_OK ) + { + pDlg->GetTitle( aTitle ); + pDlg->GetDescription( aDescription ); + pSelectedObj->SetTitle( aTitle ); + pSelectedObj->SetDescription( aDescription ); + } +} + +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( sal_uInt16 nId ) +{ + SolarMutexGuard aGuard; + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr ); + if ( !pDrawViewWrapper ) + return; + + switch ( nId ) + { + case COMMAND_ID_BRING_TO_FRONT: + { + if ( isForwardPossible() ) + { + pDrawViewWrapper->PutMarkedToTop(); + } + } + break; + case COMMAND_ID_FORWARD: + { + if ( isForwardPossible() ) + { + pDrawViewWrapper->MovMarkedToTop(); + } + } + break; + case COMMAND_ID_BACKWARD: + { + if ( isBackwardPossible() ) + { + pDrawViewWrapper->MovMarkedToBtm(); + } + } + break; + case COMMAND_ID_SEND_TO_BACK: + { + 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 ); + + SfxItemSet aNewAttr( + rPool, + svl::Items< + EE_ITEMS_START, EE_ITEMS_END, + SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS>{}); + 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; + Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->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; + Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = nCount - 1; i >= 0; --i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->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 000000000..70fcdecf9 --- /dev/null +++ b/chart2/source/controller/main/ShapeController.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_SHAPECONTROLLER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_SHAPECONTROLLER_HXX + +#include "FeatureCommandDispatchBase.hxx" +#include + +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 SAL_CALL disposing() 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( sal_uInt16 nId ); + void executeDispatch_FontDialog(); + void executeDispatch_ParagraphDialog(); + + SdrObject* getFirstAdditionalShape(); + SdrObject* getLastAdditionalShape(); + bool isBackwardPossible(); + bool isForwardPossible(); + + ChartController* m_pChartController; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_SHAPECONTROLLER_HXX +#endif + +/* 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 000000000..1e6c06c35 --- /dev/null +++ b/chart2/source/controller/main/StatusBarCommandDispatch.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 "StatusBarCommandDispatch.hxx" +#include +#include +#include +#include + +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, + const Reference< frame::XModel > & xModel, + const Reference< view::XSelectionSupplier > & xSelSupp ) : + impl::StatusBarCommandDispatch_Base( xContext ), + m_xModifiable( xModel, uno::UNO_QUERY ), + m_xSelectionSupplier( xSelSupp ), + m_bIsModified( false ) +{} + +StatusBarCommandDispatch::~StatusBarCommandDispatch() +{} + +void StatusBarCommandDispatch::initialize() +{ + if( m_xModifiable.is()) + { + m_xModifiable->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 ) + { + uno::Any aArg; + Reference< chart2::XChartDocument > xDoc( m_xModifiable, uno::UNO_QUERY ); + aArg <<= ObjectNameProvider::getSelectedObjectText( m_aSelectedOID.getObjectCID(), xDoc ); + 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 SAL_CALL StatusBarCommandDispatch::disposing() +{ + m_xModifiable.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL StatusBarCommandDispatch::disposing( const lang::EventObject& /* Source */ ) +{ + m_xModifiable.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XModifyListener ____ +void SAL_CALL StatusBarCommandDispatch::modified( const lang::EventObject& aEvent ) +{ + if( m_xModifiable.is()) + m_bIsModified = m_xModifiable->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 000000000..8ad9e62aa --- /dev/null +++ b/chart2/source/controller/main/StatusBarCommandDispatch.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_STATUSBARCOMMANDDISPATCH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_STATUSBARCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" +#include +#include +#include + +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, + const css::uno::Reference< css::frame::XModel > & 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 SAL_CALL disposing() 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: + css::uno::Reference< css::util::XModifiable > m_xModifiable; + css::uno::Reference< css::view::XSelectionSupplier > m_xSelectionSupplier; + bool m_bIsModified; + ObjectIdentifier m_aSelectedOID; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_STATUSBARCOMMANDDISPATCH_HXX +#endif + +/* 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 000000000..b985558a3 --- /dev/null +++ b/chart2/source/controller/main/ToolbarController.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/. + */ + +#include + +#include +#include +#include +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart { + +ChartToolbarController::ChartToolbarController(const css::uno::Sequence& rProperties): + ChartToolbarControllerBase(m_aMutex) +{ + css::uno::Reference xFrame; + sal_Int32 nLength = rProperties.getLength(); + for (sal_Int32 i = 0; i < nLength; ++i) + { + css::beans::PropertyValue aPropValue; + rProperties[i] >>= aPropValue; + if (aPropValue.Name == "Frame") + aPropValue.Value >>= xFrame; + } + + css::uno::Reference xFramesSupplier(xFrame, css::uno::UNO_QUERY); + mxFramesSupplier = xFramesSupplier; +} + +ChartToolbarController::~ChartToolbarController() +{ +} + +void ChartToolbarController::execute(sal_Int16 /*nKeyModifier*/) +{ +} + +void ChartToolbarController::click() +{ + css::uno::Reference xActiveFrame = mxFramesSupplier->getActiveFrame(); + if (!xActiveFrame.is()) + return; + + css::uno::Reference xActiveController = xActiveFrame->getController(); + if (!xActiveController.is()) + return; + + css::uno::Reference xDispatch(xActiveController, css::uno::UNO_QUERY); + if (!xDispatch.is()) + return; + + css::util::URL aURL; + aURL.Path = "FormatSelection"; + xDispatch->dispatch(aURL, css::uno::Sequence()); +} + +void ChartToolbarController::doubleClick() +{ + SAL_INFO("chart2", "double clicked"); +} + + +css::uno::Reference ChartToolbarController::createPopupWindow() +{ + return css::uno::Reference(); +} + +css::uno::Reference ChartToolbarController::createItemWindow( + const css::uno::Reference& /*rParent*/) +{ + return css::uno::Reference(); +} + +void ChartToolbarController::statusChanged(const css::frame::FeatureStateEvent& /*rEvent*/) +{ + +} + +void ChartToolbarController::disposing(const css::lang::EventObject& /*rSource*/) +{ +} + +void ChartToolbarController::initialize(const css::uno::Sequence& /*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 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 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 000000000..78bc1f6b0 --- /dev/null +++ b/chart2/source/controller/main/UndoActions.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 "UndoActions.hxx" +#include "ChartModelClone.hxx" + +#include + +#include + +#include + +using namespace ::com::sun::star; + +namespace chart::impl +{ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::lang::DisposedException; + +UndoElement::UndoElement( const OUString& i_actionString, const Reference< XModel >& i_documentModel, const std::shared_ptr< ChartModelClone >& i_modelClone ) + :UndoElement_MBase() + ,UndoElement_TBase( m_aMutex ) + ,m_sActionString( i_actionString ) + ,m_xDocumentModel( i_documentModel ) + ,m_pModelClone( i_modelClone ) +{ +} + +UndoElement::~UndoElement() +{ +} + +void SAL_CALL UndoElement::disposing() +{ + 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( 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 xSdrUndoAction ) + :ShapeUndoElement_MBase() + ,ShapeUndoElement_TBase( m_aMutex ) + ,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(); +} + +void SAL_CALL ShapeUndoElement::disposing() +{ +} + +} // 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 000000000..770cb06cf --- /dev/null +++ b/chart2/source/controller/main/UndoActions.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOACTIONS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOACTIONS_HXX + +#include + +#include +#include +#include + +#include + +namespace com::sun::star::frame { class XModel; } + +class SdrUndoAction; + +namespace chart +{ +class ChartModelClone; + +namespace impl +{ + +typedef ::cppu::BaseMutex UndoElement_MBase; +typedef ::cppu::WeakComponentImplHelper< css::document::XUndoAction > UndoElement_TBase; + +class UndoElement :public UndoElement_MBase + ,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 invoking, the clone model is applied to the document model. + */ + UndoElement( const OUString & i_actionString, + const css::uno::Reference< css::frame::XModel >& i_documentModel, + const std::shared_ptr< ChartModelClone >& i_modelClone + ); + + 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; + + // OComponentHelper + virtual void SAL_CALL disposing() override; + +protected: + virtual ~UndoElement() override; + +private: + void impl_toggleModelState(); + +private: + OUString m_sActionString; + css::uno::Reference< css::frame::XModel > m_xDocumentModel; + std::shared_ptr< ChartModelClone > m_pModelClone; +}; + +typedef ::cppu::BaseMutex ShapeUndoElement_MBase; +typedef ::cppu::WeakComponentImplHelper< css::document::XUndoAction > ShapeUndoElement_TBase; +class ShapeUndoElement :public ShapeUndoElement_MBase + ,public ShapeUndoElement_TBase +{ +public: + explicit ShapeUndoElement( std::unique_ptr xSdrUndoAction ); + + // XUndoAction + virtual OUString SAL_CALL getTitle() override; + virtual void SAL_CALL undo( ) override; + virtual void SAL_CALL redo( ) override; + + // OComponentHelper + virtual void SAL_CALL disposing() override; + +protected: + virtual ~ShapeUndoElement() override; + +private: + std::unique_ptr m_xAction; +}; + +} // namespace impl +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOACTIONS_HXX +#endif + +/* 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 000000000..e4bd85a3b --- /dev/null +++ b/chart2/source/controller/main/UndoCommandDispatch.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 "UndoCommandDispatch.hxx" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +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, + const Reference< frame::XModel > & xModel ) : + CommandDispatch( xContext ), + m_xModel( xModel ) +{ + uno::Reference< document::XUndoManagerSupplier > xSuppUndo( m_xModel, uno::UNO_QUERY_THROW ); + m_xUndoManager.set( xSuppUndo->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 SAL_CALL UndoCommandDispatch::disposing() +{ + 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 000000000..aa5f5b2e3 --- /dev/null +++ b/chart2/source/controller/main/UndoCommandDispatch.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOCOMMANDDISPATCH_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" + +namespace com::sun::star::document { class XUndoManager; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +/** This is a CommandDispatch implementation for Undo and Redo. + */ +class UndoCommandDispatch : public CommandDispatch +{ +public: + explicit UndoCommandDispatch( + const css::uno::Reference< css::uno::XComponentContext > & xContext, + const css::uno::Reference< css::frame::XModel > & 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 SAL_CALL disposing() 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: + css::uno::Reference< css::frame::XModel > m_xModel; + css::uno::Reference< css::document::XUndoManager > m_xUndoManager; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOCOMMANDDISPATCH_HXX +#endif + +/* 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 000000000..91687aebd --- /dev/null +++ b/chart2/source/controller/main/UndoGuard.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 "UndoGuard.hxx" +#include "ChartModelClone.hxx" +#include "UndoActions.hxx" + +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +UndoGuard::UndoGuard( const OUString& i_undoString, const uno::Reference< document::XUndoManager > & i_undoManager, + const ModelFacet i_facet ) + :m_xChartModel( i_undoManager->getParent(), uno::UNO_QUERY_THROW ) + ,m_xUndoManager( i_undoManager ) + ,m_pDocumentSnapshot() + ,m_aUndoString( i_undoString ) + ,m_bActionPosted( false ) +{ + m_pDocumentSnapshot = std::make_shared( 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 000000000..0d9fa7538 --- /dev/null +++ b/chart2/source/controller/main/UndoGuard.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOGUARD_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOGUARD_HXX + +#include "ChartModelClone.hxx" + +#include + +#include + +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( + const 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: + const css::uno::Reference< css::frame::XModel > 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 + commitAction 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; +}; + +} +// INCLUDED_CHART2_SOURCE_CONTROLLER_MAIN_UNDOGUARD_HXX +#endif + +/* 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 000000000..3ae735880 --- /dev/null +++ b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx @@ -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 . + */ + +#include "Chart2PanelFactory.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include "ChartElementsPanel.hxx" +#include "ChartTypePanel.hxx" +#include "ChartSeriesPanel.hxx" +#include +#include "ChartAxisPanel.hxx" +#include "ChartErrorBarPanel.hxx" +#include "ChartAreaPanel.hxx" +#include "ChartLinePanel.hxx" + +using namespace css::uno; + +namespace chart::sidebar { + +ChartPanelFactory::ChartPanelFactory() + : PanelFactoryInterfaceBase(m_aMutex) +{ +} + +ChartPanelFactory::~ChartPanelFactory() +{ +} + +Reference SAL_CALL ChartPanelFactory::createUIElement ( + const OUString& rsResourceURL, + const ::css::uno::Sequence& rArguments) +{ + Reference xElement; + + try + { + const ::comphelper::NamedValueCollection aArguments (rArguments); + Reference xFrame (aArguments.getOrDefault("Frame", Reference())); + Reference xParentWindow (aArguments.getOrDefault("ParentWindow", Reference())); + Reference xController (aArguments.getOrDefault("Controller", Reference())); + + VclPtr pParentWindow = VCLUnoHelper::GetWindow(xParentWindow); + if ( ! xParentWindow.is() || pParentWindow==nullptr) + 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(xController.get()); + if (!pController) + throw RuntimeException( + "ChartPanelFactory::createUIElement called without valid ChartController", + nullptr); + + VclPtr pPanel; + if (rsResourceURL.endsWith("/ElementsPanel")) + pPanel = ChartElementsPanel::Create( pParentWindow, xFrame, pController ); + else if (rsResourceURL.endsWith("/TypePanel")) + { + //pPanel = ChartTypePanel::Create( pParentWindow, xFrame, pController ); + VclPtrInstance ppPanel(pParentWindow, xFrame, pController); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + ppPanel, + css::ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/SeriesPanel")) + pPanel = ChartSeriesPanel::Create(pParentWindow, xFrame, pController); + else if (rsResourceURL.endsWith("/AxisPanel")) + pPanel = ChartAxisPanel::Create(pParentWindow, xFrame, pController); + else if (rsResourceURL.endsWith("/ErrorBarPanel")) + pPanel = ChartErrorBarPanel::Create(pParentWindow, xFrame, pController); + else if (rsResourceURL.endsWith("/AreaPanel")) + pPanel = ChartAreaPanel::Create(pParentWindow, xFrame, pController); + else if (rsResourceURL.endsWith("/LinePanel")) + pPanel = ChartLinePanel::Create(pParentWindow, xFrame, pController); + + if (pPanel) + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + 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 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 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 000000000..c91c14442 --- /dev/null +++ b/chart2/source/controller/sidebar/Chart2PanelFactory.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 . + */ +#ifndef INCLUDED_SC_INC_SCPANELFACTORY_HXX +#define INCLUDED_SC_INC_SCPANELFACTORY_HXX + +#include +#include +#include +#include + + +namespace chart::sidebar { + +typedef ::cppu::WeakComponentImplHelper < + css::ui::XUIElementFactory, css::lang::XServiceInfo + > PanelFactoryInterfaceBase; + +class ChartPanelFactory + : private ::cppu::BaseMutex, + public PanelFactoryInterfaceBase +{ +public: + ChartPanelFactory(); + virtual ~ChartPanelFactory() override; + + ChartPanelFactory(const ChartPanelFactory&) = delete; + const ChartPanelFactory& operator=(const ChartPanelFactory&) = delete; + + // XUIElementFactory + virtual css::uno::Reference SAL_CALL createUIElement( + const OUString& rsResourceURL, + const ::css::uno::Sequence& rArguments) override; + + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; + + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; +}; + +} // end of namespace chart::sidebar + +#endif + +/* 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 000000000..1f6230709 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartAreaPanel.cxx @@ -0,0 +1,536 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 "ChartAreaPanel.hxx" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace chart::sidebar { + +namespace { + +SvxColorToolBoxControl* getColorToolBoxControl(ToolbarUnoDispatcher& rColorDispatch) +{ + css::uno::Reference xController = rColorDispatch.GetControllerForCommand(".uno:FillColor"); + SvxColorToolBoxControl* pToolBoxColorControl = dynamic_cast(xController.get()); + return pToolBoxColorControl; +} + +OUString getCID(const css::uno::Reference& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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 getPropSet( + const css::uno::Reference& xModel) +{ + OUString aCID = getCID(xModel); + css::uno::Reference xPropSet = + ObjectIdentifier::getObjectPropertySet(aCID, xModel); + + ObjectType eType = ObjectIdentifier::getObjectType(aCID); + if (eType == OBJECTTYPE_DIAGRAM) + { + css::uno::Reference xDiagram( + xPropSet, css::uno::UNO_QUERY); + if (!xDiagram.is()) + return xPropSet; + + xPropSet.set(xDiagram->getWall()); + } + + return xPropSet; +} + +ChartController* getController(const css::uno::Reference& xModel) +{ + css::uno::ReferencexController = xModel->getCurrentController(); + if (!xController.is()) + throw std::exception(); + + ChartController* pController = dynamic_cast(xController.get()); + if (!pController) + throw std::exception(); + + return pController; +} + +ViewElementListProvider getViewElementListProvider( const css::uno::Reference& xModel) +{ + ChartController* pController = getController(xModel); + ViewElementListProvider aProvider = pController->getViewElementListProvider(); + return aProvider; +} + +DrawModelWrapper* getDrawModelWrapper(const css::uno::Reference& xModel) +{ + ChartController* pController = getController(xModel); + return pController->GetDrawModelWrapper(); +} + +XFillGradientItem getXGradientForName(const css::uno::Reference& xModel, + const OUString& rName) +{ + css::uno::Reference xFact(xModel, css::uno::UNO_QUERY); + css::uno::Reference 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& xModel, + const OUString& rName) +{ + css::uno::Reference xFact(xModel, css::uno::UNO_QUERY); + css::uno::Reference 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& 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& xModel, + const OUString& 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; +}; + +} + +VclPtr ChartAreaPanel::Create( + vcl::Window* pParent, + const css::uno::Reference& 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 VclPtr::Create( + pParent, rxFrame, pController); +} + +ChartAreaPanel::ChartAreaPanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController): + svx::sidebar::AreaPropertyPanelBase(pParent, rxFrame), + mxModel(pController->getModel()), + mxListener(new ChartSidebarModifyListener(this)), + mxSelectionListener(new ChartSidebarSelectionListener(this)), + mbUpdate(true), + mbModelValid(true), + maFillColorWrapper(mxModel, getColorToolBoxControl(*mxColorDispatch), "FillColor") +{ + std::vector aAcceptedTypes { OBJECTTYPE_PAGE, OBJECTTYPE_DIAGRAM, + OBJECTTYPE_DATA_SERIES, OBJECTTYPE_DATA_POINT, + OBJECTTYPE_TITLE, OBJECTTYPE_LEGEND}; + mxSelectionListener->setAcceptedTypes(aAcceptedTypes); + Initialize(); +} + +ChartAreaPanel::~ChartAreaPanel() +{ + disposeOnce(); +} + +void ChartAreaPanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + + AreaPropertyPanelBase::dispose(); +} + +void ChartAreaPanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener.get()); + + SvxColorToolBoxControl* pToolBoxColor = getColorToolBoxControl(*mxColorDispatch); + pToolBoxColor->setColorSelectFunction(maFillColorWrapper); + + updateData(); +} + +void ChartAreaPanel::setFillTransparence(const XFillTransparenceItem& rItem) +{ + PreventUpdate aProtector(mbUpdate); + css::uno::Reference 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 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, css::uno::Reference(mxModel, css::uno::UNO_QUERY_THROW), aName); + xPropSet->setPropertyValue("FillTransparenceGradientName", css::uno::Any(aNewName)); +} + +void ChartAreaPanel::setFillStyle(const XFillStyleItem& rItem) +{ + PreventUpdate aProtector(mbUpdate); + css::uno::Reference 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 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 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, css::uno::Reference(mxModel, css::uno::UNO_QUERY_THROW), aName); + xPropSet->setPropertyValue("FillGradientName", css::uno::Any(aNewName)); +} + +void ChartAreaPanel::setFillStyleAndHatch(const XFillStyleItem* pStyleItem, + const XFillHatchItem& rHatchItem) +{ + PreventUpdate aProtector(mbUpdate); + css::uno::Reference 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 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, css::uno::Reference(mxModel, css::uno::UNO_QUERY_THROW), aPreferredName); + xPropSet->setPropertyValue("FillBitmapName", aBitmap); +} + +void ChartAreaPanel::updateData() +{ + if (!mbUpdate || !mbModelValid) + return; + + css::uno::Reference xPropSet = getPropSet(mxModel); + if (!xPropSet.is()) + return; + + css::uno::Reference 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 pBitmapItem; + DrawModelWrapper* pModelWrapper = nullptr; + try + { + 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(nFillColor)); + updateFillColor(true, &aFillColorItem); + } +} + +void ChartAreaPanel::modelInvalid() +{ + mbModelValid = false; +} + +void ChartAreaPanel::selectionChanged(bool bCorrectType) +{ + if (bCorrectType) + updateData(); +} + +void ChartAreaPanel::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + css::uno::Reference oldSelectionSupplier( + mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (oldSelectionSupplier.is()) { + oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener.get()); +} + + +} + +/* 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 000000000..5c0e0b23b --- /dev/null +++ b/chart2/source/controller/sidebar/ChartAreaPanel.hxx @@ -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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTAREAPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTAREAPANEL_HXX + +#include +#include +#include +#include +#include + +#include + +#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 VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + + // constructor/destructor + ChartAreaPanel( + vcl::Window* pParent, + const css::uno::Reference& 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 updateData() override; + virtual void modelInvalid() override; + + virtual void selectionChanged(bool bCorrectType) override; + + virtual void dispose() override; + + virtual void updateModel(css::uno::Reference xModel) override; + +private: + + css::uno::Reference mxModel; + css::uno::Reference mxListener; + rtl::Reference mxSelectionListener; + + void Initialize(); + + bool mbUpdate; + bool mbModelValid; + + ChartColorWrapper maFillColorWrapper; +}; + +} } // end of namespace svx::sidebar + +#endif + +/* 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 000000000..084ec37a2 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartAxisPanel.cxx @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "ChartAxisPanel.hxx" +#include + +using namespace css; +using namespace css::uno; + +namespace chart::sidebar { + +namespace { + +bool isLabelShown(const css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + 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 css::uno::Reference& xModel, + const OUString& rCID, bool bVisible) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xAxis.is()) + return; + + xAxis->setPropertyValue("DisplayLabels", css::uno::Any(bVisible)); +} + +struct AxisLabelPosMap +{ + sal_Int32 nPos; + css::chart::ChartAxisLabelPosition ePos; +}; + +static 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + 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 css::uno::Reference& xModel, + const OUString& rCID, sal_Int32 nPos) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::chart2::XAxis > 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 css::uno::Reference& xModel, + const OUString& rCID, bool bReverse) +{ + css::uno::Reference< css::chart2::XAxis > 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& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID, double nVal) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xAxis.is()) + return; + + xAxis->setPropertyValue("TextRotation", css::uno::Any(nVal)); +} + +double getAxisRotation(const css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::beans::XPropertySet > xAxis( + ObjectIdentifier::getAxisForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xAxis.is()) + return 0; + + css::uno::Any aAny = xAxis->getPropertyValue("TextRotation"); + double nVal = 0; + aAny >>= nVal; + return nVal; +} + +} + +ChartAxisPanel::ChartAxisPanel( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) + : PanelLayout(pParent, "ChartAxisPanel", "modules/schart/ui/sidebaraxis.ui", rxFrame) + , 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->getModel()) + , mxModifyListener(new ChartSidebarModifyListener(this)) + , mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_AXIS)) + , mbModelValid(true) +{ + Initialize(); +} + +ChartAxisPanel::~ChartAxisPanel() +{ + disposeOnce(); +} + +void ChartAxisPanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxModifyListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(mxSelectionListener); + + mxCBShowLabel.reset(); + mxCBReverse.reset(); + + mxLBLabelPos.reset(); + mxGridLabel.reset(); + + mxNFRotation.reset(); + + PanelLayout::dispose(); +} + +void ChartAxisPanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxModifyListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); + + updateData(); + + Link aLink = LINK(this, ChartAxisPanel, CheckBoxHdl); + mxCBShowLabel->connect_toggled(aLink); + mxCBReverse->connect_toggled(aLink); + + Link 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); +} + +VclPtr ChartAxisPanel::Create ( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ChartAxisPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ChartAxisPanel::Create", nullptr, 1); + + return VclPtr::Create( + pParent, rxFrame, pController); +} + +void ChartAxisPanel::DataChanged( + const DataChangedEvent& ) +{ + 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::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxModifyListener); + } + + css::uno::Reference oldSelectionSupplier( + mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (oldSelectionSupplier.is()) { + oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxModifyListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); +} + +void ChartAxisPanel::selectionChanged(bool bCorrectType) +{ + if (bCorrectType) + updateData(); +} + +IMPL_LINK(ChartAxisPanel, CheckBoxHdl, weld::ToggleButton&, 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 000000000..b510ef8b5 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartAxisPanel.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/. + * + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTAXISPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTAXISPANEL_HXX + +#include +#include +#include +#include + +#include "ChartSidebarModifyListener.hxx" +#include "ChartSidebarSelectionListener.hxx" + +namespace com::sun::star::util { class XModifyListener; } +namespace com::sun::star::view { class XSelectionChangeListener; } + +class Edit; +class ListBox; +class MetricField; + +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 VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + 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( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + virtual ~ChartAxisPanel() override; + virtual void dispose() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void selectionChanged(bool bCorrectType) override; + + virtual void updateModel(css::uno::Reference xModel) override; + +private: + //ui controls + std::unique_ptr mxCBShowLabel; + std::unique_ptr mxCBReverse; + std::unique_ptr mxLBLabelPos; + std::unique_ptr mxGridLabel; + std::unique_ptr mxNFRotation; + + css::uno::Reference mxModel; + css::uno::Reference mxModifyListener; + css::uno::Reference mxSelectionListener; + + bool mbModelValid; + + void Initialize(); + + DECL_LINK(CheckBoxHdl, weld::ToggleButton&, void); + DECL_LINK(ListBoxHdl, weld::ComboBox&, void); + DECL_LINK(TextRotationHdl, weld::MetricSpinButton&, void); +}; + +} } // end of namespace ::chart::sidebar + +#endif + +/* 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 000000000..d9903b12c --- /dev/null +++ b/chart2/source/controller/sidebar/ChartColorWrapper.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 "ChartColorWrapper.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace chart::sidebar { + +namespace { + +OUString getCID(const css::uno::Reference& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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 getPropSet( + const css::uno::Reference& xModel) +{ + OUString aCID = getCID(xModel); + css::uno::Reference xPropSet = + ObjectIdentifier::getObjectPropertySet(aCID, xModel); + + ObjectType eType = ObjectIdentifier::getObjectType(aCID); + if (eType == OBJECTTYPE_DIAGRAM) + { + css::uno::Reference xDiagram( + xPropSet, css::uno::UNO_QUERY); + if (!xDiagram.is()) + return xPropSet; + + xPropSet.set(xDiagram->getWall()); + } + + return xPropSet; +} + +} + +ChartColorWrapper::ChartColorWrapper( + css::uno::Reference const & xModel, + SvxColorToolBoxControl* pControl, + const OUString& rName): + mxModel(xModel), + mpControl(pControl), + maPropertyName(rName) +{ +} + +void ChartColorWrapper::operator()(const OUString& , const NamedColor& rColor) +{ + css::uno::Reference xPropSet = getPropSet(mxModel); + + if (!xPropSet.is()) + { + SAL_WARN("chart2", "Invalid reference to xPropSet"); + return; + } + + xPropSet->setPropertyValue(maPropertyName, css::uno::makeAny(rColor.first)); +} + +void ChartColorWrapper::updateModel(const css::uno::Reference& xModel) +{ + mxModel = xModel; +} + +void ChartColorWrapper::updateData() +{ + static const OUStringLiteral aLineColor = "LineColor"; + static const OUStringLiteral aCommands[2] = {".uno:XLineColor", ".uno:FillColor"}; + + css::uno::Reference 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); +} + +ChartLineStyleWrapper::ChartLineStyleWrapper( + css::uno::Reference const & xModel, + SvxLineStyleToolBoxControl* pControl) + : mxModel(xModel) + , mpControl(pControl) +{ +} + +void ChartLineStyleWrapper::updateModel(const css::uno::Reference& xModel) +{ + mxModel = xModel; +} + +namespace +{ + css::uno::Any getLineDash( + const css::uno::Reference& xModel, const OUString& rDashName) + { + css::uno::Reference xFact(xModel, css::uno::UNO_QUERY); + css::uno::Reference 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 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()(const OUString& rCommand, const css::uno::Any& rValue) +{ + css::uno::Reference xPropSet = getPropSet(mxModel); + + if (!xPropSet.is()) + { + SAL_WARN("chart2", "Invalid reference to xPropSet"); + return false; + } + + if (rCommand == ".uno:XLineStyle") + { + xPropSet->setPropertyValue("LineStyle", rValue); + return true; + } + else if (rCommand == ".uno:LineDash") + { + XLineDashItem aDashItem; + aDashItem.PutValue(rValue, 0); + css::uno::Any aAny; + aDashItem.QueryValue(aAny, MID_LINEDASH); + OUString aDashName = PropertyHelper::addLineDashUniqueNameToTable(aAny, + css::uno::Reference(mxModel, css::uno::UNO_QUERY), + ""); + 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 000000000..425b074f9 --- /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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTCOLORWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTCOLORWRAPPER_HXX + +#include +#include + +namespace com::sun::star::frame { class XModel; } + +class SvxColorToolBoxControl; +class SvxLineStyleToolBoxControl; + +namespace chart::sidebar { + +class ChartColorWrapper +{ +public: + ChartColorWrapper(css::uno::Reference const & xModel, + SvxColorToolBoxControl* pControl, + const OUString& rPropertyName); + + void operator()(const OUString& rCommand, const NamedColor& rColor); + + void updateModel(const css::uno::Reference& xModel); + + void updateData(); + +private: + + css::uno::Reference mxModel; + + SvxColorToolBoxControl* mpControl; + + OUString maPropertyName; +}; + +class ChartLineStyleWrapper +{ +public: + ChartLineStyleWrapper(css::uno::Reference const & xModel, + SvxLineStyleToolBoxControl* pControl); + + bool operator()(const OUString& rCommand, const css::uno::Any& rValue); + + void updateModel(const css::uno::Reference& xModel); + + void updateData(); + +private: + + css::uno::Reference mxModel; + + SvxLineStyleToolBoxControl* mpControl; +}; + +} + +#endif + +/* 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 000000000..c15572717 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartElementsPanel.cxx @@ -0,0 +1,634 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include + +#include "ChartElementsPanel.hxx" +#include +#include + +#include +#include +#include +#include +#include + +#include + + +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& xModel) +{ + ChartModel* pModel = dynamic_cast(xModel.get()); + + return pModel; +} + +bool isLegendVisible(const css::uno::Reference& xModel) +{ + ChartModel* pModel = getChartModel(xModel); + if (!pModel) + return false; + + Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(*pModel), uno::UNO_QUERY ); + 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& 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& xModel) +{ + ChartModel* pModel = getChartModel(xModel); + if (!pModel) + return false; + + Reference< beans::XPropertySet > xLegendProp(LegendHelper::getLegend(*pModel), uno::UNO_QUERY); + 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& xModel, bool bOverlay) +{ + ChartModel* pModel = getChartModel(xModel); + if (!pModel) + return; + + Reference xLegendProp(LegendHelper::getLegend(*pModel), uno::UNO_QUERY); + if (!xLegendProp.is()) + return; + + xLegendProp->setPropertyValue("Overlay", css::uno::Any(bOverlay)); +} + +bool isTitleVisisble(const css::uno::Reference& xModel, TitleHelper::eTitleType eTitle) +{ + css::uno::Reference xTitle = TitleHelper::getTitle(eTitle, xModel); + if (!xTitle.is()) + return false; + + css::uno::Reference xPropSet(xTitle, css::uno::UNO_QUERY_THROW); + css::uno::Any aAny = xPropSet->getPropertyValue("Visible"); + bool bVisible = aAny.get(); + return bVisible; +} + +bool isGridVisible(const css::uno::Reference& xModel, GridType eType) +{ + Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel)); + 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 css::uno::Reference& xModel, GridType eType, bool bVisible) +{ + Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel)); + 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 css::uno::Reference& xModel, AxisType eType) +{ + Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel)); + 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 css::uno::Reference& xModel, AxisType eType, bool bVisible) +{ + Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel)); + 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& xModel) +{ + ChartModel* pModel = getChartModel(xModel); + if (!pModel) + return -1; + + Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(*pModel), uno::UNO_QUERY ); + 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& xModel, sal_Int32 nPos) +{ + ChartModel* pModel = getChartModel(xModel); + if (!pModel) + return; + + Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(*pModel), uno::UNO_QUERY ); + 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( + vcl::Window* pParent, const css::uno::Reference& rxFrame, + ChartController* pController) + : PanelLayout(pParent, "ChartElementsPanel", "modules/schart/ui/sidebarelements.ui", rxFrame) + , mxCBTitle(m_xBuilder->weld_check_button("checkbutton_title")) + , mxCBSubtitle(m_xBuilder->weld_check_button("checkbutton_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")) + , maContext() + , mxModel(pController->getModel()) + , mxListener(new ChartSidebarModifyListener(this)) + , mbModelValid(true) +{ + maTextTitle = mxTextTitle->get_label(); + maTextSubTitle = mxTextSubTitle->get_label(); + + Initialize(); +} + +ChartElementsPanel::~ChartElementsPanel() +{ + disposeOnce(); +} + +void ChartElementsPanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + mxCBTitle.reset(); + mxCBSubtitle.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(); + + PanelLayout::dispose(); +} + +void ChartElementsPanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxListener); + updateData(); + + Link 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)); +} + +namespace { + +css::uno::Reference getChartType(const css::uno::Reference& xModel) +{ + css::uno::Reference xChartDoc(xModel, css::uno::UNO_QUERY_THROW); + css::uno::Reference xDiagram = xChartDoc->getFirstDiagram(); + if (!xDiagram.is()) { + return css::uno::Reference(); + } + + css::uno::Reference xCooSysContainer( xDiagram, css::uno::UNO_QUERY_THROW ); + + css::uno::Sequence> xCooSysSequence(xCooSysContainer->getCoordinateSystems()); + + if (!xCooSysSequence.hasElements()) + return css::uno::Reference(); + + css::uno::Reference xChartTypeContainer(xCooSysSequence[0], css::uno::UNO_QUERY_THROW); + + css::uno::Sequence> xChartTypeSequence(xChartTypeContainer->getChartTypes()); + + if (!xChartTypeSequence.hasElements()) + return css::uno::Reference(); + + return xChartTypeSequence[0]; +} + +} + +void ChartElementsPanel::updateData() +{ + if (!mbModelValid) + return; + + Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(mxModel)); + sal_Int32 nDimension = DiagramHelper::getDimension(xDiagram); + SolarMutexGuard aGuard; + + mxCBLegend->set_active(isLegendVisible(mxModel)); + mxCBLegendNoOverlay->set_sensitive(isLegendVisible(mxModel)); + mxCBLegendNoOverlay->set_active(!isLegendOverlay(mxModel)); + mxBoxLegend->set_sensitive(isLegendVisible(mxModel)); + mxCBTitle->set_active(isTitleVisisble(mxModel, TitleHelper::MAIN_TITLE)); + mxCBSubtitle->set_active(isTitleVisisble(mxModel, TitleHelper::SUB_TITLE)); + mxCBXAxisTitle->set_active(isTitleVisisble(mxModel, TitleHelper::X_AXIS_TITLE)); + mxCBYAxisTitle->set_active(isTitleVisisble(mxModel, TitleHelper::Y_AXIS_TITLE)); + mxCBZAxisTitle->set_active(isTitleVisisble(mxModel, TitleHelper::Z_AXIS_TITLE)); + mxCB2ndXAxisTitle->set_active(isTitleVisisble(mxModel, TitleHelper::SECONDARY_X_AXIS_TITLE)); + mxCB2ndYAxisTitle->set_active(isTitleVisisble(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)); +} + +VclPtr ChartElementsPanel::Create ( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ChartElementsPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ChartElementsPanel::Create", nullptr, 1); + return VclPtr::Create( + pParent, rxFrame, pController); +} + +void ChartElementsPanel::DataChanged( + const DataChangedEvent& ) +{ + 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::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); +} + +IMPL_LINK(ChartElementsPanel, CheckBoxHdl, weld::ToggleButton&, 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); +} + +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 000000000..9d3ea7f6d --- /dev/null +++ b/chart2/source/controller/sidebar/ChartElementsPanel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTELEMENTSPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTELEMENTSPANEL_HXX + +#include +#include +#include +#include +#include "ChartSidebarModifyListener.hxx" +#include + +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 VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + + virtual void DataChanged( + const DataChangedEvent& rEvent) override; + + virtual void HandleContextChange( + const vcl::EnumContext& rContext) override; + + // constructor/destructor + ChartElementsPanel( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + + virtual ~ChartElementsPanel() override; + + virtual void dispose() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void updateModel(css::uno::Reference xModel) override; + +private: + //ui controls + std::unique_ptr mxCBTitle; + std::unique_ptr mxCBSubtitle; + std::unique_ptr mxCBXAxis; + std::unique_ptr mxCBXAxisTitle; + std::unique_ptr mxCBYAxis; + std::unique_ptr mxCBYAxisTitle; + std::unique_ptr mxCBZAxis; + std::unique_ptr mxCBZAxisTitle; + std::unique_ptr mxCB2ndXAxis; + std::unique_ptr mxCB2ndXAxisTitle; + std::unique_ptr mxCB2ndYAxis; + std::unique_ptr mxCB2ndYAxisTitle; + std::unique_ptr mxCBLegend; + std::unique_ptr mxCBLegendNoOverlay; + std::unique_ptr mxCBGridVerticalMajor; + std::unique_ptr mxCBGridHorizontalMajor; + std::unique_ptr mxCBGridVerticalMinor; + std::unique_ptr mxCBGridHorizontalMinor; + std::unique_ptr mxTextTitle; + std::unique_ptr mxTextSubTitle; + std::unique_ptr mxLBAxis; + std::unique_ptr mxLBGrid; + + std::unique_ptr mxLBLegendPosition; + std::unique_ptr mxBoxLegend; + + vcl::EnumContext maContext; + + css::uno::Reference mxModel; + css::uno::Reference mxListener; + + bool mbModelValid; + + OUString maTextTitle; + OUString maTextSubTitle; + + void Initialize(); + + void setTitleVisible(TitleHelper::eTitleType eTitle, bool bVisible); + + DECL_LINK(CheckBoxHdl, weld::ToggleButton&, void); + DECL_LINK(LegendPosHdl, weld::ComboBox&, void); +}; + +} } // end of namespace ::chart::sidebar + +#endif + +/* 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 000000000..7e035f9b7 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.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 +#include +#include + +#include "ChartErrorBarPanel.hxx" +#include +#include +#include + + +using namespace css; +using namespace css::uno; + +namespace chart::sidebar { + +namespace { + +enum class ErrorBarDirection +{ + POSITIVE, + NEGATIVE +}; + +css::uno::Reference getErrorBarPropSet( + const css::uno::Reference& xModel, const OUString& rCID) +{ + return ObjectIdentifier::getObjectPropertySet(rCID, xModel); +} + +bool showPositiveError(const css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID, bool bShow) +{ + css::uno::Reference xPropSet = + getErrorBarPropSet(xModel, rCID); + + if (!xPropSet.is()) + return; + + xPropSet->setPropertyValue("ShowPositiveError", css::uno::Any(bShow)); +} + +void setShowNegativeError(const css::uno::Reference& xModel, + const OUString& rCID, bool bShow) +{ + css::uno::Reference xPropSet = + getErrorBarPropSet(xModel, rCID); + + if (!xPropSet.is()) + return; + + xPropSet->setPropertyValue("ShowNegativeError", css::uno::Any(bShow)); +} + +struct ErrorBarTypeMap +{ + sal_Int32 nPos; + sal_Int32 nApi; +}; + +static 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID, sal_Int32 nPos) +{ + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID, ErrorBarDirection eDir) +{ + css::uno::Reference 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 css::uno::Reference& xModel, + const OUString& rCID, double nVal, ErrorBarDirection eDir) +{ + css::uno::Reference 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 css::uno::Reference& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, ChartController* pController) + : PanelLayout(pParent, "ChartErrorBarPanel", "modules/schart/ui/sidebarerrorbar.ui", rxFrame) + , 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->getModel()) + , mxListener(new ChartSidebarModifyListener(this)) + , mbModelValid(true) +{ + Initialize(); +} + +ChartErrorBarPanel::~ChartErrorBarPanel() +{ + disposeOnce(); +} + +void ChartErrorBarPanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + + mxRBPosAndNeg.reset(); + mxRBPos.reset(); + mxRBNeg.reset(); + + mxLBType.reset(); + + mxMFPos.reset(); + mxMFNeg.reset(); + + PanelLayout::dispose(); +} + +void ChartErrorBarPanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxListener); + mxRBNeg->set_active(false); + mxRBPos->set_active(false); + mxRBPosAndNeg->set_active(false); + + updateData(); + + Link 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 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); + } +} + +VclPtr ChartErrorBarPanel::Create ( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ChartErrorBarPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ChartErrorBarPanel::Create", nullptr, 1); + + return VclPtr::Create( + pParent, rxFrame, pController); +} + +void ChartErrorBarPanel::DataChanged( + const DataChangedEvent& ) +{ + 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::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); +} + +IMPL_LINK_NOARG(ChartErrorBarPanel, RadioBtnHdl, weld::ToggleButton&, 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 000000000..ee5a306ba --- /dev/null +++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.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/. + * + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTERRORBARPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTERRORBARPANEL_HXX + +#include +#include +#include +#include + +#include "ChartSidebarModifyListener.hxx" + +namespace com::sun::star::util { class XModifyListener; } + +namespace chart { + +class ChartController; + +namespace sidebar { + +class ChartErrorBarPanel : public PanelLayout, + public ::sfx2::sidebar::IContextChangeReceiver, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface, + public sfx2::sidebar::SidebarModelUpdate, + public ChartSidebarModifyListenerParent +{ +public: + static VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + 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( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + virtual ~ChartErrorBarPanel() override; + virtual void dispose() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void updateModel(css::uno::Reference xModel) override; + +private: + //ui controls + std::unique_ptr mxRBPosAndNeg; + std::unique_ptr mxRBPos; + std::unique_ptr mxRBNeg; + + std::unique_ptr mxLBType; + + std::unique_ptr mxMFPos; + std::unique_ptr mxMFNeg; + + css::uno::Reference mxModel; + css::uno::Reference mxListener; + + bool mbModelValid; + + void Initialize(); + + DECL_LINK(RadioBtnHdl, weld::ToggleButton&, void); + DECL_LINK(ListBoxHdl, weld::ComboBox&, void); + DECL_LINK(NumericFieldHdl, weld::SpinButton&, void); +}; + +} } // end of namespace ::chart::sidebar + +#endif + +/* 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 000000000..449b3efa2 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartLinePanel.cxx @@ -0,0 +1,280 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace chart::sidebar { + +namespace { + +SvxLineStyleToolBoxControl* getLineStyleToolBoxControl(ToolbarUnoDispatcher& rToolBoxColor) +{ + css::uno::Reference xController = rToolBoxColor.GetControllerForCommand(".uno:XLineStyle"); + SvxLineStyleToolBoxControl* pToolBoxLineStyleControl = dynamic_cast(xController.get()); + return pToolBoxLineStyleControl; +} + +SvxColorToolBoxControl* getColorToolBoxControl(ToolbarUnoDispatcher& rToolBoxLineStyle) +{ + css::uno::Reference xController = rToolBoxLineStyle.GetControllerForCommand(".uno:XLineColor"); + SvxColorToolBoxControl* pToolBoxColorControl = dynamic_cast(xController.get()); + return pToolBoxColorControl; +} + +OUString getCID(const css::uno::Reference& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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 getPropSet( + const css::uno::Reference& xModel) +{ + OUString aCID = getCID(xModel); + css::uno::Reference xPropSet = + ObjectIdentifier::getObjectPropertySet(aCID, xModel); + + ObjectType eType = ObjectIdentifier::getObjectType(aCID); + if (eType == OBJECTTYPE_DIAGRAM) + { + css::uno::Reference 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; +}; + +} + +VclPtr ChartLinePanel::Create( + vcl::Window* pParent, + const css::uno::Reference& 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 VclPtr::Create( + pParent, rxFrame, pController); +} + +ChartLinePanel::ChartLinePanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController): + svx::sidebar::LinePropertyPanelBase(pParent, rxFrame), + mxModel(pController->getModel()), + mxListener(new ChartSidebarModifyListener(this)), + mxSelectionListener(new ChartSidebarSelectionListener(this)), + mbUpdate(true), + mbModelValid(true), + maLineColorWrapper(mxModel, getColorToolBoxControl(*mxColorDispatch), "LineColor"), + maLineStyleWrapper(mxModel, getLineStyleToolBoxControl(*mxLineStyleDispatch)) +{ + disableArrowHead(); + std::vector 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(aAcceptedTypes); + Initialize(); +} + +ChartLinePanel::~ChartLinePanel() +{ + disposeOnce(); +} + +void ChartLinePanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + + LinePropertyPanelBase::dispose(); +} + +void ChartLinePanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener.get()); + + 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 xPropSet = getPropSet(mxModel); + if (!xPropSet.is()) + return; + + sal_uInt16 nLineTransparence = 0; + xPropSet->getPropertyValue("LineTransparence") >>= nLineTransparence; + XLineTransparenceItem aLineTransparenceItem(nLineTransparence); + updateLineTransparence(false, true, &aLineTransparenceItem); + + maLineStyleWrapper.updateData(); + maLineColorWrapper.updateData(); +} + +void ChartLinePanel::modelInvalid() +{ + mbModelValid = false; +} + +void ChartLinePanel::selectionChanged(bool bCorrectType) +{ + if (bCorrectType) + updateData(); +} + +void ChartLinePanel::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + css::uno::Reference oldSelectionSupplier( + mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (oldSelectionSupplier.is()) { + oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + } + + mxModel = xModel; + mbModelValid = true; + + maLineStyleWrapper.updateModel(mxModel); + maLineColorWrapper.updateModel(mxModel); + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener.get()); +} + +void ChartLinePanel::setLineJoint(const XLineJointItem* pItem) +{ + css::uno::Reference 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 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 xPropSet = + getPropSet(mxModel); + + if (!xPropSet.is()) + return; + + PreventUpdate aPreventUpdate(mbUpdate); + xPropSet->setPropertyValue("LineWidth", css::uno::Any(rItem.GetValue())); +} + +} + +/* 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 000000000..2f1c520dd --- /dev/null +++ b/chart2/source/controller/sidebar/ChartLinePanel.hxx @@ -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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTLINEPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTLINEPANEL_HXX + +#include +#include + +#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 VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + + // constructor/destructor + ChartLinePanel( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + + virtual ~ChartLinePanel() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void selectionChanged(bool bCorrectType) override; + + virtual void dispose() override; + + virtual void updateModel(css::uno::Reference 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; + +private: + + css::uno::Reference mxModel; + css::uno::Reference mxListener; + rtl::Reference mxSelectionListener; + + void Initialize(); + + bool mbUpdate; + bool mbModelValid; + ChartColorWrapper maLineColorWrapper; + ChartLineStyleWrapper maLineStyleWrapper; +}; + +} } // end of namespace svx::sidebar + +#endif + +/* 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 000000000..abc45c555 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartSeriesPanel.cxx @@ -0,0 +1,488 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ChartSeriesPanel.hxx" +#include + +#include +#include +#include + +using namespace css; +using namespace css::uno; + +namespace chart::sidebar { + +namespace { + +bool isDataLabelVisible(const css::uno::Reference& xModel, const OUString& rCID) +{ + css::uno::Reference< css::chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID(rCID, xModel); + + if (!xSeries.is()) + return false; + + return DataSeriesHelper::hasDataLabelsAtSeries(xSeries); +} + +void setDataLabelVisible(const css::uno::Reference& xModel, const OUString& rCID, bool bVisible) +{ + css::uno::Reference< css::chart2::XDataSeries > 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; +}; + +static 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::beans::XPropertySet > xSeries( + ObjectIdentifier::getDataSeriesForCID(rCID, xModel), uno::UNO_QUERY ); + + 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 css::uno::Reference& xModel, + const OUString& rCID, sal_Int32 nPos) +{ + css::uno::Reference< css::beans::XPropertySet > xSeries( + ObjectIdentifier::getDataSeriesForCID(rCID, xModel), uno::UNO_QUERY ); + + 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 css::uno::Reference& xModel, + const OUString& rCID) +{ + css::uno::Reference< css::chart2::XRegressionCurveContainer > xRegressionCurveContainer( + ObjectIdentifier::getDataSeriesForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xRegressionCurveContainer.is()) + return false; + + return xRegressionCurveContainer->getRegressionCurves().hasElements(); +} + +void setTrendlineVisible(const css::uno::Reference& + xModel, const OUString& rCID, bool bVisible) +{ + css::uno::Reference< css::chart2::XRegressionCurveContainer > xRegressionCurveContainer( + ObjectIdentifier::getDataSeriesForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xRegressionCurveContainer.is()) + return; + + if (bVisible) + { + RegressionCurveHelper::addRegressionCurve( + SvxChartRegress::Linear, + xRegressionCurveContainer); + } + else + RegressionCurveHelper::removeAllExceptMeanValueLine( + xRegressionCurveContainer ); + +} + +bool isErrorBarVisible(const css::uno::Reference& xModel, + const OUString& rCID, bool bYError) +{ + css::uno::Reference< css::chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID(rCID, xModel); + + if (!xSeries.is()) + return false; + + return StatisticsHelper::hasErrorBars(xSeries, bYError); +} + +void setErrorBarVisible(const css::uno::Reference& + xModel, const OUString& rCID, bool bYError, bool bVisible) +{ + css::uno::Reference< css::chart2::XDataSeries > 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 css::uno::Reference& + xModel, const OUString& rCID) +{ + css::uno::Reference< css::chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID(rCID, xModel); + + if (!xSeries.is()) + return true; + + return DataSeriesHelper::getAttachedAxisIndex(xSeries) == 0; +} + +void setAttachedAxisType(const css::uno::Reference& + xModel, const OUString& rCID, bool bPrimary) +{ + css::uno::Reference< css::beans::XPropertySet > xSeries( + ObjectIdentifier::getDataSeriesForCID(rCID, xModel), uno::UNO_QUERY ); + + if (!xSeries.is()) + return; + + sal_Int32 nIndex = bPrimary ? 0 : 1; + xSeries->setPropertyValue("AttachedAxisIndex", css::uno::Any(nIndex)); +} + +css::uno::Reference getChartType( + const css::uno::Reference& xModel) +{ + css::uno::Reference xChartDoc (xModel, css::uno::UNO_QUERY); + css::uno::Reference xDiagram = xChartDoc->getFirstDiagram(); + css::uno::Reference< css::chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, UNO_QUERY_THROW ); + css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems()); + css::uno::Reference< css::chart2::XChartTypeContainer > xChartTypeContainer( xCooSysSequence[0], UNO_QUERY_THROW ); + css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() ); + return xChartTypeSequence[0]; +} + +OUString getSeriesLabel(const css::uno::Reference& xModel, const OUString& rCID) +{ + css::uno::Reference< css::chart2::XDataSeries > xSeries = + ObjectIdentifier::getDataSeriesForCID(rCID, xModel); + + if (!xSeries.is()) + return OUString(); + + css::uno::Reference xChartType = getChartType(xModel); + return DataSeriesHelper::getDataSeriesLabel(xSeries, xChartType->getRoleOfSequenceForSeriesLabel()); +} + +OUString getCID(const css::uno::Reference& xModel) +{ + css::uno::Reference xController(xModel->getCurrentController()); + css::uno::Reference 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( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) + : PanelLayout(pParent, "ChartSeriesPanel", "modules/schart/ui/sidebarseries.ui", rxFrame) + , 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->getModel()) + , mxListener(new ChartSidebarModifyListener(this)) + , mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_DATA_SERIES)) + , mbModelValid(true) +{ + Initialize(); +} + +ChartSeriesPanel::~ChartSeriesPanel() +{ + disposeOnce(); +} + +void ChartSeriesPanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(mxSelectionListener); + + mxCBLabel.reset(); + mxCBTrendline.reset(); + mxCBXError.reset(); + mxCBYError.reset(); + + mxRBPrimaryAxis.reset(); + mxRBSecondaryAxis.reset(); + + mxBoxLabelPlacement.reset(); + mxLBLabelPlacement.reset(); + + mxFTSeriesName.reset(); + mxFTSeriesTemplate.reset(); + + PanelLayout::dispose(); +} + +void ChartSeriesPanel::Initialize() +{ + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->addModifyListener(mxListener); + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); + + updateData(); + + Link aLink = LINK(this, ChartSeriesPanel, CheckBoxHdl); + mxCBLabel->connect_toggled(aLink); + mxCBTrendline->connect_toggled(aLink); + mxCBXError->connect_toggled(aLink); + mxCBYError->connect_toggled(aLink); + + Link 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); +} + +VclPtr ChartSeriesPanel::Create ( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ChartSeriesPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ChartSeriesPanel::Create", nullptr, 1); + + return VclPtr::Create( + pParent, rxFrame, pController); +} + +void ChartSeriesPanel::DataChanged( + const DataChangedEvent& ) +{ + 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::updateModel( + css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + css::uno::Reference oldSelectionSupplier( + mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (oldSelectionSupplier.is()) { + oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener.get()); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); + + css::uno::Reference xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); +} + +void ChartSeriesPanel::selectionChanged(bool bCorrectType) +{ + if (bCorrectType) + updateData(); +} + +IMPL_LINK(ChartSeriesPanel, CheckBoxHdl, weld::ToggleButton&, 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::ToggleButton&, 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 000000000..319723729 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartSeriesPanel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSERIESPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSERIESPANEL_HXX + +#include +#include +#include +#include + +#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 VclPtr Create( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + 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( + vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ChartController* pController); + virtual ~ChartSeriesPanel() override; + virtual void dispose() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void selectionChanged(bool bCorrectType) override; + + virtual void updateModel(css::uno::Reference xModel) override; + +private: + //ui controls + std::unique_ptr mxCBLabel; + std::unique_ptr mxCBTrendline; + std::unique_ptr mxCBXError; + std::unique_ptr mxCBYError; + + std::unique_ptr mxRBPrimaryAxis; + std::unique_ptr mxRBSecondaryAxis; + + std::unique_ptr mxBoxLabelPlacement; + std::unique_ptr mxLBLabelPlacement; + + std::unique_ptr mxFTSeriesName; + std::unique_ptr mxFTSeriesTemplate; + + css::uno::Reference mxModel; + css::uno::Reference mxListener; + css::uno::Reference mxSelectionListener; + + bool mbModelValid; + + void Initialize(); + + DECL_LINK(CheckBoxHdl, weld::ToggleButton&, void); + DECL_LINK(RadioBtnHdl, weld::ToggleButton&, void); + DECL_LINK(ListBoxHdl, weld::ComboBox&, void); +}; + +} } // end of namespace ::chart::sidebar + +#endif + +/* 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 000000000..5cc6b5bea --- /dev/null +++ b/chart2/source/controller/sidebar/ChartSidebarModifyListener.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/. + */ + +#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 000000000..9efe382e2 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartSidebarModifyListener.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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSIDEBAR_MODIFYLISTENER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSIDEBAR_MODIFYLISTENER_HXX + +#include +#include + +namespace chart { +namespace sidebar { + +class ChartSidebarModifyListenerParent +{ +public: + virtual ~ChartSidebarModifyListenerParent(); + + virtual void updateData() = 0; + + virtual void modelInvalid() = 0; +}; + +class ChartSidebarModifyListener : public cppu::WeakImplHelper +{ +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; +}; + +} } + +#endif + +/* 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 000000000..0c8018eb0 --- /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 +#include + +#include + +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 xController(rEvent.Source, css::uno::UNO_QUERY); + if (xController.is()) + { + css::uno::Reference 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(const std::vector& aTypes) +{ + maTypes = 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 000000000..84efd0323 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartSidebarSelectionListener.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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSIDEBARSELECTIONLISTENER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTSIDEBARSELECTIONLISTENER_HXX + +#include +#include + +#include + +#include + +namespace chart { +namespace sidebar { + +class ChartSidebarSelectionListenerParent +{ +public: + virtual ~ChartSidebarSelectionListenerParent(); + + virtual void selectionChanged(bool bSelected) = 0; +}; + +class ChartSidebarSelectionListener : public cppu::WeakImplHelper +{ +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(const std::vector& aTypes); + +private: + ChartSidebarSelectionListenerParent* mpParent; + + std::vector maTypes; +}; + +} } + +#endif + +/* 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 000000000..ceea3b218 --- /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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +using namespace css; +using namespace css::uno; + +namespace chart::sidebar +{ +ChartTypePanel::ChartTypePanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + ::chart::ChartController* pController) + : PanelLayout(pParent, "ChartTypePanel", "modules/schart/ui/sidebartype.ui", rxFrame) + , maContext() + , mxModel(pController->getModel()) + , 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(mxModel, css::uno::UNO_QUERY_THROW) + , 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"))) + , 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 xProps(m_xChartModel, 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()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + } + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique()); + } + m_aChartTypeDialogControllerList.push_back( + std::make_unique()); + + 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() { disposeOnce(); } + +void ChartTypePanel::dispose() +{ + css::uno::Reference xBroadcaster(mxModel, + css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + + //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(); + + PanelLayout::dispose(); +} + +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; + uno::Reference xTemplateManager( + m_xChartModel->getChartTypeManager(), uno::UNO_QUERY); + uno::Reference xDiagram(ChartModelHelper::findDiagram(m_xChartModel)); + DiagramHelper::tTemplateWithServiceName aTemplate + = DiagramHelper::getTemplateForDiagram(xDiagram, xTemplateManager); + OUString aServiceName(aTemplate.second); + + 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 xTemplateProps(aTemplate.first, uno::UNO_QUERY); + ChartTypeParameter aParameter + = elem->getChartTypeParameterForService(aServiceName, xTemplateProps); + m_pCurrentMainType = getSelectedMainType(); + + //set ThreeDLookScheme + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme(xDiagram); + if (!aParameter.b3DLook && aParameter.eThreeDLookScheme != ThreeDLookScheme_Realistic) + aParameter.eThreeDLookScheme = ThreeDLookScheme_Realistic; + + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->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; + uno::Reference xTemplateManager( + m_xChartModel->getChartTypeManager(), uno::UNO_QUERY); + uno::Reference xModel(m_xChartModel); + uno::Reference xDiagram(ChartModelHelper::findDiagram(xModel)); + DiagramHelper::tTemplateWithServiceName aTemplate + = DiagramHelper::getTemplateForDiagram(xDiagram, xTemplateManager); + OUString aServiceName(aTemplate.second); + + 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&) { 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::updateModel(css::uno::Reference xModel) +{ + if (mbModelValid) + { + css::uno::Reference xBroadcaster(mxModel, + css::uno::UNO_QUERY_THROW); + xBroadcaster->removeModifyListener(mxListener); + } + + mxModel = xModel; + mbModelValid = true; + + css::uno::Reference xBroadcasterNew(mxModel, + css::uno::UNO_QUERY_THROW); + xBroadcasterNew->addModifyListener(mxListener); +} + +uno::Reference ChartTypePanel::getCurrentTemplate() const +{ + if (m_pCurrentMainType && m_xChartModel.is()) + { + ChartTypeParameter aParameter(getCurrentParameter()); + m_pCurrentMainType->adjustParameterToSubType(aParameter); + uno::Reference xTemplateManager( + m_xChartModel->getChartTypeManager(), uno::UNO_QUERY); + return m_pCurrentMainType->getCurrentTemplate(aParameter, xTemplateManager); + } + return nullptr; +} + +ChartTypeDialogController* ChartTypePanel::getSelectedMainType() +{ + ChartTypeDialogController* pTypeController = nullptr; + auto nM = static_cast::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(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(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 + uno::Reference xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme(xDiagram); + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->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 + = ThreeDHelper::detectScheme(ChartModelHelper::findDiagram(m_xChartModel)); + if (!aParameter.b3DLook && aParameter.eThreeDLookScheme != ThreeDLookScheme_Realistic) + aParameter.eThreeDLookScheme = ThreeDLookScheme_Realistic; + + uno::Reference xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + try + { + uno::Reference xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + fillAllControls(aParameter); + uno::Reference xTemplateProps(getCurrentTemplate(), 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 000000000..0186cf641 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartTypePanel.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTTYPEPANEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_SIDEBAR_CHARTTYPEPANEL_HXX + +#include +#include +#include +#include +#include "ChartSidebarModifyListener.hxx" +#include +#include +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace 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(vcl::Window* pParent, const css::uno::Reference& rxFrame, + ::chart::ChartController* pController); + + virtual ~ChartTypePanel() override; + + virtual void dispose() override; + + virtual void updateData() override; + virtual void modelInvalid() override; + + virtual void updateModel(css::uno::Reference xModel) override; + + virtual css::uno::Reference + 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 mxModel; + css::uno::Reference mxListener; + + bool mbModelValid; + + void Initialize(); + + std::unique_ptr m_pDim3DLookResourceGroup; + std::unique_ptr m_pStackingResourceGroup; + std::unique_ptr m_pSplineResourceGroup; + std::unique_ptr m_pGeometryResourceGroup; + std::unique_ptr m_pSortByXValuesResourceGroup; + + css::uno::Reference m_xChartModel; + + std::vector> m_aChartTypeDialogControllerList; + ChartTypeDialogController* m_pCurrentMainType; + + sal_Int32 m_nChangingCalls; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + std::unique_ptr m_xMainTypeList; + std::unique_ptr m_xSubTypeList; + std::unique_ptr m_xSubTypeListWin; +}; +} +} // end of namespace ::chart::sidebar + +#endif + +/* 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 000000000..e850573b9 --- /dev/null +++ b/chart2/source/controller/uitest/uiobject.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/. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +ChartUIObject::ChartUIObject(const VclPtr& xChartWindow, + const OUString& rCID): + maCID(rCID), + 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 pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get()); + + StringMap aParams; + aParams["NAME"] = maCID; + pWindow->execute(rAction, aParams); + } + else if (rAction == "COMMAND") + { + // first select object + std::unique_ptr 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(pCommand); + mxChartWindow->GetController()->dispatch(aURL, css::uno::Sequence()); +} + +std::unique_ptr ChartUIObject::get_child(const OUString& rID) +{ + std::unique_ptr pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get()); + + return pWindow->get_child(rID); +} + +std::set ChartUIObject::get_children() const +{ + std::unique_ptr pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get()); + + return pWindow->get_children(); +} + +OUString ChartUIObject::get_type() const +{ + return "ChartUIObject for type: "; +} + +ChartWindowUIObject::ChartWindowUIObject(const VclPtr& 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 ChartWindowUIObject::get_child(const OUString& rID) +{ + if (chart::ObjectIdentifier::isCID(rID)) + return std::unique_ptr(new ChartUIObject(mxChartWindow, rID)); + + throw css::uno::RuntimeException("unknown child"); +} + +namespace { + +void recursiveAdd(chart::ObjectIdentifier const & rID, std::set& rChildren, const chart::ObjectHierarchy& rHierarchy) +{ + std::vector aChildIndentifiers = rHierarchy.getChildren(rID); + std::transform(aChildIndentifiers.begin(), aChildIndentifiers.end(), std::inserter(rChildren, rChildren.begin()), + [](const chart::ObjectIdentifier& rObject) + { + return rObject.getObjectCID(); + } + ); + + for (const chart::ObjectIdentifier& ID: aChildIndentifiers) + recursiveAdd(ID, rChildren, rHierarchy); +} + +} + +std::set ChartWindowUIObject::get_children() const +{ + std::set aChildren; + + chart::ChartController* pController = mxChartWindow->GetController(); + if (!pController) + return aChildren; + + css::uno::Reference< css::chart2::XChartDocument > xChartDoc( pController->getModel(), css::uno::UNO_QUERY ); + + css::uno::Reference xChartView = pController->getChartView(); + chart::ExplicitValueProvider* pValueProvider = comphelper::getUnoTunnelImplementation( xChartView ); + chart::ObjectHierarchy aHierarchy(xChartDoc, pValueProvider); + chart::ObjectIdentifier aIdentifier = chart::ObjectHierarchy::getRootNodeOID(); + aChildren.insert(aIdentifier.getObjectCID()); + + recursiveAdd(aIdentifier, aChildren, aHierarchy); + + return aChildren; +} + +std::unique_ptr ChartWindowUIObject::create(vcl::Window* pWindow) +{ + chart::ChartWindow* pChartWindow = dynamic_cast(pWindow); + assert(pChartWindow); + + return std::unique_ptr(new ChartWindowUIObject(pChartWindow)); +} + +OUString ChartWindowUIObject::get_name() const +{ + return "ChartWindowUIObject"; +} + +/* 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 000000000..2097d216b --- /dev/null +++ b/chart2/source/inc/AxisHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_AXISHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_AXISHELPER_HXX + +#include "charttoolsdllapi.hxx" +#include + +#include + +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 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 css::uno::Reference< css::chart2::XAxis >& xAxis, ChartModel& rModel ); + + static sal_Int32 getExplicitNumberFormatKeyForAxis( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCorrespondingCoordinateSystem + , const css::uno::Reference< css::chart2::XChartDocument>& xChartDoc + , bool bSearchForParallelAxisIfNothingIsFound ); + + static css::uno::Reference< + css::chart2::XAxis > + createAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , const css::uno::Reference< css::uno::XComponentContext >& xContext + , ReferenceSizeProvider * pRefSizeProvider = nullptr ); + + static css::uno::Reference< css::chart2::XAxis > + createAxis( + sal_Int32 nDimensionIndex + , sal_Int32 nAxisIndex // 0==main or 1==secondary axis + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys + , const css::uno::Reference< css::uno::XComponentContext > & xContext + , ReferenceSizeProvider * pRefSizeProvider = nullptr ); + + static void showAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , const css::uno::Reference< css::uno::XComponentContext >& xContext + , ReferenceSizeProvider * pRefSizeProvider = nullptr ); + + static void showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static void hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + static void hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static bool isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + static bool isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static void makeAxisVisible( const css::uno::Reference< css::chart2::XAxis >& xAxis ); + static void makeGridVisible( const css::uno::Reference< css::beans::XPropertySet >& xGridProperties ); + + static void makeAxisInvisible( const css::uno::Reference< css::chart2::XAxis >& xAxis ); + static void makeGridInvisible( const css::uno::Reference< css::beans::XPropertySet >& xGridProperties ); + + static void hideAxisIfNoDataIsAttached( const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram); + + SAL_DLLPRIVATE static bool areAxisLabelsVisible( const css::uno::Reference< css::beans::XPropertySet >& xAxisProperties ); + static bool isAxisVisible( const css::uno::Reference< css::chart2::XAxis >& xAxis ); + static bool isGridVisible( const css::uno::Reference< css::beans::XPropertySet >& xGridProperties ); + + static css::uno::Reference< css::chart2::XCoordinateSystem > + getCoordinateSystemByIndex( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , sal_Int32 nIndex ); + + static css::uno::Reference< css::chart2::XCoordinateSystem > + getCoordinateSystemOfAxis( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static css::uno::Reference< css::chart2::XAxis > + getAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + static css::uno::Reference< css::chart2::XAxis > + getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + + static css::uno::Reference< css::chart2::XAxis > + getCrossingMainAxis( const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + + static css::uno::Reference< css::chart2::XAxis > + getParallelAxis( const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static css::uno::Reference< css::beans::XPropertySet > + getGridProperties( const css::uno::Reference< css::chart2::XCoordinateSystem >& 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 css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static bool getIndicesForAxis( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys + , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex ); + + static bool getIndicesForAxis( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex ); + + /** @param bOnlyVisible if , only axes with property "Show" set to + are returned + */ + static css::uno::Sequence< css::uno::Reference< css::chart2::XAxis > > + getAllAxesOfDiagram( const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , bool bOnlyVisible = false ); + + /** @param bOnlyVisible if
, only axes with property "Show" set to + are returned + */ + SAL_DLLPRIVATE static std::vector< css::uno::Reference< css::chart2::XAxis > > + getAllAxesOfCoordinateSystem( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys + , bool bOnlyVisible = false ); + + static css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > + getAllGrids( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static void getAxisOrGridPossibilities( css::uno::Sequence< sal_Bool >& rPossibilityList + , const css::uno::Reference< css::chart2::XDiagram>& xDiagram, bool bAxis=true ); + + static void getAxisOrGridExcistence( css::uno::Sequence< sal_Bool >& rExcistenceList + , const css::uno::Reference< css::chart2::XDiagram>& xDiagram, bool bAxis=true ); + + static bool changeVisibilityOfGrids( const css::uno::Reference< css::chart2::XDiagram>& xDiagram + , const css::uno::Sequence< sal_Bool >& rOldExistenceList + , const css::uno::Sequence< sal_Bool >& rNewExistenceList ); + + static bool changeVisibilityOfAxes( const css::uno::Reference< css::chart2::XDiagram>& 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 css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + static bool isSecondaryYAxisNeeded( const css::uno::Reference< + css::chart2::XCoordinateSystem >& xCooSys ); + + static css::uno::Reference< css::chart2::XChartType > + getChartTypeByIndex( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys, + sal_Int32 nIndex ); + + static void setRTLAxisLayout( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + + static css::uno::Reference< css::chart2::XChartType > + getFirstChartTypeWithSeriesAttachedToAxisIndex( const css::uno::Reference< css::chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex ); + + static bool isAxisPositioningEnabled(); +}; + +} //namespace chart +#endif + +/* 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 000000000..779f8fc7f --- /dev/null +++ b/chart2/source/inc/AxisIndexDefines.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_AXISINDEXDEFINES_HXX +#define INCLUDED_CHART2_SOURCE_INC_AXISINDEXDEFINES_HXX + +#include + +namespace chart +{ +const sal_Int32 MAIN_AXIS_INDEX = 0; +const sal_Int32 SECONDARY_AXIS_INDEX = 1; + +} // namespace chart + +#endif + +/* 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 000000000..014371bfa --- /dev/null +++ b/chart2/source/inc/BaseGFXHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_BASEGFXHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_BASEGFXHELPER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::awt { struct Rectangle; } +namespace com::sun::star::drawing { struct PolyPolygonShape3D; } + +namespace chart +{ +namespace BaseGFXHelper +{ + +OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DRange getBoundVolume( const css::drawing::PolyPolygonShape3D& 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 ); + +::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 BaseGFXHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_BASEGFXHELPER_HXX +#endif + +/* 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 000000000..90acd6dbf --- /dev/null +++ b/chart2/source/inc/CachedDataSequence.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CACHEDDATASEQUENCE_HXX +#define INCLUDED_CHART2_SOURCE_INC_CACHEDDATASEQUENCE_HXX + +// helper classes +#include +#include +#include +#include +#include + +// interfaces and types +#include +#include +#include +#include +#include +#include +#include + +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; + + // + sal_Int32 m_nNumberFormatKey; + OUString m_sRole; + // + + 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; + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_CACHEDDATASEQUENCE_HXX +#endif + +/* 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 000000000..ca39d92b8 --- /dev/null +++ b/chart2/source/inc/ChangingResource.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHANGINGRESOURCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHANGINGRESOURCE_HXX + +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 +#endif + +/* 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 000000000..7385bfe12 --- /dev/null +++ b/chart2/source/inc/CharacterProperties.hxx @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_CHARACTERPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARACTERPROPERTIES_HXX + +#include "PropertyHelper.hxx" +#include "FastPropertyIdRanges.hxx" +#include "charttoolsdllapi.hxx" +#include + +#include + +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 + +// INCLUDED_CHART2_SOURCE_INC_CHARACTERPROPERTIES_HXX +#endif + +/* 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 000000000..0a8192706 --- /dev/null +++ b/chart2/source/inc/ChartModelHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTMODELHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTMODELHELPER_HXX + +#include +#include "charttoolsdllapi.hxx" + +#include + +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 OOO_DLLPUBLIC_CHARTTOOLS ChartModelHelper +{ +public: + static css::uno::Reference< css::chart2::data::XRangeHighlighter > createRangeHighlighter( + const css::uno::Reference< css::view::XSelectionSupplier >& xSelectionSupplier ); + + static css::uno::Reference< css::chart2::data::XDataProvider > createInternalDataProvider( + const css::uno::Reference< css::chart2::XChartDocument >& xChartDoc, bool bConnectToModel ); + + static css::uno::Reference< css::chart2::XDiagram > + findDiagram( const css::uno::Reference< css::frame::XModel >& xModel ); + + static css::uno::Reference< css::chart2::XDiagram > + findDiagram( const css::uno::Reference< css::chart2::XChartDocument >& xChartDoc ); + + static css::uno::Reference< css::chart2::XCoordinateSystem > + getFirstCoordinateSystem( ChartModel& rModel ); + + static css::uno::Reference< css::chart2::XCoordinateSystem > + getFirstCoordinateSystem( const css::uno::Reference< css::frame::XModel >& xModel ); + + SAL_DLLPRIVATE static std::vector< css::uno::Reference< css::chart2::XDataSeries > > + getDataSeries( ChartModel& rModel ); + + SAL_DLLPRIVATE static std::vector< css::uno::Reference< css::chart2::XDataSeries > > + getDataSeries( const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc ); + static std::vector< css::uno::Reference< css::chart2::XDataSeries > > + getDataSeries( const css::uno::Reference< css::frame::XModel > & xModel ); + + static css::uno::Reference< css::chart2::XChartType > + getChartTypeOfSeries( + const css::uno::Reference< css::frame::XModel >& xModel + , const css::uno::Reference< css::chart2::XDataSeries >& xGivenDataSeries ); + + static css::awt::Size getDefaultPageSize(); + + static css::awt::Size getPageSize( const css::uno::Reference< css::frame::XModel >& xModel ); + + static void triggerRangeHighlighting( const css::uno::Reference< css::frame::XModel >& xModel ); + + static bool isIncludeHiddenCells( const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static bool setIncludeHiddenCells( bool bIncludeHiddenCells, ChartModel& rModel); +}; + +} //namespace chart +#endif + +/* 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 000000000..755e7af15 --- /dev/null +++ b/chart2/source/inc/ChartResourceGroupDlgs.hxx @@ -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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CHARTRESOURCEGROUPDLGS_HXX +#define INCLUDED_CHART2_SOURCE_CHARTRESOURCEGROUPDLGS_HXX + +#include + +namespace chart +{ +class ChartTypeParameter; + +class SplinePropertiesDialog : 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 m_xLB_Spline_Type; + std::unique_ptr m_xMF_SplineResolution; + std::unique_ptr m_xFT_SplineOrder; + std::unique_ptr m_xMF_SplineOrder; +}; + +class SteppedPropertiesDialog : public weld::GenericDialogController +{ +public: + explicit SteppedPropertiesDialog(weld::Window* pParent); + + void fillControls(const ChartTypeParameter& rParameter); + void fillParameter(ChartTypeParameter& rParameter, bool bSteppedLines); + +private: + std::unique_ptr m_xRB_Start; + std::unique_ptr m_xRB_End; + std::unique_ptr m_xRB_CenterX; + std::unique_ptr m_xRB_CenterY; +}; + +} //namespace chart +#endif + +/* 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 000000000..f3b3e2f4b --- /dev/null +++ b/chart2/source/inc/ChartResourceGroups.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CHARTRESOURCEGROUPS_HXX +#define INCLUDED_CHART2_SOURCE_CHARTRESOURCEGROUPS_HXX + +#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 : 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::ToggleButton&, void); + DECL_LINK(SelectSchemeHdl, weld::ComboBox&, void); + +private: + std::unique_ptr m_xCB_3DLook; + std::unique_ptr m_xLB_Scheme; +}; + +class SortByXValuesResourceGroup : 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::ToggleButton&, void); + +private: + std::unique_ptr m_xCB_XValueSorting; +}; + +class StackingResourceGroup : 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::ToggleButton&, void); + DECL_LINK(StackingEnableHdl, weld::ToggleButton&, void); + +private: + std::unique_ptr m_xCB_Stacked; + std::unique_ptr m_xRB_Stack_Y; + std::unique_ptr m_xRB_Stack_Y_Percent; + std::unique_ptr m_xRB_Stack_Z; +}; + +#define POS_LINETYPE_STRAIGHT 0 +#define POS_LINETYPE_SMOOTH 1 +#define POS_LINETYPE_STEPPED 2 + +class SplineResourceGroup : 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); + SplinePropertiesDialog& getSplinePropertiesDialog(); + SteppedPropertiesDialog& getSteppedPropertiesDialog(); + +private: + weld::Window* m_pParent; + std::unique_ptr m_xFT_LineType; + std::unique_ptr m_xLB_LineType; + std::unique_ptr m_xPB_DetailsDialog; + std::unique_ptr m_xSplinePropertiesDialog; + std::unique_ptr m_xSteppedPropertiesDialog; +}; + +class GeometryResourceGroup : 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 +#endif + +/* 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 000000000..f65ce90a5 --- /dev/null +++ b/chart2/source/inc/ChartTypeDialogController.hxx @@ -0,0 +1,363 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHARTTYPEDIALOGCONTROLLER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHARTTYPEDIALOGCONTROLLER_HXX + +#include + +#include + +#include "ChangingResource.hxx" +#include "ThreeDHelper.hxx" + +#include +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace beans +{ +class XPropertySet; +} +} +} +} +namespace com +{ +namespace sun +{ +namespace star +{ +namespace chart2 +{ +class XChartDocument; +} +} +} +} +namespace com +{ +namespace sun +{ +namespace star +{ +namespace chart2 +{ +class XChartTypeTemplate; +} +} +} +} +namespace com +{ +namespace sun +{ +namespace star +{ +namespace lang +{ +class XMultiServiceFactory; +} +} +} +} + +class ValueSet; + +namespace chart +{ +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 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 css::uno::Reference& xChartModel, + const css::uno::Reference& xTemplateProps) const; + /// @throws css::uno::RuntimeException + virtual void setTemplateProperties( + const css::uno::Reference& xTemplateProps) const; + + bool isSubType(const OUString& rServiceName); + ChartTypeParameter getChartTypeParameterForService( + const OUString& rServiceName, + const css::uno::Reference& 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 css::uno::Reference& xChartModel); + css::uno::Reference getCurrentTemplate( + const ChartTypeParameter& rParameter, + const css::uno::Reference& 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 : 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 : 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 : 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 : 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 : 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 : 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 : 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 : 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 : 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 css::uno::Reference& xChartModel, + const css::uno::Reference& xTemplateProps) const override; + + virtual void setTemplateProperties( + const css::uno::Reference& xTemplateProps) const override; + +private: + DECL_LINK(ChangeLineCountHdl, weld::SpinButton&, void); + +private: + std::unique_ptr m_xFT_NumberOfLines; + std::unique_ptr m_xMF_NumberOfLines; +}; + +class BubbleChartDialogController : 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 +#endif + +/* 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 000000000..e749dd5b4 --- /dev/null +++ b/chart2/source/inc/ChartTypeHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTTYPEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTTYPEHELPER_HXX + +#include +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::chart2 { class XChartType; } +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTTOOLS ChartTypeHelper +{ +public: + static bool isSupportingGeometryProperties( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingStatisticProperties( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingRegressionProperties(const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingMainAxis( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex ); + static bool isSupportingSecondaryAxis( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingAreaProperties( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingSymbolProperties( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingOverlapAndGapWidthProperties( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingBarConnectors( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingRightAngledAxes( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + static bool isSupportingAxisSideBySide( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + static bool isSupportingStartingAngle( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + //starting value for bars or baseline for areas for example + static bool isSupportingBaseValue( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + static bool isSupportingAxisPositioning( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex ); + static bool isSupportingDateAxis( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionIndex ); + static bool isSupportingComplexCategory( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + static bool isSupportingCategoryPositioning( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nDimensionCount ); + + //returns sequence of css::chart::DataLabelPlacement + static css::uno::Sequence < sal_Int32 > getSupportedLabelPlacements( + const css::uno::Reference< css::chart2::XChartType >& xChartType, bool bSwapXAndY + , const css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + + //returns sequence of css::chart::MissingValueTreatment + static css::uno::Sequence < sal_Int32 > getSupportedMissingValueTreatments( + const css::uno::Reference< css::chart2::XChartType >& xChartType ); + + SAL_DLLPRIVATE static css::drawing::Direction3D getDefaultSimpleLightDirection( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + SAL_DLLPRIVATE static css::drawing::Direction3D getDefaultRealisticLightDirection( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + SAL_DLLPRIVATE static sal_Int32 getDefaultDirectLightColor( bool bSimple, const css::uno::Reference< css::chart2::XChartType >& xChartType ); + SAL_DLLPRIVATE static sal_Int32 getDefaultAmbientLightColor( bool bSimple, const css::uno::Reference< css::chart2::XChartType >& xChartType ); + static sal_Int32 getNumberOfDisplayedSeries( const css::uno::Reference< css::chart2::XChartType >& xChartType, sal_Int32 nNumberOfSeries ); + SAL_DLLPRIVATE static bool noBordersForSimpleScheme( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + + static bool isSeriesInFrontOfAxisLine( const css::uno::Reference< css::chart2::XChartType >& xChartType ); + + static sal_Int32 //one of css::chart2::AxisType + getAxisType( const css::uno::Reference< css::chart2::XChartType >& xChartType + , sal_Int32 nDimensionIndex ); + + static OUString getRoleOfSequenceForYAxisNumberFormatDetection( const css::uno::Reference< + css::chart2::XChartType >& xChartType ); + + static OUString getRoleOfSequenceForDataLabelNumberFormatDetection( const css::uno::Reference< + css::chart2::XChartType >& xChartType ); + + static bool isSupportingOnlyDeepStackingFor3D( const css::uno::Reference< css::chart2::XChartType >& xChartType ); +}; + +} //namespace chart +#endif + +/* 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 000000000..fc4517d1b --- /dev/null +++ b/chart2/source/inc/ChartTypeTemplateProvider.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHARTTYPETEMPLATEPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_CHARTTYPETEMPLATEPROVIDER_HXX + +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace chart2 +{ +class XChartTypeTemplate; +} +} +} +} + +namespace chart +{ +class ChartTypeTemplateProvider +{ +public: + virtual css::uno::Reference getCurrentTemplate() const = 0; + virtual ~ChartTypeTemplateProvider() {} +}; + +} //namespace chart +#endif + +/* 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 000000000..48f7c27b6 --- /dev/null +++ b/chart2/source/inc/ChartViewHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEWHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEWHELPER_HXX + +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::uno { template class Reference; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTTOOLS ChartViewHelper +{ +public: + static void setViewToDirtyState( const css::uno::Reference< css::frame::XModel >& xChartModel ); +}; + +} //namespace chart +#endif + +/* 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 000000000..da697e05e --- /dev/null +++ b/chart2/source/inc/CloneHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CLONEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CLONEHELPER_HXX + +#include + +#include +#include +#include + +namespace chart +{ +namespace CloneHelper +{ + +/// functor that clones a UNO-Reference +template< class Interface > + struct CreateRefClone +{ + css::uno::Reference operator() ( const css::uno::Reference & xOther ) + { + css::uno::Reference 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 >()); +} + +/// clones a UNO-sequence of UNO-References +template< class Interface > + void CloneRefSequence( + const css::uno::Sequence< css::uno::Reference > & rSource, + css::uno::Sequence< css::uno::Reference > & rDestination ) +{ + rDestination.realloc( rSource.getLength()); + std::transform( rSource.begin(), rSource.end(), + rDestination.getArray(), + CreateRefClone< Interface >()); +} + +} // namespace CloneHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_CLONEHELPER_HXX +#endif + +/* 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 000000000..6c34693da --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_COLORPERPOINTHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_COLORPERPOINTHELPER_HXX + +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::uno { template class Reference; } + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTTOOLS ColorPerPointHelper +{ +public: + static bool hasPointOwnColor( + const css::uno::Reference< css::beans::XPropertySet >& xDataSeriesProperties + , 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 css::uno::Reference< css::beans::XPropertySet >& xSeriesProperties + , sal_Int32 nPointIndex ); +}; + +} //namespace chart +#endif + +/* 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 000000000..940b95d70 --- /dev/null +++ b/chart2/source/inc/CommonConverters.hxx @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_COMMONCONVERTERS_HXX +#define INCLUDED_CHART2_SOURCE_INC_COMMONCONVERTERS_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 ); + +/** get a single Point from a Polygon +*/ +OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly( + const css::drawing::PolyPolygonShape3D& rPolygon + , sal_Int32 nPointIndex, sal_Int32 nPolyIndex ); + +OOO_DLLPUBLIC_CHARTTOOLS +void addPolygon( css::drawing::PolyPolygonShape3D& rRet + , const css::drawing::PolyPolygonShape3D& rAdd ); +/** PolyPolygonShape3D + PolyPolygonShape3D -> PolyPolygonShape3D +*/ +OOO_DLLPUBLIC_CHARTTOOLS +void appendPoly( css::drawing::PolyPolygonShape3D& rRet + , const css::drawing::PolyPolygonShape3D& 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 ); + +/** drawing::PointSequenceSequence + drawing::PointSequenceSequence +*/ +OOO_DLLPUBLIC_CHARTTOOLS +void appendPointSequence( css::drawing::PointSequenceSequence& rTarget + , 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 ); + +/** B3DPoint -> Sequence +*/ +OOO_DLLPUBLIC_CHARTTOOLS css::uno::Sequence< double > B3DPointToSequence( const ::basegfx::B3DPoint& rPoint ); + +/** Sequence -> drawing::Position3D +*/ +OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D + SequenceToPosition3D( const css::uno::Sequence< double >& rSeq ); + +/** drawing::Position3D -> Sequence +*/ + +OOO_DLLPUBLIC_CHARTTOOLS css::uno::Sequence< double > + Position3DToSequence( const css::drawing::Position3D& rPosition ); + +/** 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 ); + +/** uno::Sequence< uno::Sequence< T > > -> uno::Sequence< T > + */ +template< typename T > +css::uno::Sequence< T > + FlattenSequence( const css::uno::Sequence< css::uno::Sequence< T > > & aSeqSeq ) +{ + sal_Int32 nOuter, nInner, nCount = 0, + nResultSize = 0; + const sal_Int32 nOuterSize = aSeqSeq.getLength(); + for( nOuter=0; nOuter aResult( nResultSize ); + + for( nOuter=0; nOuter +#include +#include +#include +#include "charttoolsdllapi.hxx" + +namespace chart +{ +namespace CommonFunctors +{ + +/** unary function to convert any type T into a css::uno::Any. + +

uno::makeAny is an inline function. Thus is cannot be taken directly + (via mem_fun_ptr)

+*/ +template< typename T > + struct makeAny +{ + css::uno::Any operator() ( const T & aVal ) + { + return css::uno::makeAny( aVal ); + } +}; + +/** unary function to convert css::uno::Any into a double number. + +

In case no number can be generated from the Any, NaN (see + rtl::math::SetNAN()) is returned.

+*/ +struct OOO_DLLPUBLIC_CHARTTOOLS AnyToDouble +{ + double operator() ( const css::uno::Any & rAny ) + { + double fResult; + ::rtl::math::setNan( & fResult ); + 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(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(rAny) ) + { + return *s; + } + + return OUString(); + } +}; + +/** unary function to convert an OUString into a double number. + +

For conversion rtl::math::StringToDouble is used.

+ */ +struct OOO_DLLPUBLIC_CHARTTOOLS OUStringToDouble +{ + double operator() ( const OUString & rStr ) + { + rtl_math_ConversionStatus eConversionStatus; + double fResult = ::rtl::math::stringToDouble( rStr, '.', ',', & eConversionStatus ); + + if( eConversionStatus != rtl_math_ConversionStatus_Ok ) + ::rtl::math::setNan( & fResult ); + + return fResult; + } +}; + +/** unary function to convert a double number into an OUString. + +

For conversion rtl::math::DoubleToOUString is used.

+ */ +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 CommonFunctors +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_COMMONFUNCTORS_HXX +#endif + +/* 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 000000000..7d0bbf662 --- /dev/null +++ b/chart2/source/inc/ConfigColorScheme.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CONFIGCOLORSCHEME_HXX +#define INCLUDED_CHART2_SOURCE_INC_CONFIGCOLORSCHEME_HXX + +#include "charttoolsdllapi.hxx" +#include +#include +#include + +#include + +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 : + 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( const OUString & rPropertyName ); + +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 + +// INCLUDED_CHART2_SOURCE_INC_CONFIGCOLORSCHEME_HXX +#endif + +/* 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 000000000..090becde9 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CONTROLLERLOCKGUARD_HXX +#define INCLUDED_CHART2_SOURCE_INC_CONTROLLERLOCKGUARD_HXX + +#include "charttoolsdllapi.hxx" +#include + +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( const css::uno::Reference< css::frame::XModel > & xModel ); + ~ControllerLockGuardUNO(); + +private: + css::uno::Reference< css::frame::XModel > 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( + const css::uno::Reference< css::frame::XModel > & xModel ); + ~ControllerLockHelper(); + + SAL_DLLPRIVATE void lockControllers(); + SAL_DLLPRIVATE void unlockControllers(); + +private: + css::uno::Reference< css::frame::XModel > 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 + +// INCLUDED_CHART2_SOURCE_INC_CONTROLLERLOCKGUARD_HXX +#endif + +/* 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 000000000..c6fba94de --- /dev/null +++ b/chart2/source/inc/DataSeriesHelper.hxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_DATASERIESHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_DATASERIESHELPER_HXX + +#include "StackMode.hxx" +#include "charttoolsdllapi.hxx" +#include +#include + +#include + +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 Sequence; } + +namespace chart +{ + +namespace DataSeriesHelper +{ + +OOO_DLLPUBLIC_CHARTTOOLS OUString + getRole( const css::uno::Reference& 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 > +getAllDataSequences( + const css::uno::Sequence >& 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 css::uno::Reference< css::chart2::data::XDataSource > + getDataSource( const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > > & aSeries ); + +/** 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. + */ +OOO_DLLPUBLIC_CHARTTOOLS OUString getDataSeriesLabel( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const OUString & rLabelSequenceRole ); + +/** Get the label of a labeled sequence including necessary automatic generation + */ +OOO_DLLPUBLIC_CHARTTOOLS OUString getLabelForLabeledDataSequence( + const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xLabeledSeq ); + +OOO_DLLPUBLIC_CHARTTOOLS void setStackModeAtSeries( + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > > & aSeries, + const css::uno::Reference< css::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, + StackMode eStackMode ); + +OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getAttachedAxisIndex( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries ); + +/// @param nAxisIndex, if -1 it is determined by the given data series via getAttachedAxisIndex +OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getNumberFormatKeyFromAxis( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, + sal_Int32 nDimensionIndex, + sal_Int32 nAxisIndex = -1 ); + +OOO_DLLPUBLIC_CHARTTOOLS +css::uno::Reference< css::chart2::XCoordinateSystem > + getCoordinateSystemOfSeries( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + +OOO_DLLPUBLIC_CHARTTOOLS +css::uno::Reference< css::chart2::XChartType > + getChartTypeOfSeries( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + +OOO_DLLPUBLIC_CHARTTOOLS void deleteSeries( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XChartType > & xChartType ); + +OOO_DLLPUBLIC_CHARTTOOLS void switchSymbolsOnOrOff( + const css::uno::Reference< css::beans::XPropertySet > & xSeriesProperties, + bool bSymbolsOn, sal_Int32 nSeriesIndex ); + +OOO_DLLPUBLIC_CHARTTOOLS void switchLinesOnOrOff( + const css::uno::Reference< css::beans::XPropertySet > & xSeriesProperties, + bool bLinesOn ); + +OOO_DLLPUBLIC_CHARTTOOLS +void makeLinesThickOrThin( const css::uno::Reference< css::beans::XPropertySet > & xSeriesProperties, bool bThick ); + +OOO_DLLPUBLIC_CHARTTOOLS void setPropertyAlsoToAllAttributedDataPoints( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, + const css::uno::Any& rPropertyValue ); + +OOO_DLLPUBLIC_CHARTTOOLS bool hasAttributedDataPointDifferentValue( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, + const css::uno::Any& rPropertyValue ); + +OOO_DLLPUBLIC_CHARTTOOLS bool hasUnhiddenData( const css::uno::Reference< + css::chart2::XDataSeries >& xSeries ); + +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 css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + +OOO_DLLPUBLIC_CHARTTOOLS bool hasDataLabelsAtPoints( const css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + +OOO_DLLPUBLIC_CHARTTOOLS bool hasDataLabelAtPoint( const css::uno::Reference< css::chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex ); + +OOO_DLLPUBLIC_CHARTTOOLS void insertDataLabelsToSeriesAndAllPoints( const css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + +OOO_DLLPUBLIC_CHARTTOOLS void insertDataLabelToPoint( const css::uno::Reference< css::beans::XPropertySet >& xPointPropertySet ); + +OOO_DLLPUBLIC_CHARTTOOLS void deleteDataLabelsFromSeriesAndAllPoints( const css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + +OOO_DLLPUBLIC_CHARTTOOLS void deleteDataLabelsFromPoint( const css::uno::Reference< css::beans::XPropertySet >& xPointPropertySet ); + +} // namespace DataSeriesHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_DATASERIESHELPER_HXX +#endif + +/* 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 000000000..6ad8bbffc --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_DATASOURCE_HXX +#define INCLUDED_CHART2_SOURCE_INC_DATASOURCE_HXX + +#include +#include +#include +#include + +namespace chart +{ + +class DataSource : 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 ); + + 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; + +protected: + // ____ 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 + +// INCLUDED_CHART2_SOURCE_INC_DATASOURCE_HXX +#endif + +/* 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 000000000..5f159f6a5 --- /dev/null +++ b/chart2/source/inc/DataSourceHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_DATASOURCEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_DATASOURCEHELPER_HXX + +#include "charttoolsdllapi.hxx" +#include +#include + +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 OOO_DLLPUBLIC_CHARTTOOLS DataSourceHelper +{ +public: + static css::uno::Reference< css::chart2::data::XDataSource > + createDataSource( const css::uno::Sequence< + css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & rSequences ); + + static css::uno::Reference< css::chart2::data::XDataSequence > + createCachedDataSequence(); + + static css::uno::Reference< css::chart2::data::XDataSequence > + createCachedDataSequence( const OUString & rSingleText ); + + static css::uno::Reference< css::chart2::data::XLabeledDataSequence > + createLabeledDataSequence( + const css::uno::Reference< css::chart2::data::XDataSequence >& xValues , + const css::uno::Reference< css::chart2::data::XDataSequence >& xLabels ); + + static css::uno::Reference< css::chart2::data::XLabeledDataSequence > + createLabeledDataSequence( + const css::uno::Reference< css::chart2::data::XDataSequence >& xValues ); + + static css::uno::Reference< css::chart2::data::XLabeledDataSequence > + 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 css::uno::Reference< css::chart2::data::XDataSource > + pressUsedDataIntoRectangularFormat( const css::uno::Reference< css::chart2::XChartDocument >& xChartDoc ); + + SAL_DLLPRIVATE static css::uno::Sequence< OUString > getUsedDataRanges( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + static css::uno::Sequence< OUString > getUsedDataRanges( + const css::uno::Reference< css::frame::XModel > & xChartModel ); + + static css::uno::Reference< css::chart2::data::XDataSource > getUsedData( + ChartModel& rModel ); + + static css::uno::Reference< css::chart2::data::XDataSource > getUsedData( + const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static css::uno::Reference< css::chart2::data::XDataSource > getUsedData( + const css::uno::Reference& xChartDoc ); + + static bool detectRangeSegmentation( + const css::uno::Reference< css::frame::XModel >& xChartModel + , OUString& rOutRangeString + , css::uno::Sequence< sal_Int32 >& rSequenceMapping + , bool& rOutUseColumns + , bool& rOutFirstCellAsLabel + , bool& rOutHasCategories ); + + static void setRangeSegmentation( + const css::uno::Reference< css::frame::XModel >& 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 css::uno::Reference< css::chart2::XChartDocument >& 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 +#endif + +/* 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 000000000..3fcd9a0af --- /dev/null +++ b/chart2/source/inc/DiagramHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_DIAGRAMHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_DIAGRAMHELPER_HXX + +#include "StackMode.hxx" +#include "charttoolsdllapi.hxx" +#include +#include + +#include +#include + +namespace chart { class ChartModel; } +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 XDiagram; } +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 +{ + +enum DiagramPositioningMode +{ + DiagramPositioningMode_AUTO, + DiagramPositioningMode_EXCLUDING, + DiagramPositioningMode_INCLUDING +}; + +class OOO_DLLPUBLIC_CHARTTOOLS DiagramHelper +{ +public: + typedef std::pair< + css::uno::Reference< css::chart2::XChartTypeTemplate >, + OUString > + tTemplateWithServiceName; + + /** tries to find a template in the chart-type manager that matches the + given 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. + */ + static tTemplateWithServiceName + getTemplateForDiagram( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + const css::uno::Reference< css::lang::XMultiServiceFactory > & xChartTypeManager); + + /** Sets the "SwapXAndYAxis" property at all coordinate systems found in the + given diagram. + + "vertical==true" for bar charts, "vertical==false" for column charts + */ + static void setVertical( const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + 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 + */ + static bool getVertical( const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + bool& rbOutFoundResult, bool& rbOutAmbiguousResult ); + + static StackMode getStackMode( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + 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) + */ + static void setStackMode( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + StackMode eStackMode + ); + + /** 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 css::uno::Reference< css::chart2::XChartType > & xChartType, + bool& rbFound, bool& rbAmbiguous, + const css::uno::Reference< css::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem + ); + + /** Returns the dimension found for all chart types in the tree. If the + dimension is not unique, 0 is returned. + */ + static sal_Int32 getDimension( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + /** 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. + */ + static void setDimension( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + sal_Int32 nNewDimensionCount ); + + /** Replaces all occurrences of xCooSysToReplace in the tree with + xReplacement in the diagram's tree + */ + SAL_DLLPRIVATE static void replaceCoordinateSystem( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + const css::uno::Reference< css::chart2::XCoordinateSystem > & xCooSysToReplace, + const css::uno::Reference< css::chart2::XCoordinateSystem > & xReplacement ); + + static bool isSeriesAttachedToMainAxis( + const css::uno::Reference< css::chart2::XDataSeries >& xDataSeries ); + + static bool attachSeriesToAxis( bool bMainAxis, + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + const css::uno::Reference< css::uno::XComponentContext > & xContext, + bool bAdaptAxes=true ); + + static css::uno::Reference< css::chart2::XAxis > getAttachedAxis( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static css::uno::Reference< css::chart2::XChartType > + getChartTypeOfSeries( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + const css::uno::Reference< css::chart2::XDataSeries >& xSeries ); + + static std::vector< css::uno::Reference< css::chart2::XDataSeries > > + getDataSeriesFromDiagram( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + /** return all data series in this diagram grouped by chart-types + */ + static css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< css::chart2::XDataSeries > > > + getDataSeriesGroups( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + static bool isCategoryDiagram( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static void setCategoriesToDiagram( + const css::uno::Reference< css::chart2::data::XLabeledDataSequence >& xCategories, + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + bool bSetAxisType = false, // when this flag is true ... + bool bCategoryAxis = true);// set the AxisType to CATEGORY or back to REALNUMBER + + static css::uno::Reference< css::chart2::data::XLabeledDataSequence > + getCategoriesFromDiagram( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + static css::uno::Sequence< OUString > + getExplicitSimpleCategories( ChartModel& rModel ); + + SAL_DLLPRIVATE static css::uno::Sequence< OUString > + generateAutomaticCategoriesFromCooSys( + const css::uno::Reference< css::chart2::XCoordinateSystem > & xCooSys ); + + static void switchToDateCategories( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc ); + + static void switchToTextCategories( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc ); + + static bool isSupportingDateAxis( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + 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 ); + + static css::uno::Reference< css::chart2::XChartType > + getChartTypeByIndex( const css::uno::Reference< css::chart2::XDiagram >& xDiagram, sal_Int32 nIndex ); + + static css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > > + getChartTypesFromDiagram( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + SAL_DLLPRIVATE static bool areChartTypesCompatible( const css::uno::Reference< + css::chart2::XChartType >& xFirstType, + const css::uno::Reference< css::chart2::XChartType >& xSecondType ); + + /** + * 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 if the series can be moved. + * + */ + static bool isSeriesMoveable( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + const css::uno::Reference< css::chart2::XDataSeries >& xGivenDataSeries, + bool bForward ); + + /** + * 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 if the series was moved successfully. + * + */ + static bool moveSeries( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + const css::uno::Reference< css::chart2::XDataSeries >& xGivenDataSeries, + bool bForward ); + + static bool isSupportingFloorAndWall( const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + static bool isPieOrDonutChart( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + + static sal_Int32 getGeometry3D( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + bool& rbFound, bool& rbAmbiguous ); + + static void setGeometry3D( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + sal_Int32 nNewGeometry ); + + //returns integer from constant group css::chart::MissingValueTreatment + static sal_Int32 getCorrectedMissingValueTreatment( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram, + const css::uno::Reference< css::chart2::XChartType >& xChartType ); + + static DiagramPositioningMode getDiagramPositioningMode( const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + + static bool setDiagramPositioning( const css::uno::Reference< css::frame::XModel >& xChartModel, + const css::awt::Rectangle& rPosRect /*100th mm*/ ); + + static css::awt::Rectangle getDiagramRectangleFromModel( const css::uno::Reference< css::frame::XModel >& 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 + +// INCLUDED_CHART2_SOURCE_INC_DIAGRAMHELPER_HXX +#endif + +/* 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 000000000..9f02ca3f8 --- /dev/null +++ b/chart2/source/inc/DisposeHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_DISPOSEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_DISPOSEHELPER_HXX + +#include +#include + +namespace chart +{ +namespace DisposeHelper +{ + +template +void Dispose(const T & xInterface) +{ + css::uno::Reference xComponent(xInterface, css::uno::UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); +} + +template +void DisposeAndClear(css::uno::Reference & rInterface) +{ + Dispose>(rInterface); + rInterface.set(nullptr); +} + +template +void DisposeAllElements(Container & rContainer) +{ + for (const auto & rElement : rContainer) + { + Dispose(rElement); + } +} + +}} // namespace chart::DisposeHelper + +#endif // INCLUDED_CHART2_SOURCE_INC_DISPOSEHELPER_HXX + +/* 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 000000000..6cd513ebc --- /dev/null +++ b/chart2/source/inc/ErrorBar.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_ERRORBAR_HXX +#define INCLUDED_CHART2_SOURCE_INC_ERRORBAR_HXX + +#include "MutexContainer.hxx" +#include "charttoolsdllapi.hxx" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +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 MutexContainer, + 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_ERRORBAR_HXX +#endif + +/* 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 000000000..c40fdc49c --- /dev/null +++ b/chart2/source/inc/EventListenerHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_EVENTLISTENERHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_EVENTLISTENERHELPER_HXX + +#include + +#include + +namespace com::sun::star::lang { class XEventListener; } + +namespace chart +{ +namespace EventListenerHelper +{ + +namespace impl +{ + +template< class InterfaceRef > +struct addListenerFunctor +{ + explicit addListenerFunctor( const css::uno::Reference< css::lang::XEventListener > & xListener ) : + m_xListener( 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( const css::uno::Reference< css::lang::XEventListener > & xListener ) : + m_xListener( 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 + +// INCLUDED_CHART2_SOURCE_INC_EVENTLISTENERHELPER_HXX +#endif + +/* 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 000000000..13c9a3605 --- /dev/null +++ b/chart2/source/inc/ExplicitCategoriesProvider.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_EXPLICITCATEGORIESPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_INC_EXPLICITCATEGORIESPROVIDER_HXX + +#include "charttoolsdllapi.hxx" +#include +#include +#include + +#include + +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 +{ + +struct OOO_DLLPUBLIC_CHARTTOOLS ComplexCategory +{ + OUString Text; + sal_Int32 Count; + + ComplexCategory( const OUString& rText, sal_Int32 nCount ) : Text( rText ), 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 css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSysModel + , ChartModel& rChartModel + ); + ~ExplicitCategoriesProvider(); + + void init(); + + css::uno::Reference< css::chart2::data::XDataSequence > getOriginalCategories(); + + css::uno::Sequence< OUString > const & getSimpleCategories(); + const std::vector* getCategoriesByLevel( sal_Int32 nLevel ); + + static OUString getCategoryByIndex( + const css::uno::Reference< css::chart2::XCoordinateSystem >& 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 css::uno::Sequence< 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; + css::uno::WeakReference< css::chart2::XCoordinateSystem > 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; + css::uno::Sequence< css::uno::Reference< + css::chart2::data::XLabeledDataSequence> > m_aSplitCategoriesList; + + bool m_bIsDateAxis; + bool m_bIsAutoDate; + std::vector< double > m_aDateCategories; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_EXPLICITCATEGORIESPROVIDER_HXX +#endif + +/* 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 000000000..ba08bb13d --- /dev/null +++ b/chart2/source/inc/ExponentialRegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_EXPONENTIALREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_EXPONENTIALREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" + +namespace chart +{ + +class ExponentialRegressionCurveCalculator : public RegressionCurveCalculator +{ +public: + ExponentialRegressionCurveCalculator(); + virtual ~ExponentialRegressionCurveCalculator() override; + +protected: + virtual OUString ImplGetRepresentation( + const css::uno::Reference& xNumFormatter, + sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override; + +private: + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL recalculateRegression( + const css::uno::Sequence& aXValues, + const css::uno::Sequence& aYValues ) override; + + virtual double SAL_CALL getCurveValue( double x ) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& 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 + +// INCLUDED_CHART2_SOURCE_INC_EXPONENTIALREGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..a2572c511 --- /dev/null +++ b/chart2/source/inc/FastPropertyIdRanges.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_FASTPROPERTYIDRANGES_HXX +#define INCLUDED_CHART2_SOURCE_INC_FASTPROPERTYIDRANGES_HXX + +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 + +// INCLUDED_CHART2_SOURCE_INC_FASTPROPERTYIDRANGES_HXX +#endif + +/* 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 000000000..65a7b221e --- /dev/null +++ b/chart2/source/inc/FillProperties.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_FILLPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_INC_FILLPROPERTIES_HXX + +#include "PropertyHelper.hxx" +#include "FastPropertyIdRanges.hxx" +#include "charttoolsdllapi.hxx" + +#include + +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 + +// INCLUDED_CHART2_SOURCE_INC_FILLPROPERTIES_HXX +#endif + +/* 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 000000000..9953de31a --- /dev/null +++ b/chart2/source/inc/FormattedStringHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_FORMATTEDSTRINGHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_FORMATTEDSTRINGHELPER_HXX + +#include + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::chart2 { class XFormattedString2; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::uno { template class Reference; } + +namespace chart +{ + +class FormattedStringHelper +{ +public: + static css::uno::Sequence< + css::uno::Reference< css::chart2::XFormattedString2 > > + createFormattedStringSequence( + const css::uno::Reference< css::uno::XComponentContext > & xContext + , const OUString & rString + , const css::uno::Reference< css::beans::XPropertySet > & xTextProperties ) throw(); +}; + +} //namespace chart +#endif + +/* 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 000000000..25ed60606 --- /dev/null +++ b/chart2/source/inc/InternalData.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_INTERNALDATA_HXX +#define INCLUDED_CHART2_SOURCE_INC_INTERNALDATA_HXX + +#include + +#include +#include + +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, const std::vector< css::uno::Any >& rComplexLabel ); + void setComplexRowLabel( sal_Int32 nRowIndex, const 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( const tVecVecAny& rNewRowLabels ); + const tVecVecAny& getComplexRowLabels() const; + void setComplexColumnLabels( const 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 , 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 +}; + +#endif + +} // 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 000000000..7c3491ae1 --- /dev/null +++ b/chart2/source/inc/InternalDataProvider.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_INTERNALDATAPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_INC_INTERNALDATAPROVIDER_HXX + +#include "InternalData.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::chart2 { class XChartDocument; } + +namespace chart +{ + +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. + +

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.

+ +

The format for a complete range is "all". (Do we need more than + that?)

+ */ +class InternalDataProvider : + 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 css::uno::Reference< css::chart2::XChartDocument > & 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 SAL_CALL + createDataSequenceByValueArray( const OUString& aRole, const OUString& aRangeRepresentation ) 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 ); + css::uno::Reference< css::chart2::data::XDataSequence > + createDataSequenceAndAddToMap( const OUString & rRangeRepresentation ); + + css::uno::Reference + createDataSequenceFromArray( const OUString& rArrayStr, const OUString& rRole ); + + 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 + +// INCLUDED_CHART2_SOURCE_INC_INTERNALDATAPROVIDER_HXX +#endif + +/* 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 000000000..dd99ac847 --- /dev/null +++ b/chart2/source/inc/LabeledDataSequence.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_LABELEDDATASEQUENCE_HXX +#define INCLUDED_CHART2_SOURCE_INC_LABELEDDATASEQUENCE_HXX + +#include "MutexContainer.hxx" +#include + +#include +#include + +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 LabeledDataSequence : + public MutexContainer, + public impl::LabeledDataSequence_Base +{ +public: + explicit LabeledDataSequence(); + explicit LabeledDataSequence( + const css::uno::Reference< css::chart2::data::XDataSequence > & rValues ); + explicit LabeledDataSequence( + const css::uno::Reference< css::chart2::data::XDataSequence > & rValues, + const css::uno::Reference< css::chart2::data::XDataSequence > & rLabels ); + + 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; + +protected: + // ____ 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_LABELEDDATASEQUENCE_HXX +#endif + +/* 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 000000000..75064f594 --- /dev/null +++ b/chart2/source/inc/LegendHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_LEGENDHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_LEGENDHELPER_HXX + +#include +#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 OOO_DLLPUBLIC_CHARTTOOLS LegendHelper +{ +public: + static css::uno::Reference< css::chart2::XLegend > + showLegend( ChartModel& rModel + , const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + static void hideLegend( ChartModel& rModel ); + + static css::uno::Reference< css::chart2::XLegend > + getLegend( ChartModel& rModel + , const css::uno::Reference< css::uno::XComponentContext >& xContext = nullptr + , bool bCreate = false ); + + /** returns , if either there is no legend at the diagram, or there + is a legend which has a "Show" property of value . Otherwise, + is returned. + */ + static bool hasLegend( const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); +}; + +} //namespace chart +#endif + +/* 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 000000000..ca1e583f9 --- /dev/null +++ b/chart2/source/inc/LifeTime.hxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_LIFETIME_HXX +#define INCLUDED_CHART2_SOURCE_INC_LIFETIME_HXX + +#include +#include +#include +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::lang { class XComponent; } +namespace com::sun::star::util { class CloseVetoException; } +namespace com::sun::star::util { class XCloseListener; } +namespace com::sun::star::util { class XCloseable; } + +namespace apphelper +{ + +class OOO_DLLPUBLIC_CHARTTOOLS LifeTimeManager +{ +friend class LifeTimeGuard; +protected: + mutable ::osl::Mutex m_aAccessMutex; +public: + LifeTimeManager( css::lang::XComponent* pComponent ); + virtual ~LifeTimeManager(); + + bool impl_isDisposed( bool bAssert=true ); + /// @throws css::uno::RuntimeException + bool dispose(); + +public: + ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; + +protected: + SAL_DLLPRIVATE virtual bool impl_canStartApiCall(); + SAL_DLLPRIVATE virtual void impl_apiCallCountReachedNull(){} + + SAL_DLLPRIVATE void impl_registerApiCall(bool bLongLastingCall); + SAL_DLLPRIVATE void impl_unregisterApiCall(bool bLongLastingCall); + +protected: + 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() override; + + void impl_setOwnership( bool bDeliverOwnership, bool bMyVeto ); + void impl_doClose(); +}; + +/* +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.clear(); } + +private: + osl::ClearableMutexGuard m_guard; + LifeTimeManager& m_rManager; + bool m_bCallRegistered; + bool m_bLongLastingCallRegistered; + +private: + LifeTimeGuard( const LifeTimeGuard& ) = delete; + LifeTimeGuard& operator= ( const LifeTimeGuard& ) = delete; +}; + +template +class NegativeGuard final +{ + T * m_pT; +public: + + NegativeGuard(T & t) : m_pT(&t) + { + m_pT->release(); + } + + ~NegativeGuard() + { + m_pT->acquire(); + } +}; + +}//end namespace apphelper +#endif + +/* 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 000000000..e870a5688 --- /dev/null +++ b/chart2/source/inc/LinePropertiesHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_LINEPROPERTIESHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_LINEPROPERTIESHELPER_HXX + +#include "PropertyHelper.hxx" +#include "FastPropertyIdRanges.hxx" +#include "charttoolsdllapi.hxx" + +#include + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::beans { struct Property; } +namespace com::sun::star::uno { template 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 + +// INCLUDED_CHART2_SOURCE_INC_LINEPROPERTIESHELPER_HXX +#endif + +/* 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 000000000..24d82d1ec --- /dev/null +++ b/chart2/source/inc/LinearRegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_LINEARREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_LINEARREGRESSIONCURVECALCULATOR_HXX + +#include "PolynomialRegressionCurveCalculator.hxx" + +namespace chart +{ + +class LinearRegressionCurveCalculator : public PolynomialRegressionCurveCalculator +{ +public: + LinearRegressionCurveCalculator(); + virtual ~LinearRegressionCurveCalculator() override; + +private: + virtual void SAL_CALL setRegressionProperties( + sal_Int32 aDegree, + sal_Bool aForceIntercept, + double aInterceptValue, + sal_Int32 aPeriod) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_LINEARREGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..522756afe --- /dev/null +++ b/chart2/source/inc/LogarithmicRegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_LOGARITHMICREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_LOGARITHMICREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" + +namespace chart +{ + +class LogarithmicRegressionCurveCalculator : public RegressionCurveCalculator +{ +public: + LogarithmicRegressionCurveCalculator(); + virtual ~LogarithmicRegressionCurveCalculator() override; + +protected: + virtual OUString ImplGetRepresentation( + const css::uno::Reference& xNumFormatter, + sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override; + +private: + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL recalculateRegression( + const css::uno::Sequence& aXValues, + const css::uno::Sequence& aYValues ) override; + + virtual double SAL_CALL getCurveValue( double x ) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) override; + + // formula is: f(x) = m_fSlope * log( x ) + m_fIntercept + double m_fSlope; + double m_fIntercept; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_LOGARITHMICREGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..7c947bec4 --- /dev/null +++ b/chart2/source/inc/MeanValueRegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_MEANVALUEREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_MEANVALUEREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" + +namespace chart +{ + +class MeanValueRegressionCurveCalculator : public RegressionCurveCalculator +{ +public: + MeanValueRegressionCurveCalculator(); + virtual ~MeanValueRegressionCurveCalculator() override; + +protected: + virtual OUString ImplGetRepresentation( + const css::uno::Reference& xNumFormatter, + sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override; + +private: + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL recalculateRegression( + const css::uno::Sequence& aXValues, + const css::uno::Sequence& aYValues ) override; + + virtual double SAL_CALL getCurveValue( double x ) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) override; + + // formula is: f(x) = m_fMeanValue + double m_fMeanValue; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_MEANVALUEREGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..f44d5d1d0 --- /dev/null +++ b/chart2/source/inc/MediaDescriptorHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_MEDIADESCRIPTORHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_MEDIADESCRIPTORHELPER_HXX + +#include +#include +#include +#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(); +}; + +} + +#endif + +/* 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 000000000..29c4106f5 --- /dev/null +++ b/chart2/source/inc/ModifyListenerHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_MODIFYLISTENERHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_MODIFYLISTENERHELPER_HXX + +#include +#include +#include + +#include "MutexContainer.hxx" + +#include +#include +#include + +namespace com::sun::star::uno { class XWeak; } +namespace com::sun::star::uno { template class WeakReference; } + +namespace chart +{ +namespace ModifyListenerHelper +{ + +css::uno::Reference< css::util::XModifyListener > createModifyEventForwarder(); + +/** 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. + +

The listeners are held as WeakReferences if they support XWeak. Thus the + life time of the listeners is independent of the broadcaster's lifetime in + this case.

+ */ +class ModifyEventForwarder : + public MutexContainer, + public ::cppu::WeakComponentImplHelper< + css::util::XModifyBroadcaster, + css::util::XModifyListener > +{ +public: + ModifyEventForwarder(); + + void AddListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ); + void RemoveListener( + const css::uno::Reference< css::util::XModifyListener >& aListener ); + +protected: + // ____ 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; + + // ____ WeakComponentImplHelperBase ____ + virtual void SAL_CALL disposing() override; + +private: + /// call disposing() at all listeners and remove all listeners + void DisposeAndClear( const css::uno::Reference< + css::uno::XWeak > & xSource ); + +// ::osl::Mutex & m_rMutex; + ::cppu::OBroadcastHelper m_aModifyListeners; + + typedef std::vector< + std::pair< + css::uno::WeakReference< css::util::XModifyListener >, + css::uno::Reference< css::util::XModifyListener > > > + tListenerMap; + + tListenerMap m_aListenerMap; +}; + +namespace impl +{ + +template< class InterfaceRef > +struct addListenerFunctor +{ + explicit addListenerFunctor( const css::uno::Reference< css::util::XModifyListener > & xListener ) : + m_xListener( 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( const css::uno::Reference< css::util::XModifyListener > & xListener ) : + m_xListener( 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( const css::uno::Reference< css::util::XModifyListener > & xListener ) : + m_xListener( 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( const css::uno::Reference< css::util::XModifyListener > & xListener ) : + m_xListener( 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 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 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< typename T > +void addListenerToAllSequenceElements( + const css::uno::Sequence< T > & rSequence, + const css::uno::Reference< css::util::XModifyListener > & xListener ) +{ + if( xListener.is()) + std::for_each( rSequence.begin(), rSequence.end(), + impl::addListenerFunctor< T >( 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 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 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 )); +} + +template< typename T > +void removeListenerFromAllSequenceElements( + const css::uno::Sequence< T > & rSequence, + const css::uno::Reference< css::util::XModifyListener > & xListener ) +{ + if( xListener.is()) + std::for_each( rSequence.begin(), rSequence.end(), + impl::removeListenerFunctor< T >( xListener )); +} + +} // namespace ModifyListenerHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_MODIFYLISTENERHELPER_HXX +#endif + +/* 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 000000000..fb6185098 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_MOVINGAVERAGEREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_MOVINGAVERAGEREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" +#include + +namespace chart +{ + +class MovingAverageRegressionCurveCalculator : public RegressionCurveCalculator +{ +public: + MovingAverageRegressionCurveCalculator(); + virtual ~MovingAverageRegressionCurveCalculator() override; + +protected: + virtual OUString ImplGetRepresentation( + const css::uno::Reference& xNumFormatter, + sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override; + +private: + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL recalculateRegression( + const css::uno::Sequence& aXValues, + const css::uno::Sequence& aYValues ) override; + + virtual double SAL_CALL getCurveValue( double x ) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) override; + + std::vector aYList; + std::vector aXList; +}; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_INC_MOVINGAVERAGEREGRESSIONCURVECALCULATOR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/MutexContainer.hxx b/chart2/source/inc/MutexContainer.hxx new file mode 100644 index 000000000..bab6b6c3f --- /dev/null +++ b/chart2/source/inc/MutexContainer.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_MUTEXCONTAINER_HXX +#define INCLUDED_CHART2_SOURCE_INC_MUTEXCONTAINER_HXX + +#include + +namespace chart +{ +class MutexContainer +{ +protected: + MutexContainer() = default; + + ~MutexContainer() = default; + + mutable ::osl::Mutex m_aMutex; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_MUTEXCONTAINER_HXX +#endif + +/* 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 000000000..8d13d8037 --- /dev/null +++ b/chart2/source/inc/NameContainer.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_NAMECONTAINER_HXX +#define INCLUDED_CHART2_SOURCE_INC_NAMECONTAINER_HXX + +#include +#include +#include +#include +#include "charttoolsdllapi.hxx" + +#include + +namespace chart +{ + +OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::container::XNameContainer > createNameContainer( + const css::uno::Type& rType, const OUString& rServicename, const OUString& rImplementationName ); + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::container::XNameContainer, + css::lang::XServiceInfo, + css::util::XCloneable > + NameContainer_Base; +} + +class NameContainer : public impl::NameContainer_Base +{ +public: + NameContainer() = delete; + NameContainer( const css::uno::Type& rType, const OUString& rServicename, const OUString& rImplementationName ); + 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 + const css::uno::Type m_aType; + const OUString m_aServicename; + const OUString m_aImplementationName; + + typedef std::map< OUString, css::uno::Any > tContentMap; + + tContentMap m_aMap; +}; + +} //namespace chart +#endif + +/* 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 000000000..828ef6a3c --- /dev/null +++ b/chart2/source/inc/NumberFormatterWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_NUMBERFORMATTERWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_NUMBERFORMATTERWRAPPER_HXX + +#include "charttoolsdllapi.hxx" +#include +#include +#include + +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_uLong m_nNumberFormatKey; +}; + +} //namespace chart +#endif + +/* 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 000000000..1fafa218a --- /dev/null +++ b/chart2/source/inc/OPropertySet.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_OPROPERTYSET_HXX +#define INCLUDED_CHART2_SOURCE_INC_OPROPERTYSET_HXX + +// helper classes +#include + +// interfaces and types +#include +#include +#include +#include +#include "charttoolsdllapi.hxx" + +#include + +namespace property +{ + +namespace impl +{ class ImplOPropertySet; } + +class OPropertySet : + 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( ::osl::Mutex & rMutex ); + virtual ~OPropertySet(); + +protected: + explicit OPropertySet( const OPropertySet & rOther, ::osl::Mutex & rMutex ); + + 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. + + @throws css::beans::UnknownPropertyException + @throws css::uno::RuntimeException + */ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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 rValue to the type required by the + property associated with nHandle. + + Override this method to take influence in modification of properties. + + If the conversion changed , is returned and the converted value + is in rConvertedValue. The former value is contained in + rOldValue. + + 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; + + /** 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; + + /// make original interface function visible again + using ::com::sun::star::beans::XFastPropertySet::getFastPropertyValue; + + /** implement this method in derived classes to get called when properties + change. + */ + virtual void firePropertyChangeEvent(); + + // 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; + 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 ____ + // Note: getPropertyStates() is already implemented in XPropertyState with the + // same signature + 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; + + // ____ XStyleSupplier ____ + virtual css::uno::Reference< css::style::XStyle > SAL_CALL getStyle() override; + virtual void SAL_CALL setStyle( const css::uno::Reference< css::style::XStyle >& xStyle ) override; + + // ____ XMultiPropertySet ____ + virtual void SAL_CALL setPropertyValues( + const css::uno::Sequence< OUString >& PropertyNames, + const css::uno::Sequence< css::uno::Any >& Values ) override; + + // ____ XFastPropertySet ____ + virtual void SAL_CALL setFastPropertyValue( sal_Int32 nHandle, const css::uno::Any& rValue ) override; + + // Note: it is assumed that the base class implements setPropertyValue by + // using setFastPropertyValue + +private: + /// reference to mutex of class deriving from here + ::osl::Mutex & m_rMutex; + + /// pImpl idiom implementation + std::unique_ptr< impl::ImplOPropertySet > m_pImplProperties; + bool m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault; +}; + +} // namespace property + +// INCLUDED_CHART2_SOURCE_INC_OPROPERTYSET_HXX +#endif + +/* 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 000000000..59248857b --- /dev/null +++ b/chart2/source/inc/ObjectIdentifier.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_OBJECTIDENTIFIER_HXX +#define INCLUDED_CHART2_SOURCE_INC_OBJECTIDENTIFIER_HXX + +#include "TitleHelper.hxx" +#include "charttoolsdllapi.hxx" + +#include + +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 +{ + +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_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( const OUString& rObjectCID ); + 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 + , ChartModel& rModel); + + static OUString createClassifiedIdentifierForObject( + const css::uno::Reference< css::uno::XInterface >& xObject + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static OUString createClassifiedIdentifierForParticle( + const OUString& rParticle ); + + static OUString createClassifiedIdentifierForParticles( + const OUString& rParentParticle + , const OUString& rChildParticle + , const OUString& rDragMethodServiceName = OUString() + , const OUString& rDragParameterString = OUString() ); + + static OUString createClassifiedIdentifierForGrid( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::frame::XModel >& xChartModel + , sal_Int32 nSubIndex = -1 );//-1: main grid, 0: first subgrid etc + + SAL_DLLPRIVATE static OUString createParticleForDiagram(); + + static OUString createParticleForCoordinateSystem( + const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys + , ChartModel& rModel ); + + static OUString createParticleForCoordinateSystem( + const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys + , const css::uno::Reference< css::frame::XModel >& 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( ChartModel& rModel ); + + static OUString createParticleForLegend( + const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static OUString addChildParticle( const OUString& rParticle, const OUString& rChildParticle ); + static OUString createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex ); + static sal_Int32 getIndexFromParticleOrCID( const OUString& rParticleOrCID ); + + static OUString createClassifiedIdentifier( + enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES + , const OUString& rParticleID );//e.g. SeriesID + + static OUString createClassifiedIdentifierWithParent( + enum ObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID + , const OUString& rParticleID //for points or subgrids this is an Index or otherwise an identifier from the model object + , const OUString& rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId" + , const OUString& rDragMethodServiceName = OUString() + , const OUString& rDragParameterString = OUString() + ); + + static bool isCID( const OUString& rName ); + static OUString getDragMethodServiceName( const OUString& rClassifiedIdentifier ); + static OUString getDragParameterString( const OUString& rCID ); + static bool isDragableObject( const OUString& rClassifiedIdentifier ); + bool isDragableObject() const; + static bool isRotateableObject( const OUString& rClassifiedIdentifier ); + static bool isMultiClickObject( const OUString& rClassifiedIdentifier ); + static bool areSiblings( const OUString& rCID1, const OUString& rCID2 );//identical object is no sibling + static bool areIdenticalObjects( const OUString& rCID1, const OUString& rCID2 ); + + static OUString getStringForType( ObjectType eObjectType ); + static ObjectType getObjectType( const OUString& rCID ); + ObjectType getObjectType() const; + + static OUString createSeriesSubObjectStub( ObjectType eSubObjectType + , const OUString& rSeriesParticle + , const OUString& rDragMethodServiceName = OUString() + , const OUString& rDragParameterString = OUString() ); + static OUString createPointCID( const OUString& rPointCID_Stub, sal_Int32 nIndex ); + + static OUString createDataCurveCID( const OUString& rSeriesParticle, sal_Int32 nCurveIndex, bool bAverageLine ); + static OUString createDataCurveEquationCID( const OUString& rSeriesParticle, sal_Int32 nCurveIndex ); + + SAL_DLLPRIVATE static OUString getObjectID( const OUString& rCID ); + static OUString getParticleID( const OUString& rCID ); + static OUString getFullParentParticle( const OUString& rCID ); + + //returns the series particle of a CID when the CID is a child of the series + static OUString getSeriesParticleFromCID( const OUString& rCID ); + + //return the model object that is indicated by rObjectCID + static css::uno::Reference< css::beans::XPropertySet > + getObjectPropertySet( + const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + static css::uno::Reference< css::beans::XPropertySet > + getObjectPropertySet( + const OUString& rObjectCID + , const css::uno::Reference< css::chart2::XChartDocument >& xChartDocument ); + + //return the axis object that belongs to rObjectCID if any + static css::uno::Reference< css::chart2::XAxis > + getAxisForCID( + const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + + //return the series object that belongs to rObjectCID if any + static css::uno::Reference< css::chart2::XDataSeries > + getDataSeriesForCID( + const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static css::uno::Reference< css::chart2::XDiagram > + getDiagramForCID( + const OUString& rObjectCID + , const css::uno::Reference< css::frame::XModel >& xChartModel ); + + static const OUString& getPieSegmentDragMethodServiceName(); + static OUString createPieSegmentDragParameterString( + sal_Int32 nOffsetPercent + , const css::awt::Point& rMinimumPosition + , const css::awt::Point& rMaximumPosition ); + static bool parsePieSegmentDragParameterString( const OUString& rDragParameterString + , sal_Int32& rOffsetPercent + , css::awt::Point& rMinimumPosition + , css::awt::Point& rMaximumPosition ); + + static TitleHelper::eTitleType getTitleTypeForCID( const OUString& rCID ); + + static OUString getMovedSeriesCID( const OUString& 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 +#endif + +/* 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 000000000..e47d882d4 --- /dev/null +++ b/chart2/source/inc/PolynomialRegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_POLYNOMIALREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_POLYNOMIALREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" +#include + +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& 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& aXValues, + const css::uno::Sequence& aYValues ) override; + + void computeCorrelationCoefficient( + RegressionCalculationHelper::tDoubleVectorPair& rValues, + const sal_Int32 aNoValues, + double yAverage ); + + std::vector mCoefficients; +}; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_INC_POLYNOMIALREGRESSIONCURVECALCULATOR_HXX + +/* 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 000000000..0c9af2f50 --- /dev/null +++ b/chart2/source/inc/PopupRequest.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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_POPUPREQUEST_HXX +#define INCLUDED_CHART2_SOURCE_INC_POPUPREQUEST_HXX + +#include "MutexContainer.hxx" +#include "charttoolsdllapi.hxx" + +#include +#include + +namespace chart +{ + +namespace impl +{ + +typedef cppu::WeakComponentImplHelper PopupRequest_Base; + +} + +class OOO_DLLPUBLIC_CHARTTOOLS PopupRequest : public MutexContainer, public impl::PopupRequest_Base +{ +public: + explicit PopupRequest(); + virtual ~PopupRequest() override; + + css::uno::Reference const & getCallback() const + { + return m_xCallback; + } + +protected: + // ____ XRequestCallback ____ + virtual void SAL_CALL addCallback(const css::uno::Reference< ::css::awt::XCallback >& xCallback, + const css::uno::Any& aData) override; + + // ____ WeakComponentImplHelperBase ____ + // is called when dispose() is called at this component + virtual void SAL_CALL disposing() override; + +private: + css::uno::Reference m_xCallback; +}; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_INC_POPUPREQUEST_HXX + +/* 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 000000000..c3306d3c6 --- /dev/null +++ b/chart2/source/inc/PotentialRegressionCurveCalculator.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_POTENTIALREGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_POTENTIALREGRESSIONCURVECALCULATOR_HXX + +#include "RegressionCurveCalculator.hxx" + +namespace chart +{ + +class PotentialRegressionCurveCalculator : public RegressionCurveCalculator +{ +public: + PotentialRegressionCurveCalculator(); + virtual ~PotentialRegressionCurveCalculator() override; + +protected: + virtual OUString ImplGetRepresentation( + const css::uno::Reference& xNumFormatter, + sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override; + +private: + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL recalculateRegression( + const css::uno::Sequence& aXValues, + const css::uno::Sequence& aYValues ) override; + + virtual double SAL_CALL getCurveValue( double x ) override; + + virtual css::uno::Sequence SAL_CALL getCurveValues( + double min, + double max, + sal_Int32 nPointCount, + const css::uno::Reference& xScalingX, + const css::uno::Reference& 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 + +// INCLUDED_CHART2_SOURCE_INC_POTENTIALREGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..19ce354c9 --- /dev/null +++ b/chart2/source/inc/PropertyHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_PROPERTYHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_PROPERTYHELPER_HXX + +#include +#include +#include "charttoolsdllapi.hxx" + +#include + +namespace com::sun::star::lang { class XMultiServiceFactory; } + +namespace chart +{ + +typedef int tPropertyValueMapKey; + +typedef std::unordered_map 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 + +// INCLUDED_CHART2_SOURCE_INC_PROPERTYHELPER_HXX +#endif + +/* 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 000000000..c1fe2d721 --- /dev/null +++ b/chart2/source/inc/RangeHighlighter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_RANGEHIGHLIGHTER_HXX +#define INCLUDED_CHART2_SOURCE_INC_RANGEHIGHLIGHTER_HXX + +#include "MutexContainer.hxx" +#include +#include +#include + +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 +{ + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper< + css::chart2::data::XRangeHighlighter, + css::view::XSelectionChangeListener + > + RangeHighlighter_Base; +} + +class RangeHighlighter : + public MutexContainer, + public impl::RangeHighlighter_Base +{ +public: + explicit RangeHighlighter( + const css::uno::Reference< css::view::XSelectionSupplier > & 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 SAL_CALL disposing() override; + +private: + void fireSelectionEvent(); + void startListening(); + void stopListening(); + void determineRanges(); + + void fillRangesForDiagram( const css::uno::Reference< css::chart2::XDiagram > & xDiagram ); + void fillRangesForDataSeries( const css::uno::Reference< css::chart2::XDataSeries > & xSeries ); + void fillRangesForCategories( const css::uno::Reference< css::chart2::XAxis > & xAxis ); + void fillRangesForDataPoint( const css::uno::Reference< css::uno::XInterface > & 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; + css::uno::Reference< css::view::XSelectionChangeListener > + m_xListener; + css::uno::Sequence< css::chart2::data::HighlightedRange > + m_aSelectedRanges; + sal_Int32 m_nAddedListenerCount; + bool m_bIncludeHiddenCells; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_RANGEHIGHLIGHTER_HXX +#endif + +/* 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 000000000..253ab79fb --- /dev/null +++ b/chart2/source/inc/ReferenceSizeProvider.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_REFERENCESIZEPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_INC_REFERENCESIZEPROVIDER_HXX + +#include +#include +#include "charttoolsdllapi.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 css::uno::Reference< css::chart2::XChartDocument > & 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 css::uno::Reference< css::chart2::XChartDocument > & 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_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; + css::uno::Reference< css::chart2::XChartDocument > m_xChartDoc; + bool m_bUseAutoScale; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_REFERENCESIZEPROVIDER_HXX +#endif + +/* 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 000000000..a5b2b3b16 --- /dev/null +++ b/chart2/source/inc/RegressionCalculationHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_REGRESSIONCALCULATIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_REGRESSIONCALCULATIONHELPER_HXX + +#include + +#include + +#include +#include + +namespace chart +{ +namespace 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. + +

The function below provide a set of useful predicates that can be + used to pass as parameter aPred.

+ */ +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= 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 RegressionCalculationHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_REGRESSIONCALCULATIONHELPER_HXX +#endif + +/* 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 000000000..183db2b65 --- /dev/null +++ b/chart2/source/inc/RegressionCurveCalculator.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVECALCULATOR_HXX +#define INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVECALCULATOR_HXX + +#include +#include + +#include + +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 ); + +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; + + // ____ XRegressionCurveCalculator ____ + virtual void SAL_CALL setRegressionProperties( + sal_Int32 aDegree, + sal_Bool aForceIntercept, + double aInterceptValue, + sal_Int32 aPeriod) 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; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVECALCULATOR_HXX +#endif + +/* 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 000000000..8fa407147 --- /dev/null +++ b/chart2/source/inc/RegressionCurveHelper.hxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVEHELPER_HXX + +#include +#include "charttoolsdllapi.hxx" + +#include + +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 +{ + +namespace RegressionCurveHelper +{ + /// returns a model mean-value line + css::uno::Reference createMeanValueLine(); + + /// returns a model regression curve + css::uno::Reference + createRegressionCurveByServiceName( const OUString& aServiceName ); + + OOO_DLLPUBLIC_CHARTTOOLS bool hasMeanValueLine( + const css::uno::Reference & xRegCnt ); + + OOO_DLLPUBLIC_CHARTTOOLS bool isMeanValueLine( + const css::uno::Reference & xRegCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference + getMeanValueLine( + const css::uno::Reference & 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 const & xRegCnt, + const css::uno::Reference& xSeriesProp ); + + OOO_DLLPUBLIC_CHARTTOOLS void removeMeanValueLine( + css::uno::Reference const & xRegCnt ); + + /** Returns the first regression curve found that is not of type + mean-value line + */ + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference + getFirstCurveNotMeanValueLine( + const css::uno::Reference& xCurveContainer ); + + /** Returns the regression curve found at the index provided. + */ + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference + getRegressionCurveAtIndex( + const css::uno::Reference& 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& xCurveContainer ); + + OOO_DLLPUBLIC_CHARTTOOLS SvxChartRegress getRegressionType( + const css::uno::Reference& 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 css::uno::Reference + addRegressionCurve( + SvxChartRegress eType, + css::uno::Reference const & xCurveContainer, + const css::uno::Reference& xPropertySource = + css::uno::Reference(), + const css::uno::Reference& xEquationProperties = + css::uno::Reference() ); + + OOO_DLLPUBLIC_CHARTTOOLS bool removeAllExceptMeanValueLine( + css::uno::Reference const & xCurveContainer ); + + OOO_DLLPUBLIC_CHARTTOOLS void removeEquations( + css::uno::Reference const & xCurveContainer ); + + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference + changeRegressionCurveType( + SvxChartRegress eType, + css::uno::Reference const & xRegressionCurveContainer, + css::uno::Reference const & xRegressionCurve ); + + /// returns a calculator object for regression curves (used by the view) + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference + createRegressionCurveCalculatorByServiceName( const OUString& 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& xOutCurveCalculator, + const css::uno::Reference& 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& xOutCurveCalculator, + const css::uno::Reference& xSeries, + const css::uno::Reference& xModel ); + + OOO_DLLPUBLIC_CHARTTOOLS OUString getUINameForRegressionCurve( + const css::uno::Reference& xCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveName( + const css::uno::Reference& xCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveGenericName( + const css::uno::Reference& xCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveSpecificName( + const css::uno::Reference& xCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS std::vector > + getAllRegressionCurvesNotMeanValueLine( + const css::uno::Reference& xDiagram ); + + OOO_DLLPUBLIC_CHARTTOOLS void resetEquationPosition( + const css::uno::Reference& xCurve ); + + /// @return the index of the given curve in the given container. -1 if not contained + OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getRegressionCurveIndex( + const css::uno::Reference& xContainer, + const css::uno::Reference& xCurve ); + + OOO_DLLPUBLIC_CHARTTOOLS bool hasEquation(const css::uno::Reference& xCurve ); +} + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_INC_REGRESSIONCURVEHELPER_HXX + +/* 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 000000000..961a55e99 --- /dev/null +++ b/chart2/source/inc/RelativePositionHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_RELATIVEPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_RELATIVEPOSITIONHELPER_HXX + +#include +#include +#include +#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 , if changes were applied. + +

That means, if the position's alignment is center, the position will + not change at all.

+ */ + 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 , if changes were applied. + */ + static bool moveObject( + css::chart2::RelativePosition & rInOutPosition, + const css::chart2::RelativeSize & rObjectSize, + double fAmountX, double fAmountY ); +}; + +} //namespace chart +#endif + +/* 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 000000000..517804096 --- /dev/null +++ b/chart2/source/inc/RelativeSizeHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_RELATIVESIZEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_RELATIVESIZEHELPER_HXX + +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::awt { struct Size; } +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::uno { template class Reference; } + +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 ); + +private: + RelativeSizeHelper() = delete; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_RELATIVESIZEHELPER_HXX +#endif + +/* 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 000000000..31d96d155 --- /dev/null +++ b/chart2/source/inc/ResId.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_RESID_HXX +#define INCLUDED_CHART2_SOURCE_INC_RESID_HXX + +#include +#include "charttoolsdllapi.hxx" + +namespace chart +{ + +OUString OOO_DLLPUBLIC_CHARTTOOLS SchResId(const char *pId); + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_RESID_HXX +#endif + +/* 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 000000000..7314ce84e --- /dev/null +++ b/chart2/source/inc/Scaling.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_SCALING_HXX +#define INCLUDED_CHART2_SOURCE_INC_SCALING_HXX + +#include +#include +#include +#include + +namespace chart +{ + +class LogarithmicScaling : + 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 : + 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 : 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 : 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 +#endif + +/* 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 000000000..9fedd60a6 --- /dev/null +++ b/chart2/source/inc/SceneProperties.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_SCENEPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_INC_SCENEPROPERTIES_HXX + +#include "PropertyHelper.hxx" +#include "FastPropertyIdRanges.hxx" +#include "charttoolsdllapi.hxx" + +#include + +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 + +#endif // INCLUDED_CHART2_SOURCE_INC_SCENEPROPERTIES_HXX + +/* 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 000000000..14e5fe6ee --- /dev/null +++ b/chart2/source/inc/StackMode.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_STACKMODE_HXX +#define INCLUDED_CHART2_SOURCE_INC_STACKMODE_HXX + +namespace chart +{ +// needed for chart type templates + +enum class StackMode +{ + NONE, + YStacked, + YStackedPercent, + ZStacked +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_STACKMODE_HXX +#endif + +/* 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 000000000..d97934569 --- /dev/null +++ b/chart2/source/inc/StatisticsHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_STATISTICSHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_STATISTICSHELPER_HXX + +#include +#include +#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 class Sequence; } + +namespace chart +{ + +namespace 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 css::uno::Reference< css::chart2::XDataSeries > & xDataSeries, + sal_Int32 nStyle, + bool bYError = true ); + + OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::beans::XPropertySet > + getErrorBars( + const css::uno::Reference< css::chart2::XDataSeries > & xDataSeries, + bool bYError = true ); + + OOO_DLLPUBLIC_CHARTTOOLS bool hasErrorBars( + const css::uno::Reference< css::chart2::XDataSeries > & xDataSeries, + bool bYError = true ); + + OOO_DLLPUBLIC_CHARTTOOLS void removeErrorBars( + const css::uno::Reference< css::chart2::XDataSeries > & xDataSeries, + bool bYError = true ); + + OOO_DLLPUBLIC_CHARTTOOLS bool usesErrorBarRanges( + const css::uno::Reference< css::chart2::XDataSeries > & xDataSeries, + bool bYError = true ); +} + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_STATISTICSHELPER_HXX +#endif + +/* 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 000000000..52c97392b --- /dev/null +++ b/chart2/source/inc/ThreeDHelper.hxx @@ -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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_THREEDHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_THREEDHELPER_HXX + +#include +#include "charttoolsdllapi.hxx" + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::chart2 { class XDiagram; } + +namespace chart +{ + +enum 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 getRotationAngleFromDiagram( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad ); + static void setRotationAngleToDiagram( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , double fXAngleRad, double fYAngleRad, double fZAngleRad ); + + static void getRotationFromDiagram( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree ); + static void setRotationToDiagram( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree ); + + static void switchRightAngledAxes( const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , bool bRightAngledAxes ); + + 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 ); + + static double getCameraDistance( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties ); + static void setCameraDistance( + const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties + , double fCameraDistance ); + 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 void set3DSettingsToDefault( const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties ); + static void setDefaultRotation( const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties ); + static void setDefaultIllumination( const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties ); + + static void setDefaultRotation( const css::uno::Reference< css::beans::XPropertySet >& xSceneProperties, bool bPieOrDonut ); + + static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardLeftWall( const css::uno::Reference< + css::beans::XPropertySet >& xSceneProperties ); + static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardBackWall(const css::uno::Reference< + css::beans::XPropertySet >& xSceneProperties ); + static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardBottom(const css::uno::Reference< + css::beans::XPropertySet >& xSceneProperties ); + + static ThreeDLookScheme detectScheme( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ); + static void setScheme( const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , ThreeDLookScheme aScheme ); + + //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 css::uno::Reference< css::chart2::XDiagram >& xDiagram + , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines ); + static void setRoundedEdgesAndObjectLines( const css::uno::Reference< css::chart2::XDiagram >& xDiagram + , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines ); +}; + +} //namespace chart +#endif + +/* 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 000000000..e16beda39 --- /dev/null +++ b/chart2/source/inc/TitleHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_TITLEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_TITLEHELPER_HXX + +#include +#include +#include "charttoolsdllapi.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 css::uno::Reference< css::chart2::XTitle > + getTitle( eTitleType nTitleIndex + , ChartModel& rModel ); + + static css::uno::Reference< css::chart2::XTitle > + getTitle( eTitleType nTitleIndex + , const css::uno::Reference< css::frame::XModel >& xModel ); + + static css::uno::Reference< + css::chart2::XTitle > + createTitle( eTitleType nTitleIndex + , const OUString& rTitleText + , const css::uno::Reference< css::frame::XModel >& xModel + , const css::uno::Reference< css::uno::XComponentContext > & xContext + , ReferenceSizeProvider * pRefSizeProvider = nullptr ); + static css::uno::Reference< + css::chart2::XTitle > + createOrShowTitle( eTitleType nTitleIndex + , const OUString& rTitleText + , const css::uno::Reference< css::frame::XModel >& xModel + , const css::uno::Reference< css::uno::XComponentContext > & xContex ); + + static void removeTitle( eTitleType nTitleIndex + , const css::uno::Reference< css::frame::XModel >& xModel ); + + static void hideTitle( eTitleType nTitleIndex + , const css::uno::Reference< css::frame::XModel >& xModel ); + + + static OUString getCompleteString( const css::uno::Reference< css::chart2::XTitle >& xTitle ); + static void setCompleteString( const OUString& rNewText + , const css::uno::Reference< css::chart2::XTitle >& xTitle + , const css::uno::Reference< css::uno::XComponentContext > & xContext + , const float * pDefaultCharHeight = nullptr ); + + static bool getTitleType( eTitleType& rType + , const css::uno::Reference< css::chart2::XTitle >& xTitle + , ChartModel& rModel); + + static bool getTitleType( eTitleType& rType + , const css::uno::Reference< css::chart2::XTitle >& xTitle + , const css::uno::Reference< css::frame::XModel >& xModel ); +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/TrueGuard.hxx b/chart2/source/inc/TrueGuard.hxx new file mode 100644 index 000000000..109c64a06 --- /dev/null +++ b/chart2/source/inc/TrueGuard.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_TRUEGUARD_HXX +#define INCLUDED_CHART2_SOURCE_INC_TRUEGUARD_HXX + +namespace chart +{ +/** This guard sets the given boolean reference to true in the constructor and to false in the destructor + */ +class TrueGuard final +{ +public: + explicit TrueGuard(bool& rbTrueDuringGuardedTime); + ~TrueGuard(); + +private: + bool& m_rbTrueDuringGuardedTime; +}; +} +// INCLUDED_CHART2_SOURCE_INC_TRUEGUARD_HXX +#endif + +/* 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 000000000..0829ceffa --- /dev/null +++ b/chart2/source/inc/UncachedDataSequence.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_UNCACHEDDATASEQUENCE_HXX +#define INCLUDED_CHART2_SOURCE_INC_UNCACHEDDATASEQUENCE_HXX + +// helper classes +#include +#include +#include +#include +#include + +// interfaces and types +#include +#include +#include +#include +#include +#include +#include +#include + +namespace com::sun::star::beans { class XPropertySetInfo; } +namespace com::sun::star::chart2 { class XInternalDataProvider; } + +namespace chart +{ + +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. + * + *

A range representation can be either '0', '1', '2', ..., or 'label 1', + * 'label 2', ...

+ */ +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( + const css::uno::Reference< css::chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation ); + UncachedDataSequence( + const css::uno::Reference< css::chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation, + 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(); + + // + sal_Int32 m_nNumberFormatKey; + OUString m_sRole; + OUString m_aXMLRange; + // + + /** This method registers all properties. It should be called by all + constructors. + */ + void registerProperties(); + + css::uno::Reference< css::chart2::XInternalDataProvider > m_xDataProvider; + OUString m_aSourceRepresentation; + css::uno::Reference< css::util::XModifyListener > + m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_UNCACHEDDATASEQUENCE_HXX +#endif + +/* 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 000000000..93d7af9fd --- /dev/null +++ b/chart2/source/inc/UserDefinedProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_USERDEFINEDPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_INC_USERDEFINEDPROPERTIES_HXX + +#include "FastPropertyIdRanges.hxx" +#include "charttoolsdllapi.hxx" + +#include + +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 + +// INCLUDED_CHART2_SOURCE_INC_USERDEFINEDPROPERTIES_HXX +#endif + +/* 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 000000000..08568f253 --- /dev/null +++ b/chart2/source/inc/WeakListenerAdapter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WEAKLISTENERADAPTER_HXX +#define INCLUDED_CHART2_SOURCE_INC_WEAKLISTENERADAPTER_HXX + +#include +#include +#include +#include +#include + +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. + +

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.

+ +

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.

+ */ +template< class Listener > + class WeakListenerAdapter : public + ::cppu::WeakImplHelper< Listener > +{ +public: + explicit WeakListenerAdapter( const css::uno::Reference< Listener > & xListener ) : + m_xListener( xListener ) + {} + explicit WeakListenerAdapter( const css::uno::WeakReference< 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 WeakModifyListenerAdapter : + public WeakListenerAdapter< css::util::XModifyListener > +{ +public: + explicit WeakModifyListenerAdapter( + const css::uno::WeakReference< css::util::XModifyListener > & xListener ); + virtual ~WeakModifyListenerAdapter() override; + +protected: + // ____ XModifyListener ____ + virtual void SAL_CALL modified( const css::lang::EventObject& aEvent ) override; +}; + +class WeakSelectionChangeListenerAdapter : + 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 + +// INCLUDED_CHART2_SOURCE_INC_WEAKLISTENERADAPTER_HXX +#endif + +/* 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 000000000..a36321181 --- /dev/null +++ b/chart2/source/inc/WrappedDefaultProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WRAPPEDDEFAULTPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_INC_WRAPPEDDEFAULTPROPERTY_HXX + +#include "WrappedProperty.hxx" +#include "charttoolsdllapi.hxx" + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTTOOLS WrappedDefaultProperty : public WrappedProperty +{ +public: + explicit WrappedDefaultProperty( + const OUString& rOuterName, const OUString& rInnerName, + const css::uno::Any& rNewOuterDefault ); + 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 +#endif + +/* 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 000000000..ba2bc0aac --- /dev/null +++ b/chart2/source/inc/WrappedDirectStateProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WRAPPEDDIRECTSTATEPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_INC_WRAPPEDDIRECTSTATEPROPERTY_HXX + +#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 +#endif + +/* 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 000000000..185e06d66 --- /dev/null +++ b/chart2/source/inc/WrappedIgnoreProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WRAPPEDIGNOREPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_INC_WRAPPEDIGNOREPROPERTY_HXX + +#include "WrappedProperty.hxx" +#include "charttoolsdllapi.hxx" + +#include + +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 >& rList ); + + static void addIgnoreFillProperties( std::vector< std::unique_ptr >& rList ); + SAL_DLLPRIVATE static void addIgnoreFillProperties_without_BitmapProperties( std::vector< std::unique_ptr >& rList ); + SAL_DLLPRIVATE static void addIgnoreFillProperties_only_BitmapProperties( std::vector< std::unique_ptr >& rList ); +}; + +} //namespace chart + +// INCLUDED_CHART2_SOURCE_INC_WRAPPEDIGNOREPROPERTY_HXX +#endif + +/* 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 000000000..82b9f3b0c --- /dev/null +++ b/chart2/source/inc/WrappedProperty.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTY_HXX +#define INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTY_HXX + +#include +#include +#include +#include "charttoolsdllapi.hxx" + +#include +#include + +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::beans { class XPropertyState; } +namespace com::sun::star::uno { template 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( const OUString& rOuterName, const OUString& rInnerName ); + 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 > tWrappedPropertyMap; + +} //namespace chart + +// INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTY_HXX +#endif + +/* 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 000000000..09c768fc7 --- /dev/null +++ b/chart2/source/inc/WrappedPropertySet.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTYSET_HXX +#define INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTYSET_HXX + +#include "WrappedProperty.hxx" +#include "MutexContainer.hxx" +#include "charttoolsdllapi.hxx" +#include +#include +#include +#include +#include + +#include +#include + +namespace cppu { class IPropertyArrayHelper; } +namespace cppu { class OPropertyArrayHelper; } + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTTOOLS WrappedPropertySet : + public MutexContainer + , 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 > 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 ); + +protected: //member + 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 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 + +// INCLUDED_CHART2_SOURCE_INC_WRAPPEDPROPERTYSET_HXX +#endif + +/* 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 000000000..207770dbb --- /dev/null +++ b/chart2/source/inc/XMLRangeHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_XMLRANGEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_XMLRANGEHELPER_HXX + +#include +#include +#include "charttoolsdllapi.hxx" + +namespace chart +{ +namespace 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 XMLRangeHelper +} // namespace chart + +// INCLUDED_CHART2_SOURCE_INC_XMLRANGEHELPER_HXX +#endif + +/* 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 000000000..3a5b8144b --- /dev/null +++ b/chart2/source/inc/charttoolsdllapi.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTTOOLSDLLAPI_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTTOOLSDLLAPI_HXX + +#include + +#include + +#if defined OOO_DLLIMPLEMENTATION_CHARTTOOLS +#define OOO_DLLPUBLIC_CHARTTOOLS SAL_DLLPUBLIC_EXPORT +#else +#define OOO_DLLPUBLIC_CHARTTOOLS SAL_DLLPUBLIC_IMPORT +#endif + +#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 000000000..2d02f2f8b --- /dev/null +++ b/chart2/source/inc/chartview/ChartSfxItemIds.hxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_CHARTSFXITEMIDS_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_CHARTSFXITEMIDS_HXX + +#include + +class SvxSizeItem; +class SfxIntegerListItem; +class SfxBoolItem; +class SfxStringItem; +class SfxInt32Item; +class SfxUInt32Item; +class SvxChartIndicateItem; +class SvxDoubleItem; +class SvxBrushItem; +class SvxChartKindErrorItem; +class SvxChartTextOrderItem; +class SvxChartRegressItem; + +// SCHATTR + +// can't this be changed to 0? +constexpr sal_uInt16 SCHATTR_START = 1; + +constexpr sal_uInt16 SCHATTR_DATADESCR_START (SCHATTR_START); +constexpr TypedWhichId SCHATTR_DATADESCR_SHOW_NUMBER (SCHATTR_DATADESCR_START); +constexpr TypedWhichId SCHATTR_DATADESCR_SHOW_PERCENTAGE (SCHATTR_DATADESCR_START + 1); +constexpr TypedWhichId SCHATTR_DATADESCR_SHOW_CATEGORY (SCHATTR_DATADESCR_START + 2); +constexpr TypedWhichId SCHATTR_DATADESCR_SHOW_SYMBOL (SCHATTR_DATADESCR_START + 3); +constexpr TypedWhichId SCHATTR_DATADESCR_WRAP_TEXT (SCHATTR_DATADESCR_START + 4); +constexpr TypedWhichId SCHATTR_DATADESCR_SEPARATOR (SCHATTR_DATADESCR_START + 5); +constexpr TypedWhichId SCHATTR_DATADESCR_PLACEMENT (SCHATTR_DATADESCR_START + 6); +constexpr TypedWhichId SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS (SCHATTR_DATADESCR_START + 7); +constexpr TypedWhichId SCHATTR_DATADESCR_NO_PERCENTVALUE (SCHATTR_DATADESCR_START + 8); //percentage values should not be offered +constexpr TypedWhichId SCHATTR_PERCENT_NUMBERFORMAT_VALUE (SCHATTR_DATADESCR_START + 9); +constexpr TypedWhichId SCHATTR_PERCENT_NUMBERFORMAT_SOURCE (SCHATTR_DATADESCR_START + 10); +constexpr sal_uInt16 SCHATTR_DATADESCR_END (SCHATTR_PERCENT_NUMBERFORMAT_SOURCE); + +//legend +constexpr sal_uInt16 SCHATTR_LEGEND_START (SCHATTR_DATADESCR_END + 1); +constexpr TypedWhichId SCHATTR_LEGEND_POS (SCHATTR_LEGEND_START); +constexpr TypedWhichId SCHATTR_LEGEND_SHOW (SCHATTR_LEGEND_START + 1); +constexpr TypedWhichId 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 SCHATTR_TEXT_DEGREES (SCHATTR_TEXT_START); +constexpr TypedWhichId 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 SCHATTR_STAT_AVERAGE (SCHATTR_STAT_START); +constexpr TypedWhichId SCHATTR_STAT_KIND_ERROR (SCHATTR_STAT_START + 1); +constexpr TypedWhichId SCHATTR_STAT_PERCENT (SCHATTR_STAT_START + 2); +constexpr TypedWhichId SCHATTR_STAT_BIGERROR (SCHATTR_STAT_START + 3); +constexpr TypedWhichId SCHATTR_STAT_CONSTPLUS (SCHATTR_STAT_START + 4); +constexpr TypedWhichId SCHATTR_STAT_CONSTMINUS (SCHATTR_STAT_START + 5); +constexpr TypedWhichId SCHATTR_STAT_INDICATE (SCHATTR_STAT_START + 6); +constexpr TypedWhichId SCHATTR_STAT_RANGE_POS (SCHATTR_STAT_START + 7); +constexpr TypedWhichId SCHATTR_STAT_RANGE_NEG (SCHATTR_STAT_START + 8); +constexpr TypedWhichId 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 SCHATTR_STYLE_DEEP (SCHATTR_STYLE_START ); +constexpr TypedWhichId SCHATTR_STYLE_3D (SCHATTR_STYLE_START + 1); +constexpr TypedWhichId SCHATTR_STYLE_VERTICAL (SCHATTR_STYLE_START + 2); + +// also for series +constexpr TypedWhichId SCHATTR_STYLE_BASETYPE (SCHATTR_STYLE_START + 3);// Line,Area,...,Pie +constexpr TypedWhichId SCHATTR_STYLE_LINES (SCHATTR_STYLE_START + 4);// draw line +constexpr TypedWhichId SCHATTR_STYLE_PERCENT (SCHATTR_STYLE_START + 5); +constexpr TypedWhichId SCHATTR_STYLE_STACKED (SCHATTR_STYLE_START + 6); +constexpr TypedWhichId SCHATTR_STYLE_SPLINES (SCHATTR_STYLE_START + 7); + +// also for data point +constexpr TypedWhichId SCHATTR_STYLE_SYMBOL (SCHATTR_STYLE_START + 8); +constexpr TypedWhichId SCHATTR_STYLE_SHAPE (SCHATTR_STYLE_START + 9); +constexpr sal_uInt16 SCHATTR_STYLE_END (SCHATTR_STYLE_SHAPE ); + +constexpr TypedWhichId 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 SCHATTR_AXISTYPE (SCHATTR_AXIS_START); +constexpr TypedWhichId SCHATTR_AXIS_REVERSE (SCHATTR_AXIS_START + 1); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_MIN (SCHATTR_AXIS_START + 2); +constexpr TypedWhichId SCHATTR_AXIS_MIN (SCHATTR_AXIS_START + 3); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_MAX (SCHATTR_AXIS_START + 4); +constexpr TypedWhichId SCHATTR_AXIS_MAX (SCHATTR_AXIS_START + 5); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_STEP_MAIN (SCHATTR_AXIS_START + 6); +constexpr TypedWhichId SCHATTR_AXIS_STEP_MAIN (SCHATTR_AXIS_START + 7); +constexpr TypedWhichId SCHATTR_AXIS_MAIN_TIME_UNIT (SCHATTR_AXIS_START + 8); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_STEP_HELP (SCHATTR_AXIS_START + 9); +constexpr TypedWhichId SCHATTR_AXIS_STEP_HELP (SCHATTR_AXIS_START + 10); +constexpr TypedWhichId SCHATTR_AXIS_HELP_TIME_UNIT (SCHATTR_AXIS_START + 11); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_TIME_RESOLUTION (SCHATTR_AXIS_START + 12); +constexpr TypedWhichId SCHATTR_AXIS_TIME_RESOLUTION (SCHATTR_AXIS_START + 13); +constexpr TypedWhichId SCHATTR_AXIS_LOGARITHM (SCHATTR_AXIS_START + 14); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_DATEAXIS (SCHATTR_AXIS_START + 15); +constexpr TypedWhichId SCHATTR_AXIS_ALLOW_DATEAXIS (SCHATTR_AXIS_START + 16); +constexpr TypedWhichId SCHATTR_AXIS_AUTO_ORIGIN (SCHATTR_AXIS_START + 17); +constexpr TypedWhichId SCHATTR_AXIS_ORIGIN (SCHATTR_AXIS_START + 18); +//axis position +constexpr sal_uInt16 SCHATTR_AXIS_POSITION_START (SCHATTR_AXIS_ORIGIN + 1); +constexpr TypedWhichId SCHATTR_AXIS_TICKS (SCHATTR_AXIS_POSITION_START); +constexpr TypedWhichId SCHATTR_AXIS_HELPTICKS (SCHATTR_AXIS_POSITION_START + 1); +constexpr TypedWhichId SCHATTR_AXIS_POSITION (SCHATTR_AXIS_POSITION_START + 2); +constexpr TypedWhichId SCHATTR_AXIS_POSITION_VALUE (SCHATTR_AXIS_POSITION_START + 3); +constexpr TypedWhichId SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT (SCHATTR_AXIS_POSITION_START + 4); +constexpr TypedWhichId SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION (SCHATTR_AXIS_POSITION_START + 5); +constexpr TypedWhichId SCHATTR_AXIS_LABEL_POSITION (SCHATTR_AXIS_POSITION_START + 6); +constexpr TypedWhichId 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 SCHATTR_AXIS_SHOWDESCR (SCHATTR_AXIS_LABEL_START); +constexpr TypedWhichId SCHATTR_AXIS_LABEL_ORDER (SCHATTR_AXIS_LABEL_START + 1); +constexpr TypedWhichId SCHATTR_AXIS_LABEL_OVERLAP (SCHATTR_AXIS_LABEL_START + 2); +constexpr TypedWhichId 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 SCHATTR_SYMBOL_BRUSH (SCHATTR_AXIS_END + 1); +constexpr TypedWhichId SCHATTR_STOCK_VOLUME (SCHATTR_AXIS_END + 2); +constexpr TypedWhichId SCHATTR_STOCK_UPDOWN (SCHATTR_AXIS_END + 3); +constexpr TypedWhichId SCHATTR_SYMBOL_SIZE (SCHATTR_AXIS_END + 4); +constexpr TypedWhichId 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 SCHATTR_BAR_OVERLAP (SCHATTR_CHARTTYPE_START ); +constexpr TypedWhichId SCHATTR_BAR_GAPWIDTH (SCHATTR_CHARTTYPE_START + 1); +constexpr TypedWhichId SCHATTR_BAR_CONNECT (SCHATTR_CHARTTYPE_START + 2); +constexpr TypedWhichId SCHATTR_NUM_OF_LINES_FOR_BAR (SCHATTR_CHARTTYPE_START + 3); +constexpr TypedWhichId SCHATTR_SPLINE_ORDER (SCHATTR_CHARTTYPE_START + 4); +constexpr TypedWhichId SCHATTR_SPLINE_RESOLUTION (SCHATTR_CHARTTYPE_START + 5); +constexpr TypedWhichId SCHATTR_GROUP_BARS_PER_AXIS (SCHATTR_CHARTTYPE_START + 6); +constexpr TypedWhichId SCHATTR_STARTING_ANGLE (SCHATTR_CHARTTYPE_START + 7); +constexpr TypedWhichId SCHATTR_CLOCKWISE (SCHATTR_CHARTTYPE_START + 8); +constexpr TypedWhichId SCHATTR_MISSING_VALUE_TREATMENT (SCHATTR_CHARTTYPE_START + 9); +constexpr TypedWhichId SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS (SCHATTR_CHARTTYPE_START + 10); +constexpr TypedWhichId SCHATTR_INCLUDE_HIDDEN_CELLS (SCHATTR_CHARTTYPE_START + 11); +constexpr TypedWhichId 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 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 SCHATTR_REGRESSION_TYPE (SCHATTR_REGRESSION_START); +constexpr TypedWhichId SCHATTR_REGRESSION_SHOW_EQUATION (SCHATTR_REGRESSION_START + 1); +constexpr TypedWhichId SCHATTR_REGRESSION_SHOW_COEFF (SCHATTR_REGRESSION_START + 2); +constexpr TypedWhichId SCHATTR_REGRESSION_DEGREE (SCHATTR_REGRESSION_START + 3); +constexpr TypedWhichId SCHATTR_REGRESSION_PERIOD (SCHATTR_REGRESSION_START + 4); +constexpr TypedWhichId SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD (SCHATTR_REGRESSION_START + 5); +constexpr TypedWhichId SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD (SCHATTR_REGRESSION_START + 6); +constexpr TypedWhichId SCHATTR_REGRESSION_SET_INTERCEPT (SCHATTR_REGRESSION_START + 7); +constexpr TypedWhichId SCHATTR_REGRESSION_INTERCEPT_VALUE (SCHATTR_REGRESSION_START + 8); +constexpr TypedWhichId SCHATTR_REGRESSION_CURVE_NAME (SCHATTR_REGRESSION_START + 9); +constexpr TypedWhichId SCHATTR_REGRESSION_XNAME (SCHATTR_REGRESSION_START + 10); +constexpr TypedWhichId SCHATTR_REGRESSION_YNAME (SCHATTR_REGRESSION_START + 11); +constexpr sal_uInt16 SCHATTR_REGRESSION_END (SCHATTR_REGRESSION_YNAME); + +constexpr sal_uInt16 SCHATTR_END (SCHATTR_REGRESSION_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 + +#endif + +/* 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 000000000..203c3c390 --- /dev/null +++ b/chart2/source/inc/chartview/DataPointSymbolSupplier.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_DATAPOINTSYMBOLSUPPLIER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_DATAPOINTSYMBOLSUPPLIER_HXX + +#include +#include + +namespace com::sun::star::drawing { class XShapes; } +namespace com::sun::star::drawing { struct Direction3D; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + +namespace chart +{ + +class OOO_DLLPUBLIC_CHARTVIEW DataPointSymbolSupplier +{ +public: + static css::uno::Reference< css::drawing::XShapes > + create2DSymbolList( const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory + , const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Direction3D& rSize ); +}; + +} //namespace chart +#endif + +/* 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 000000000..3bc0b4fef --- /dev/null +++ b/chart2/source/inc/chartview/DrawModelWrapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_DRAWMODELWRAPPER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_DRAWMODELWRAPPER_HXX + +#include + +#include + +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 : private SdrModel +{ +private: + SfxItemPool* m_pChartItemPool; + + css::uno::Reference< css::drawing::XDrawPage > m_xMainDrawPage; + css::uno::Reference< css::drawing::XDrawPage > m_xHiddenDrawPage; + + VclPtr 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 + css::uno::Reference< css::drawing::XDrawPage > const & getMainDrawPage(); + SAL_DLLPRIVATE void clearMainDrawPage(); + + // the extra page is not visible, but contains some extras like the symbols for data points + css::uno::Reference< css::drawing::XDrawPage > const & getHiddenDrawPage(); + + static css::uno::Reference< css::drawing::XShapes > + getChartRootShape( const css::uno::Reference< css::drawing::XDrawPage>& xPage ); + + SAL_DLLPRIVATE void lockControllers(); + SAL_DLLPRIVATE void unlockControllers(); + + OutputDevice* getReferenceDevice() const; + + SfxItemPool& GetItemPool(); + + SAL_DLLPRIVATE virtual css::uno::Reference< css::uno::XInterface > + 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 css::uno::Reference< css::drawing::XShape >& xShape ); +}; +} //namespace chart +#endif + +/* 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 000000000..731d4c087 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_EXPLICITSCALEVALUES_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_EXPLICITSCALEVALUES_HXX + +#include +#include +#include +#include +#include +#include + +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 ShiftedCategoryPosition; + sal_Int32 TimeResolution; //constant of type css::chart::TimeUnit + Date NullDate; +}; + +struct ExplicitSubIncrement +{ + ExplicitSubIncrement(); + + /** Numbers of intervals between two superior ticks. For an axis + this usually means, that IntervalCount - 1 + sub-tick-marks are displayed between two superior ticks. + + */ + sal_Int32 IntervalCount; + + /** If , the distance between two sub-tick-marks on the + screen is always the same. If , the distances may + differ depending on the XScaling. + */ + 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 + */ + + /** Distance describes the distance between two + neighboring main tickmarks on a Scale of an axis. + All neighboring main tickmarks have the same constant distance. + +

If the Scale has a XScaling the Distance + may be measured in two different ways - that is - before or after the + scaling is applied.

+ +

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.

+ +

PostEquidistant rules whether the Distance + is meant to be a value before or after scaling.

+ */ + double Distance; + + /** + PostEquidistant rules whether the member Distance + describes a distance before or after the scaling is applied. + +

If PostEquidistant equals Distance + is given in values after XScaling is applied, thus resulting + main tickmarks will always look equidistant on the screen. + If PostEquidistant equals Distance + is given in values before XScaling is applied.

+ */ + bool PostEquidistant; + + /** The BaseValue gives a starting point on the scale + to which all further main tickmarks are relatively positioned. + +

The BaseValue 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.

+ +

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.

+ */ + double BaseValue; + + /** SubIncrements describes the positioning of further + sub tickmarks on the scale of an axis. + +

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.

+ */ + std::vector< ExplicitSubIncrement > SubIncrements; +}; + +} //namespace chart +#endif + +/* 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 000000000..e2ff1e01a --- /dev/null +++ b/chart2/source/inc/chartview/ExplicitValueProvider.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_EXPLICITVALUEPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_EXPLICITVALUEPROVIDER_HXX + +#include +#include + +#include + +namespace chart { class ChartModel; } +namespace chart { struct ExplicitIncrementData; } +namespace chart { struct ExplicitScaleData; } +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 class Reference; } +namespace com::sun::star::uno { template class Sequence; } +namespace com::sun::star::util { class XNumberFormatsSupplier; } + +namespace chart +{ + +class DrawModelWrapper; +class OOO_DLLPUBLIC_CHARTVIEW 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( + css::uno::Reference< css::chart2::XAxis > 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 css::uno::Reference< css::drawing::XShape > + getShapeForCID( const OUString& rObjectCID )=0; + + virtual std::shared_ptr< DrawModelWrapper > getDrawModelWrapper() = 0; + + static const css::uno::Sequence& getUnoTunnelId(); + + static css::awt::Rectangle + AddSubtractAxisTitleSizes( + ChartModel& rModel + , const css::uno::Reference< css::uno::XInterface >& xChartView + , const css::awt::Rectangle& rPositionAndSize, bool bSubtract ); + + static sal_Int32 getExplicitNumberFormatKeyForAxis( + const css::uno::Reference< css::chart2::XAxis >& xAxis + , const css::uno::Reference< css::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem + , const css::uno::Reference< css::chart2::XChartDocument>& 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() {} +}; + +} //namespace chart +#endif + +/* 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 000000000..276210438 --- /dev/null +++ b/chart2/source/inc/chartview/chartviewdllapi.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_CHARTVIEWDLLAPI_HXX +#define INCLUDED_CHART2_SOURCE_INC_CHARTVIEW_CHARTVIEWDLLAPI_HXX + +#include + +#include + +#if defined OOO_DLLIMPLEMENTATION_CHARTVIEW +#define OOO_DLLPUBLIC_CHARTVIEW SAL_DLLPUBLIC_EXPORT +#else +#define OOO_DLLPUBLIC_CHARTVIEW SAL_DLLPUBLIC_IMPORT +#endif + +#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 000000000..135afe44b --- /dev/null +++ b/chart2/source/inc/defines.hxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_INC_DEFINES_HXX +#define INCLUDED_CHART2_SOURCE_INC_DEFINES_HXX + +#define FIXED_SIZE_FOR_3D_CHART_VOLUME 10000.0 + +#endif + +/* 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 000000000..235c5f4fe --- /dev/null +++ b/chart2/source/inc/res_BarGeometry.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_BARGEOMETRY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_BARGEOMETRY_HXX + +#include + +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& rLink); + +private: + std::unique_ptr m_xFT_Geometry; + std::unique_ptr m_xLB_Geometry; +}; + +} //namespace chart + +#endif + +/* 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 000000000..a63c09393 --- /dev/null +++ b/chart2/source/inc/servicenames.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_HXX +#define INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_HXX + +namespace chart +{ +#define CHART_MODEL_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartModel" +#define CHART_MODEL_SERVICE_NAME "com.sun.star.chart2.ChartDocument" +//@todo create your own service containing the service com.sun.star.document.OfficeDocument + +#define CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartController" +#define CHART_CONTROLLER_SERVICE_NAME "com.sun.star.chart2.ChartController" +//@todo create your own service containing the service com.sun.star.frame.Controller + +#define CHART_VIEW_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartView" +#define CHART_VIEW_SERVICE_NAME "com.sun.star.chart2.ChartView" + +#define CHART_FRAMELOADER_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartFrameLoader" +#define CHART_FRAMELOADER_SERVICE_NAME "com.sun.star.frame.SynchronousFrameLoader" + +#define CHART_WIZARD_DIALOG_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.WizardDialog" +#define CHART_WIZARD_DIALOG_SERVICE_NAME "com.sun.star.chart2.WizardDialog" + +#define CHART_TYPE_DIALOG_SERVICE_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartTypeDialog" +#define CHART_TYPE_DIALOG_SERVICE_NAME "com.sun.star.chart2.ChartTypeDialog" + +// wrapper for old UNO API (com.sun.star.chart) +#define CHART_CHARTAPIWRAPPER_IMPLEMENTATION_NAME "com.sun.star.comp.chart2.ChartDocumentWrapper" +#define CHART_CHARTAPIWRAPPER_SERVICE_NAME "com.sun.star.chart2.ChartDocumentWrapper" + +// accessibility +#define CHART_ACCESSIBLE_TEXT_SERVICE_NAME "com.sun.star.accessibility.AccessibleTextComponent" + +} //namespace chart + +#endif + +/* 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 000000000..9a1ee83db --- /dev/null +++ b/chart2/source/inc/servicenames_charttypes.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_CHARTTYPES_HXX +#define INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_CHARTTYPES_HXX + +namespace chart { + +#define CHART2_SERVICE_NAME_CHARTTYPE_AREA "com.sun.star.chart2.AreaChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_BAR "com.sun.star.chart2.BarChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_COLUMN "com.sun.star.chart2.ColumnChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_LINE "com.sun.star.chart2.LineChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_SCATTER "com.sun.star.chart2.ScatterChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_PIE "com.sun.star.chart2.PieChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_NET "com.sun.star.chart2.NetChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET "com.sun.star.chart2.FilledNetChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK "com.sun.star.chart2.CandleStickChartType" +#define CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE "com.sun.star.chart2.BubbleChartType" + +} //namespace chart + +#endif + +/* 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 000000000..176486199 --- /dev/null +++ b/chart2/source/inc/servicenames_coosystems.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_COOSYSTEMS_HXX +#define INCLUDED_CHART2_SOURCE_INC_SERVICENAMES_COOSYSTEMS_HXX + +namespace chart +{ + +#define CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME "com.sun.star.chart2.CoordinateSystems.CartesianView" +#define CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME "com.sun.star.chart2.CoordinateSystems.PolarView" + +} //namespace chart +#endif + +/* 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 000000000..a8633cc2d --- /dev/null +++ b/chart2/source/model/filter/XMLFilter.cxx @@ -0,0 +1,786 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::osl::MutexGuard; + +namespace +{ +char const sXML_metaStreamName[] = "meta.xml"; +char const sXML_styleStreamName[] = "styles.xml"; +char const sXML_contentStreamName[] = "content.xml"; + + +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( 3 ); + if( aMDHelper.ISSET_OutputStream ) + aStorageArgs[0] <<= aMDHelper.OutputStream; + else + aStorageArgs[0] <<= aMDHelper.URL; + aStorageArgs[1] <<= (embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE); + aStorageArgs[2] <<= comphelper::containerToSequence( aPropertiesForStorage ); + + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + } + + // set correct media type at storage + uno::Reference 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( 3 ); + aStorageArgs[0] <<= xStream; + aStorageArgs[1] <<= (embed::ElementModes::READ | embed::ElementModes::NOCREATE); + aStorageArgs[2] <<= 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 ), + m_bCancelOperation( false ) +{} + +XMLFilter::~XMLFilter() +{} + +// ____ XFilter ____ +sal_Bool SAL_CALL XMLFilter::filter( + const Sequence< beans::PropertyValue >& aDescriptor ) +{ + bool bResult = false; + + MutexGuard aGuard( m_aMutex ); + + // ignore cancel flag at start of function + // note: is currently ignored during import/export + if( m_bCancelOperation ) + m_bCancelOperation = false; + + 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() +{ + // if mutex is locked set "cancel state" + // note: is currently ignored in filter-method + if( ! m_aMutex.tryToAcquire()) + { + m_bCancelOperation = true; + } +} + +// ____ 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 xGraphicStorageHandler; + uno::Reference xServiceFactory(xFactory, uno::UNO_QUERY); + if (xServiceFactory.is()) + { + uno::Sequence aArgs(1); + aArgs[0] <<= 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 */ + comphelper::PropertyMapEntry const aImportInfoMap[] = + { + // necessary properties for XML progress bar at load time + { OUString("ProgressRange"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressMax"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("ProgressCurrent"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("PrivateData"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BuildId"), 0, cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString(), 0, css::uno::Type(), 0, 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 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 ); + + nArgs = 0; + if( xGraphicStorageHandler.is()) + aFilterCompArgs[nArgs++] <<= xGraphicStorageHandler; + if( xImportInfo.is()) + aFilterCompArgs[ nArgs++ ] <<= xImportInfo; + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< xml::sax::XDocumentHandler > xDocHandler( + xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext ), + uno::UNO_QUERY_THROW ); + + Reference< document::XImporter > xImporter( xDocHandler, uno::UNO_QUERY_THROW ); + xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_SET_THROW )); + + if ( !m_sDocumentHandler.isEmpty() ) + { + try + { + uno::Sequence< uno::Any > aArgs(2); + beans::NamedValue aValue; + aValue.Name = "DocumentHandler"; + aValue.Value <<= xDocHandler; + aArgs[0] <<= aValue; + aValue.Name = "Model"; + aValue.Value <<= m_xTargetDoc; + aArgs[1] <<= aValue; + + xDocHandler.set(xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext), uno::UNO_QUERY_THROW ); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + } + xml::sax::InputSource aParserInput; + aParserInput.aInputStream.set(xInputStream, uno::UNO_QUERY_THROW); + + // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler + Reference< xml::sax::XFastParser > xFastParser(xDocHandler, uno::UNO_QUERY); + if (xFastParser.is()) + xFastParser->parseStream(aParserInput); + else + { + Reference xParser = xml::sax::Parser::create(m_xContext); + xParser->setDocumentHandler( xDocHandler ); + 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(2); + beans::NamedValue aValue; + aValue.Name = "DocumentHandler"; + aValue.Value <<= xDocHandler; + aArgs[0] <<= aValue; + aValue.Name = "Model"; + aValue.Value <<= xDocumentComp; + aArgs[1] <<= aValue; + + xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY ); + xSaxWriter.set(xDocHandler,uno::UNO_QUERY); + } + catch (const uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } + } + + Reference xGraphicStorageHandler; + xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(m_xContext, xStorage)); + + // property map for export info set + comphelper::PropertyMapEntry const aExportInfoMap[] = + { + { OUString("UsePrettyPrinting"), 0, cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0}, + { OUString("BaseURI"), 0, ::cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("ExportTableNumberList"), 0, cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString(), 0, css::uno::Type(), 0, 0 } + }; + + uno::Reference< beans::XPropertySet > xInfoSet = + comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ); + + SvtSaveOptions aSaveOpt; + bool bUsePrettyPrinting( aSaveOpt.IsPrettyPrinting() ); + 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 ); + { + nArgs = 0; + aFilterProperties[ nArgs++ ] <<= xInfoSet; + aFilterProperties[ nArgs++ ] <<= xDocHandler; + if( xGraphicStorageHandler.is()) + aFilterProperties[ 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 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 ? OUString(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII) : OUString(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 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 const &) +{ + return cppu::acquire(new ::chart::XMLReportFilterHelper(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/BaseCoordinateSystem.hxx b/chart2/source/model/inc/BaseCoordinateSystem.hxx new file mode 100644 index 000000000..1f20e83a0 --- /dev/null +++ b/chart2/source/model/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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_BASECOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_BASECOORDINATESYSTEM_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +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 BaseCoordinateSystem : + public impl::BaseCoordinateSystem_Base, + public MutexContainer, + public ::property::OPropertySet +{ +public: + BaseCoordinateSystem( sal_Int32 nDimensionCount ); + explicit BaseCoordinateSystem( const BaseCoordinateSystem & rSource ); + virtual ~BaseCoordinateSystem() override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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() + +protected: + // ____ 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 ) 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; + + void fireModifyEvent(); + +protected: + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; + +private: + sal_Int32 m_nDimensionCount; + typedef std::vector< std::vector< css::uno::Reference< css::chart2::XAxis > > > tAxisVecVecType; + tAxisVecVecType m_aAllAxis; //outer sequence is the dimension; inner sequence is the axis index that indicates main or secondary axis + std::vector< css::uno::Reference< css::chart2::XChartType > > m_aChartTypes; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_INC_BASECOORDINATESYSTEM_HXX +#endif + +/* 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 000000000..7b2847cd8 --- /dev/null +++ b/chart2/source/model/inc/CartesianCoordinateSystem.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_CARTESIANCOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_CARTESIANCOORDINATESYSTEM_HXX + +#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 : 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 : 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 + +// INCLUDED_CHART2_SOURCE_MODEL_INC_CARTESIANCOORDINATESYSTEM_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/ChartTypeManager.hxx b/chart2/source/model/inc/ChartTypeManager.hxx new file mode 100644 index 000000000..176681564 --- /dev/null +++ b/chart2/source/model/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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_CHARTTYPEMANAGER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_CHARTTYPEMANAGER_HXX + +#include +#include +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +class ChartTypeManager : + public ::cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::lang::XMultiServiceFactory, + css::chart2::XChartTypeManager > +{ +public: + explicit ChartTypeManager( + css::uno::Reference< css::uno::XComponentContext > const & 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; + +protected: + // ____ 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 + +private: + css::uno::Reference< css::uno::XComponentContext > + m_xContext; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_INC_CHARTTYPEMANAGER_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/DataSeries.hxx b/chart2/source/model/inc/DataSeries.hxx new file mode 100644 index 000000000..7a571f1eb --- /dev/null +++ b/chart2/source/model/inc/DataSeries.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_DATASERIES_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_DATASERIES_HXX + +// UNO types +#include +#include +#include +#include +#include +#include +#include +#include + +// helper classes +#include +#include + +// STL +#include +#include + +#include +#include + +namespace com::sun::star::beans { class XPropertySet; } + +namespace chart +{ + +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 DataSeries final : + public MutexContainer, + 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() + +private: + explicit DataSeries( const DataSeries & rOther ); + + // late initialization to call after copy-constructing + void Init( 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ 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(); + + typedef std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > tDataSequenceContainer; + tDataSequenceContainer m_aDataSequences; + + typedef std::map< sal_Int32, + css::uno::Reference< css::beans::XPropertySet > > tDataPointAttributeContainer; + tDataPointAttributeContainer m_aAttributedDataPoints; + + typedef + std::vector< css::uno::Reference< css::chart2::XRegressionCurve > > + tRegressionCurveContainerType; + tRegressionCurveContainerType m_aRegressionCurves; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_INC_DATASERIES_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/inc/Diagram.hxx b/chart2/source/model/inc/Diagram.hxx new file mode 100644 index 000000000..c909f183f --- /dev/null +++ b/chart2/source/model/inc/Diagram.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_DIAGRAM_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_DIAGRAM_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::chart2::data { class XDataSource; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +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 Diagram final : + public MutexContainer, + public impl::Diagram_Base, + public ::property::OPropertySet +{ +public: + Diagram( css::uno::Reference< css::uno::XComponentContext > const & 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() + +private: + explicit Diagram( const Diagram & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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( 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; + + // ____ 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; + + // ____ 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; + + typedef + std::vector< css::uno::Reference< css::chart2::XCoordinateSystem > > + tCoordinateSystemContainerType; + + tCoordinateSystemContainerType m_aCoordSystems; + + css::uno::Reference< css::beans::XPropertySet > + m_xWall; + + css::uno::Reference< css::beans::XPropertySet > + m_xFloor; + + css::uno::Reference< css::chart2::XTitle > + m_xTitle; + + css::uno::Reference< css::chart2::XLegend > + m_xLegend; + + css::uno::Reference< css::chart2::XColorScheme > + m_xColorScheme; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_INC_DIAGRAM_HXX +#endif + +/* 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 000000000..4572201f5 --- /dev/null +++ b/chart2/source/model/inc/PolarCoordinateSystem.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_POLARCOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_POLARCOORDINATESYSTEM_HXX + +#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 : 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 : 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 + +// INCLUDED_CHART2_SOURCE_MODEL_INC_POLARCOORDINATESYSTEM_HXX +#endif + +/* 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 000000000..b1247e584 --- /dev/null +++ b/chart2/source/model/inc/StockBar.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_INC_STOCKBAR_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_STOCKBAR_HXX + +#include +#include +#include +#include +#include + +#include +#include + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + StockBar_Base; +} + +class StockBar final : + public MutexContainer, + 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 ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_INC_STOCKBAR_HXX +#endif + +/* 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 000000000..4f4ba101a --- /dev/null +++ b/chart2/source/model/inc/XMLFilter.hxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_MODEL_INC_XMLFILTER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_INC_XMLFILTER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 & 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 m_aMediaDescriptor; + + OUString m_sDocumentHandler; // when set it will be set as doc handler + + volatile bool m_bCancelOperation; + ::osl::Mutex m_aMutex; +}; + +class XMLReportFilterHelper : 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 + +// INCLUDED_CHART2_SOURCE_MODEL_INC_XMLFILTER_HXX +#endif + +/* 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 000000000..ff42899d0 --- /dev/null +++ b/chart2/source/model/main/Axis.cxx @@ -0,0 +1,632 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverPosition", + PROP_AXIS_CROSSOVER_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CrossoverValue", + PROP_AXIS_CROSSOVER_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "DisplayLabels", + PROP_AXIS_DISPLAY_LABELS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_AXIS_NUMBERFORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LabelPosition", + PROP_AXIS_LABEL_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextRotation", + PROP_AXIS_TEXT_ROTATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextBreak", + PROP_AXIS_TEXT_BREAK, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextOverlap", + PROP_AXIS_TEXT_OVERLAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "StackCharacters", + PROP_AXIS_TEXT_STACKED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ArrangeOrder", + PROP_AXIS_TEXT_ARRANGE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_AXIS_REFERENCE_DIAGRAM_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MajorTickmarks", + PROP_AXIS_MAJOR_TICKMARKS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MinorTickmarks", + PROP_AXIS_MINOR_TICKMARKS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MarkPosition", + PROP_AXIS_MARK_POSITION, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for display units: + rOutProperties.emplace_back( "DisplayUnits", + PROP_AXIS_DISPLAY_UNITS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //Properties for labels: + rOutProperties.emplace_back( "BuiltInUnit", + PROP_AXIS_BUILTINUNIT, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MajorOrigin", + PROP_AXIS_MAJOR_ORIGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + +} + +struct StaticAxisDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::CharacterProperties::AddDefaultsToMap( rOutMap ); + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_SHOW, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_CROSSOVER_POSITION, css::chart::ChartAxisPosition_ZERO ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_DISPLAY_LABELS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_LABEL_POSITION, css::chart::ChartAxisLabelPosition_NEAR_AXIS ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_AXIS_TEXT_ROTATION, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_BREAK, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_OVERLAP, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_STACKED, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TEXT_ARRANGE_ORDER, css::chart::ChartAxisArrangeOrderType_AUTO ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_AXIS_MAJOR_TICKMARKS, 2 /* CHAXIS_MARK_OUTER */ ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_AXIS_MINOR_TICKMARKS, 0 /* CHAXIS_MARK_NONE */ ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_MARK_POSITION, css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_DISPLAY_UNITS, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_AXIS_TRY_STAGGERING_FIRST, false ); + } +}; + +struct StaticAxisDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticAxisDefaults_Initializer > +{ +}; + +struct StaticAxisInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticAxisInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticAxisInfoHelper_Initializer > +{ +}; + +struct StaticAxisInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticAxisInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticAxisInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticAxisInfo_Initializer > +{ +}; + +typedef uno::Reference< beans::XPropertySet > lcl_tSubGridType; + +void lcl_CloneSubGrids( + const uno::Sequence< lcl_tSubGridType > & rSource, uno::Sequence< lcl_tSubGridType > & rDestination ) +{ + rDestination.realloc( rSource.getLength()); + lcl_tSubGridType * pDestBegin = rDestination.getArray(); + lcl_tSubGridType * pDestEnd = pDestBegin + rDestination.getLength(); + lcl_tSubGridType * pDestIt = pDestBegin; + + for( Reference< beans::XPropertySet > const & i : rSource ) + { + Reference< beans::XPropertySet > xSubGrid( i ); + if( xSubGrid.is()) + { + Reference< util::XCloneable > xCloneable( xSubGrid, uno::UNO_QUERY ); + if( xCloneable.is()) + xSubGrid.set( xCloneable->createClone(), uno::UNO_QUERY ); + } + + (*pDestIt) = xSubGrid; + OSL_ASSERT( pDestIt != pDestEnd ); + ++pDestIt; + } + OSL_ASSERT( pDestIt == pDestEnd ); +} + +} // anonymous namespace + +namespace chart +{ + +Axis::Axis() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_aScaleData( AxisHelper::createDefaultScale() ), + m_xGrid( new GridProperties() ), + m_aSubGridProperties(), + m_xTitle() +{ + 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_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_aScaleData( rOther.m_aScaleData ) +{ + m_xGrid.set( CloneHelper::CreateRefClone< beans::XPropertySet >()( 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.hasElements() ) + lcl_CloneSubGrids( rOther.m_aSubGridProperties, m_aSubGridProperties ); + ModifyListenerHelper::addListenerToAllSequenceElements( m_aSubGridProperties, m_xModifyEventForwarder ); + + m_xTitle.set( CloneHelper::CreateRefClone< chart2::XTitle >()( 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::removeListenerFromAllSequenceElements( 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.set(nullptr); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + m_aSubGridProperties.realloc(0); + m_xGrid = nullptr; + m_xTitle = nullptr; +} + +void Axis::AllocateSubGrids() +{ + Reference< util::XModifyListener > xModifyEventForwarder; + Reference< lang::XEventListener > xEventListener; + std::vector< Reference< beans::XPropertySet > > aOldBroadcasters; + std::vector< Reference< beans::XPropertySet > > aNewBroadcasters; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + xEventListener = this; + + sal_Int32 nNewSubIncCount = m_aScaleData.IncrementData.SubIncrements.getLength(); + sal_Int32 nOldSubIncCount = m_aSubGridProperties.getLength(); + + if( nOldSubIncCount > nNewSubIncCount ) + { + // remove superfluous entries + for( sal_Int32 i = nNewSubIncCount; i < nOldSubIncCount; ++i ) + aOldBroadcasters.push_back( m_aSubGridProperties[ i ] ); + m_aSubGridProperties.realloc( nNewSubIncCount ); + } + else if( nOldSubIncCount < nNewSubIncCount ) + { + m_aSubGridProperties.realloc( 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(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; +} +Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubGridProperties() +{ + 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; +} + +void SAL_CALL Axis::setTitleObject( const Reference< chart2::XTitle >& xNewTitle ) +{ + Reference< util::XModifyListener > xModifyEventForwarder; + Reference< chart2::XTitle > 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() +{ + Axis * pNewAxis( new Axis( *this )); + // hold a reference to the clone + Reference< util::XCloneable > xResult( pNewAxis ); + // do initialization that uses uno references to the clone + pNewAxis->Init(); + return xResult; +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Axis::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL Axis::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 ____ +uno::Any Axis::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticAxisDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Axis::getInfoHelper() +{ + return *StaticAxisInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL Axis::getPropertySetInfo() +{ + return *StaticAxisInfo::get(); +} + +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 const &) +{ + return cppu::acquire(new ::chart::Axis); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Axis.hxx b/chart2/source/model/main/Axis.hxx new file mode 100644 index 000000000..49f4003bb --- /dev/null +++ b/chart2/source/model/main/Axis.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_AXIS_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_AXIS_HXX + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace chart +{ + +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 Axis final : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ 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; + + // ____ 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(); + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; + + css::chart2::ScaleData m_aScaleData; + + css::uno::Reference< css::beans::XPropertySet > m_xGrid; + + css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > m_aSubGridProperties; + + css::uno::Reference< css::chart2::XTitle > m_xTitle; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_AXIS_HXX +#endif + +/* 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 000000000..7075f2ed6 --- /dev/null +++ b/chart2/source/model/main/BaseCoordinateSystem.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 +#include +#include +#include +#include +#include "Axis.hxx" +#include +#include +#include +#include +#include + +#include + +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticCooSysDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::PropertyHelper::setPropertyValueDefault( aStaticDefaults, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false ); + return &aStaticDefaults; + } +}; + +struct StaticCooSysDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticCooSysDefaults_Initializer > +{ +}; + +struct StaticCooSysInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticCooSysInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticCooSysInfoHelper_Initializer > +{ +}; + +struct StaticCooSysInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticCooSysInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticCooSysInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticCooSysInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BaseCoordinateSystem::BaseCoordinateSystem( + sal_Int32 nDimensionCount /* = 2 */ ) : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_nDimensionCount( nDimensionCount ) + { + m_aAllAxis.resize( m_nDimensionCount ); + for( sal_Int32 nN=0; nN 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_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_nDimensionCount( rSource.m_nDimensionCount ) +{ + m_aAllAxis.resize(rSource.m_aAllAxis.size()); + tAxisVecVecType::size_type nN=0; + for( nN=0; nN( rSource.m_aAllAxis[nN], m_aAllAxis[nN] ); + CloneHelper::CloneRefVector( rSource.m_aChartTypes, m_aChartTypes ); + + for( nN=0; nN& 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; + } + + Reference< chart2::XAxis > 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]; +} + +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 ) +{ + if( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), aChartType ) + != m_aChartTypes.end()) + throw lang::IllegalArgumentException(); + + m_aChartTypes.push_back( aChartType ); + ModifyListenerHelper::addListener( aChartType, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL BaseCoordinateSystem::removeChartType( const Reference< chart2::XChartType >& aChartType ) +{ + std::vector< uno::Reference< chart2::XChartType > >::iterator + aIt( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), aChartType )); + 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( m_aChartTypes ); +} + +void SAL_CALL BaseCoordinateSystem::setChartTypes( const Sequence< Reference< chart2::XChartType > >& aChartTypes ) +{ + ModifyListenerHelper::removeListenerFromAllElements( m_aChartTypes, m_xModifyEventForwarder ); + m_aChartTypes = comphelper::sequenceToContainer >>( aChartTypes ); + ModifyListenerHelper::addListenerToAllElements( m_aChartTypes, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL BaseCoordinateSystem::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +void SAL_CALL BaseCoordinateSystem::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +// ____ 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 ____ +uno::Any BaseCoordinateSystem::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticCooSysDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL BaseCoordinateSystem::getInfoHelper() +{ + return *StaticCooSysInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo() +{ + return *StaticCooSysInfo::get(); +} + +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 000000000..288749d85 --- /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 +#include +#include + +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 +{ + +static const char CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME[] = "com.sun.star.chart2.CoordinateSystems.Cartesian"; + +} + +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 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 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 000000000..96c49fb56 --- /dev/null +++ b/chart2/source/model/main/ChartModel.cxx @@ -0,0 +1,1301 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "PageBackground.hxx" +#include +#include +#include "UndoManager.hxx" +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 +{ +const OUString lcl_aGDIMetaFileMIMEType( + "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""); +const OUString lcl_aGDIMetaFileMIMETypeHighContrast( + "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""); + +} // anonymous namespace + +// ChartModel Constructor and Destructor + +namespace chart +{ + +ChartModel::ChartModel(uno::Reference const & 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( xContext ) + , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() ) + , m_xPageBackground( new PageBackground ) + , m_xXMLNamespaceMap( createNameContainer( ::cppu::UnoType::get(), + "com.sun.star.xml.NamespaceMap", "com.sun.star.comp.chart.XMLNameSpaceMap" ) ) + , 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 ); + } + + { + ModifyListenerHelper::addListener( m_xPageBackground, this ); + m_xChartTypeManager.set( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.ChartTypeManager", m_xContext ), uno::UNO_QUERY ); + } + 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; + Reference< chart2::XTitle > xNewTitle = CreateRefClone< chart2::XTitle >()( rOther.m_xTitle ); + Reference< chart2::XDiagram > xNewDiagram = CreateRefClone< chart2::XDiagram >()( rOther.m_xDiagram ); + Reference< beans::XPropertySet > xNewPageBackground = CreateRefClone< beans::XPropertySet >()( rOther.m_xPageBackground ); + Reference< chart2::XChartTypeManager > xChartTypeManager = CreateRefClone< chart2::XChartTypeManager >()( rOther.m_xChartTypeManager ); + Reference< container::XNameAccess > xXMLNamespaceMap = CreateRefClone< container::XNameAccess >()( 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 ); + ModifyListenerHelper::addListener( xNewDiagram, xListener ); + ModifyListenerHelper::addListener( xNewPageBackground, 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"? +} + +css::uno::Reference< css::uno::XInterface > ChartModel::getChartView() const +{ + return static_cast< ::cppu::OWeakObject* >( 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 > 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 xI = m_aControllers.getElements()[0]; + return uno::Reference( xI, uno::UNO_QUERY ); + } + + //return nothing if no controllers are connected at all + return uno::Reference< frame::XController > (); +} + +void ChartModel::impl_notifyCloseListeners() +{ + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType::get()); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent*>(this) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XCloseListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->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< long >( aPos.X * fWidth ); + aPos.Y = static_cast< long >( aPos.Y * fHeight ); + aSize.Width = static_cast< long >( aSize.Width * fWidth ); + aSize.Height = static_cast< 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(); + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + 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; + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + 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, Reference< XChartDocument >(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 + //XEventListener::disposing + + //hold no mutex + if( !m_aLifeTimeManager.dispose() ) + return; + + //--release all resources and references + //// @todo + + if ( m_xDiagram.is() ) + ModifyListenerHelper::removeListener( m_xDiagram, this ); + + if ( m_xDataProvider.is() ) + { + Reference xModifyBroadcaster( m_xDataProvider, uno::UNO_QUERY ); + if ( xModifyBroadcaster.is() ) + xModifyBroadcaster->removeModifyListener( this ); + } + + m_xDataProvider.clear(); + m_xInternalDataProvider.clear(); + m_xNumberFormatsSupplier.clear(); + DisposeHelper::DisposeAndClear( m_xOwnNumberFormatsSupplier ); + DisposeHelper::DisposeAndClear( m_xChartTypeManager ); + DisposeHelper::DisposeAndClear( m_xDiagram ); + DisposeHelper::DisposeAndClear( m_xTitle ); + DisposeHelper::DisposeAndClear( m_xPageBackground ); + DisposeHelper::DisposeAndClear( m_xXMLNamespaceMap ); + + 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(); + + DisposeHelper::DisposeAndClear( m_xRangeHighlighter ); + 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 + + m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType::get(), 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 + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType::get(), 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 + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType::get(), 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::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.get(); +} + +// 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 ) +{ + Reference< chart2::XDiagram > xOldDiagram; + Reference< util::XModifyListener > xListener; + { + MutexGuard aGuard( m_aModelMutex ); + if( xDiagram == m_xDiagram ) + return; + xOldDiagram = m_xDiagram; + m_xDiagram = xDiagram; + xListener = this; + } + //don't keep the mutex locked while calling out + ModifyListenerHelper::removeListener( xOldDiagram, xListener ); + ModifyListenerHelper::addListener( xDiagram, xListener ); + setModified( true ); +} + +Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData() +{ + Reference< chart2::data::XDataSource > xDataSource; + if( hasInternalDataProvider() ) + { + uno::Reference< lang::XInitialization > xIni(m_xInternalDataProvider,uno::UNO_QUERY); + if( xIni.is() ) + { + //init internal dataprovider + { + uno::Sequence< uno::Any > aArgs(1); + beans::NamedValue aParam( "CreateDefaultData" ,uno::Any(true) ); + aArgs[0] <<= aParam; + xIni->initialize(aArgs); + } + //create data + uno::Sequence 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( Reference(), 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(); +} + +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( Reference< frame::XModel >(this) ); + xProp->setPropertyValue("IncludeHiddenCells", uno::Any(bIncludeHiddenCells)); + } + catch (const beans::UnknownPropertyException&) + { + } + } + + uno::Reference 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==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() ) + { + Reference< chart2::XDiagram > xDia( getFirstDiagram() ); + if( !xDia.is() ) + { + Reference< chart2::XChartTypeTemplate > 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( Reference< frame::XModel >(this)); +} + +Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData() +{ + return DataSourceHelper::getUsedData( Reference< chart2::XChartDocument >(this)); +} + +Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter() +{ + if( ! m_xRangeHighlighter.is()) + { + uno::Reference< view::XSelectionSupplier > xSelSupp( getCurrentController(), uno::UNO_QUERY ); + if( xSelSupp.is() ) + m_xRangeHighlighter.set( ChartModelHelper::createRangeHighlighter( xSelSupp )); + } + return m_xRangeHighlighter; +} + +Reference SAL_CALL ChartModel::getPopupRequest() +{ + if (!m_xPopupRequest.is()) + m_xPopupRequest.set(new PopupRequest); + return m_xPopupRequest; +} + +Reference< chart2::XChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate() +{ + Reference< chart2::XChartTypeTemplate > xTemplate; + Reference< lang::XMultiServiceFactory > xFact( m_xChartTypeManager, uno::UNO_QUERY ); + if( xFact.is() ) + xTemplate.set( xFact->createInstance( "com.sun.star.chart2.template.Column" ), uno::UNO_QUERY ); + return xTemplate; +} + +void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_xChartTypeManager = xNewManager; + } + 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; +} + +void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& 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>::get() ); + + uno::Any aData( xTransferable->getTransferData( aDataFlavor ) ); + aData >>= aMetafile; + } + + aResult.Flavor.MimeType = lcl_aGDIMetaFileMIMEType; + aResult.Flavor.DataType = cppu::UnoType::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() +{ + uno::Sequence< datatransfer::DataFlavor > aRet(1); + + aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast, + "GDIMetaFile", + cppu::UnoType>::get() ); + + return aRet; +} + +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 Reference< uno::XInterface >( m_xXMLNamespaceMap ); + } + } + 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::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::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( isUnoTunnelId(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() +{ + Reference< chart2::data::XDataSource > xSource( + DataSourceHelper::getUsedData( uno::Reference< frame::XModel >(this) ) ); + if( xSource.is()) + return xSource->getDataSequences(); + + return uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >(); +} + +//XDumper +OUString SAL_CALL ChartModel::dump() +{ + uno::Reference< qa::XDumper > xDumper( + createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if (xDumper.is()) + return xDumper->dump(); + + 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 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 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 000000000..b3dd7a7cf --- /dev/null +++ b/chart2/source/model/main/ChartModel_Persistence.cxx @@ -0,0 +1,809 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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( const OUString & rStrToCompareWith ) : + m_aStr( rStrToCompareWith ) + {} + 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[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( 3 ); + aStorageArgs[0] <<= xStream; + aStorageArgs[1] <<= embed::ElementModes::READWRITE; + aStorageArgs[2] <<= 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.set( + m_xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.comp.chart2.XMLFilter", m_xContext ), + uno::UNO_QUERY_THROW ); + } + + 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 ) + { + Reference< io::XStream > xStream( + io::TempFile::create(m_xContext), uno::UNO_QUERY_THROW ); + 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 ); + + Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW ); + xSeekable->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 + Reference< chart2::XChartTypeTemplate > 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.realloc( 1 ); + aParam[0] = beans::PropertyValue( "HasCategories", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ); + } + + Reference< chart2::XDiagram > xDiagram( xTemplate->createDiagramByDataSource( 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 + Reference< chart2::XLegend > xLegend( + m_xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.Legend", m_xContext ), uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySet > xLegendProperties( xLegend, uno::UNO_QUERY ); + if( xLegendProperties.is() ) + { + xLegendProperties->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE )); + xLegendProperties->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE )); + xLegendProperties->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30 + xLegendProperties->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + + if( bIsRTL ) + xLegendProperties->setPropertyValue( "AnchorPosition", uno::Any( chart2::LegendPosition_LINE_START )); + } + if(xDiagram.is()) + xDiagram->setLegend( xLegend ); + + // set simple 3D look + Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + if( xDiagramProperties.is() ) + { + xDiagramProperties->setPropertyValue( "RightAngledAxes", uno::Any( true )); + xDiagramProperties->setPropertyValue( "D3DScenePerspective", uno::Any( drawing::ProjectionMode_PARALLEL )); + ThreeDHelper::setScheme( xDiagram, 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( 2 ); + aStorageArgs[0] <<= aMDHelper.Stream; + // todo: check if stream is read-only + aStorageArgs[1] <<= 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( 2 ); + aStorageArgs[0] <<= aMDHelper.InputStream; + aStorageArgs[1] <<= 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 ); + + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType::get()); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent*>(this) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XModifyListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->modified( aEvent ); + } + } +} + +sal_Bool SAL_CALL ChartModel::isModified() +{ + //@todo guard + return m_bModified; +} + +void SAL_CALL ChartModel::setModified( sal_Bool bModified ) +{ + 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 ) + { + m_bUpdateNotificationsPending = true; + 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 + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + cppu::UnoType::get(), 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 + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + cppu::UnoType::get(), xListener ); +} + +// util::XModifyListener +void SAL_CALL ChartModel::modified( const lang::EventObject& rEvenObject) +{ + uno::Reference xPivotTableDataProvider(rEvenObject.Source, uno::UNO_QUERY); + if (xPivotTableDataProvider.is()) + { + lockControllers(); + uno::Reference xDataProvider(xPivotTableDataProvider, uno::UNO_QUERY); + try + { + uno::Sequence aArguments = + DataSourceHelper::createArguments("PivotChart", uno::Sequence(), true, true, true); + + Reference xDataSource(xDataProvider->createDataSource(aArguments)); + Reference xFactory(getChartTypeManager(), uno::UNO_QUERY); + Reference xDiagram(getFirstDiagram()); + + DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram(xDiagram, xFactory); + css::uno::Reference xChartTypeTemplate(aTemplateAndService.first); + 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() +{ + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( cppu::UnoType::get()); + if( pIC ) + { + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< document::XStorageChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->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 + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + cppu::UnoType::get(), 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 + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + cppu::UnoType::get(), 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 000000000..6e9f6d483 --- /dev/null +++ b/chart2/source/model/main/DataPoint.cxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticDataPointInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticDataPointInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticDataPointInfoHelper_Initializer > +{ +}; + +struct StaticDataPointInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticDataPointInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticDataPointInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticDataPointInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +DataPoint::DataPoint( const uno::Reference< beans::XPropertySet > & rParentProperties ) : + ::property::OPropertySet( m_aMutex ), + m_xParentProperties( rParentProperties ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_bNoParentPropAllowed( false ) +{ + SetNewValuesExplicitlyEvenIfTheyEqualDefault(); +} + +DataPoint::DataPoint( const DataPoint & rOther ) : + impl::DataPoint_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + 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 ____ +uno::Any DataPoint::GetDefaultValue( sal_Int32 nHandle ) 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" ); + return uno::Any(); + } + + return 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::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL DataPoint::getPropertySetInfo() +{ + return *StaticDataPointInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL DataPoint::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL DataPoint::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 000000000..de3e50203 --- /dev/null +++ b/chart2/source/model/main/DataPoint.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINT_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINT_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; + bool m_bNoParentPropAllowed; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINT_HXX +#endif + +/* 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 000000000..dba488fdd --- /dev/null +++ b/chart2/source/model/main/DataPointProperties.cxx @@ -0,0 +1,540 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillColor", + PROP_DATAPOINT_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Transparency", + PROP_DATAPOINT_TRANSPARENCY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillTransparence", + PROP_DATAPOINT_TRANSPARENCY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // Fill Properties + rOutProperties.emplace_back( "FillStyle", + PROP_DATAPOINT_FILL_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TransparencyGradientName", + PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillTransparenceGradientName", + PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GradientName", + PROP_DATAPOINT_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillGradientName", + PROP_DATAPOINT_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GradientStepCount", + PROP_DATAPOINT_GRADIENT_STEPCOUNT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillGradientStepCount", + PROP_DATAPOINT_GRADIENT_STEPCOUNT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HatchName", + PROP_DATAPOINT_HATCH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillHatchName", + PROP_DATAPOINT_HATCH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillBitmapName", + PROP_DATAPOINT_FILL_BITMAP_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillBackground", + PROP_DATAPOINT_FILL_BACKGROUND, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + // border for filled objects + rOutProperties.emplace_back( "BorderColor", + PROP_DATAPOINT_BORDER_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderStyle", + PROP_DATAPOINT_BORDER_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderWidth", + PROP_DATAPOINT_BORDER_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "BorderDashName", + PROP_DATAPOINT_BORDER_DASH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "BorderTransparency", + PROP_DATAPOINT_BORDER_TRANSPARENCY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Line Properties + + rOutProperties.emplace_back( "LineColor", + PROP_DATAPOINT_BORDER_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineStyle", + LinePropertiesHelper::PROP_LINE_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineWidth", + LinePropertiesHelper::PROP_LINE_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineDash", + LinePropertiesHelper::PROP_LINE_DASH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineDashName", + LinePropertiesHelper::PROP_LINE_DASH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineTransparence", + PROP_DATAPOINT_BORDER_TRANSPARENCY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineCap", + ::chart::LinePropertiesHelper::PROP_LINE_CAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // FillProperties + // bitmap properties + rOutProperties.emplace_back( "FillBitmapOffsetX", + FillProperties::PROP_FILL_BITMAP_OFFSETX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapOffsetY", + FillProperties::PROP_FILL_BITMAP_OFFSETY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetX", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetY", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapRectanglePoint", + FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapLogicalSize", + FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeX", + FillProperties::PROP_FILL_BITMAP_SIZEX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeY", + FillProperties::PROP_FILL_BITMAP_SIZEY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapMode", + FillProperties::PROP_FILL_BITMAP_MODE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // others + rOutProperties.emplace_back( "Symbol", + PROP_DATAPOINT_SYMBOL_PROP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Offset", + PROP_DATAPOINT_OFFSET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Geometry3D", + PROP_DATAPOINT_GEOMETRY3D, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_DATAPOINT_NUMBER_FORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT, + PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + //additional 'PercentageNumberFormat' + rOutProperties.emplace_back( "PercentageNumberFormat", + PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LabelPlacement", + PROP_DATAPOINT_LABEL_PLACEMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "TextRotation", + PROP_DATAPOINT_TEXT_ROTATION, + cppu::UnoType::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::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ShowErrorBox", + PROP_DATAPOINT_SHOW_ERROR_BOX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "PercentDiagonal", + PROP_DATAPOINT_PERCENT_DIAGONAL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Properties specific to data label. + + rOutProperties.emplace_back( CHART_UNONAME_LABEL, + PROP_DATAPOINT_LABEL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextWordWrap", + PROP_DATAPOINT_TEXT_WORD_WRAP, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_SEP, + PROP_DATAPOINT_LABEL_SEPARATOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_STYLE, + PROP_DATAPOINT_LABEL_BORDER_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_COLOR, + PROP_DATAPOINT_LABEL_BORDER_COLOR, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_COLOR, + PROP_DATAPOINT_LABEL_FILL_COLOR, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_HATCH_NAME, + PROP_DATAPOINT_LABEL_FILL_HATCH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_WIDTH, + PROP_DATAPOINT_LABEL_BORDER_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASH, + PROP_DATAPOINT_LABEL_BORDER_DASH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASHNAME, + PROP_DATAPOINT_LABEL_BORDER_DASH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_TRANS, + PROP_DATAPOINT_LABEL_BORDER_TRANS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_CUSTOM_LABEL_FIELDS, + PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, + cppu::UnoType>>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( "CustomLabelPosition", + PROP_DATAPOINT_LABEL_CUSTOM_POS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +void DataPointProperties::AddDefaultsToMap( + ::chart::tPropertyValueMap & rOutMap ) +{ + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATAPOINT_COLOR, 0x0099ccff ); // blue 8 + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_DATAPOINT_TRANSPARENCY, 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< sal_Int32 >( rOutMap, PROP_DATAPOINT_BORDER_COLOR, 0x000000 ); // black + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_STYLE, drawing::LineStyle_SOLID ); // drawing::LineStyle_NONE + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DATAPOINT_BORDER_WIDTH, 0 ); + PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_DASH_NAME ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_DATAPOINT_BORDER_TRANSPARENCY, 0 ); + + //line + PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_SOLID ); + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, LinePropertiesHelper::PROP_LINE_WIDTH, 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< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE ); + PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true ); + + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, 0 ); + PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, 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 = 0x000000; // Black + aSymbProp.FillColor = 0xee4000; // OrangeRed2 + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_SYMBOL_PROP, aSymbProp ); + + PropertyHelper::setPropertyValueDefault< double >( 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< sal_Int16 >( rOutMap, PROP_DATAPOINT_PERCENT_DIAGONAL, 0 ); + + PropertyHelper::setPropertyValueDefault< double >( 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 + )); + + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TEXT_WORD_WRAP, false ); + PropertyHelper::setPropertyValueDefault< OUString >( rOutMap, PROP_DATAPOINT_LABEL_SEPARATOR, " " ); + PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_STYLE, sal_Int32(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, 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, 0); + + uno::Sequence> 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 000000000..1998c4e20 --- /dev/null +++ b/chart2/source/model/main/DataPointProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINTPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINTPROPERTIES_HXX + +#include +#include + +#include + +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 + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATAPOINTPROPERTIES_HXX +#endif + +/* 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 000000000..5c0ded40c --- /dev/null +++ b/chart2/source/model/main/DataSeries.cxx @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "DataSeriesProperties.hxx" +#include "DataPointProperties.hxx" +#include +#include +#include "DataPoint.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 +{ + +struct StaticDataSeriesDefaults : public rtl::StaticWithInit< ::chart::tPropertyValueMap, StaticDataSeriesDefaults > +{ + ::chart::tPropertyValueMap operator()() + { + ::chart::tPropertyValueMap aStaticDefaults; + ::chart::DataSeriesProperties::AddDefaultsToMap( aStaticDefaults ); + ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults ); + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( aStaticDefaults, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + return aStaticDefaults; + } +}; + +struct StaticDataSeriesInfoHelper : public rtl::StaticWithInit< ::cppu::OPropertyArrayHelper, StaticDataSeriesInfoHelper, StaticDataSeriesInfoHelper, uno::Sequence< Property > > +{ + uno::Sequence< Property > operator()() + { + 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 ); + } +}; + +struct StaticDataSeriesInfo : public rtl::StaticWithInit< uno::Reference< beans::XPropertySetInfo >, StaticDataSeriesInfo > +{ + uno::Reference< beans::XPropertySetInfo > operator()() + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper::get() ); + } +}; + +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() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ +} + +DataSeries::DataSeries( const DataSeries & rOther ) : + impl::DataSeries_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + if( ! rOther.m_aDataSequences.empty()) + { + CloneHelper::CloneRefVector( + rOther.m_aDataSequences, m_aDataSequences ); + ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder ); + } + + CloneHelper::CloneRefVector< chart2::XRegressionCurve >( 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 ) +{ + if( ! rOther.m_aDataSequences.empty()) + EventListenerHelper::addListenerToAllElements( m_aDataSequences, this ); + + 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() +{ + DataSeries * pNewSeries( new DataSeries( *this )); + // hold a reference to the clone + uno::Reference< util::XCloneable > xResult( pNewSeries ); + // do initialization that uses uno references to the clone + pNewSeries->Init( *this ); + + return xResult; +} + +// ____ OPropertySet ____ +uno::Any DataSeries::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = StaticDataSeriesDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper() +{ + return StaticDataSeriesInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo() +{ + return StaticDataSeriesInfo::get(); +} + +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; + + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences; + { + MutexGuard aGuard( m_aMutex ); + aSequences = comphelper::containerToSequence( m_aDataSequences ); + } + + std::vector< 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; + Reference< lang::XEventListener > xListener; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + xListener = this; + std::swap( aOldDataSequences, m_aDataSequences ); + aNewDataSequences = comphelper::sequenceToContainer( aData ); + m_aDataSequences = aNewDataSequences; + } + ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); + EventListenerHelper::removeListenerFromAllElements( aOldDataSequences, xListener ); + EventListenerHelper::addListenerToAllElements( aNewDataSequences, xListener ); + ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ XDataSource ____ +Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences() +{ + MutexGuard aGuard( m_aMutex ); + return comphelper::containerToSequence( m_aDataSequences ); +} + +// ____ XRegressionCurveContainer ____ +void SAL_CALL DataSeries::addRegressionCurve( + const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve ) +{ + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + if( std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) + != m_aRegressionCurves.end()) + throw lang::IllegalArgumentException(); + m_aRegressionCurves.push_back( xRegressionCurve ); + } + ModifyListenerHelper::addListener( xRegressionCurve, xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL DataSeries::removeRegressionCurve( + const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve ) +{ + if( !xRegressionCurve.is() ) + throw container::NoSuchElementException(); + + Reference< util::XModifyListener > xModifyEventForwarder; + { + MutexGuard aGuard( m_aMutex ); + xModifyEventForwarder = m_xModifyEventForwarder; + tRegressionCurveContainerType::iterator aIt( + std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), xRegressionCurve ) ); + 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( xRegressionCurve, xModifyEventForwarder ); + fireModifyEvent(); +} + +uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves() +{ + MutexGuard aGuard( m_aMutex ); + return comphelper::containerToSequence( m_aRegressionCurves ); +} + +void SAL_CALL DataSeries::setRegressionCurves( + const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves ) +{ + tRegressionCurveContainerType aOldCurves; + auto aNewCurves( comphelper::sequenceToContainer( aRegressionCurves ) ); + 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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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& rEventObject ) +{ + // forget disposed data sequences + tDataSequenceContainer::iterator aIt( + std::find( m_aDataSequences.begin(), m_aDataSequences.end(), rEventObject.Source )); + if( aIt != m_aDataSequences.end()) + m_aDataSequences.erase( aIt ); +} + +// ____ 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" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart_DataSeries_get_implementation(css::uno::XComponentContext *, + css::uno::Sequence 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 000000000..5d0cb777e --- /dev/null +++ b/chart2/source/model/main/DataSeriesProperties.cxx @@ -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 . + */ + +#include "DataSeriesProperties.hxx" +#include "DataPointProperties.hxx" +#include +#include + +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>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "StackingDirection", + PROP_DATASERIES_STACKING_DIRECTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "VaryColorsByPoint", + PROP_DATASERIES_VARY_COLORS_BY_POINT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "AttachedAxisIndex", + PROP_DATASERIES_ATTACHED_AXIS_INDEX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ShowLegendEntry", + PROP_DATASERIES_SHOW_LEGEND_ENTRY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "DeletedLegendEntries", + PROP_DATASERIES_DELETED_LEGEND_ENTRIES, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // 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< sal_Int32 >( rOutMap, PROP_DATASERIES_ATTACHED_AXIS_INDEX, 0 ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_LEGEND_ENTRY, 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/DataSeriesProperties.hxx b/chart2/source/model/main/DataSeriesProperties.hxx new file mode 100644 index 000000000..331396b49 --- /dev/null +++ b/chart2/source/model/main/DataSeriesProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATASERIESPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATASERIESPROPERTIES_HXX + +#include +#include + +#include + +namespace com::sun::star::beans { struct Property; } + +namespace chart +{ + +namespace 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 + }; + + void AddPropertiesToVector( + std::vector< css::beans::Property > & rOutProperties ); + + void AddDefaultsToMap( tPropertyValueMap & rOutMap ); +} + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_DATASERIESPROPERTIES_HXX +#endif + +/* 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 000000000..0b9efc80f --- /dev/null +++ b/chart2/source/model/main/Diagram.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 +#include +#include "Wall.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans::PropertyAttribute; + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativeSize", + PROP_DIAGRAM_REL_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "PosSizeExcludeAxes", + PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_SORT_BY_XVALUES, + PROP_DIAGRAM_SORT_BY_X_VALUES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ConnectBars", + PROP_DIAGRAM_CONNECT_BARS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GroupBarsPerAxis", + PROP_DIAGRAM_GROUP_BARS_PER_AXIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "IncludeHiddenCells", + PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "StartingAngle", + PROP_DIAGRAM_STARTING_ANGLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "RightAngledAxes", + PROP_DIAGRAM_RIGHT_ANGLED_AXES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Perspective", + PROP_DIAGRAM_PERSPECTIVE, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationHorizontal", + PROP_DIAGRAM_ROTATION_HORIZONTAL, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RotationVertical", + PROP_DIAGRAM_ROTATION_VERTICAL, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MissingValueTreatment", + PROP_DIAGRAM_MISSING_VALUE_TREATMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "3DRelativeHeight", + PROP_DIAGRAM_3DRELATIVEHEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "DataTableHBorder", + PROP_DIAGRAM_DATATABLEHBORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableVBorder", + PROP_DIAGRAM_DATATABLEVBORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DataTableOutline", + PROP_DIAGRAM_DATATABLEOUTLINE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ExternalData", + PROP_DIAGRAM_EXTERNALDATA, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticDiagramDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_SORT_BY_X_VALUES, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_CONNECT_BARS, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_GROUP_BARS_PER_AXIS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_RIGHT_ANGLED_AXES, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_DATATABLEHBORDER, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_DATATABLEVBORDER, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_DATATABLEOUTLINE, false ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DIAGRAM_STARTING_ANGLE, 90 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DIAGRAM_3DRELATIVEHEIGHT, 100 ); + ::chart::SceneProperties::AddDefaultsToMap( rOutMap ); + } +}; + +struct StaticDiagramDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticDiagramDefaults_Initializer > +{ +}; + +struct StaticDiagramInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticDiagramInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticDiagramInfoHelper_Initializer > +{ +}; + +struct StaticDiagramInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticDiagramInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticDiagramInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticDiagramInfo_Initializer > +{ +}; + +/// clones a UNO-sequence of UNO-References +typedef Reference< chart2::XCoordinateSystem > lcl_tCooSysRef; +typedef std::vector< lcl_tCooSysRef > lcl_tCooSysVector; + +void lcl_CloneCoordinateSystems( + const lcl_tCooSysVector & rSource, + lcl_tCooSysVector & rDestination ) +{ + for( auto const & i : rSource ) + { + lcl_tCooSysRef xClone; + css::uno::Reference< css::util::XCloneable > xCloneable( i, css::uno::UNO_QUERY ); + if( xCloneable.is()) + xClone.set( xCloneable->createClone(), css::uno::UNO_QUERY ); + + if( xClone.is()) + { + rDestination.push_back( xClone ); + } + else + rDestination.push_back( i ); + } +} + +} // anonymous namespace + +namespace chart +{ + +Diagram::Diagram( uno::Reference< uno::XComponentContext > const & xContext ) : + ::property::OPropertySet( m_aMutex ), + m_xContext( xContext ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + // 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( + SceneProperties::PROP_SCENE_CAMERA_GEOMETRY, uno::Any( + ThreeDHelper::getDefaultCameraGeometry())); +} + +Diagram::Diagram( const Diagram & rOther ) : + impl::Diagram_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xContext( rOther.m_xContext ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + lcl_CloneCoordinateSystems( rOther.m_aCoordSystems, m_aCoordSystems ); + ModifyListenerHelper::addListenerToAllElements( m_aCoordSystems, m_xModifyEventForwarder ); + + m_xWall.set( CloneHelper::CreateRefClone< beans::XPropertySet >()( rOther.m_xWall )); + m_xFloor.set( CloneHelper::CreateRefClone< beans::XPropertySet >()( rOther.m_xFloor )); + m_xTitle.set( CloneHelper::CreateRefClone< chart2::XTitle >()( rOther.m_xTitle )); + m_xLegend.set( CloneHelper::CreateRefClone< chart2::XLegend >()( rOther.m_xLegend )); + + ModifyListenerHelper::addListener( m_xWall, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xFloor, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder ); + ModifyListenerHelper::addListener( m_xLegend, m_xModifyEventForwarder ); +} + +Diagram::~Diagram() +{ + try + { + ModifyListenerHelper::removeListenerFromAllElements( m_aCoordSystems, m_xModifyEventForwarder ); + + ModifyListenerHelper::removeListener( m_xWall, m_xModifyEventForwarder ); + ModifyListenerHelper::removeListener( m_xFloor, 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() +{ + uno::Reference< beans::XPropertySet > xRet; + bool bAddListener = false; + { + MutexGuard aGuard( m_aMutex ); + if( !m_xWall.is() ) + { + m_xWall.set( new Wall() ); + bAddListener = true; + } + xRet = m_xWall; + } + if(bAddListener) + ModifyListenerHelper::addListener( xRet, m_xModifyEventForwarder ); + return xRet; +} + +uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getFloor() +{ + uno::Reference< beans::XPropertySet > xRet; + bool bAddListener = false; + { + MutexGuard aGuard( m_aMutex ); + if( !m_xFloor.is() ) + { + m_xFloor.set( new Wall() ); + bAddListener = true; + } + xRet = m_xFloor; + } + if(bAddListener) + ModifyListenerHelper::addListener( xRet, m_xModifyEventForwarder ); + return xRet; +} + +uno::Reference< chart2::XLegend > SAL_CALL Diagram::getLegend() +{ + MutexGuard aGuard( m_aMutex ); + return m_xLegend; +} + +void SAL_CALL Diagram::setLegend( const uno::Reference< chart2::XLegend >& xNewLegend ) +{ + Reference< chart2::XLegend > 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 ) +{ + uno::Reference< lang::XMultiServiceFactory > xChartTypeManager( m_xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.ChartTypeManager", m_xContext ), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram( this, xChartTypeManager ); + uno::Reference< chart2::XChartTypeTemplate > xTemplate( aTemplateAndService.first ); + if( !xTemplate.is() ) + xTemplate.set( xChartTypeManager->createInstance( "com.sun.star.chart2.template.Column" ), uno::UNO_QUERY ); + if(!xTemplate.is()) + return; + xTemplate->changeDiagramData( 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() +{ + ThreeDHelper::set3DSettingsToDefault( this ); +} + +void SAL_CALL Diagram::setDefaultRotation() +{ + ThreeDHelper::setDefaultRotation( this ); +} + +void SAL_CALL Diagram::setDefaultIllumination() +{ + ThreeDHelper::setDefaultIllumination( this ); +} + +// ____ XCoordinateSystemContainer ____ +void SAL_CALL Diagram::addCoordinateSystem( + const uno::Reference< chart2::XCoordinateSystem >& aCoordSys ) +{ + { + MutexGuard aGuard( m_aMutex ); + if( std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), aCoordSys ) + != m_aCoordSystems.end()) + throw lang::IllegalArgumentException(); + + if( !m_aCoordSystems.empty() ) + { + OSL_FAIL( "more than one coordinatesystem is not supported yet by the fileformat" ); + return; + } + m_aCoordSystems.push_back( aCoordSys ); + } + ModifyListenerHelper::addListener( aCoordSys, m_xModifyEventForwarder ); + fireModifyEvent(); +} + +void SAL_CALL Diagram::removeCoordinateSystem( + const uno::Reference< chart2::XCoordinateSystem >& aCoordSys ) +{ + { + MutexGuard aGuard( m_aMutex ); + std::vector< uno::Reference< chart2::XCoordinateSystem > >::iterator + aIt( std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), aCoordSys )); + 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( 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" ); + aNew.push_back( aCoordinateSystems[0] ); + } + { + MutexGuard aGuard( m_aMutex ); + std::swap( aOld, m_aCoordSystems ); + m_aCoordSystems = aNew; + } + ModifyListenerHelper::removeListenerFromAllElements( aOld, m_xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( aNew, 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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL Diagram::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 ____ +uno::Any Diagram::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticDiagramDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL Diagram::getInfoHelper() +{ + return *StaticDiagramInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Diagram::getPropertySetInfo() +{ + return *StaticDiagramInfo::get(); +} + +// ____ XFastPropertySet ____ +void SAL_CALL Diagram::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue ) +{ + //special treatment for some 3D properties + if( nHandle == PROP_DIAGRAM_PERSPECTIVE ) + { + sal_Int32 fPerspective = 20; + if( rValue >>=fPerspective ) + ThreeDHelper::setCameraDistance( this, 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; + ThreeDHelper::getRotationFromDiagram( this, nHorizontal, nVertical ); + if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL ) + nHorizontal = nNewAngleDegree; + else + nVertical = nNewAngleDegree; + ThreeDHelper::setRotationToDiagram( this, nHorizontal, nVertical ); + } + } + else + ::property::OPropertySet::setFastPropertyValue( 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( + ThreeDHelper::getCameraDistance( const_cast< Diagram* >( this ) ) ) ); + rValue <<= nPerspective; + } + else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL + || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL ) + { + sal_Int32 nHorizontal, nVertical; + ThreeDHelper::getRotationFromDiagram( const_cast< Diagram* >( this ), 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 ); +} + +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" }; +} + +} // 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 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 000000000..0d6e733a2 --- /dev/null +++ b/chart2/source/model/main/FormattedString.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 "FormattedString.hxx" + +#include +#include +#include +#include +#include + +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 +{ + +struct StaticFormattedStringDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::CharacterProperties::AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +}; + +struct StaticFormattedStringDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticFormattedStringDefaults_Initializer > +{ +}; + +struct StaticFormattedStringInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + ::chart::CharacterProperties::AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticFormattedStringInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticFormattedStringInfoHelper_Initializer > +{ +}; + +struct StaticFormattedStringInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticFormattedStringInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticFormattedStringInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticFormattedStringInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +FormattedString::FormattedString() : + ::property::OPropertySet( m_aMutex ), + m_aString(), + m_aType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT), + m_aGuid(), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +FormattedString::FormattedString( const FormattedString & rOther ) : + impl::FormattedString_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_aString( rOther.m_aString ), + m_aType(rOther.m_aType), + m_aGuid(rOther.m_aGuid), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +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(); + +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL FormattedString::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL FormattedString::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 ____ +uno::Any FormattedString::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticFormattedStringDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL FormattedString::getInfoHelper() +{ + return *StaticFormattedStringInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL FormattedString::getPropertySetInfo() +{ + return *StaticFormattedStringInfo::get(); +} + +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 const &) +{ + return cppu::acquire(new ::chart::FormattedString); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/FormattedString.hxx b/chart2/source/model/main/FormattedString.hxx new file mode 100644 index 000000000..9d17d5f38 --- /dev/null +++ b/chart2/source/model/main/FormattedString.hxx @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_MODEL_MAIN_FORMATTEDSTRING_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_FORMATTEDSTRING_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 MutexContainer, + 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& p2) override + { ::property::OPropertySet::addPropertyChangeListener(p1, p2); } + virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference& p2) override + { ::property::OPropertySet::removePropertyChangeListener(p1, p2); } + virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference& p2) override + { ::property::OPropertySet::addVetoableChangeListener(p1, p2); } + virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference& p2) override + { ::property::OPropertySet::removeVetoableChangeListener(p1, p2); } + +private: + 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; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + void fireModifyEvent(); + + // ____ XFormattedString ____ + OUString m_aString; + + // ____ XDataPointCustomLabelField ____ + css::chart2::DataPointCustomLabelFieldType m_aType; + OUString m_aGuid; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_FORMATTEDSTRING_HXX +#endif + +/* 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 000000000..44d3fffd8 --- /dev/null +++ b/chart2/source/model/main/GridProperties.cxx @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticGridDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_GRID_SHOW, false ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( + rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_COLOR, 0xb3b3b3 ); // gray30 + } +}; + +struct StaticGridDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticGridDefaults_Initializer > +{ +}; + +struct StaticGridInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticGridInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticGridInfoHelper_Initializer > +{ +}; + +struct StaticGridInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticGridInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticGridInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticGridInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +GridProperties::GridProperties() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +GridProperties::GridProperties( const GridProperties & rOther ) : + impl::GridProperties_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ +} + +GridProperties::~GridProperties() +{} + +// ____ OPropertySet ____ +uno::Any GridProperties::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticGridDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL GridProperties::getInfoHelper() +{ + return *StaticGridInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL GridProperties::getPropertySetInfo() +{ + return *StaticGridInfo::get(); +} + +// ____ 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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL GridProperties::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 const &) +{ + return cppu::acquire(new ::chart::GridProperties); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/GridProperties.hxx b/chart2/source/model/main/GridProperties.hxx new file mode 100644 index 000000000..38d1f9a74 --- /dev/null +++ b/chart2/source/model/main/GridProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_GRIDPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_GRIDPROPERTIES_HXX + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + GridProperties_Base; +} + +class GridProperties final : + public MutexContainer, + public impl::GridProperties_Base, + public ::property::OPropertySet +{ +public: + explicit GridProperties(); + 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() + +private: + explicit GridProperties( const GridProperties & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_GRIDPROPERTIES_HXX +#endif + +/* 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 000000000..4c3b9f0e5 --- /dev/null +++ b/chart2/source/model/main/Legend.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 "Legend.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Expansion", + PROP_LEGEND_EXPANSION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Show", + PROP_LEGEND_SHOW, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "Overlay", + PROP_LEGEND_OVERLAY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_LEGEND_REF_PAGE_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativePosition", + PROP_LEGEND_REL_POS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativeSize", + PROP_LEGEND_REL_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + +} + +struct StaticLegendDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + ::chart::CharacterProperties::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_ANCHOR_POSITION, chart2::LegendPosition_LINE_END ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_EXPANSION, css::chart::ChartLegendExpansion_HIGH ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_SHOW, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LEGEND_OVERLAY, false ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + } +}; + +struct StaticLegendDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticLegendDefaults_Initializer > +{ +}; + +struct StaticLegendInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticLegendInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticLegendInfoHelper_Initializer > +{ +}; + +struct StaticLegendInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticLegendInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticLegendInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticLegendInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Legend::Legend() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ +} + +Legend::Legend( const Legend & rOther ) : + impl::Legend_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ +} + +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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL Legend::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 ____ +Any Legend::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticLegendDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Legend::getInfoHelper() +{ + return *StaticLegendInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL Legend::getPropertySetInfo() +{ + return *StaticLegendInfo::get(); +} + +// 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 const &) +{ + return cppu::acquire(new ::chart::Legend); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Legend.hxx b/chart2/source/model/main/Legend.hxx new file mode 100644 index 000000000..516324f2e --- /dev/null +++ b/chart2/source/model/main/Legend.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_LEGEND_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_LEGEND_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 Legend final : + public MutexContainer, + 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() + +private: + explicit Legend( const Legend & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_LEGEND_HXX +#endif + +/* 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 000000000..5dda4cb5a --- /dev/null +++ b/chart2/source/model/main/PageBackground.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 "PageBackground.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticPageBackgroundDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( rOutMap, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticPageBackgroundDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticPageBackgroundDefaults_Initializer > +{ +}; + +struct StaticPageBackgroundInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticPageBackgroundInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticPageBackgroundInfoHelper_Initializer > +{ +}; + +struct StaticPageBackgroundInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticPageBackgroundInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticPageBackgroundInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticPageBackgroundInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +PageBackground::PageBackground() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +PageBackground::PageBackground( const PageBackground & rOther ) : + impl::PageBackground_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +PageBackground::~PageBackground() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL PageBackground::createClone() +{ + return uno::Reference< util::XCloneable >( new PageBackground( *this )); +} + +// ____ OPropertySet ____ +uno::Any PageBackground::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticPageBackgroundDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL PageBackground::getInfoHelper() +{ + return *StaticPageBackgroundInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PageBackground::getPropertySetInfo() +{ + return *StaticPageBackgroundInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL PageBackground::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL PageBackground::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 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 000000000..9157eb9d9 --- /dev/null +++ b/chart2/source/model/main/PageBackground.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_PAGEBACKGROUND_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_PAGEBACKGROUND_HXX + +#include +#include +#include +#include +#include +#include +#include + +#include + +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 MutexContainer, + 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() + +private: + explicit PageBackground( const PageBackground & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_PAGEBACKGROUND_HXX +#endif + +/* 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 000000000..f6780bbb5 --- /dev/null +++ b/chart2/source/model/main/PolarCoordinateSystem.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 +#include +#include + +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 +{ + +static const char CHART2_COOSYSTEM_POLAR_SERVICE_NAME[] = "com.sun.star.chart2.CoordinateSystems.Polar"; + +} + +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 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 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 000000000..22e082ad0 --- /dev/null +++ b/chart2/source/model/main/StockBar.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 +{ + +struct StaticStockBarInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticStockBarInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticStockBarInfoHelper_Initializer > +{ +}; + +struct StaticStockBarInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticStockBarInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticStockBarInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticStockBarInfo_Initializer > +{ +}; + +struct StaticStockBarDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( rOutMap, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); // white + } +}; + +struct StaticStockBarDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticStockBarDefaults_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +StockBar::StockBar( bool bRisingCourse ) : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + 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_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +StockBar::~StockBar() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL StockBar::createClone() +{ + return uno::Reference< util::XCloneable >( new StockBar( *this )); +} + +// ____ OPropertySet ____ +uno::Any StockBar::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticStockBarDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL StockBar::getInfoHelper() +{ + return *StaticStockBarInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL StockBar::getPropertySetInfo() +{ + return *StaticStockBarInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL StockBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL StockBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 000000000..a42374ce5 --- /dev/null +++ b/chart2/source/model/main/Title.cxx @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaLastLineAdjust", + PROP_TITLE_PARA_LAST_LINE_ADJUST, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaLeftMargin", + PROP_TITLE_PARA_LEFT_MARGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaRightMargin", + PROP_TITLE_PARA_RIGHT_MARGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaTopMargin", + PROP_TITLE_PARA_TOP_MARGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaBottomMargin", + PROP_TITLE_PARA_BOTTOM_MARGIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaIsHyphenation", + PROP_TITLE_PARA_IS_HYPHENATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + + rOutProperties.emplace_back( "Visible", + PROP_TITLE_VISIBLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "TextRotation", + PROP_TITLE_TEXT_ROTATION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "StackCharacters", + PROP_TITLE_TEXT_STACKED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "RelativePosition", + PROP_TITLE_REL_POS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_TITLE_REF_PAGE_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticTitleDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // ParagraphProperties + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_PARA_ADJUST, + css::style::ParagraphAdjust_CENTER ); + // PROP_TITLE_PARA_LAST_LINE_ADJUST + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_LEFT_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_RIGHT_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_TOP_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_TITLE_PARA_BOTTOM_MARGIN, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_PARA_IS_HYPHENATION, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_VISIBLE, true ); + + // own properties + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_TITLE_TEXT_ROTATION, 0.0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_TITLE_TEXT_STACKED, false ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticTitleDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticTitleDefaults_Initializer > +{ +}; + +struct StaticTitleInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticTitleInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticTitleInfoHelper_Initializer > +{ +}; + +struct StaticTitleInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticTitleInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticTitleInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticTitleInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Title::Title() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +Title::Title( const Title & rOther ) : + impl::Title_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + CloneHelper::CloneRefSequence( + rOther.m_aStrings, m_aStrings ); + ModifyListenerHelper::addListenerToAllElements( + comphelper::sequenceToContainer > >( m_aStrings ), + m_xModifyEventForwarder ); +} + +Title::~Title() +{ + ModifyListenerHelper::removeListenerFromAllElements( + comphelper::sequenceToContainer > >( 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 > >( aOldStrings ), + m_xModifyEventForwarder ); + ModifyListenerHelper::addListenerToAllElements( + comphelper::sequenceToContainer > >( rNewStrings ), + m_xModifyEventForwarder ); + fireModifyEvent(); +} + +// ____ OPropertySet ____ +uno::Any Title::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticTitleDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Title::getInfoHelper() +{ + return *StaticTitleInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Title::getPropertySetInfo() +{ + return *StaticTitleInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Title::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL Title::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 const &) +{ + return cppu::acquire(new ::chart::Title); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/main/Title.hxx b/chart2/source/model/main/Title.hxx new file mode 100644 index 000000000..9326b54b2 --- /dev/null +++ b/chart2/source/model/main/Title.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_TITLE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_TITLE_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 Title final : + public MutexContainer, + 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() + +private: + explicit Title( const Title & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_TITLE_HXX +#endif + +/* 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 000000000..f295bc288 --- /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 + +#include +#include +#include + +#include +#include +#include +#include + +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, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ) + :m_rAntiImpl( i_antiImpl ) + ,m_rParent( i_parent ) + ,m_rMutex( i_mutex ) + ,m_bDisposed( false ) + ,m_aUndoManager() + ,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 + ::cppu::OWeakObject& 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; + ::cppu::OWeakObject& 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( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ) + :m_pImpl( new impl::UndoManager_Impl( *this, i_parent, i_mutex ) ) + { + } + + UndoManager::~UndoManager() + { + } + + void SAL_CALL UndoManager::acquire() throw () + { + m_pImpl->getParent().acquire(); + } + + void SAL_CALL UndoManager::release() throw () + { + 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( Reference< XModel >( getParent(), UNO_QUERY ) ); + } + + void SAL_CALL UndoManager::redo( ) + { + UndoManagerMethodGuard aGuard( *m_pImpl ); + m_pImpl->getUndoHelper().redo( aGuard ); + + ChartViewHelper::setViewToDirtyState( Reference< XModel >( getParent(), UNO_QUERY ) ); + } + + 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 000000000..c599113d4 --- /dev/null +++ b/chart2/source/model/main/UndoManager.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_UNDOMANAGER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_UNDOMANAGER_HXX + +#include +#include + +#include + +#include + +namespace chart +{ + + namespace impl + { + class UndoManager_Impl; + typedef ::cppu::ImplHelper2 < css::document::XUndoManager + , css::util::XModifyBroadcaster + > UndoManager_Base; + } + + class UndoManager : public impl::UndoManager_Base + { + public: + UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex ); + virtual ~UndoManager(); + + // XInterface + virtual void SAL_CALL acquire( ) throw () override; + virtual void SAL_CALL release( ) throw () 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 + +#endif // INCLUDED_CHART2_SOURCE_MODEL_MAIN_UNDOMANAGER_HXX + +/* 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 000000000..5ba8aaf18 --- /dev/null +++ b/chart2/source/model/main/Wall.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 "Wall.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticWallDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + } +}; + +struct StaticWallDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticWallDefaults_Initializer > +{ +}; + +struct StaticWallInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticWallInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticWallInfoHelper_Initializer > +{ +}; + +struct StaticWallInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticWallInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticWallInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticWallInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +Wall::Wall() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +Wall::Wall( const Wall & rOther ) : + impl::Wall_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{} + +Wall::~Wall() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL Wall::createClone() +{ + return uno::Reference< util::XCloneable >( new Wall( *this )); +} + +// ____ OPropertySet ____ +uno::Any Wall::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticWallDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL Wall::getInfoHelper() +{ + return *StaticWallInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL Wall::getPropertySetInfo() +{ + return *StaticWallInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL Wall::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL Wall::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 000000000..a3112a614 --- /dev/null +++ b/chart2/source/model/main/Wall.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_MAIN_WALL_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_MAIN_WALL_HXX + +#include +#include +#include +#include +#include + +#include +#include + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakImplHelper< + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::util::XModifyListener > + Wall_Base; +} + +class Wall final : + public MutexContainer, + public impl::Wall_Base, + public ::property::OPropertySet +{ +public: + Wall(); + virtual ~Wall() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + +private: + explicit Wall( const Wall & rOther ); + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + // ____ OPropertySet ____ + virtual void firePropertyChangeEvent() override; + using OPropertySet::disposing; + +private: + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_MAIN_WALL_HXX +#endif + +/* 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 000000000..840bdba03 --- /dev/null +++ b/chart2/source/model/template/AreaChartType.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 "AreaChartType.hxx" +#include +#include + +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 )); +} + +// ____ 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 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 000000000..acb76ef10 --- /dev/null +++ b/chart2/source/model/template/AreaChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPE_HXX + +#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; + +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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPE_HXX +#endif + +/* 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 000000000..401dc6971 --- /dev/null +++ b/chart2/source/model/template/AreaChartTypeTemplate.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticAreaChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aStaticDefaults, PROP_AREA_TEMPLATE_DIMENSION, 2 ); + return &aStaticDefaults; + } +}; + +struct StaticAreaChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticAreaChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticAreaChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticAreaChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticAreaChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticAreaChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticAreaChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticAreaChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticAreaChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +AreaChartTypeTemplate::AreaChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nDim /* = 2 */ ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ) +{ + setFastPropertyValue_NoBroadcast( PROP_AREA_TEMPLATE_DIMENSION, uno::Any( nDim )); +} + +AreaChartTypeTemplate::~AreaChartTypeTemplate() +{} + +// ____ OPropertySet ____ +uno::Any AreaChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticAreaChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL AreaChartTypeTemplate::getInfoHelper() +{ + return *StaticAreaChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL AreaChartTypeTemplate::getPropertySetInfo() +{ + return *StaticAreaChartTypeTemplateInfo::get(); +} + +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; +} + +// ____ XChartTypeTemplate ____ +void SAL_CALL AreaChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); +} + +void SAL_CALL AreaChartTypeTemplate::resetStyles( const Reference< chart2::XDiagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles( xDiagram ); + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + Reference< beans::XPropertyState > xState(series, uno::UNO_QUERY); + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY); + if( xState.is() && + xProp.is() && + xProp->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + xState->setPropertyToDefault( "BorderStyle"); + } + } +} + +Reference< chart2::XChartType > AreaChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_AREA ), uno::UNO_QUERY_THROW ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL AreaChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > 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 000000000..e56be9833 --- /dev/null +++ b/chart2/source/model/template/AreaChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include + +#include +#include +#include + +namespace chart +{ + +class AreaChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void SAL_CALL resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_AREACHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..87675e3f1 --- /dev/null +++ b/chart2/source/model/template/BarChartType.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 "BarChartType.hxx" +#include +#include + +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 )); +} + +// ____ XChartType ____ +OUString SAL_CALL BarChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_BAR; +} + +uno::Sequence< OUString > BarChartType::getSupportedPropertyRoles() +{ + uno::Sequence< OUString > aPropRoles(2); + aPropRoles[0] = "FillColor"; + aPropRoles[1] = "BorderColor"; + + return aPropRoles; +} + +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 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 000000000..4d090c783 --- /dev/null +++ b/chart2/source/model/template/BarChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPE_HXX + +#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; + +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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPE_HXX +#endif + +/* 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 000000000..dce1ffbb0 --- /dev/null +++ b/chart2/source/model/template/BarChartTypeTemplate.cxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Geometry3D", + PROP_BAR_TEMPLATE_GEOMETRY3D, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticBarChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_BAR_TEMPLATE_DIMENSION, 2 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BAR_TEMPLATE_GEOMETRY3D, ::chart2::DataPointGeometry3D::CUBOID ); + } +}; + +struct StaticBarChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBarChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticBarChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticBarChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBarChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticBarChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBarChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBarChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBarChartTypeTemplateInfo_Initializer > +{ +}; + +} // 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 ), + ::property::OPropertySet( m_aMutex ), + 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); +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL BarChartTypeTemplate::matchesTemplate( + const Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate( xDiagram, bAdaptProperties ); + + //check BarDirection + if( bResult ) + { + bool bFound = false; + bool bAmbiguous = false; + bool bVertical = DiagramHelper::getVertical( xDiagram, 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 = DiagramHelper::getGeometry3D( xDiagram, bGeomFound, bGeomAmbiguous ); + + if( !bGeomAmbiguous ) + { + setFastPropertyValue_NoBroadcast( + PROP_BAR_TEMPLATE_GEOMETRY3D, uno::Any( aCommonGeom )); + } + } + + return bResult; +} +Reference< chart2::XChartType > BarChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY_THROW ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL BarChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult( getChartTypeForIndex( 0 ) ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + return xResult; +} + +// ____ OPropertySet ____ +uno::Any BarChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBarChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL BarChartTypeTemplate::getInfoHelper() +{ + return *StaticBarChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL BarChartTypeTemplate::getPropertySetInfo() +{ + return *StaticBarChartTypeTemplateInfo::get(); +} + +void SAL_CALL BarChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( 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 SAL_CALL BarChartTypeTemplate::resetStyles( + const Reference< chart2::XDiagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles( xDiagram ); + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + Reference< beans::XPropertyState > xState(series, uno::UNO_QUERY); + if( xState.is()) + { + if( getDimension() == 3 ) + xState->setPropertyToDefault( "Geometry3D"); + Reference< beans::XPropertySet > xProp( xState, uno::UNO_QUERY ); + if( xProp.is() && + xProp->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + xState->setPropertyToDefault( "BorderStyle"); + } + } + } + + DiagramHelper::setVertical( xDiagram, false ); +} + +void BarChartTypeTemplate::createCoordinateSystems( + const Reference< chart2::XCoordinateSystemContainer > & xCooSysCnt ) +{ + ChartTypeTemplate::createCoordinateSystems( xCooSysCnt ); + + Reference< chart2::XDiagram > xDiagram( xCooSysCnt, uno::UNO_QUERY ); + DiagramHelper::setVertical( xDiagram, 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 000000000..593a1f7fe --- /dev/null +++ b/chart2/source/model/template/BarChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPETEMPLATE_HXX + +#include +#include +#include + +#include "ChartTypeTemplate.hxx" +#include + +namespace chart +{ + +class BarChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void SAL_CALL resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + 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 css::uno::Reference< css::chart2::XCoordinateSystemContainer > & xCooSysCnt ) override; + +private: + StackMode m_eStackMode; + BarDirection m_eBarDirection; + sal_Int32 m_nDim; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BARCHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..4abdbb826 --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.cxx @@ -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 . + */ + +#include "BubbleChartType.hxx" +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +struct StaticBubbleChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + return &aStaticDefaults; + } +}; + +struct StaticBubbleChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBubbleChartTypeDefaults_Initializer > +{ +}; + +struct StaticBubbleChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticBubbleChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBubbleChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticBubbleChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBubbleChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBubbleChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBubbleChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ XChartType ____ +Reference< chart2::XCoordinateSystem > SAL_CALL + BubbleChartType::createCoordinateSystem( ::sal_Int32 DimensionCount ) +{ + Reference< chart2::XCoordinateSystem > xResult( + new CartesianCoordinateSystem( DimensionCount )); + + for( sal_Int32 i=0; i xAxis( xResult->getAxisByDimension( 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() +{ + uno::Sequence< OUString > aMandRolesSeq(4); + aMandRolesSeq[0] = "label"; + aMandRolesSeq[1] = "values-x"; + aMandRolesSeq[2] = "values-y"; + aMandRolesSeq[3] = "values-size"; + return aMandRolesSeq; +} + +uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedPropertyRoles() +{ + uno::Sequence< OUString > aPropertyRoles(2); + aPropertyRoles[0] = "FillColor"; + aPropertyRoles[1] = "BorderColor"; + return aPropertyRoles; +} + +OUString SAL_CALL BubbleChartType::getRoleOfSequenceForSeriesLabel() +{ + return "values-size"; +} + +// ____ OPropertySet ____ +uno::Any BubbleChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBubbleChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartType::getInfoHelper() +{ + return *StaticBubbleChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartType::getPropertySetInfo() +{ + return *StaticBubbleChartTypeInfo::get(); +} + +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 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 000000000..e37a01ac2 --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPE_HXX + +#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; + +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 css::uno::Reference< css::chart2::XCoordinateSystem > SAL_CALL + createCoordinateSystem( ::sal_Int32 DimensionCount ) override; + virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPE_HXX +#endif + +/* 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 000000000..90ec1a75d --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.cxx @@ -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 . + */ + +#include "BubbleChartTypeTemplate.hxx" +#include "BubbleDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ + +struct StaticBubbleChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + return &aStaticDefaults; + } +}; + +struct StaticBubbleChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticBubbleChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticBubbleChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticBubbleChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticBubbleChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticBubbleChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticBubbleChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticBubbleChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticBubbleChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +BubbleChartTypeTemplate::BubbleChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ) +{ +} + +BubbleChartTypeTemplate::~BubbleChartTypeTemplate() +{} + +// ____ OPropertySet ____ +uno::Any BubbleChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticBubbleChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartTypeTemplate::getInfoHelper() +{ + return *StaticBubbleChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartTypeTemplate::getPropertySetInfo() +{ + return *StaticBubbleChartTypeTemplateInfo::get(); +} + +sal_Int32 BubbleChartTypeTemplate::getDimension() const +{ + return 2; +} + +StackMode BubbleChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return StackMode::NONE; +} + +void SAL_CALL BubbleChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL BubbleChartTypeTemplate::supportsCategories() +{ + return false; +} + +Reference< chart2::XChartType > BubbleChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ), uno::UNO_QUERY_THROW ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL BubbleChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ), uno::UNO_QUERY_THROW ); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XDataInterpreter > SAL_CALL BubbleChartTypeTemplate::getDataInterpreter() +{ + 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 000000000..b771d6f57 --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include +#include +#include + +namespace chart +{ + +class BubbleChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL supportsCategories() override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual css::uno::Reference< css::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLECHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..3078d3590 --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "BubbleDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +BubbleDataInterpreter::BubbleDataInterpreter() : + DataInterpreter() +{ +} + +BubbleDataInterpreter::~BubbleDataInterpreter() +{ +} + +// ____ XDataInterpreter ____ +chart2::InterpretedData SAL_CALL BubbleDataInterpreter::interpretDataSource( + const Reference< chart2::data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); + + Reference< data::XLabeledDataSequence > xValuesX; + vector< Reference< data::XLabeledDataSequence > > aYValuesVector; + vector< Reference< data::XLabeledDataSequence > > aSizeValuesVector; + + Reference< data::XLabeledDataSequence > xCategories; + bool bHasCategories = HasCategories( aArguments, aData ); + bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); + + sal_Int32 nDataSeqCount = aData.getLength(); + + 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.set( aData[nDataIdx] ); + if( xCategories.is()) + { + SetRole( xCategories->getValues(), "categories"); + if( bUseCategoriesAsX ) + { + bSetXValues = false; + bNextIsYValues = nDataSeqCount > 2; + } + } + bCategoriesUsed = true; + } + else if( !xValuesX.is() && bSetXValues ) + { + xValuesX.set( 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 + sal_Int32 nSeriesIndex = 0; + vector< Reference< XDataSeries > > 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 ) + { + vector< Reference< 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]); + + Reference< XDataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.getLength()) + xSeries.set( aSeriesToReUse[nSeriesIndex] ); + else + xSeries.set( new DataSeries ); + OSL_ASSERT( xSeries.is() ); + Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + OSL_ASSERT( xSink.is() ); + xSink->setData( comphelper::containerToSequence( aNewData ) ); + + aSeriesVec.push_back( xSeries ); + } + + Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); + aSeries[0] = comphelper::containerToSequence( aSeriesVec ); + return InterpretedData( aSeries, xCategories ); +} + +chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( + const chart2::InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.getLength(); + for( ; i xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; + + Reference< data::XLabeledDataSequence > xValuesSize( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-size" )); + Reference< data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-y" )); + Reference< data::XLabeledDataSequence > xValuesX( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-x" )); + + if( ! xValuesX.is() || + ! xValuesY.is() || + ! xValuesSize.is() ) + { + vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole( + xSeriesSource->getDataSequences(), "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.set( aValueSeqVec[nIndex++] ); + if( xValuesSize.is()) + SetRole( xValuesSize->getValues(), "values-size"); + } + + if( ! xValuesY.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesY.set( aValueSeqVec[nIndex++] ); + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + + if( ! xValuesX.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesX.set( aValueSeqVec[nIndex++] ); + if( xValuesX.is()) + SetRole( xValuesY->getValues(), "values-x"); + } + } + if( xValuesSize.is()) + { + if( xValuesY.is() ) + { + if( xValuesX.is() ) + { + aNewSequences.realloc(3); + aNewSequences[0] = xValuesX; + aNewSequences[1] = xValuesY; + aNewSequences[2] = xValuesSize; + } + else + { + aNewSequences.realloc(2); + aNewSequences[0] = xValuesY; + aNewSequences[1] = xValuesSize; + } + } + else + { + aNewSequences.realloc(1); + aNewSequences[0] = xValuesSize; + } + } + + const Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); + if( aSeqs.getLength() != aNewSequences.getLength() ) + { +#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 + Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); + xSink->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +sal_Bool SAL_CALL BubbleDataInterpreter::isDataCompatible( + const chart2::InterpretedData& aInterpretedData ) +{ + const Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( Reference< XDataSeries > const & dataSeries : aSeries ) + { + try + { + Reference< data::XDataSource > xSrc( dataSeries, uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + if( aSeq.getLength() != 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 000000000..43921262e --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLEDATAINTERPRETER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLEDATAINTERPRETER_HXX + +#include "DataInterpreter.hxx" + +namespace chart +{ + +class BubbleDataInterpreter : public DataInterpreter +{ +public: + explicit BubbleDataInterpreter(); + virtual ~BubbleDataInterpreter() override; + +protected: + // ____ XDataInterpreter ____ + virtual css::chart2::InterpretedData SAL_CALL interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aSeriesToReUse ) override; + virtual css::chart2::InterpretedData SAL_CALL reinterpretDataSeries( + const css::chart2::InterpretedData& aInterpretedData ) override; + virtual sal_Bool SAL_CALL isDataCompatible( + const css::chart2::InterpretedData& aInterpretedData ) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_BUBBLEDATAINTERPRETER_HXX +#endif + +/* 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 000000000..af0c1f04f --- /dev/null +++ b/chart2/source/model/template/CandleStickChartType.cxx @@ -0,0 +1,342 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "WhiteDay", + PROP_CANDLESTICKCHARTTYPE_WHITE_DAY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "BlackDay", + PROP_CANDLESTICKCHARTTYPE_BLACK_DAY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ShowFirst", + PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "ShowHighLow", + PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticCandleStickChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + // must match default in CTOR! + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_JAPANESE, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW, true ); + } +}; + +struct StaticCandleStickChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticCandleStickChartTypeDefaults_Initializer > +{ +}; + +struct StaticCandleStickChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticCandleStickChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticCandleStickChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticCandleStickChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticCandleStickChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticCandleStickChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticCandleStickChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ 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 ____ +uno::Any CandleStickChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticCandleStickChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL CandleStickChartType::getInfoHelper() +{ + return *StaticCandleStickChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL CandleStickChartType::getPropertySetInfo() +{ + return *StaticCandleStickChartTypeInfo::get(); +} + +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 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 000000000..b3f8d37ec --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CANDLESTICKCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CANDLESTICKCHARTTYPE_HXX + +#include "ChartType.hxx" + +namespace chart +{ + +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; + +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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CANDLESTICKCHARTTYPE_HXX +#endif + +/* 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 000000000..999f7c1ed --- /dev/null +++ b/chart2/source/model/template/ChartType.cxx @@ -0,0 +1,308 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + m_bNotifyChanges( true ) +{} + +ChartType::ChartType( const ChartType & rOther ) : + impl::ChartType_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + 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 ) +{ + Reference< chart2::XCoordinateSystem > xResult( + new CartesianCoordinateSystem( DimensionCount )); + + for( sal_Int32 i=0; i xAxis( xResult->getAxisByDimension( 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() +{ + Sequence< OUString > aDefaultSeq(2); + aDefaultSeq[0] = "label"; + aDefaultSeq[1] = "values-y"; + return aDefaultSeq; +} + +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 Reference< chart2::XDataSeries >& xDataSeries ) +{ + if( std::find( m_aDataSeries.begin(), m_aDataSeries.end(), xDataSeries ) + != m_aDataSeries.end()) + throw lang::IllegalArgumentException(); + + m_aDataSeries.push_back( xDataSeries ); + ModifyListenerHelper::addListener( xDataSeries, m_xModifyEventForwarder ); +} + +// ____ XDataSeriesContainer ____ +void SAL_CALL ChartType::addDataSeries( const Reference< chart2::XDataSeries >& xDataSeries ) +{ + SolarMutexGuard g; + + impl_addDataSeriesWithoutNotification( xDataSeries ); + fireModifyEvent(); +} + +void SAL_CALL ChartType::removeDataSeries( const Reference< chart2::XDataSeries >& xDataSeries ) +{ + if( !xDataSeries.is()) + throw container::NoSuchElementException(); + + SolarMutexGuard g; + + tDataSeriesContainerType::iterator 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( m_aDataSeries ); +} + +void SAL_CALL ChartType::setDataSeries( const Sequence< Reference< chart2::XDataSeries > >& aDataSeries ) +{ + SolarMutexGuard g; + + m_bNotifyChanges = false; + try + { + const Sequence< Reference< chart2::XDataSeries > > aOldSeries( getDataSeries() ); + for( auto const & i : aOldSeries ) + 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 ____ +uno::Any ChartType::GetDefaultValue( sal_Int32 /* nHandle */ ) const +{ + return uno::Any(); +} + +namespace +{ + +struct StaticChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( Sequence< beans::Property >{} ); + return &aPropHelper; + } +}; + +struct StaticChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticChartTypeInfo_Initializer > +{ +}; + +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL ChartType::getInfoHelper() +{ + return *StaticChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ChartType::getPropertySetInfo() +{ + return *StaticChartTypeInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL ChartType::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL ChartType::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->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/ChartType.hxx b/chart2/source/model/template/ChartType.hxx new file mode 100644 index 000000000..3274d5660 --- /dev/null +++ b/chart2/source/model/template/ChartType.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPE_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +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 ChartType : + public MutexContainer, + public impl::ChartType_Base, + public ::property::OPropertySet +{ +public: + explicit ChartType(); + virtual ~ChartType() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + +protected: + 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 ) 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; + + // ____ 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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: + css::uno::Reference< css::util::XModifyListener > + const m_xModifyEventForwarder; + +private: + void impl_addDataSeriesWithoutNotification( + const css::uno::Reference< css::chart2::XDataSeries >& aDataSeries ); + +private: + typedef + std::vector< css::uno::Reference< css::chart2::XDataSeries > > tDataSeriesContainerType; + + // --- mutable members: the following members need mutex guard --- + + tDataSeriesContainerType m_aDataSeries; + + bool m_bNotifyChanges; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPE_HXX +#endif + +/* 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 000000000..c0bcc0a03 --- /dev/null +++ b/chart2/source/model/template/ChartTypeManager.cxx @@ -0,0 +1,606 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 > const & xContext ) : + m_xContext( xContext ) +{} + +ChartTypeManager::~ChartTypeManager() +{} + +// ____ XMultiServiceFactory ____ +uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstance( + const OUString& aServiceSpecifier ) +{ + uno::Reference< uno::XInterface > xResult; + TemplateId nId = lcl_GetTemplateIdForService( aServiceSpecifier ); + + if( nId == TEMPLATE_NOT_FOUND ) + { + try + { + xResult = m_xContext->getServiceManager()->createInstanceWithContext( + aServiceSpecifier, m_xContext ); + } +// catch( registry::InvalidValueException & ex ) + catch( const uno::Exception & ) + { + // couldn't create service via factory + + // As XMultiServiceFactory does not specify, what to do in case + // createInstance is called with an unknown service-name, this + // function will just return an empty XInterface. + DBG_UNHANDLED_EXCEPTION("chart2"); + SAL_WARN("chart2", "Couldn't instantiate service: "<< aServiceSpecifier ); + xResult.set( nullptr ); + } + } + else + { + uno::Reference< chart2::XChartTypeTemplate > 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; + default: break; +// case TEMPLATE_SURFACE: +// case TEMPLATE_ADDIN: +// break; + + case TEMPLATE_NOT_FOUND: + OSL_ASSERT( false ); + break; + } + xResult.set( xTemplate, uno::UNO_QUERY ); + } + + return xResult; +} + +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 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 000000000..8aafc1fd1 --- /dev/null +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -0,0 +1,877 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; + +namespace +{ + +void lcl_applyDefaultStyle( + const Reference< XDataSeries > & xSeries, + sal_Int32 nIndex, + const Reference< XDiagram > & xDiagram ) +{ + // @deprecated: correct default color should be found by view without + // setting color as hard attribute + if( xSeries.is() && xDiagram.is()) + { + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xSeriesProp.is() && xColorScheme.is() ) + xSeriesProp->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 Reference< chart2::XDiagram >& xDiagram, const Reference< XChartType >& xChartType ) +{ + Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY ); + if( xDiaProp.is() ) + { + uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment( + ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) ); + + if( aAvailableMissingValueTreatment.hasElements() ) + xDiaProp->setPropertyValue( "MissingValueTreatment", uno::Any( aAvailableMissingValueTreatment[0] ) ); + else + xDiaProp->setPropertyValue( "MissingValueTreatment", uno::Any() ); + } +} + +} // anonymous namespace + +namespace chart +{ + +ChartTypeTemplate::ChartTypeTemplate( + Reference< uno::XComponentContext > const & xContext, + const OUString & rServiceName ) : + m_xContext( xContext ), + m_aServiceName( rServiceName ) +{ +} + +ChartTypeTemplate::~ChartTypeTemplate() +{} + +// ____ XChartTypeTemplate ____ +uno::Reference< XDiagram > SAL_CALL ChartTypeTemplate::createDiagramByDataSource( + const uno::Reference< data::XDataSource >& xDataSource, + const uno::Sequence< beans::PropertyValue >& aArguments ) +{ + Reference< XDiagram > xDia; + + try + { + // create diagram + xDia.set( + GetComponentContext()->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.Diagram", + GetComponentContext() ), + uno::UNO_QUERY_THROW ); + + // modify diagram + Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter()); + chart2::InterpretedData aData( + xInterpreter->interpretDataSource( + xDataSource, aArguments, Sequence< Reference< XDataSeries > >() )); + + const Sequence< Sequence< Reference< XDataSeries > > > aSeries( aData.Series ); + sal_Int32 nCount = 0; + for( auto const & i : aSeries ) + for( auto const & j : i ) + lcl_applyDefaultStyle( j, nCount++, xDia ); + + Sequence< Reference< XChartType > > 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 SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram >& xDiagram ) +{ + if( ! xDiagram.is()) + return; + + try + { + Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( + DiagramHelper::getDataSeriesGroups( xDiagram )); + Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); + const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength(); + + // chart-type specific interpretation of existing data series + Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter()); + chart2::InterpretedData aData; + aData.Series = aSeriesSeq; + aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + + if( xInterpreter->isDataCompatible( aData ) ) + { + aData = xInterpreter->reinterpretDataSeries( aData ); + } + else + { + Reference< data::XDataSource > xSource( xInterpreter->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.realloc( 1 ); + aParam[0] = 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 + Sequence< Reference< XChartType > > aOldChartTypesSeq( + DiagramHelper::getChartTypesFromDiagram(xDiagram) ); + + Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY ); + OSL_ASSERT( xCoordSysCnt.is()); + if( xCoordSysCnt.is()) + { + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCoordSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xContainer( coords, uno::UNO_QUERY ); + if( xContainer.is() ) + xContainer->setChartTypes( Sequence< Reference< XChartType > >() ); + } + } + + FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL ChartTypeTemplate::changeDiagramData( + const Reference< chart2::XDiagram >& 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 + Sequence< Reference< XDataSeries > > aFlatSeriesSeq( + comphelper::containerToSequence( DiagramHelper::getDataSeriesFromDiagram( xDiagram ))); + const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength(); + Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter()); + chart2::InterpretedData aData = + xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq ); + + // data series + Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( aData.Series ); + + sal_Int32 i, j, nIndex = 0; + for( i=0; i= nFormerSeriesCount ) + { + lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram ); + applyStyle( aSeriesSeq[i][j], i, j, aSeriesSeq[i].getLength() ); + } + } + + // categories + DiagramHelper::setCategoriesToDiagram( aData.Categories, xDiagram, true, supportsCategories() ); + + Sequence< Reference< XChartType > > aChartTypes( + DiagramHelper::getChartTypesFromDiagram( xDiagram )); + sal_Int32 nMax = std::min( aChartTypes.getLength(), aSeriesSeq.getLength()); + for( i=0; i xDSCnt( aChartTypes[i], uno::UNO_QUERY_THROW ); + xDSCnt->setDataSeries( aSeriesSeq[i] ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +sal_Bool SAL_CALL ChartTypeTemplate::matchesTemplate( + const Reference< chart2::XDiagram >& xDiagram, + sal_Bool /* bAdaptProperties */ ) +{ + bool bResult = false; + + if( ! xDiagram.is()) + return bResult; + + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + + // need to have at least one coordinate system + bResult = aCooSysSeq.hasElements(); + if( bResult ) + { + Sequence< Reference< XChartType > > aFormerlyUsedChartTypes; + Reference xOldCT = getChartTypeForNewSeries(aFormerlyUsedChartTypes); + if (!xOldCT.is()) + return false; + + const OUString aChartTypeToMatch = xOldCT->getChartType(); + const sal_Int32 nDimensionToMatch = getDimension(); + for( sal_Int32 nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.getLength()); ++nCooSysIdx ) + { + // match dimension + bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch); + + Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( sal_Int32 nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.getLength()); ++nCTIdx ) + { + if (!aChartTypeSeq[nCTIdx].is()) + return false; + + // 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; +} + +Reference< chart2::XDataInterpreter > SAL_CALL ChartTypeTemplate::getDataInterpreter() +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new DataInterpreter ); + + return m_xDataInterpreter; +} + +void SAL_CALL ChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 /* nSeriesIndex */, + ::sal_Int32 /* nSeriesCount */ ) +{ + // sset stacking mode + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + if( !xSeriesProp.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 ); + xSeriesProp->setPropertyValue( "StackingDirection", aPropValue ); + + //ensure valid label placement + { + uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( + getChartTypeForIndex( nChartTypeIndex ), isSwapXAndY(), xSeries ) ); + lcl_ensureCorrectLabelPlacement( xSeriesProp, aAvailablePlacements ); + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= 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 Reference< chart2::XDiagram >& xDiagram ) +{ + // apply chart-type specific styles, like "symbols on" for example + Sequence< Sequence< Reference< XDataSeries > > > aNewSeriesSeq( + DiagramHelper::getDataSeriesGroups( xDiagram )); + for( sal_Int32 i=0; i& xDiagram ) +{ + // reset number format if we had percent stacking on + bool bPercent = (getStackMode(0) == StackMode::YStackedPercent); + if( bPercent ) + { + const Sequence< Reference< chart2::XAxis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( Reference< chart2::XAxis > const & axis : aAxisSeq ) + { + if( AxisHelper::getDimensionIndexOfAxis( axis, xDiagram )== 1 ) + { + Reference< beans::XPropertySet > xAxisProp( axis, uno::UNO_QUERY ); + if( xAxisProp.is()) + { + // set number format to source format + xAxisProp->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true)); + xAxisProp->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any()); + } + } + } + } + + //reset label placement if default + { + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + const uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( uno::Reference< XCoordinateSystem > const & xCooSys : aCooSysList ) + { + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + const uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( uno::Reference< XChartType > const & xChartType : aChartTypeList ) + { + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + const uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( Reference< XDataSeries > const & xSeries : aSeriesList ) + { + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + if(!xSeries.is() || !xSeriesProp.is() ) + continue; + + uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( + xChartType, isSwapXAndY(), xSeries ) ); + if(!aAvailablePlacements.hasElements()) + continue; + + sal_Int32 nDefaultPlacement = aAvailablePlacements[0]; + + lcl_resetLabelPlacementIfDefault( xSeriesProp, nDefaultPlacement ); + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= 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 Reference< chart2::XCoordinateSystemContainer > & xOutCooSysCnt ) +{ + if( ! xOutCooSysCnt.is()) + return; + Sequence< Reference< XChartType > > aFormerlyUsedChartTypes; + Reference< XChartType > xChartType( getChartTypeForNewSeries(aFormerlyUsedChartTypes)); + if( ! xChartType.is()) + return; + Reference< XCoordinateSystem > xCooSys( xChartType->createCoordinateSystem( getDimension())); + if( ! xCooSys.is()) + { + // chart type wants no coordinate systems + xOutCooSysCnt->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >()); + return; + } + // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before) + if( xCooSys->getDimension() >= 2 ) + { + Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1, 0 )); + if( xAxis.is()) + AxisHelper::makeGridVisible( xAxis->getGridProperties() ); + } + + Sequence< Reference< XCoordinateSystem > > aCoordinateSystems( + xOutCooSysCnt->getCoordinateSystems()); + + if( aCoordinateSystems.hasElements()) + { + bool bOk = true; + for( sal_Int32 i=0; bOk && igetCoordinateSystemType() == 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.hasElements() ) + { + Reference< XCoordinateSystem > xOldCooSys( aCoordinateSystems[0] ); + sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() ); + + for(sal_Int32 nDimensionIndex=0; nDimensionIndexgetMaximumAxisIndexByDimension(nDimensionIndex); + for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) + { + uno::Reference< XAxis > xAxis( xOldCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); + if( xAxis.is()) + { + xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex ); + } + } + } + } + + // set new coordinate systems + aCoordinateSystems.realloc( 1 ); + aCoordinateSystems[0] = xCooSys; + + xOutCooSysCnt->setCoordinateSystems( aCoordinateSystems ); +} + +void ChartTypeTemplate::adaptScales( + const Sequence< Reference< chart2::XCoordinateSystem > > & 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( Reference< XCoordinateSystem > const & xCooSys : aCooSysSeq ) + { + try + { + if( !xCooSys.is() ) + continue; + + // 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) + { + Reference< XAxis > xAxis( xCooSys->getAxisByDimension(nDimensionX,nI) ); + if( xAxis.is()) + { + ScaleData aData( xAxis->getScaleData() ); + aData.Categories = xCategories; + if(bSupportsCategories) + { + Reference< XChartType > xChartType(getChartTypeForNewSeries(Sequence< Reference< XChartType > >())); + 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) + { + Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 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 Reference< XDiagram > & /* xDiagram */ ) +{ + } + +void ChartTypeTemplate::createAxes( + const Sequence< Reference< XCoordinateSystem > > & rCoordSys ) +{ + //create missing axes + if( !rCoordSys.hasElements() ) + return; + + Reference< XCoordinateSystem > 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 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 Sequence< Reference< XCoordinateSystem > > & rCoordSys ) +{ + //adapt properties of existing axes and remove superfluous axes + + if( !rCoordSys.hasElements() ) + return; + + for( Reference< XCoordinateSystem > const & xCooSys : rCoordSys ) + { + if( !xCooSys.is() ) + continue; + sal_Int32 nDimCount = xCooSys->getDimension(); + for( sal_Int32 nDim=0; nDimgetMaximumAxisIndexByDimension( nDim ); + for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ ) + { + Reference< XAxis > 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 ) + { + Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY ); + if( xAxisProp.is()) + { + // set number format to source format + xAxisProp->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true)); + xAxisProp->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any()); + } + } + } + } + } + } +} + +sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension ) +{ + return (nDimension < getDimension()) ? 1 : 0; +} + +void ChartTypeTemplate::FillDiagram( + const Reference< XDiagram >& xDiagram, + const Sequence< Sequence< Reference< XDataSeries > > >& aSeriesSeq, + const Reference< data::XLabeledDataSequence >& xCategories, + const Sequence< Reference< XChartType > >& aOldChartTypesSeq ) +{ + adaptDiagram( xDiagram ); + + try + { + // create coordinate systems and scales + Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + createCoordinateSystems( xCoordSysCnt ); + Sequence< Reference< XCoordinateSystem > > aCoordinateSystems( xCoordSysCnt->getCoordinateSystems()); + 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 Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq, + const Sequence< Reference< XCoordinateSystem > > & rCoordSys, + const Sequence< Reference< XChartType > >& aOldChartTypesSeq ) +{ + if( ! rCoordSys.hasElements() || + ! rCoordSys[0].is() ) + return; + + try + { + sal_Int32 nCooSysIdx=0; + Reference< XChartType > xCT; + if( !aSeriesSeq.hasElements() ) + { + // we need a new chart type + xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq )); + Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes()); + aCTSeq.realloc( 1 ); + aCTSeq[0] = xCT; + xCTCnt->setChartTypes( aCTSeq ); + } + else + { + for( sal_Int32 nSeriesIdx=0; nSeriesIdx xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes()); + if( aCTSeq.hasElements()) + { + aCTSeq[0] = xCT; + xCTCnt->setChartTypes( aCTSeq ); + } + else + xCTCnt->addChartType( xCT ); + + Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + xDSCnt->setDataSeries( aSeriesSeq[nSeriesIdx] ); + } + else + { + // reuse existing chart type + OSL_ASSERT( xCT.is()); + Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aNewSeriesSeq( xDSCnt->getDataSeries()); + sal_Int32 nNewStartIndex = aNewSeriesSeq.getLength(); + aNewSeriesSeq.realloc( nNewStartIndex + aSeriesSeq[nSeriesIdx].getLength() ); + std::copy( aSeriesSeq[nSeriesIdx].begin(), + aSeriesSeq[nSeriesIdx].end(), + aNewSeriesSeq.getArray() + nNewStartIndex ); + xDSCnt->setDataSeries( aNewSeriesSeq ); + } + + // spread the series over the available coordinate systems + if( rCoordSys.getLength() > (nCooSysIdx + 1) ) + ++nCooSysIdx; + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( + const Sequence< Reference< XChartType > > & rOldChartTypesSeq, + const Reference< XChartType > & xNewChartType ) +{ + Reference< beans::XPropertySet > xDestination( xNewChartType, uno::UNO_QUERY ); + if( !xDestination.is() ) + return; + + OUString aNewChartType( xNewChartType->getChartType() ); + + Reference< beans::XPropertySet > xSource; + for( Reference< XChartType > const & xOldType : rOldChartTypesSeq ) + { + if( xOldType.is() && xOldType->getChartType() == aNewChartType ) + { + xSource.set( Reference< beans::XPropertySet >(xOldType, uno::UNO_QUERY ) ); + if( xSource.is() ) + break; + } + } + if( xSource.is() ) + comphelper::copyProperties( xSource, xDestination ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/ChartTypeTemplate.hxx b/chart2/source/model/template/ChartTypeTemplate.hxx new file mode 100644 index 000000000..0fe236ce1 --- /dev/null +++ b/chart2/source/model/template/ChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPETEMPLATE_HXX + +#include +#include +#include +#include + +namespace com::sun::star::chart2 { class XChartType; } +namespace com::sun::star::chart2 { class XCoordinateSystemContainer; } +namespace com::sun::star::chart2 { class XDataSeries; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +/** 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 ChartTypeTemplate : public ::cppu::WeakImplHelper< + css::chart2::XChartTypeTemplate, + css::lang::XServiceName > +{ +public: + explicit ChartTypeTemplate( css::uno::Reference< css::uno::XComponentContext > const & xContext, + const OUString & rServiceName ); + virtual ~ChartTypeTemplate() override; + +protected: + // ____ 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; + /// 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; + 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; + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< + css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + // still abstract: getChartTypeForNewSeries() + virtual css::uno::Reference< css::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void SAL_CALL resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override; + + /// @throws css::uno::RuntimeException + void applyStyles( + const css::uno::Reference< css::chart2::XDiagram >& 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 css::uno::Reference< css::chart2::XChartType > + 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 css::uno::Reference< css::chart2::XDiagram > & 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. + +

The dimension depends on the value returned by getDimension().

+ */ + virtual void createCoordinateSystems( + const css::uno::Reference< css::chart2::XCoordinateSystemContainer > & xOutCooSysCnt ); + + /** Sets categories at the scales of dimension 0 and the percent stacking at + the scales of dimension 1 of all given coordinate systems. + +

Called by FillDiagram.

+ */ + virtual void adaptScales( + const css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > & aCooSysSeq, + const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories ); + + /** create a data series tree, that fits the requirements of the chart type. + +

As default, this creates a tree with the following structure:

+ +
+          root
+           |
+           +-- chart type (determined by getChartTypeForNewSeries())
+                   |
+                   +-- category (DiscreteStackableScaleGroup using scale 0)
+                          |
+                          +-- values (ContinuousStackableScaleGroup using scale 1)
+                                |
+                                +-- series 0
+                                |
+                                +-- series 1
+                                |
+                                ...
+                                |
+                                +.. series n-1
+        
+ +

If there are less than two scales available the returned tree is + empty.

+ */ + virtual void createChartTypes( + const css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< + css::chart2::XDataSeries > > > & aSeriesSeq, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XCoordinateSystem > > & rCoordSys, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > > & aOldChartTypesSeq + ); + + /** create axes and add them to the given container. If there are already + compatible axes in the container these should be maintained. + +

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

+ */ + void createAxes( + const css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > & 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 css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > & rCoordSys ); + + const css::uno::Reference< css::uno::XComponentContext >& + GetComponentContext() const { return m_xContext;} + + static void copyPropertiesFromOldToNewCoordinateSystem( + const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > > & rOldChartTypesSeq, + const css::uno::Reference< css::chart2::XChartType > & xNewChartType ); + +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + mutable css::uno::Reference< css::chart2::XDataInterpreter > m_xDataInterpreter; + +private: + const OUString m_aServiceName; + +private: + /** modifies the given diagram + */ + void FillDiagram( const css::uno::Reference< + css::chart2::XDiagram > & xDiagram, + const css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< + css::chart2::XDataSeries > > > & aSeriesSeq, + const css::uno::Reference< + css::chart2::data::XLabeledDataSequence >& xCategories, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > > & aOldChartTypesSeq); +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_CHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..4c95b1c1b --- /dev/null +++ b/chart2/source/model/template/ColumnChartType.cxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +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>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "GapwidthSequence", + PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticColumnChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + Sequence< sal_Int32 > aSeq(2); + + aSeq[0] = aSeq[1] = 0; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BARCHARTTYPE_OVERLAP_SEQUENCE, aSeq ); + + aSeq[0] = aSeq[1] = 100; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq ); + } +}; + +struct StaticColumnChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticColumnChartTypeDefaults_Initializer > +{ +}; + +struct StaticColumnChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticColumnChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticColumnChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticColumnChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticColumnChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticColumnChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticColumnChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ XChartType ____ +OUString SAL_CALL ColumnChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_COLUMN; +} + +uno::Sequence< OUString > ColumnChartType::getSupportedPropertyRoles() +{ + uno::Sequence< OUString > aPropRoles(2); + aPropRoles[0] = "FillColor"; + aPropRoles[1] = "BorderColor"; + + return aPropRoles; +} + +// ____ OPropertySet ____ +uno::Any ColumnChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticColumnChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ColumnChartType::getInfoHelper() +{ + return *StaticColumnChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnChartType::getPropertySetInfo() +{ + return *StaticColumnChartTypeInfo::get(); +} + +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 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 000000000..d7b879479 --- /dev/null +++ b/chart2/source/model/template/ColumnChartType.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNCHARTTYPE_HXX + +#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; + +private: + explicit ColumnChartType( const ColumnChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNCHARTTYPE_HXX +#endif + +/* 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 000000000..560332b81 --- /dev/null +++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx @@ -0,0 +1,410 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include "ColumnLineDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "NumberOfLines", + PROP_COL_LINE_NUMBER_OF_LINES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticColumnLineChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aStaticDefaults, PROP_COL_LINE_NUMBER_OF_LINES, 1 ); + return &aStaticDefaults; + } +}; + +struct StaticColumnLineChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticColumnLineChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticColumnLineChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticColumnLineChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticColumnLineChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticColumnLineChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticColumnLineChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticColumnLineChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticColumnLineChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +ColumnLineChartTypeTemplate::ColumnLineChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StackMode eStackMode, + sal_Int32 nNumberOfLines ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ) +{ + setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines )); +} + +ColumnLineChartTypeTemplate::~ColumnLineChartTypeTemplate() +{} + +// ____ OPropertySet ____ +uno::Any ColumnLineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticColumnLineChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ColumnLineChartTypeTemplate::getInfoHelper() +{ + return *StaticColumnLineChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnLineChartTypeTemplate::getPropertySetInfo() +{ + return *StaticColumnLineChartTypeTemplateInfo::get(); +} + +void ColumnLineChartTypeTemplate::createChartTypes( + const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq, + const Sequence< Reference< XCoordinateSystem > > & rCoordSys, + const Sequence< Reference< XChartType > >& aOldChartTypesSeq ) +{ + if( ! rCoordSys.hasElements() || + ! rCoordSys[0].is() ) + return; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); + sal_Int32 nNumberOfSeries = aFlatSeriesSeq.getLength(); + 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 + + Reference< XChartType > xCT( + xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY_THROW ); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aOldChartTypesSeq, xCT ); + + Reference< XChartTypeContainer > xCTCnt( rCoordSys[ 0 ], uno::UNO_QUERY_THROW ); + xCTCnt->setChartTypes( Sequence< Reference< chart2::XChartType > >( &xCT, 1 )); + + if( nNumberOfColumns > 0 ) + { + Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aColumnSeq( nNumberOfColumns ); + std::copy( aFlatSeriesSeq.begin(), + aFlatSeriesSeq.begin() + nNumberOfColumns, + aColumnSeq.getArray()); + xDSCnt->setDataSeries( aColumnSeq ); + } + + // Lines + + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + xCTCnt.set( rCoordSys[ 0 ], uno::UNO_QUERY_THROW ); + xCTCnt->addChartType( xCT ); + + if( nNumberOfLines > 0 ) + { + Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aLineSeq( nNumberOfLines ); + std::copy( aFlatSeriesSeq.begin() + nNumberOfColumns, + aFlatSeriesSeq.end(), + aLineSeq.getArray()); + xDSCnt->setDataSeries( aLineSeq ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL ColumnLineChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + if( nChartTypeIndex==0 ) // columns + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) ); + } + else if( nChartTypeIndex==1 ) // lines + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + DataSeriesHelper::switchLinesOnOrOff( xProp, true ); + DataSeriesHelper::switchSymbolsOnOrOff( xProp, false, nSeriesIndex ); + DataSeriesHelper::makeLinesThickOrThin( xProp, true ); + } + } +} + +StackMode ColumnLineChartTypeTemplate::getStackMode( sal_Int32 nChartTypeIndex ) const +{ + if( nChartTypeIndex == 0 ) + return m_eStackMode; + return StackMode::NONE; +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL ColumnLineChartTypeTemplate::matchesTemplate( + const uno::Reference< XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = false; + + if( ! xDiagram.is()) + return bResult; + + try + { + Reference< chart2::XChartType > xColumnChartType; + Reference< XCoordinateSystem > xColumnChartCooSys; + Reference< chart2::XChartType > xLineChartType; + sal_Int32 nNumberOfChartTypes = 0; + + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( Reference< XChartType > const & chartType : aChartTypeSeq ) + { + if( chartType.is()) + { + ++nNumberOfChartTypes; + if( nNumberOfChartTypes > 2 ) + break; + OUString aCTService = chartType->getChartType(); + if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) + { + xColumnChartType.set( chartType ); + xColumnChartCooSys.set( coords ); + } + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE ) + xLineChartType.set( 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 ) + { + Reference< XDataSeriesContainer > xSeriesContainer( xLineChartType, uno::UNO_QUERY ); + if( xSeriesContainer.is() ) + { + sal_Int32 nNumberOfLines = xSeriesContainer->getDataSeries().getLength(); + setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines )); + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return bResult; +} + +Reference< chart2::XChartType > ColumnLineChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex ) +{ + Reference< chart2::XChartType > xCT; + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY ); + if(xFact.is()) + { + if( nChartTypeIndex == 0 ) + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY ); + else + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY ); + } + return xCT; +} + +Reference< XChartType > SAL_CALL ColumnLineChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< XDataInterpreter > SAL_CALL ColumnLineChartTypeTemplate::getDataInterpreter() +{ + if( ! m_xDataInterpreter.is()) + { + sal_Int32 nNumberOfLines = 1; + getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines; + m_xDataInterpreter.set( 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 000000000..9f04b633d --- /dev/null +++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINECHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINECHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include + +#include +#include +#include + +namespace chart +{ + +class ColumnLineChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual css::uno::Reference< css::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() override; + + // ____ ChartTypeTemplate ____ + virtual void createChartTypes( + const css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< + css::chart2::XDataSeries > > > & aSeriesSeq, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XCoordinateSystem > > & rCoordSys, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > > & aOldChartTypesSeq + ) override; + + virtual css::uno::Reference< css::chart2::XChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override; + +private: + StackMode m_eStackMode; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINECHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..b99324d27 --- /dev/null +++ b/chart2/source/model/template/ColumnLineDataInterpreter.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 "ColumnLineDataInterpreter.hxx" +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +// explicit +ColumnLineDataInterpreter::ColumnLineDataInterpreter( + sal_Int32 nNumberOfLines ) : + DataInterpreter(), + m_nNumberOfLines( nNumberOfLines ) +{} + +ColumnLineDataInterpreter::~ColumnLineDataInterpreter() +{} + +// ____ XDataInterpreter ____ +InterpretedData SAL_CALL ColumnLineDataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) +{ + InterpretedData aResult( DataInterpreter::interpretDataSource( xSource, aArguments, aSeriesToReUse )); + + // the base class should return one group + OSL_ASSERT( aResult.Series.getLength() == 1 ); + if( aResult.Series.getLength() == 1 ) + { + sal_Int32 nNumberOfSeries = aResult.Series[0].getLength(); + + // 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.realloc(2); + + Sequence< Reference< XDataSeries > > & rColumnDataSeries = aResult.Series[0]; + Sequence< Reference< XDataSeries > > & rLineDataSeries = aResult.Series[1]; + rLineDataSeries.realloc( nNumOfLines ); + std::copy( rColumnDataSeries.begin() + nNumberOfSeries - nNumOfLines, + rColumnDataSeries.begin() + nNumberOfSeries, + rLineDataSeries.getArray() ); + rColumnDataSeries.realloc( 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 000000000..e6956db4c --- /dev/null +++ b/chart2/source/model/template/ColumnLineDataInterpreter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINEDATAINTERPRETER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINEDATAINTERPRETER_HXX + +#include "DataInterpreter.hxx" + +namespace chart +{ + +class ColumnLineDataInterpreter : public DataInterpreter +{ +public: + explicit ColumnLineDataInterpreter( + sal_Int32 nNumberOfLines ); + virtual ~ColumnLineDataInterpreter() override; + +protected: + // ____ XDataInterpreter ____ + virtual css::chart2::InterpretedData SAL_CALL interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aSeriesToReUse ) override; + +private: + sal_Int32 m_nNumberOfLines; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_COLUMNLINEDATAINTERPRETER_HXX +#endif + +/* 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 000000000..7e85e0b36 --- /dev/null +++ b/chart2/source/model/template/DataInterpreter.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +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 SAL_CALL DataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + +#ifdef DEBUG_CHART2_TEMPLATE + lcl_ShowDataSource( xSource ); +#endif + + const Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); + + Reference< data::XLabeledDataSequence > xCategories; + vector< Reference< data::XLabeledDataSequence > > aSequencesVec; + + // check if we should use categories + + bool bHasCategories( HasCategories( aArguments, aData )); + + // parse data + bool bCategoriesUsed = false; + for( Reference< data::XLabeledDataSequence > const & labeledData : aData ) + { + try + { + if( bHasCategories && ! bCategoriesUsed ) + { + xCategories.set( 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 + sal_Int32 nSeriesIndex = 0; + vector< Reference< XDataSeries > > aSeriesVec; + aSeriesVec.reserve( aSequencesVec.size()); + + for (auto const& elem : aSequencesVec) + { + Sequence< Reference< data::XLabeledDataSequence > > aNewData( &elem, 1 ); + Reference< XDataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.getLength()) + xSeries.set( aSeriesToReUse[nSeriesIndex] ); + else + xSeries.set( new DataSeries ); + OSL_ASSERT( xSeries.is() ); + Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + OSL_ASSERT( xSink.is() ); + xSink->setData( aNewData ); + + aSeriesVec.push_back( xSeries ); + ++nSeriesIndex; + } + + Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); + aSeries[0] = comphelper::containerToSequence( aSeriesVec ); + return InterpretedData( aSeries, xCategories ); +} + +InterpretedData SAL_CALL DataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.getLength(); + for( ; i xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; + + // values-y + Reference< data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-y" )); + // re-use values-... as values-y + if( ! xValuesY.is()) + { + xValuesY.set( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values", true )); + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + if( xValuesY.is()) + { + aNewSequences.realloc(1); + aNewSequences[0] = xValuesY; + } + + Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); + if( aSeqs.getLength() != aNewSequences.getLength() ) + { +#ifdef DEBUG_CHART2_TEMPLATE + sal_Int32 j=0; + for( ; j xSink( xSeriesSource, uno::UNO_QUERY_THROW ); + xSink->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +// criterion: all series must have exactly one data::XLabeledDataSequence +sal_Bool SAL_CALL DataInterpreter::isDataCompatible( + const chart2::InterpretedData& aInterpretedData ) +{ + const Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( Reference< XDataSeries > const & i : aSeries ) + { + try + { + Reference< data::XDataSource > xSrc( i, uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + if( aSeq.getLength() != 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 + +Reference< data::XDataSource > SAL_CALL DataInterpreter::mergeInterpretedData( + const InterpretedData& aInterpretedData ) +{ + vector< Reference< data::XLabeledDataSequence > > aResultVec; + aResultVec.reserve( aInterpretedData.Series.getLength() + + 1 // categories + ); + + if( aInterpretedData.Categories.is()) + aResultVec.push_back( aInterpretedData.Categories ); + + const Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( Reference< XDataSeries > const & dataSeries : aSeries ) + { + try + { + Reference< data::XDataSource > xSrc( dataSeries, uno::UNO_QUERY_THROW ); + const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + + // add all sequences of data series + for( Reference< data::XLabeledDataSequence > const & xAdd : aSeq ) + { + // 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 DataSourceHelper::createDataSource( comphelper::containerToSequence( aResultVec ) ); +} + +// 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, + const OUString & 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 Sequence< Reference< data::XLabeledDataSequence > > & rData ) +{ + bool bHasCategories = false; + + if( rArguments.hasElements() ) + GetProperty( rArguments, "HasCategories" ) >>= bHasCategories; + + for( sal_Int32 nLSeqIdx=0; ! bHasCategories && nLSeqIdxgetValues() ) == "categories"); + + return bHasCategories; +} + +bool DataInterpreter::UseCategoriesAsX( const Sequence< beans::PropertyValue > & rArguments ) +{ + bool bUseCategoriesAsX = true; + if( rArguments.hasElements() ) + GetProperty( rArguments, "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" }; +} + +} // 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(""); + 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", " Role: " << aId << ", Source: "<< aSourceRepr); + } + else + { + SAL_INFO("chart2", " unknown Role, Source: " << aSourceRepr ); + } + + aSourceRepr = ""; + 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", " Role: " << aId + << ", Source: " << aSourceRepr ); + } + else + { + SAL_INFO("chart2", " unknown Role, Source: " << aSourceRepr ); + } + } + } +} + +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/DataInterpreter.hxx b/chart2/source/model/template/DataInterpreter.hxx new file mode 100644 index 000000000..72d3d61e4 --- /dev/null +++ b/chart2/source/model/template/DataInterpreter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_DATAINTERPRETER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_DATAINTERPRETER_HXX + +#include +#include +#include + +namespace chart +{ + +class DataInterpreter : public ::cppu::WeakImplHelper< + css::chart2::XDataInterpreter, + 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 & aArguments, + const OUString & rName ); + + static bool HasCategories( + const css::uno::Sequence< css::beans::PropertyValue > & rArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & rData ); + + static bool UseCategoriesAsX( + const css::uno::Sequence< css::beans::PropertyValue > & rArguments ); + +protected: + // ____ XDataInterpreter ____ + virtual css::chart2::InterpretedData SAL_CALL interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aSeriesToReUse ) override; + virtual css::chart2::InterpretedData SAL_CALL reinterpretDataSeries( + const css::chart2::InterpretedData& aInterpretedData ) override; + virtual sal_Bool SAL_CALL isDataCompatible( + const css::chart2::InterpretedData& aInterpretedData ) override; + virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL mergeInterpretedData( + const css::chart2::InterpretedData& aInterpretedData ) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_DATAINTERPRETER_HXX +#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 000000000..3179317da --- /dev/null +++ b/chart2/source/model/template/FilledNetChartType.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 "FilledNetChartType.hxx" +#include +#include + +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 )); +} + +// ____ 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 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 000000000..baa2b9efb --- /dev/null +++ b/chart2/source/model/template/FilledNetChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_FILLEDNETCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_FILLEDNETCHARTTYPE_HXX + +#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; + +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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_FILLEDNETCHARTTYPE_HXX +#endif + +/* 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 000000000..64b2fe9c1 --- /dev/null +++ b/chart2/source/model/template/LineChartType.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 "LineChartType.hxx" +#include +#include +#include +#include + +#include +#include + +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 +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( CHART_UNONAME_CURVE_STYLE, + PROP_LINECHARTTYPE_CURVE_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_CURVE_RESOLUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER, + PROP_LINECHARTTYPE_SPLINE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticLineChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINECHARTTYPE_CURVE_STYLE, ::chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, 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 >( rOutMap, PROP_LINECHARTTYPE_SPLINE_ORDER, 3 ); + } +}; + +struct StaticLineChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticLineChartTypeDefaults_Initializer > +{ +}; + +struct StaticLineChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticLineChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticLineChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticLineChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticLineChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticLineChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticLineChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ XChartType ____ +OUString SAL_CALL LineChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_LINE; +} + +// ____ OPropertySet ____ +uno::Any LineChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticLineChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL LineChartType::getInfoHelper() +{ + return *StaticLineChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartType::getPropertySetInfo() +{ + return *StaticLineChartTypeInfo::get(); +} + +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 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 000000000..27ebc7ffb --- /dev/null +++ b/chart2/source/model/template/LineChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPE_HXX + +#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; + +private: + explicit LineChartType( const LineChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPE_HXX +#endif + +/* 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 000000000..7989a7435 --- /dev/null +++ b/chart2/source/model/template/LineChartTypeTemplate.cxx @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 + +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( CHART_UNONAME_CURVE_STYLE, + PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_CURVE_RESOLUTION, + PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER, + PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticLineChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, 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 >( rOutMap, PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 ); + } +}; + +struct StaticLineChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticLineChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticLineChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticLineChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticLineChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticLineChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticLineChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticLineChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticLineChartTypeTemplateInfo_Initializer > +{ +}; + +} // 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 ), + ::property::OPropertySet( m_aMutex ), + m_eStackMode( eStackMode ), + m_bHasSymbols( bSymbols ), + m_bHasLines( bHasLines ), + m_nDim( nDim ) +{ + if( nDim == 3 ) + m_bHasSymbols = false; +} + +LineChartTypeTemplate::~LineChartTypeTemplate() +{} +// ____ OPropertySet ____ +uno::Any LineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticLineChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL LineChartTypeTemplate::getInfoHelper() +{ + return *StaticLineChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartTypeTemplate::getPropertySetInfo() +{ + return *StaticLineChartTypeTemplateInfo::get(); +} + +sal_Int32 LineChartTypeTemplate::getDimension() const +{ + return m_nDim; +} + +StackMode LineChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return m_eStackMode; +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL LineChartTypeTemplate::matchesTemplate( + const uno::Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate( 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< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY_THROW); + + bool bCurrentHasSymbol = (xProp->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (xProp->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 + { + uno::Reference< beans::XPropertySet > xChartTypeProp( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), + uno::UNO_QUERY_THROW ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_STYLE) ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) ); + setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, xChartTypeProp->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return bResult; +} + +Reference< chart2::XChartType > LineChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE )); + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xCTProp->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL LineChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE )); + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xCTProp->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +void SAL_CALL LineChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY_THROW ); + + DataSeriesHelper::switchSymbolsOnOrOff( xProp, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xProp, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xProp, 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 000000000..2663fb113 --- /dev/null +++ b/chart2/source/model/template/LineChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include +#include +#include +#include + +namespace chart +{ + +class LineChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_LINECHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..95de304b6 --- /dev/null +++ b/chart2/source/model/template/NetChartType.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 "NetChartType.hxx" +#include +#include +#include +#include + +#include +#include + +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() +{} + +Reference< XCoordinateSystem > SAL_CALL + NetChartType_Base::createCoordinateSystem( ::sal_Int32 DimensionCount ) +{ + if( DimensionCount != 2 ) + throw lang::IllegalArgumentException( + "NetChart must be two-dimensional", + static_cast< ::cppu::OWeakObject* >( this ), 0 ); + + Reference< XCoordinateSystem > xResult( + new PolarCoordinateSystem( DimensionCount )); + + Reference< XAxis > xAxis( xResult->getAxisByDimension( 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->getAxisByDimension( 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 ____ +uno::Any NetChartType_Base::GetDefaultValue( sal_Int32 /*nHandle*/ ) const +{ + return uno::Any(); +} + +namespace +{ + +struct StaticNetChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper(Sequence< beans::Property >{}); + return &aPropHelper; + } +}; + +struct StaticNetChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticNetChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticNetChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticNetChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticNetChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticNetChartTypeInfo_Initializer > +{ +}; + +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL NetChartType_Base::getInfoHelper() +{ + return *StaticNetChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL NetChartType_Base::getPropertySetInfo() +{ + return *StaticNetChartTypeInfo::get(); +} + +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 )); +} + +// ____ 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 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 000000000..3d3efed8c --- /dev/null +++ b/chart2/source/model/template/NetChartType.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPE_HXX + +#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 ); + + // ____ XChartType ____ + virtual css::uno::Reference< css::chart2::XCoordinateSystem > SAL_CALL + createCoordinateSystem( ::sal_Int32 DimensionCount ) override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() 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; + +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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPE_HXX +#endif + +/* 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 000000000..fed499cb3 --- /dev/null +++ b/chart2/source/model/template/NetChartTypeTemplate.cxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +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 SAL_CALL NetChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY_THROW ); + + DataSeriesHelper::switchSymbolsOnOrOff( xProp, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xProp, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xProp, true ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL NetChartTypeTemplate::matchesTemplate( + const Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate( xDiagram, bAdaptProperties ); + + uno::Reference< beans::XPropertySet > xChartTypeProp( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), uno::UNO_QUERY_THROW ); + + 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< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY_THROW); + + bool bCurrentHasSymbol = (xProp->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (xProp->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; +} + +Reference< chart2::XChartType > NetChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + + if( m_bHasFilledArea ) + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET ), uno::UNO_QUERY_THROW ); + else + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_NET ), uno::UNO_QUERY_THROW ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL NetChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > 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 000000000..369989e6f --- /dev/null +++ b/chart2/source/model/template/NetChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include + +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: + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_NETCHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..c18c8d11d --- /dev/null +++ b/chart2/source/model/template/PieChartType.cxx @@ -0,0 +1,241 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +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_PIECHARTTYPE_USE_RINGS, + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "UseRings", + PROP_PIECHARTTYPE_USE_RINGS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "3DRelativeHeight", + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticPieChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_PIECHARTTYPE_USE_RINGS, false ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, 100 ); + } +}; + +struct StaticPieChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticPieChartTypeDefaults_Initializer > +{ +}; + +struct StaticPieChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticPieChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticPieChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticPieChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticPieChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticPieChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticPieChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ XChartType ____ +OUString SAL_CALL PieChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_PIE; +} + +Reference< chart2::XCoordinateSystem > SAL_CALL + PieChartType::createCoordinateSystem( ::sal_Int32 DimensionCount ) +{ + Reference< chart2::XCoordinateSystem > xResult( + new PolarCoordinateSystem( DimensionCount )); + + for( sal_Int32 i=0; i xAxis( xResult->getAxisByDimension( 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() +{ + uno::Sequence< OUString > aPropRoles(2); + aPropRoles[0] = "FillColor"; + aPropRoles[1] = "BorderColor"; + + return aPropRoles; +} + +// ____ OPropertySet ____ +uno::Any PieChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticPieChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL PieChartType::getInfoHelper() +{ + return *StaticPieChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartType::getPropertySetInfo() +{ + return *StaticPieChartTypeInfo::get(); +} + +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 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 000000000..897ec9695 --- /dev/null +++ b/chart2/source/model/template/PieChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPE_HXX + +#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; + +private: + explicit PieChartType( const PieChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Reference< css::chart2::XCoordinateSystem > SAL_CALL + createCoordinateSystem( ::sal_Int32 DimensionCount ) override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedPropertyRoles() override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPE_HXX +#endif + +/* 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 000000000..964b5d96d --- /dev/null +++ b/chart2/source/model/template/PieChartTypeTemplate.cxx @@ -0,0 +1,608 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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_PIE_TEMPLATE_DEFAULT_OFFSET, + PROP_PIE_TEMPLATE_OFFSET_MODE, + PROP_PIE_TEMPLATE_DIMENSION, + PROP_PIE_TEMPLATE_USE_RINGS +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "OffsetMode", + PROP_PIE_TEMPLATE_OFFSET_MODE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DefaultOffset", + PROP_PIE_TEMPLATE_DEFAULT_OFFSET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Dimension", + PROP_PIE_TEMPLATE_DIMENSION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "UseRings", + PROP_PIE_TEMPLATE_USE_RINGS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticPieChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_PIE_TEMPLATE_OFFSET_MODE, chart2::PieChartOffsetMode_NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< double >( rOutMap, PROP_PIE_TEMPLATE_DEFAULT_OFFSET, 0.5 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_PIE_TEMPLATE_DIMENSION, 2 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_PIE_TEMPLATE_USE_RINGS, false ); + } +}; + +struct StaticPieChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticPieChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticPieChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticPieChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticPieChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticPieChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticPieChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticPieChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticPieChartTypeTemplateInfo_Initializer > +{ +}; + +} // 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 ), + ::property::OPropertySet( m_aMutex ) +{ + 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 ____ +uno::Any PieChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticPieChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL PieChartTypeTemplate::getInfoHelper() +{ + return *StaticPieChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartTypeTemplate::getPropertySetInfo() +{ + return *StaticPieChartTypeTemplateInfo::get(); +} + +// ____ 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 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > & /*rCoordSys*/ ) +{ + // hide existing axes + //hhhh todo +} + +void PieChartTypeTemplate::adaptScales( + const Sequence< Reference< chart2::XCoordinateSystem > > & 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( Reference< chart2::XCoordinateSystem > const & coords : aCooSysSeq ) + { + try + { + Reference< chart2::XAxis > xAxis( AxisHelper::getAxis( 1 /*nDimensionIndex*/,0 /*nAxisIndex*/ + , coords ) ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + AxisHelper::removeExplicitScaling( aScaleData ); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + xAxis->setScaleData( aScaleData ); + } + + xAxis = AxisHelper::getAxis( 0 /*nDimensionIndex*/,0 /*nAxisIndex*/ + , coords ); + if( xAxis.is() ) + { + chart2::ScaleData aScaleData( xAxis->getScaleData() ); + aScaleData.Orientation = chart2::AxisOrientation_REVERSE; + xAxis->setScaleData( aScaleData ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } +} + +void PieChartTypeTemplate::createChartTypes( + const Sequence< Sequence< Reference< chart2::XDataSeries > > > & aSeriesSeq, + const Sequence< Reference< chart2::XCoordinateSystem > > & rCoordSys, + const Sequence< Reference< chart2::XChartType > >& /* aOldChartTypesSeq */ ) +{ + if( ! rCoordSys.hasElements() || + ! rCoordSys[0].is() ) + return; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + + Reference< chart2::XChartType > xCT( + xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_PIE ), uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySet > xCTProp( xCT, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + } + Reference< chart2::XChartTypeContainer > xCTCnt( rCoordSys[0], uno::UNO_QUERY_THROW ); + xCTCnt->setChartTypes( Sequence< Reference< chart2::XChartType > >( &xCT, 1 )); + + if( aSeriesSeq.hasElements() ) + { + Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + Sequence< Reference< chart2::XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); + xDSCnt->setDataSeries( aFlatSeriesSeq ); + + DataSeriesHelper::setStackModeAtSeries( + aFlatSeriesSeq, rCoordSys[0], getStackMode( 0 )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL PieChartTypeTemplate::matchesTemplate( + const uno::Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate( 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; + + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + //check offset of outer series + if( !aSeriesVec.empty() ) + { + //@todo in future this will depend on Orientation of the radius axis scale + Reference< chart2::XDataSeries > xSeries( aSeriesVec[0] ); + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY_THROW ); + xProp->getPropertyValue( "Offset") >>= fOffset; + + //get AttributedDataPoints + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xProp->getPropertyValue( "AttributedDataPoints" ) >>= 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( xProp->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 ) + { + uno::Reference< beans::XPropertySet > xCTProp( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), uno::UNO_QUERY_THROW ); + bool bUseRings = false; + if( xCTProp->getPropertyValue( "UseRings") >>= bUseRings ) + { + bResult = ( bTemplateUsesRings == bUseRings ); + } + } + + return bResult; +} + +Reference< chart2::XChartType > PieChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_PIE ), uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + } + + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL PieChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_PIE ), uno::UNO_QUERY_THROW ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + "UseRings", getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); + } + + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +void SAL_CALL PieChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY_THROW ); + + bool bTemplateUsesRings = false; + getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS ) >>= bTemplateUsesRings; + if( nSeriesIndex == 0 ) //@todo in future this will depend on Orientation of the radius axis scale + { + const OUString aOffsetPropName( "Offset" ); + // 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; + xProp->getPropertyValue( "AttributedDataPoints" ) >>= 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( (xProp->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 + xProp->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 + xProp->setPropertyValue( "VaryColorsByPoint", uno::Any( true )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL PieChartTypeTemplate::resetStyles( const Reference< chart2::XDiagram >& xDiagram ) +{ + // reset axes and grids + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( xCooSysCnt.is()) + { + const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + ChartTypeTemplate::createAxes( aCooSysSeq ); + + //reset scale orientation + for( Reference< chart2::XCoordinateSystem > const & coords : aCooSysSeq ) + { + try + { + Reference< chart2::XAxis > 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::resetStyles( xDiagram ); + + // vary colors by point, + // line style + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + uno::Any aLineStyleAny( drawing::LineStyle_NONE ); + for (auto const& series : aSeriesVec) + { + Reference< beans::XPropertyState > xState(series, uno::UNO_QUERY); + if( xState.is()) + { + xState->setPropertyToDefault( "VaryColorsByPoint"); + Reference< beans::XPropertySet > xProp( xState, uno::UNO_QUERY ); + if( xProp.is() && + xProp->getPropertyValue( "BorderStyle") == aLineStyleAny ) + { + xState->setPropertyToDefault( "BorderStyle"); + } + } + } + + //reset scene properties + ThreeDHelper::setDefaultRotation( uno::Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ), false ); +} + +// ____ XChartTypeTemplate ____ +void PieChartTypeTemplate::adaptDiagram( const uno::Reference< chart2::XDiagram >& xDiagram ) +{ + if( !xDiagram.is() ) + return; + + //different default for scene geometry: + ThreeDHelper::setDefaultRotation( uno::Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ), 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 000000000..f11099fdd --- /dev/null +++ b/chart2/source/model/template/PieChartTypeTemplate.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPETEMPLATE_HXX + +#include +#include +#include + +#include "ChartTypeTemplate.hxx" +#include + +namespace chart +{ + +class PieChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void SAL_CALL resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override; + + // ____ ChartTypeTemplate ____ + virtual sal_Int32 getDimension() const override; + + virtual void adaptDiagram( + const css::uno::Reference< css::chart2::XDiagram > & xDiagram ) override; + + virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override; + + virtual void adaptAxes( + const css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > & rCoordSys ) override; + + virtual void adaptScales( + const css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > & aCooSysSeq, + const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories ) override; + + virtual void createChartTypes( + const css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< + css::chart2::XDataSeries > > >& aSeriesSeq, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XCoordinateSystem > > & rCoordSys, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > > & aOldChartTypesSeq + ) override; + + virtual css::uno::Reference< css::chart2::XChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_PIECHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..10798f9bd --- /dev/null +++ b/chart2/source/model/template/ScatterChartType.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( CHART_UNONAME_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_CURVE_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( CHART_UNONAME_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER, + PROP_SCATTERCHARTTYPE_SPLINE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticScatterChartTypeDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCATTERCHARTTYPE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, 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 >( rOutMap, PROP_SCATTERCHARTTYPE_SPLINE_ORDER, 3 ); + } +}; + +struct StaticScatterChartTypeDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticScatterChartTypeDefaults_Initializer > +{ +}; + +struct StaticScatterChartTypeInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticScatterChartTypeInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticScatterChartTypeInfoHelper_Initializer > +{ +}; + +struct StaticScatterChartTypeInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticScatterChartTypeInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticScatterChartTypeInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticScatterChartTypeInfo_Initializer > +{ +}; + +} // 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 )); +} + +// ____ XChartType ____ +Reference< chart2::XCoordinateSystem > SAL_CALL + ScatterChartType::createCoordinateSystem( ::sal_Int32 DimensionCount ) +{ + Reference< chart2::XCoordinateSystem > xResult( + new CartesianCoordinateSystem( DimensionCount )); + + for( sal_Int32 i=0; i xAxis( xResult->getAxisByDimension( 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() +{ + uno::Sequence< OUString > aMandRolesSeq(3); + aMandRolesSeq[0] = "label"; + aMandRolesSeq[1] = "values-x"; + aMandRolesSeq[2] = "values-y"; + return aMandRolesSeq; +} + +// ____ OPropertySet ____ +uno::Any ScatterChartType::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticScatterChartTypeDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartType::getInfoHelper() +{ + return *StaticScatterChartTypeInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartType::getPropertySetInfo() +{ + return *StaticScatterChartTypeInfo::get(); +} + +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 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 000000000..e7f1e24de --- /dev/null +++ b/chart2/source/model/template/ScatterChartType.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPE_HXX + +#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; + +private: + explicit ScatterChartType( const ScatterChartType & rOther ); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedMandatoryRoles() override; + virtual css::uno::Reference< css::chart2::XCoordinateSystem > SAL_CALL + createCoordinateSystem( ::sal_Int32 DimensionCount ) override; + + // ____ OPropertySet ____ + virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPE_HXX +#endif + +/* 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 000000000..e0dc1cd11 --- /dev/null +++ b/chart2/source/model/template/ScatterChartTypeTemplate.cxx @@ -0,0 +1,391 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 "XYDataInterpreter.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 + +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( CHART_UNONAME_CURVE_STYLE, + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_CURVE_RESOLUTION, + PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER, + PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticScatterChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, 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 >( rOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 ); + } +}; + +struct StaticScatterChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticScatterChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticScatterChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } + +}; + +struct StaticScatterChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticScatterChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticScatterChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticScatterChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticScatterChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticScatterChartTypeTemplateInfo_Initializer > +{ +}; + +} // 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 ), + ::property::OPropertySet( m_aMutex ), + m_bHasSymbols( bSymbols ), + m_bHasLines( bHasLines ), + m_nDim( nDim ) +{ + if( nDim == 3 ) + m_bHasSymbols = false; +} + +ScatterChartTypeTemplate::~ScatterChartTypeTemplate() +{} + +// ____ OPropertySet ____ +uno::Any ScatterChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticScatterChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartTypeTemplate::getInfoHelper() +{ + return *StaticScatterChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartTypeTemplate::getPropertySetInfo() +{ + return *StaticScatterChartTypeTemplateInfo::get(); +} + +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 SAL_CALL ScatterChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY_THROW ); + + DataSeriesHelper::switchSymbolsOnOrOff( xProp, m_bHasSymbols, nSeriesIndex ); + DataSeriesHelper::switchLinesOnOrOff( xProp, m_bHasLines ); + DataSeriesHelper::makeLinesThickOrThin( xProp, 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; +} + +sal_Bool SAL_CALL ScatterChartTypeTemplate::matchesTemplate( + const Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) +{ + bool bResult = ChartTypeTemplate::matchesTemplate( 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< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& series : aSeriesVec) + { + try + { + chart2::Symbol aSymbProp; + drawing::LineStyle eLineStyle; + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY_THROW); + + bool bCurrentHasSymbol = (xProp->getPropertyValue( "Symbol") >>= aSymbProp) && + (aSymbProp.Style != chart2::SymbolStyle_NONE); + + if( bCurrentHasSymbol ) + bSymbolFound = true; + + if( bCurrentHasSymbol && (!m_bHasSymbols) ) + { + bResult = false; + break; + } + + bool bCurrentHasLine = (xProp->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 + { + uno::Reference< beans::XPropertySet > xChartTypeProp( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), + uno::UNO_QUERY_THROW ); + 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; +} + +Reference< chart2::XChartType > ScatterChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_SCATTER ), uno::UNO_QUERY_THROW ); + + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE )); + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xCTProp->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL ScatterChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_SCATTER ), uno::UNO_QUERY_THROW ); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + + Reference< beans::XPropertySet > xCTProp( xResult, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE )); + xCTProp->setPropertyValue( + CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION )); + xCTProp->setPropertyValue( + CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< chart2::XDataInterpreter > SAL_CALL ScatterChartTypeTemplate::getDataInterpreter() +{ + 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 000000000..ee32e200f --- /dev/null +++ b/chart2/source/model/template/ScatterChartTypeTemplate.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include +#include +#include + +namespace chart +{ + +class ScatterChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL supportsCategories() override; + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual css::uno::Reference< css::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + + // ____ ChartTypeTemplate ____ + virtual css::uno::Reference< css::chart2::XChartType > + 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 + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_SCATTERCHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..7eb0e1ca5 --- /dev/null +++ b/chart2/source/model/template/StockChartTypeTemplate.cxx @@ -0,0 +1,499 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include "StockDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Open", + PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "LowHigh", + PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "Japanese", + PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); +} + +struct StaticStockChartTypeTemplateDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, true ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, false ); + } +}; + +struct StaticStockChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticStockChartTypeTemplateDefaults_Initializer > +{ +}; + +struct StaticStockChartTypeTemplateInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static Sequence< Property > lcl_GetPropertySequence() + { + std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + return comphelper::containerToSequence( aProperties ); + } +}; + +struct StaticStockChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticStockChartTypeTemplateInfoHelper_Initializer > +{ +}; + +struct StaticStockChartTypeTemplateInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticStockChartTypeTemplateInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticStockChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticStockChartTypeTemplateInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +StockChartTypeTemplate::StockChartTypeTemplate( + uno::Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName, + StockVariant eVariant, + bool bJapaneseStyle ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ), + 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 ____ +uno::Any StockChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticStockChartTypeTemplateDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL StockChartTypeTemplate::getInfoHelper() +{ + return *StaticStockChartTypeTemplateInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL StockChartTypeTemplate::getPropertySetInfo() +{ + return *StaticStockChartTypeTemplateInfo::get(); +} + +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 SAL_CALL StockChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + try + { + sal_Int32 nNewAxisIndex = 0; + + bool bHasVolume = false; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + if( bHasVolume && nChartTypeIndex != 0 ) + nNewAxisIndex = 1; + + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + xProp->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 + if( xProp.is() ) + { + drawing::LineStyle eStyle = drawing::LineStyle_NONE; + xProp->getPropertyValue( "LineStyle" ) >>= eStyle; + if( eStyle == drawing::LineStyle_NONE ) + xProp->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID )); + } + } + + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL StockChartTypeTemplate::resetStyles( + const Reference< chart2::XDiagram >& xDiagram ) +{ + ChartTypeTemplate::resetStyles( xDiagram ); + if( getDimension() == 3 ) + { + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + for (auto const& series : aSeriesVec) + { + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY); + if( xProp.is() ) + xProp->setPropertyValue( "AttachedAxisIndex", uno::Any( sal_Int32(0) ) ); + } + } + + DiagramHelper::setVertical( xDiagram, false ); +} + +Reference< XChartType > StockChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex ) +{ + Reference< XChartType > xCT; + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY ); + if(xFact.is()) + { + bool bHasVolume = false; + getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume; + if( bHasVolume ) + { + if( nChartTypeIndex == 0 ) + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY ); + else if( nChartTypeIndex == 1 ) + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ), uno::UNO_QUERY ); + else + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY ); + } + else + { + if( nChartTypeIndex == 0 ) + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ), uno::UNO_QUERY ); + else + xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY ); + } + } + return xCT; +} + +void StockChartTypeTemplate::createChartTypes( + const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq, + const Sequence< Reference< XCoordinateSystem > > & rCoordSys, + const Sequence< Reference< XChartType > >& /* aOldChartTypesSeq */ ) +{ + if( !rCoordSys.hasElements() ) + return; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + 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; + + sal_Int32 nSeriesIndex = 0; + + std::vector< Reference< chart2::XChartType > > aChartTypeVec; + // Bars (Volume) + if( bHasVolume ) + { + // chart type + Reference< XChartType > xCT( + xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY_THROW ); + aChartTypeVec.push_back( xCT ); + + if( aSeriesSeq.getLength() > nSeriesIndex && + aSeriesSeq[nSeriesIndex].hasElements() ) + { + Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + xDSCnt->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + ++nSeriesIndex; + } + + Reference< XChartType > xCT( + xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ), uno::UNO_QUERY_THROW ); + aChartTypeVec.push_back( xCT ); + + Reference< beans::XPropertySet > xCTProp( xCT, uno::UNO_QUERY ); + if( xCTProp.is()) + { + xCTProp->setPropertyValue( "Japanese", uno::Any( bJapaneseStyle )); + xCTProp->setPropertyValue( "ShowFirst", uno::Any( bShowFirst )); + xCTProp->setPropertyValue( "ShowHighLow", uno::Any( bShowHighLow )); + } + + if( aSeriesSeq.getLength() > nSeriesIndex && + aSeriesSeq[ nSeriesIndex ].hasElements() ) + { + Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + xDSCnt->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + ++nSeriesIndex; + + // Lines (remaining series) + if( aSeriesSeq.getLength() > nSeriesIndex && + aSeriesSeq[ nSeriesIndex ].hasElements() ) + { + xCT.set( + xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + aChartTypeVec.push_back( xCT ); + + Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW ); + xDSCnt->setDataSeries( aSeriesSeq[ nSeriesIndex ] ); + } + + Reference< XChartTypeContainer > xCTCnt( rCoordSys[ 0 ], uno::UNO_QUERY_THROW ); + xCTCnt->setChartTypes( comphelper::containerToSequence(aChartTypeVec) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XChartTypeTemplate ____ +sal_Bool SAL_CALL StockChartTypeTemplate::matchesTemplate( + const uno::Reference< XDiagram >& xDiagram, + sal_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; + + Reference< chart2::XChartType > xVolumeChartType; + Reference< chart2::XChartType > xCandleStickChartType; + Reference< chart2::XChartType > xLineChartType; + sal_Int32 nNumberOfChartTypes = 0; + + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( Reference< XChartType > const & chartType : aChartTypeSeq ) + { + if( chartType.is()) + { + ++nNumberOfChartTypes; + if( nNumberOfChartTypes > 3 ) + break; + OUString aCTService = chartType->getChartType(); + if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) + xVolumeChartType.set( chartType ); + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + xCandleStickChartType.set( chartType ); + else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE ) + xLineChartType.set( chartType ); + } + } + if( nNumberOfChartTypes > 3 ) + break; + } + + if (xCandleStickChartType.is() && bHasVolume == xVolumeChartType.is()) + { + bResult = true; + + // check for japanese style + Reference< beans::XPropertySet > xCTProp( xCandleStickChartType, uno::UNO_QUERY ); + if( xCTProp.is()) + { + bool bJapaneseProp = false; + xCTProp->getPropertyValue( "Japanese") >>= bJapaneseProp; + bResult = bResult && ( bHasJapaneseStyle == bJapaneseProp ); + + // in old chart japanese == showFirst + bool bShowFirstProp = false; + xCTProp->getPropertyValue( "ShowFirst") >>= bShowFirstProp; + bResult = bResult && ( bHasOpenValue == bShowFirstProp ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return bResult; +} + +Reference< XChartType > SAL_CALL StockChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW ); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return xResult; +} + +Reference< XDataInterpreter > SAL_CALL StockChartTypeTemplate::getDataInterpreter() +{ + 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 000000000..6a05450f8 --- /dev/null +++ b/chart2/source/model/template/StockChartTypeTemplate.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKCHARTTYPETEMPLATE_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKCHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include +#include +#include + +namespace chart +{ + +class StockChartTypeTemplate : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ XChartTypeTemplate ____ + virtual sal_Bool SAL_CALL matchesTemplate( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) override; + virtual css::uno::Reference< css::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override; + virtual css::uno::Reference< css::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() override; + virtual void SAL_CALL applyStyle( + const css::uno::Reference< css::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) override; + virtual void SAL_CALL resetStyles( + const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override; + + // ChartTypeTemplate + virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override; + + // ____ ChartTypeTemplate ____ + virtual void createChartTypes( + const css::uno::Sequence< + css::uno::Sequence< + css::uno::Reference< + css::chart2::XDataSeries > > >& aSeriesSeq, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XCoordinateSystem > > & rCoordSys, + const css::uno::Sequence< + css::uno::Reference< + css::chart2::XChartType > > & aOldChartTypesSeq + ) override; + + virtual css::uno::Reference< css::chart2::XChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override; + +private: + // todo: deprecate this variable + StockVariant m_eStockVariant; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKCHARTTYPETEMPLATE_HXX +#endif + +/* 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 000000000..15c289197 --- /dev/null +++ b/chart2/source/model/template/StockDataInterpreter.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 "StockDataInterpreter.hxx" +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +// explicit +StockDataInterpreter::StockDataInterpreter( + StockChartTypeTemplate::StockVariant eVariant ) : + DataInterpreter(), + m_eStockVariant( eVariant ) +{} + +StockDataInterpreter::~StockDataInterpreter() +{} + +// ____ XDataInterpreter ____ +InterpretedData SAL_CALL StockDataInterpreter::interpretDataSource( + const Reference< data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& rArguments, + const Sequence< Reference< XDataSeries > >& rSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + Reference< data::XLabeledDataSequence > xCategories; + Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); + const sal_Int32 nDataCount( aData.getLength()); + + // 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 + Sequence< Sequence< Sequence< Reference< data::XLabeledDataSequence > > > > aSequences( nNumberOfGroups ); + sal_Int32 nBarGroupIndex( 0 ); + sal_Int32 nCandleStickGroupIndex( nNumberOfGroups - 1 ); + + // allocate space for labeled sequences + if( nRemaining > 0 ) + ++nCandleStickSeries; + aSequences[nCandleStickGroupIndex].realloc( nCandleStickSeries ); + 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].realloc( nVolumeSeries ); + } + + // create data + sal_Int32 nSourceIndex = 0; // index into aData sequence + + // 1. categories + if( bHasCategories ) + { + xCategories.set( aData[nSourceIndex] ); + ++nSourceIndex; + } + + // 2. create "full" series + for( sal_Int32 nLabeledSeqIdx=0; nLabeledSeqIdxgetValues(), "values-y"); + ++nSourceIndex; + } + + sal_Int32 nSeqIdx = 0; + if( bHasOpenValues ) + { + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx].realloc( 4 ); + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-first"); + ++nSourceIndex; + ++nSeqIdx; + } + else + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx].realloc( 3 ); + + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-min"); + ++nSourceIndex; + ++nSeqIdx; + + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( aData[nSourceIndex] ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-max"); + ++nSourceIndex; + ++nSeqIdx; + + aSequences[nCandleStickGroupIndex][nLabeledSeqIdx][nSeqIdx].set( 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 ); + aSequences[nBarGroupIndex][nVolumeSeries - 1].realloc( 1 ); + OSL_ASSERT( nDataCount > nSourceIndex ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-y"); + aSequences[nBarGroupIndex][nVolumeSeries - 1][0].set( 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; + aSequences[nCandleStickGroupIndex][nSeriesIndex].realloc( nRemaining ); + OSL_ASSERT( nDataCount > nSourceIndex ); + + // 1. low + sal_Int32 nSeqIdx( 0 ); + aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( aData[nSourceIndex] ); + if( aData[nSourceIndex].is()) + SetRole( aData[nSourceIndex]->getValues(), "values-min"); + ++nSourceIndex; + ++nSeqIdx; + + // 2. high + if( nSeqIdx < nRemaining ) + { + aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( 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 ) + { + aSequences[nCandleStickGroupIndex][nSeriesIndex][nSeqIdx].set( 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 + Sequence< Sequence< Reference< XDataSeries > > > aResultSeries( nNumberOfGroups ); + sal_Int32 nGroupIndex, nReUsedSeriesIdx = 0; + for( nGroupIndex=0; nGroupIndex xSeries; + if( nReUsedSeriesIdx < rSeriesToReUse.getLength()) + xSeries.set( rSeriesToReUse[nReUsedSeriesIdx] ); + else + xSeries.set( new DataSeries ); + OSL_ASSERT( xSeries.is() ); + Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY_THROW ); + xSink->setData( aSequences[nGroupIndex][nSeriesIdx] ); + aResultSeries[nGroupIndex][nSeriesIdx].set( xSeries ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + return InterpretedData( 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) +sal_Bool SAL_CALL StockDataInterpreter::isDataCompatible( + const InterpretedData& aInterpretedData ) +{ + // high/low/close + sal_Int32 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.getLength() < (bHasVolume ? 2 : 1 )) + return false; + + // 2. a. volume -- use default check + if( bHasVolume ) + { + if( ! DataInterpreter::isDataCompatible( + InterpretedData( Sequence< Sequence< Reference< XDataSeries > > >( + aInterpretedData.Series.getConstArray(), 1 ), + aInterpretedData.Categories ))) + return false; + } + + // 2. b. candlestick + { + OSL_ASSERT( aInterpretedData.Series.getLength() > (bHasVolume ? 1 : 0)); + const Sequence< Reference< XDataSeries > > aSeries( aInterpretedData.Series[(bHasVolume ? 1 : 0)] ); + if(!aSeries.hasElements()) + return false; + for( Reference< XDataSeries > const & dataSeries : aSeries ) + { + try + { + Reference< data::XDataSource > xSrc( dataSeries, uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + if( aSeq.getLength() != nNumberOfNecessarySequences ) + return false; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + // 2. c. additional series + // ignore + + return true; +} + +InterpretedData SAL_CALL StockDataInterpreter::reinterpretDataSeries( + const InterpretedData& aInterpretedData ) +{ + // prerequisite: StockDataInterpreter::isDataCompatible() returned true + return aInterpretedData; +} + +} // 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 000000000..2bd5b2b61 --- /dev/null +++ b/chart2/source/model/template/StockDataInterpreter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKDATAINTERPRETER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKDATAINTERPRETER_HXX + +#include "DataInterpreter.hxx" + +#include "StockChartTypeTemplate.hxx" + +namespace chart +{ + +class StockDataInterpreter : public DataInterpreter +{ +public: + explicit StockDataInterpreter( + StockChartTypeTemplate::StockVariant eVariant ); + virtual ~StockDataInterpreter() override; + +protected: + // ____ XDataInterpreter ____ + virtual css::chart2::InterpretedData SAL_CALL interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aSeriesToReUse ) override; + virtual sal_Bool SAL_CALL isDataCompatible( + const css::chart2::InterpretedData& aInterpretedData ) override; + virtual css::chart2::InterpretedData SAL_CALL reinterpretDataSeries( + const css::chart2::InterpretedData& aInterpretedData ) override; + +private: + StockChartTypeTemplate::StockVariant m_eStockVariant; + + StockChartTypeTemplate::StockVariant GetStockVariant() const { return m_eStockVariant;} +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_STOCKDATAINTERPRETER_HXX +#endif + +/* 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 000000000..a3fb67fa9 --- /dev/null +++ b/chart2/source/model/template/XYDataInterpreter.cxx @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "XYDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +XYDataInterpreter::XYDataInterpreter() : + DataInterpreter() +{ +} + +XYDataInterpreter::~XYDataInterpreter() +{ +} + +// ____ XDataInterpreter ____ +chart2::InterpretedData SAL_CALL XYDataInterpreter::interpretDataSource( + const Reference< chart2::data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) +{ + if( ! xSource.is()) + return InterpretedData(); + + const Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); + + Reference< data::XLabeledDataSequence > xValuesX; + vector< Reference< data::XLabeledDataSequence > > aSequencesVec; + + Reference< data::XLabeledDataSequence > xCategories; + bool bHasCategories = HasCategories( aArguments, aData ); + bool bUseCategoriesAsX = UseCategoriesAsX( aArguments ); + + // parse data + bool bCategoriesUsed = false; + bool bSetXValues = aData.getLength()>1; + for( Reference< data::XLabeledDataSequence > const & labelData : aData ) + { + try + { + if( bHasCategories && ! bCategoriesUsed ) + { + xCategories.set( labelData ); + if( xCategories.is()) + { + SetRole( xCategories->getValues(), "categories"); + if( bUseCategoriesAsX ) + bSetXValues = false; + } + bCategoriesUsed = true; + } + else if( !xValuesX.is() && bSetXValues ) + { + xValuesX.set( 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 + vector< Reference< XDataSeries > > aSeriesVec; + aSeriesVec.reserve( aSequencesVec.size()); + + Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; + Reference< util::XCloneable > xCloneable( xValuesX, uno::UNO_QUERY ); + + sal_Int32 nSeriesIndex = 0; + for (auto const& elem : aSequencesVec) + { + vector< Reference< 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); + + Reference< XDataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.getLength()) + xSeries.set( aSeriesToReUse[nSeriesIndex] ); + else + xSeries.set( new DataSeries ); + OSL_ASSERT( xSeries.is() ); + Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + OSL_ASSERT( xSink.is() ); + xSink->setData( comphelper::containerToSequence( aNewData ) ); + + aSeriesVec.push_back( xSeries ); + ++nSeriesIndex; + } + + Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); + aSeries[0] = comphelper::containerToSequence( aSeriesVec ); + return InterpretedData( aSeries, xCategories ); +} + +chart2::InterpretedData SAL_CALL XYDataInterpreter::reinterpretDataSeries( + const chart2::InterpretedData& aInterpretedData ) +{ + InterpretedData aResult( aInterpretedData ); + + sal_Int32 i=0; + Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.getLength(); + for( ; i xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; + + // values-y + Reference< data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-y" )); + Reference< data::XLabeledDataSequence > xValuesX( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-x" )); + // re-use values-... as values-x/values-y + if( ! xValuesX.is() || + ! xValuesY.is()) + { + vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole( + xSeriesSource->getDataSequences(), "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.set( aValueSeqVec[nIndex++] ); + if( xValuesY.is()) + SetRole( xValuesY->getValues(), "values-y"); + } + + if( ! xValuesX.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesX.set( aValueSeqVec[nIndex++] ); + if( xValuesX.is()) + SetRole( xValuesY->getValues(), "values-x"); + } + } + if( xValuesY.is()) + { + if( xValuesX.is()) + { + aNewSequences.realloc(2); + aNewSequences[0] = xValuesX; + aNewSequences[1] = xValuesY; + } + else + { + aNewSequences.realloc(1); + aNewSequences[0] = xValuesY; + } + } + + const Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); + if( aSeqs.getLength() != aNewSequences.getLength() ) + { +#ifdef DBG_UTIL + for( auto const & j : aSeqs ) + { + SAL_WARN_IF((j == xValuesY || j == xValuesX), "chart2.template", "All sequences should be used" ); + } +#endif + Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); + xSink->setData( aNewSequences ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +// criterion: all series must have exactly two data::XLabeledDataSequences +sal_Bool SAL_CALL XYDataInterpreter::isDataCompatible( + const chart2::InterpretedData& aInterpretedData ) +{ + const Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( Reference< XDataSeries > const & dataSeries : aSeries ) + { + try + { + Reference< data::XDataSource > xSrc( dataSeries, uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + if( aSeq.getLength() != 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 000000000..c57889ce8 --- /dev/null +++ b/chart2/source/model/template/XYDataInterpreter.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_XYDATAINTERPRETER_HXX +#define INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_XYDATAINTERPRETER_HXX + +#include "DataInterpreter.hxx" + +namespace chart +{ + +class XYDataInterpreter : public DataInterpreter +{ +public: + explicit XYDataInterpreter(); + virtual ~XYDataInterpreter() override; + +protected: + // ____ XDataInterpreter ____ + virtual css::chart2::InterpretedData SAL_CALL interpretDataSource( + const css::uno::Reference< css::chart2::data::XDataSource >& xSource, + const css::uno::Sequence< css::beans::PropertyValue >& aArguments, + const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aSeriesToReUse ) override; + virtual css::chart2::InterpretedData SAL_CALL reinterpretDataSeries( + const css::chart2::InterpretedData& aInterpretedData ) override; + virtual sal_Bool SAL_CALL isDataCompatible( + const css::chart2::InterpretedData& aInterpretedData ) override; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_MODEL_TEMPLATE_XYDATAINTERPRETER_HXX +#endif + +/* 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 000000000..77bf0555e --- /dev/null +++ b/chart2/source/tools/AxisHelper.cxx @@ -0,0 +1,1158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +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(1); + aSubIncrements[0] = 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 Reference< chart2::XAxis >& xAxis, ChartModel& rModel ) +{ + ScaleData aScale = xAxis->getScaleData(); + Reference< chart2::XCoordinateSystem > 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 Reference< chart2::XAxis >& xAxis + , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem + , const Reference& xChartDoc + , bool bSearchForParallelAxisIfNothingIsFound ) +{ + sal_Int32 nNumberFormatKey(0); + sal_Int32 nAxisIndex = 0; + sal_Int32 nDimensionIndex = 1; + AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex ); + Reference const xNumberFormatsSupplier(xChartDoc, uno::UNO_QUERY); + + Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY ); + if (!xProp.is()) + return 0; + + bool bLinkToSource = true; + xProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource; + xProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey; + + if (bLinkToSource) + { + bool bFormatSet = false; + //check whether we have a percent scale -> use percent format + ChartModel* pModel = nullptr; + if( xNumberFormatsSupplier.is() ) + { + pModel = dynamic_cast( xChartDoc.get() ); + assert(pModel); + } + if (pModel) + { + ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, *pModel ); + if( aData.AxisType==AxisType::PERCENT ) + { + sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier ); + 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( xNumberFormatsSupplier ); + bFormatSet = true; + } + } + else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis + { + Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram() ); + if( DiagramHelper::isSupportingDateAxis( xDiagram ) ) + { + nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier ); + } + else + { + Reference< data::XDataSource > xSource( DataSourceHelper::getUsedData( xChartDoc ) ); + if( xSource.is() ) + { + std::vector< Reference< chart2::data::XLabeledDataSequence > > aXValues( + DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), "values-x" ) ); + if( aXValues.empty() ) + { + Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + 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( xNumberFormatsSupplier ); + } + } + } + } + } + bFormatSet = true; + } + } + + if( !bFormatSet ) + { + std::map< sal_Int32, sal_Int32 > aKeyMap; + bool bNumberFormatKeyFoundViaAttachedData = false; + + try + { + Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW ); + OUString aRoleToMatch; + if( nDimensionIndex == 0 ) + aRoleToMatch = "values-x"; + const Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes()); + for( Reference< XChartType > const & chartType : aChartTypes ) + { + if( nDimensionIndex != 0 ) + aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( chartType ); + Reference< XDataSeriesContainer > xDSCnt( chartType, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries()); + for( Reference< chart2::XDataSeries > const & xDataSeries : aDataSeriesSeq ) + { + Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW ); + + 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( xSource, 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; + Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) ); + nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis, xCorrespondingCoordinateSystem, xChartDoc, false); + } + } + } + } + + return nNumberFormatKey; +} + +Reference< XAxis > AxisHelper::createAxis( + sal_Int32 nDimensionIndex + , sal_Int32 nAxisIndex // 0==main or 1==secondary axis + , const Reference< XCoordinateSystem >& xCooSys + , const Reference< uno::XComponentContext > & xContext + , ReferenceSizeProvider * pRefSizeProvider ) +{ + if( !xContext.is() || !xCooSys.is() ) + return nullptr; + if( nDimensionIndex >= xCooSys->getDimension() ) + return nullptr; + + Reference< XAxis > xAxis( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.Axis", xContext ), uno::UNO_QUERY ); + + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + 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 ); + + Reference< XAxis > xMainAxis( xCooSys->getAxisByDimension( 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 + Reference< beans::XPropertySet > xMainProp( xMainAxis, uno::UNO_QUERY ); + if( xMainProp.is() ) + { + css::chart::ChartAxisPosition eMainAxisPos( css::chart::ChartAxisPosition_ZERO ); + xMainProp->getPropertyValue("CrossoverPosition") >>= eMainAxisPos; + if( eMainAxisPos == css::chart::ChartAxisPosition_END ) + eNewAxisPos = css::chart::ChartAxisPosition_START; + } + } + + Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY ); + if( xProp.is() ) + xProp->setPropertyValue("CrossoverPosition", uno::Any(eNewAxisPos) ); + } + + Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY ); + if( xProp.is() ) try + { + // set correct initial AutoScale + if( pRefSizeProvider ) + pRefSizeProvider->setValuesAtPropertySet( xProp ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xAxis; +} + +Reference< XAxis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const Reference< chart2::XDiagram >& 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; + Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ); + + // create axis + return AxisHelper::createAxis( + nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider ); +} + +void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const Reference< chart2::XDiagram >& xDiagram + , const Reference< uno::XComponentContext >& xContext + , ReferenceSizeProvider * pRefSizeProvider ) +{ + if( !xDiagram.is() ) + return; + + bool bNewAxisCreated = false; + Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); + if( !xAxis.is() && xContext.is() ) + { + // create axis + bNewAxisCreated = true; + xAxis.set( 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 Reference< XDiagram >& xDiagram ) +{ + if( !xDiagram.is() ) + return; + + Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex ); + if(!xCooSys.is()) + return; + + Reference< XAxis > 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->getGridProperties() ); + else + { + const Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( auto const & i : aSubGrids ) + AxisHelper::makeGridVisible( i ); + } +} + +void AxisHelper::makeAxisVisible( const Reference< XAxis >& xAxis ) +{ + Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY ); + if( xProps.is() ) + { + xProps->setPropertyValue( "Show", uno::Any( true ) ); + LinePropertiesHelper::SetLineVisible( xProps ); + xProps->setPropertyValue( "DisplayLabels", uno::Any( true ) ); + } +} + +void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties ) +{ + if( xGridProperties.is() ) + { + xGridProperties->setPropertyValue( "Show", uno::Any( true ) ); + LinePropertiesHelper::SetLineVisible( xGridProperties ); + } +} + +void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const Reference< XDiagram >& xDiagram ) +{ + AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); +} + +void AxisHelper::makeAxisInvisible( const Reference< XAxis >& xAxis ) +{ + Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY ); + if( xProps.is() ) + { + xProps->setPropertyValue( "Show", uno::Any( false ) ); + } +} + +void AxisHelper::hideAxisIfNoDataIsAttached( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram ) +{ + //axis is hidden if no data is attached anymore but data is available + bool bOtherSeriesAttachedToThisAxis = false; + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + for (auto const& series : aSeriesVector) + { + uno::Reference< chart2::XAxis > xCurrentAxis = DiagramHelper::getAttachedAxis(series, xDiagram ); + 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 Reference< XDiagram >& xDiagram ) +{ + if( !xDiagram.is() ) + return; + + Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex ); + if(!xCooSys.is()) + return; + + Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) ); + if(!xAxis.is()) + return; + + if( bMainGrid ) + AxisHelper::makeGridInvisible( xAxis->getGridProperties() ); + else + { + const Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( auto const & i : aSubGrids) + AxisHelper::makeGridInvisible( i ); + } +} + +void AxisHelper::makeGridInvisible( const Reference< beans::XPropertySet >& xGridProperties ) +{ + if( xGridProperties.is() ) + { + xGridProperties->setPropertyValue( "Show", uno::Any( false ) ); + } +} + +bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid + , const Reference< css::chart2::XDiagram >& xDiagram ) +{ + bool bRet = false; + + Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex ); + if(!xCooSys.is()) + return bRet; + + Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) ); + if(!xAxis.is()) + return bRet; + + if( bMainGrid ) + bRet = AxisHelper::isGridVisible( xAxis->getGridProperties() ); + else + { + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + if( aSubGrids.hasElements() ) + bRet = AxisHelper::isGridVisible( aSubGrids[0] ); + } + + return bRet; +} + +Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemByIndex( + const Reference< XDiagram >& xDiagram, sal_Int32 nIndex ) +{ + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if(!xCooSysContainer.is()) + return nullptr; + Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems(); + if(0<=nIndex && nIndex AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis + , const Reference< XDiagram >& xDiagram ) +{ + Reference< XAxis > xRet; + try + { + Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ); + xRet.set( AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys ) ); + } + catch( const uno::Exception & ) + { + } + return xRet; +} + +Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex + , const Reference< XCoordinateSystem >& xCooSys ) +{ + Reference< XAxis > 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.set( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); + return xRet; +} + +Reference< XAxis > AxisHelper::getCrossingMainAxis( const Reference< XAxis >& xAxis + , const Reference< XCoordinateSystem >& xCooSys ) +{ + sal_Int32 nDimensionIndex = 0; + sal_Int32 nAxisIndex = 0; + AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ); + if( nDimensionIndex==2 ) + { + nDimensionIndex=1; + bool bSwapXY = false; + Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY ); + if( xCooSysProp.is() && (xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXY) && bSwapXY ) + nDimensionIndex=0; + } + else if( nDimensionIndex==1 ) + nDimensionIndex=0; + else + nDimensionIndex=1; + return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys ); +} + +Reference< XAxis > AxisHelper::getParallelAxis( const Reference< XAxis >& xAxis + , const Reference< XDiagram >& 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 Reference< XDiagram >& xDiagram ) +{ + return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); +} + +bool AxisHelper::isAxisVisible( const Reference< XAxis >& xAxis ) +{ + bool bRet = false; + + Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY ); + if( xProps.is() ) + { + xProps->getPropertyValue( "Show" ) >>= bRet; + bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xProps ) + || areAxisLabelsVisible( xProps ) ); + } + + return bRet; +} + +bool AxisHelper::areAxisLabelsVisible( const Reference< beans::XPropertySet >& xAxisProperties ) +{ + bool bRet = false; + if( xAxisProperties.is() ) + { + xAxisProperties->getPropertyValue( "DisplayLabels" ) >>= bRet; + } + return bRet; +} + +bool AxisHelper::isGridVisible( const Reference< beans::XPropertySet >& xGridProperies ) +{ + bool bRet = false; + + if( xGridProperies.is() ) + { + xGridProperies->getPropertyValue( "Show" ) >>= bRet; + bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridProperies ); + } + + return bRet; +} + +Reference< beans::XPropertySet > AxisHelper::getGridProperties( + const Reference< XCoordinateSystem >& xCooSys + , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex ) +{ + Reference< beans::XPropertySet > xRet; + + Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) ); + if( xAxis.is() ) + { + if( nSubGridIndex<0 ) + xRet.set( xAxis->getGridProperties() ); + else + { + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + if (nSubGridIndex < aSubGrids.getLength()) + xRet.set( aSubGrids[nSubGridIndex] ); + } + } + + return xRet; +} + +sal_Int32 AxisHelper::getDimensionIndexOfAxis( + const Reference< XAxis >& xAxis + , const Reference< XDiagram >& 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 Reference< XAxis >& xAxis + , const Reference< XCoordinateSystem >& xCooSys + , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex ) +{ + //returns true if indices are found + + rOutDimensionIndex = -1; + rOutAxisIndex = -1; + + if( xCooSys.is() && xAxis.is() ) + { + Reference< XAxis > 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->getAxisByDimension(nDimensionIndex,nAxisIndex); + if( xCurrentAxis == xAxis ) + { + rOutDimensionIndex = nDimensionIndex; + rOutAxisIndex = nAxisIndex; + return true; + } + } + } + } + return false; +} + +bool AxisHelper::getIndicesForAxis( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram + , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex ) +{ + //returns true if indices are found + + rOutCooSysIndex = -1; + rOutDimensionIndex = -1; + rOutAxisIndex = -1; + + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if(xCooSysContainer.is()) + { + Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems(); + for( sal_Int32 nC=0; nC > AxisHelper::getAllAxesOfCoordinateSystem( + const Reference< XCoordinateSystem >& xCooSys + , bool bOnlyVisible /* = false */ ) +{ + std::vector< Reference< XAxis > > 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 + { + Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); + if( xAxis.is() ) + { + bool bAddAxis = true; + if( bOnlyVisible ) + { + Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY ); + if( !xAxisProp.is() || + !(xAxisProp->getPropertyValue( "Show") >>= bAddAxis) ) + bAddAxis = false; + } + if( bAddAxis ) + aAxisVector.push_back( xAxis ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + } + + return aAxisVector; +} + +Sequence< Reference< XAxis > > AxisHelper::getAllAxesOfDiagram( + const Reference< XDiagram >& xDiagram + , bool bOnlyVisible ) +{ + std::vector< Reference< XAxis > > aAxisVector; + + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if(xCooSysContainer.is()) + { + const Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems(); + for( Reference< XCoordinateSystem > const & coords : aCooSysList ) + { + std::vector< Reference< XAxis > > aAxesPerCooSys( AxisHelper::getAllAxesOfCoordinateSystem( coords, bOnlyVisible ) ); + aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() ); + } + } + + return comphelper::containerToSequence( aAxisVector ); +} + +Sequence< Reference< beans::XPropertySet > > AxisHelper::getAllGrids( const Reference< XDiagram >& xDiagram ) +{ + const Sequence< Reference< XAxis > > aAllAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + std::vector< Reference< beans::XPropertySet > > aGridVector; + + for( Reference< XAxis > const & xAxis : aAllAxes ) + { + if(!xAxis.is()) + continue; + Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() ); + if( xGridProperties.is() ) + aGridVector.push_back( xGridProperties ); + + const Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( Reference< beans::XPropertySet > const & xSubGrid : aSubGrids ) + { + if( xSubGrid.is() ) + aGridVector.push_back( xSubGrid ); + } + } + + return comphelper::containerToSequence( aGridVector ); +} + +void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList + , const Reference< XDiagram>& xDiagram, bool bAxis ) +{ + rPossibilityList.realloc(6); + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + //set possibilities: + sal_Int32 nIndex=0; + Reference< XChartType > xChartType = DiagramHelper::getChartTypeByIndex( xDiagram, 0 ); + for(nIndex=0;nIndex<3;nIndex++) + rPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex); + for(nIndex=3;nIndex<6;nIndex++) + if( bAxis ) + rPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount); + else + rPossibilityList[nIndex] = rPossibilityList[nIndex-3]; +} + +bool AxisHelper::isSecondaryYAxisNeeded( const Reference< XCoordinateSystem >& xCooSys ) +{ + Reference< chart2::XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY ); + if( xCTCnt.is() ) + { + const Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes() ); + for( Reference< chart2::XChartType > const & chartType : aChartTypes ) + { + Reference< XDataSeriesContainer > xSeriesContainer( chartType, uno::UNO_QUERY ); + if( !xSeriesContainer.is() ) + continue; + + Sequence< Reference< XDataSeries > > aSeriesList( xSeriesContainer->getDataSeries() ); + for( sal_Int32 nS = aSeriesList.getLength(); nS-- ; ) + { + Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY ); + if(xProp.is()) + { + sal_Int32 nAttachedAxisIndex = 0; + if( ( xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAttachedAxisIndex ) && nAttachedAxisIndex>0 ) + return true; + } + } + } + } + return false; +} + +bool AxisHelper::shouldAxisBeDisplayed( const Reference< XAxis >& xAxis + , const Reference< XCoordinateSystem >& 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(); + Reference< XChartType > 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::getAxisOrGridExcistence( Sequence< sal_Bool >& rExistenceList + , const Reference< XDiagram>& xDiagram, bool bAxis ) +{ + rExistenceList.realloc(6); + + if(bAxis) + { + sal_Int32 nN; + for(nN=0;nN<3;nN++) + rExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram ); + for(nN=3;nN<6;nN++) + rExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram ); + } + else + { + sal_Int32 nN; + + for(nN=0;nN<3;nN++) + rExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram ); + for(nN=3;nN<6;nN++) + rExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram ); + } +} + +bool AxisHelper::changeVisibilityOfAxes( const Reference< XDiagram >& 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 Reference< XDiagram >& 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; +} + +Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis( + const Reference< XAxis >& xAxis + , const Reference< XDiagram >& xDiagram ) +{ + Reference< XCoordinateSystem > xRet; + + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + const Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( Reference< XCoordinateSystem > const & xCooSys : aCooSysList ) + { + std::vector< Reference< XAxis > > aAllAxis( AxisHelper::getAllAxesOfCoordinateSystem( xCooSys ) ); + + std::vector< Reference< XAxis > >::iterator aFound = + std::find( aAllAxis.begin(), aAllAxis.end(), xAxis ); + if( aFound != aAllAxis.end()) + { + xRet.set( xCooSys ); + break; + } + } + } + return xRet; +} + +Reference< XChartType > AxisHelper::getChartTypeByIndex( const Reference< XCoordinateSystem >& xCooSys, sal_Int32 nIndex ) +{ + Reference< XChartType > xChartType; + + Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + if( xChartTypeContainer.is() ) + { + Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + if( nIndex >= 0 && nIndex < aChartTypeList.getLength() ) + xChartType.set( aChartTypeList[nIndex] ); + } + + return xChartType; +} + +void AxisHelper::setRTLAxisLayout( const Reference< XCoordinateSystem >& xCooSys ) +{ + if( !xCooSys.is() ) + return; + + bool bCartesian = xCooSys->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME; + if( !bCartesian ) + return; + + bool bVertical = false; + Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY ); + if( xCooSysProp.is() ) + xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bVertical; + + sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0; + sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1; + + try + { + //reverse direction for horizontal main axis + Reference< chart2::XAxis > 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 + Reference< chart2::XAxis > 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 + Reference< chart2::XAxis > 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 + Reference< chart2::XAxis > 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"); + } +} + +Reference< XChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const Reference< chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex ) +{ + Reference< XChartType > xChartType; + std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + for (auto const& series : aSeriesVector) + { + sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series); + if( nAttachedAxisIndex == nCurrentIndex ) + { + xChartType = DiagramHelper::getChartTypeOfSeries(xDiagram, series); + if(xChartType.is()) + break; + } + } + return xChartType; +} + +bool AxisHelper::isAxisPositioningEnabled() +{ + const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().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 000000000..9c475bc75 --- /dev/null +++ b/chart2/source/tools/BaseGFXHelper.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 +#include +#include + +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; +} + +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())); +} + +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 000000000..95777aa0e --- /dev/null +++ b/chart2/source/tools/CachedDataSequence.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 +#include +#include + +#include +#include +#include + +#include + +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 ::comphelper::OMutexAndBroadcastHelper; +using ::comphelper::OPropertyArrayUsageHelper; +using ::chart::impl::CachedDataSequence_Base; + +namespace +{ +static const char lcl_aServiceName[] = "com.sun.star.comp.chart.CachedDataSequence"; + +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( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} +CachedDataSequence::CachedDataSequence( const Reference< uno::XComponentContext > & /*xContext*/ ) + : OPropertyContainer( GetBroadcastHelper()), + CachedDataSequence_Base( GetMutex()), + m_eCurrentDataType( MIXED ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder( )) +{ + registerProperties(); +} + +CachedDataSequence::CachedDataSequence( const OUString & rSingleText ) + : OPropertyContainer( GetBroadcastHelper()), + CachedDataSequence_Base( GetMutex()), + m_eCurrentDataType( TEXTUAL ), + m_aTextualSequence({rSingleText}), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} + +CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource ) + : OMutexAndBroadcastHelper(), + OPropertyContainer( GetBroadcastHelper()), + OPropertyArrayUsageHelper< CachedDataSequence >(), + CachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey( rSource.m_nNumberFormatKey ), + m_sRole( rSource.m_sRole ), + m_eCurrentDataType( rSource.m_eCurrentDataType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + 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::get() ); + + registerProperty( "Role", + PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + & m_sRole, + cppu::UnoType::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() +{ + CachedDataSequence * pNewSeq = new CachedDataSequence( *this ); + + return Reference< util::XCloneable >( pNewSeq ); +} + +void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// 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 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 000000000..659ef6d95 --- /dev/null +++ b/chart2/source/tools/CharacterProperties.cxx @@ -0,0 +1,459 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "CharFontStyleName", + PROP_CHAR_FONT_STYLE_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + // CharFontFamily (see awt.FontFamily) + rOutProperties.emplace_back( "CharFontFamily", + PROP_CHAR_FONT_FAMILY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontCharSet (see awt.CharSet) + rOutProperties.emplace_back( "CharFontCharSet", + PROP_CHAR_FONT_CHAR_SET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontPitch (see awt.FontPitch) + rOutProperties.emplace_back( "CharFontPitch", + PROP_CHAR_FONT_PITCH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharColor + rOutProperties.emplace_back( "CharColor", + PROP_CHAR_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharEscapement + rOutProperties.emplace_back( "CharEscapement", + PROP_CHAR_ESCAPEMENT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + // CharHeight + rOutProperties.emplace_back( "CharHeight", + PROP_CHAR_CHAR_HEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharUnderline (see awt.FontUnderline) + rOutProperties.emplace_back( "CharUnderline", + PROP_CHAR_UNDERLINE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharUnderlineColor + rOutProperties.emplace_back( "CharUnderlineColor", + PROP_CHAR_UNDERLINE_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + // CharUnderlineHasColor + rOutProperties.emplace_back( "CharUnderlineHasColor", + PROP_CHAR_UNDERLINE_HAS_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharOverline (see awt.FontUnderline) + rOutProperties.emplace_back( "CharOverline", + PROP_CHAR_OVERLINE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharOverlineColor + rOutProperties.emplace_back( "CharOverlineColor", + PROP_CHAR_OVERLINE_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + // CharOverlineHasColor + rOutProperties.emplace_back( "CharOverlineHasColor", + PROP_CHAR_OVERLINE_HAS_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharWeight (see awt.FontWeight) + rOutProperties.emplace_back( "CharWeight", + PROP_CHAR_WEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharPosture + rOutProperties.emplace_back( "CharPosture", + PROP_CHAR_POSTURE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "CharAutoKerning", + PROP_CHAR_AUTO_KERNING, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "CharKerning", + PROP_CHAR_KERNING, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + // CharEscapementHeight + rOutProperties.emplace_back( "CharEscapementHeight", + PROP_CHAR_ESCAPEMENT_HEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + // CharStrikeout (see awt.FontStrikeout) + rOutProperties.emplace_back( "CharStrikeout", + PROP_CHAR_STRIKE_OUT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharWordMode + rOutProperties.emplace_back( "CharWordMode", + PROP_CHAR_WORD_MODE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharLocale + rOutProperties.emplace_back( "CharLocale", + PROP_CHAR_LOCALE, + cppu::UnoType::get(), + //#i111967# no PropertyChangeEvent is fired on change so far + beans::PropertyAttribute::MAYBEDEFAULT ); + // CharShadowed + rOutProperties.emplace_back( "CharShadowed", + PROP_CHAR_SHADOWED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharContoured + rOutProperties.emplace_back( "CharContoured", + PROP_CHAR_CONTOURED, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharRelief (see text.FontRelief) + rOutProperties.emplace_back( "CharRelief", + PROP_CHAR_RELIEF, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // CharEmphasize (see text.FontEmphasis) + rOutProperties.emplace_back( "CharEmphasis", + PROP_CHAR_EMPHASIS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharacterPropertiesAsian + + // CharFontNameAsian + rOutProperties.emplace_back( "CharFontNameAsian", + PROP_CHAR_ASIAN_FONT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontStyleNameAsian + rOutProperties.emplace_back( "CharFontStyleNameAsian", + PROP_CHAR_ASIAN_FONT_STYLE_NAME, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontCharSetAsian (see awt.CharSet) + rOutProperties.emplace_back( "CharFontCharSetAsian", + PROP_CHAR_ASIAN_CHAR_SET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontPitchAsian (see awt.FontPitch) + rOutProperties.emplace_back( "CharFontPitchAsian", + PROP_CHAR_ASIAN_FONT_PITCH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharHeightAsian + rOutProperties.emplace_back( "CharHeightAsian", + PROP_CHAR_ASIAN_CHAR_HEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharWeightAsian + rOutProperties.emplace_back( "CharWeightAsian", + PROP_CHAR_ASIAN_WEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharPostureAsian + rOutProperties.emplace_back( "CharPostureAsian", + PROP_CHAR_ASIAN_POSTURE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharLocaleAsian + rOutProperties.emplace_back( "CharLocaleAsian", + PROP_CHAR_ASIAN_LOCALE, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontStyleNameComplex + rOutProperties.emplace_back( "CharFontStyleNameComplex", + PROP_CHAR_COMPLEX_FONT_STYLE_NAME, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontCharSetComplex (see awt.CharSet) + rOutProperties.emplace_back( "CharFontCharSetComplex", + PROP_CHAR_COMPLEX_CHAR_SET, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharFontPitchComplex (see awt.FontPitch) + rOutProperties.emplace_back( "CharFontPitchComplex", + PROP_CHAR_COMPLEX_FONT_PITCH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharHeightComplex + rOutProperties.emplace_back( "CharHeightComplex", + PROP_CHAR_COMPLEX_CHAR_HEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharWeightComplex + rOutProperties.emplace_back( "CharWeightComplex", + PROP_CHAR_COMPLEX_WEIGHT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharPostureComplex + rOutProperties.emplace_back( "CharPostureComplex", + PROP_CHAR_COMPLEX_POSTURE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + // CharLocaleComplex + rOutProperties.emplace_back( "CharLocaleComplex", + PROP_CHAR_COMPLEX_LOCALE, + cppu::UnoType::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::get(), /*css::text::WritingMode2*/ + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ParaIsCharacterDistance", + PROP_PARA_IS_CHARACTER_DISTANCE, + cppu::UnoType::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("DefaultLocale") >>= aDefaultLocale; + lang::Locale aDefaultLocale_CJK; + aLinguConfig.GetProperty("DefaultLocale_CJK") >>= aDefaultLocale_CJK; + lang::Locale aDefaultLocale_CTL; + aLinguConfig.GetProperty("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< sal_Int32 >( rOutMap, PROP_CHAR_COLOR, -1 ); //automatic color (COL_AUTO) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CHAR_HEIGHT, fDefaultFontHeight ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE, awt::FontUnderline::NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_CHAR_UNDERLINE_COLOR, -1 ); //automatic color (COL_AUTO) + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE_HAS_COLOR, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_OVERLINE, awt::FontUnderline::NONE ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_CHAR_OVERLINE_COLOR, -1 ); //automatic color (COL_AUTO) + ::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< sal_Int16 >( rOutMap, PROP_CHAR_KERNING, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( 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 000000000..2d684b059 --- /dev/null +++ b/chart2/source/tools/ChartModelHelper.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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +uno::Reference< chart2::data::XRangeHighlighter > ChartModelHelper::createRangeHighlighter( + const uno::Reference< view::XSelectionSupplier > & xSelectionSupplier ) +{ + return new RangeHighlighter( xSelectionSupplier ); +} + +uno::Reference< chart2::data::XDataProvider > ChartModelHelper::createInternalDataProvider( + const uno::Reference< css::chart2::XChartDocument >& 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()) + { + css::uno::Reference< css::chart::XChartDocument > xDoc(xChartDoc, 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 ); +} + +uno::Reference< XDiagram > ChartModelHelper::findDiagram( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + if( xChartDoc.is()) + return ChartModelHelper::findDiagram( xChartDoc ); + return nullptr; +} + +uno::Reference< XDiagram > ChartModelHelper::findDiagram( const uno::Reference< chart2::XChartDocument >& xChartDoc ) +{ + try + { + if( xChartDoc.is()) + return xChartDoc->getFirstDiagram(); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return nullptr; +} + +uno::Reference< XCoordinateSystem > ChartModelHelper::getFirstCoordinateSystem( ChartModel& rModel ) +{ + uno::Reference< XCoordinateSystem > XCooSys; + uno::Reference< XCoordinateSystemContainer > xCooSysCnt( rModel.getFirstDiagram(), uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); + if( aCooSysSeq.hasElements() ) + XCooSys = aCooSysSeq[0]; + } + return XCooSys; +} + +uno::Reference< XCoordinateSystem > ChartModelHelper::getFirstCoordinateSystem( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XCoordinateSystem > XCooSys; + uno::Reference< XCoordinateSystemContainer > xCooSysCnt( ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() ); + if( aCooSysSeq.hasElements() ) + XCooSys = aCooSysSeq[0]; + } + return XCooSys; +} + +std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( + ChartModel& rModel ) +{ + std::vector< uno::Reference< XDataSeries > > aResult; + + uno::Reference< XDiagram > xDiagram = rModel.getFirstDiagram(); + if( xDiagram.is()) + aResult = DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + return aResult; +} + +std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( + const uno::Reference< XChartDocument > & xChartDoc ) +{ + std::vector< uno::Reference< XDataSeries > > aResult; + + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartDoc ); + if( xDiagram.is()) + aResult = DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + + return aResult; +} + +std::vector< uno::Reference< XDataSeries > > ChartModelHelper::getDataSeries( + const uno::Reference< frame::XModel > & xModel ) +{ + return getDataSeries( uno::Reference< chart2::XChartDocument >( xModel, uno::UNO_QUERY )); +} + +uno::Reference< XChartType > ChartModelHelper::getChartTypeOfSeries( + const uno::Reference< frame::XModel >& xModel + , const uno::Reference< XDataSeries >& xGivenDataSeries ) +{ + return DiagramHelper::getChartTypeOfSeries( ChartModelHelper::findDiagram( xModel ), xGivenDataSeries ); +} + +awt::Size ChartModelHelper::getDefaultPageSize() +{ + return awt::Size( 16000, 9000 ); +} + +awt::Size ChartModelHelper::getPageSize( const uno::Reference< frame::XModel >& xModel ) +{ + awt::Size aPageSize( ChartModelHelper::getDefaultPageSize() ); + uno::Reference< embed::XVisualObject > xVisualObject(xModel,uno::UNO_QUERY); + OSL_ENSURE(xVisualObject.is(),"need xVisualObject for page size"); + if( xVisualObject.is() ) + aPageSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + return aPageSize; +} + +void ChartModelHelper::triggerRangeHighlighting( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xModel, uno::UNO_QUERY ); + if( xDataReceiver.is() ) + { + uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY ); + //trigger selection of cell range + if( xSelectionChangeListener.is() ) + { + lang::EventObject aEvent( xSelectionChangeListener ); + xSelectionChangeListener->selectionChanged( aEvent ); + } + } +} + +bool ChartModelHelper::isIncludeHiddenCells( const uno::Reference< frame::XModel >& xChartModel ) +{ + bool bIncluded = true; // hidden cells are included by default. + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram(xChartModel) ); + if (!xDiagram.is()) + return bIncluded; + + uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY ); + if (!xProp.is()) + return bIncluded; + + try + { + xProp->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 + { + uno::Reference< chart2::data::XDataSource > 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 000000000..236d066f7 --- /dev/null +++ b/chart2/source/tools/ChartTypeHelper.cxx @@ -0,0 +1,709 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace chart +{ + +bool ChartTypeHelper::isSupportingAxisSideBySide( + const uno::Reference< chart2::XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& xChartType, sal_Int32 nDimensionCount ) +{ + // note: old chart: only scatter chart + return isSupportingStatisticProperties( xChartType, nDimensionCount ); +} + +bool ChartTypeHelper::isSupportingAreaProperties( const uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& xChartType + , bool bSwapXAndY + , const uno::Reference< chart2::XDataSeries >& 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; + uno::Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY_THROW ); + xChartTypeProp->getPropertyValue( "UseRings") >>= bDonut; + + if(!bDonut) + { + aRet.realloc(4); + 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; + } + 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; + { + uno::Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + chart2::StackingDirection eStacking = chart2::StackingDirection_NO_STACKING; + xSeriesProp->getPropertyValue( "StackingDirection" ) >>= eStacking; + 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; + { + uno::Reference xSeriesProp(xSeries, uno::UNO_QUERY); + chart2::StackingDirection eStacking = chart2::StackingDirection_NO_STACKING; + xSeriesProp->getPropertyValue("StackingDirection") >>= eStacking; + 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 uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return false; + } + return true; +} + +bool ChartTypeHelper::isSupportingStartingAngle( const uno::Reference< chart2::XChartType >& xChartType ) +{ + if(xChartType.is()) + { + OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return true; + } + return false; +} +bool ChartTypeHelper::isSupportingBaseValue( const uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& xChartType ) +{ + if( xChartType.is() ) + { + OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return false; + } + return true; +} + +bool ChartTypeHelper::isSupportingCategoryPositioning( const uno::Reference< chart2::XChartType >& 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::noBordersForSimpleScheme( const uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< chart2::XChartType >& 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 uno::Reference< + XChartType >& 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 uno::Reference< XChartType >& xChartType, + sal_Int32 nNumberOfSeries ) +{ + if( xChartType.is() ) + { + try + { + OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_PIE ) + { + uno::Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY_THROW ); + bool bDonut = false; + if( (xChartTypeProp->getPropertyValue( "UseRings") >>= bDonut) + && !bDonut ) + { + return nNumberOfSeries>0 ? 1 : 0; + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + return nNumberOfSeries; +} + +uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( const uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 uno::Reference< XChartType >& 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 000000000..a341f8894 --- /dev/null +++ b/chart2/source/tools/ChartViewHelper.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 +#include + +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +void ChartViewHelper::setViewToDirtyState( const uno::Reference< frame::XModel >& xChartModel ) +{ + try + { + uno::Reference< lang::XMultiServiceFactory > xFact( xChartModel, uno::UNO_QUERY ); + if( xFact.is() ) + { + Reference< util::XModifyListener > xModifyListener( + xFact->createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + if( xModifyListener.is() ) + { + lang::EventObject aEvent( xChartModel ); + xModifyListener->modified( aEvent ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} +} //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 000000000..34aeb7866 --- /dev/null +++ b/chart2/source/tools/ColorPerPointHelper.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 +#include +#include + +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +bool ColorPerPointHelper::hasPointOwnColor( + const css::uno::Reference< css::beans::XPropertySet >& xDataSeriesProperties + , sal_Int32 nPointIndex + , const css::uno::Reference< css::beans::XPropertySet >& xDataPointProperties //may be NULL this is just for performance + ) +{ + if( !xDataSeriesProperties.is() ) + return false; + + if( hasPointOwnProperties( xDataSeriesProperties, nPointIndex )) + { + uno::Reference< beans::XPropertyState > xPointState( xDataPointProperties, uno::UNO_QUERY ); + if( !xPointState.is() ) + { + uno::Reference< XDataSeries > xSeries( xDataSeriesProperties, uno::UNO_QUERY ); + if(xSeries.is()) + xPointState.set( xSeries->getDataPointByIndex( nPointIndex ), uno::UNO_QUERY ); + } + if( !xPointState.is() ) + return false; + + return (xPointState->getPropertyState( "Color") != beans::PropertyState_DEFAULT_VALUE ); + } + + return false; +} + +bool ColorPerPointHelper::hasPointOwnProperties( + const css::uno::Reference< css::beans::XPropertySet >& xSeriesProperties + , sal_Int32 nPointIndex ) +{ + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aIndexList ) + { + 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 000000000..01b2c2c75 --- /dev/null +++ b/chart2/source/tools/CommonConverters.cxx @@ -0,0 +1,522 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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)); + aM.set(2, 0, rM.get(3, 0)); + aM.set(2, 1, rM.get(3, 1)); + aM.set(2, 2, rM.get(3, 3)); + 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 = rM.get(2, 0); + aHM.Line3.Column2 = rM.get(2, 1); + aHM.Line3.Column3 = rM.get(2, 2); + 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; +} + +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= nAddOuterCount ) + break; + + rRet.SequenceX[nOuter] = rAdd.SequenceX[nIndex]; + rRet.SequenceY[nOuter] = rAdd.SequenceY[nIndex]; + rRet.SequenceZ[nOuter] = rAdd.SequenceZ[nIndex]; + + nIndex++; + } +} + +void appendPoly( drawing::PolyPolygonShape3D& rRet, const drawing::PolyPolygonShape3D& rAdd ) +{ + sal_Int32 nOuterCount = std::max( rRet.SequenceX.getLength(), rAdd.SequenceX.getLength() ); + rRet.SequenceX.realloc(nOuterCount); + rRet.SequenceY.realloc(nOuterCount); + rRet.SequenceZ.realloc(nOuterCount); + + for( sal_Int32 nOuter=0;nOuter0 ) + 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() ); + + for(sal_Int32 nN = 0; nN < rPolyPolygon.SequenceX.getLength(); nN++) + { + sal_Int32 nInnerLength = rPolyPolygon.SequenceX[nN].getLength(); + aRet[nN].realloc( nInnerLength ); + for( sal_Int32 nM = 0; nM < nInnerLength; nM++) + { + aRet[nN][nM].X = static_cast(rPolyPolygon.SequenceX[nN][nM]); + aRet[nN][nM].Y = static_cast(rPolyPolygon.SequenceY[nN][nM]); + } + } + return aRet; +} + +void appendPointSequence( drawing::PointSequenceSequence& rTarget + , drawing::PointSequenceSequence& rAdd ) +{ + sal_Int32 nAddCount = rAdd.getLength(); + if(!nAddCount) + return; + sal_Int32 nOldCount = rTarget.getLength(); + + rTarget.realloc(nOldCount+nAddCount); + for(sal_Int32 nS=0; nS(rPos.PositionX); + aRet.Y = static_cast(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(rDirection.DirectionX); + aRet.Height = static_cast(rDirection.DirectionY); + return aRet; +} + +uno::Sequence< double > B3DPointToSequence( const ::basegfx::B3DPoint& rPoint ) +{ + uno::Sequence< double > aRet(3); + aRet[0] = rPoint.getX(); + aRet[1] = rPoint.getY(); + aRet[2] = rPoint.getZ(); + 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; +} + +uno::Sequence< double > Position3DToSequence( const drawing::Position3D& rPosition ) +{ + uno::Sequence< double > aRet(3); + aRet[0] = rPosition.PositionX; + aRet[1] = rPosition.PositionY; + aRet[2] = rPosition.PositionZ; + 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()); + for(sal_Int32 nN=aValues.getLength();nN--;) + { + if( !(aValues[nN] >>= aResult[nN]) ) + ::rtl::math::setNan( &aResult[nN] ); + } + } + + 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()); + + for(sal_Int32 nN=aValues.getLength();nN--;) + aValues[nN] >>= aResult[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(n32); + } + return nRet; +} + +bool replaceParamterInString( OUString & rInOutResourceString, + const OUString & rParamToReplace, + const OUString & rReplaceWith ) +{ + sal_Int32 nPos = rInOutResourceString.indexOf( rParamToReplace ); + if( nPos == -1 ) + return false; + + rInOutResourceString = rInOutResourceString.replaceAt( nPos + , rParamToReplace.getLength(), 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 000000000..e3bdb20fa --- /dev/null +++ b/chart2/source/tools/ConfigColorScheme.cxx @@ -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 . + */ + +#include + +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +static const char aSeriesPropName[] = "Series"; + +} // 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 ); + + void addPropertyNotification( const OUString & rPropertyName ); + 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; + std::set< OUString > m_aPropertiesToNotify; +}; + +ChartConfigItem::ChartConfigItem( ConfigColorScheme & rListener ) : + ::utl::ConfigItem( "Office.Chart/DefaultColor" ), + m_rListener( rListener ) +{} + +void ChartConfigItem::Notify( const Sequence< OUString > & aPropertyNames ) +{ + for( OUString const & s : aPropertyNames ) + { + if( m_aPropertiesToNotify.find( s ) != m_aPropertiesToNotify.end()) + m_rListener.notify( s ); + } +} + +void ChartConfigItem::ImplCommit() +{} + +void ChartConfigItem::addPropertyNotification( const OUString & rPropertyName ) +{ + m_aPropertiesToNotify.insert( rPropertyName ); + EnableNotification( comphelper::containerToSequence( m_aPropertiesToNotify )); +} + +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 )); + m_apChartConfigItem->addPropertyNotification( aSeriesPropName ); + } + OSL_ASSERT(m_apChartConfigItem); + if (!m_apChartConfigItem) + return; + + // 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 = SAL_N_ELEMENTS( nDefaultColors ); + return nDefaultColors[ nIndex % nMaxDefaultColors ]; +} + +void ConfigColorScheme::notify( const OUString & rPropertyName ) +{ + if( rPropertyName == aSeriesPropName ) + 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 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 000000000..7719755e9 --- /dev/null +++ b/chart2/source/tools/ControllerLockGuard.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 +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +ControllerLockGuardUNO::ControllerLockGuardUNO( const uno::Reference< frame::XModel >& xModel ) : + mxModel( xModel ) +{ + mxModel->lockControllers(); +} + +ControllerLockGuardUNO::~ControllerLockGuardUNO() +{ + mxModel->unlockControllers(); +} + +ControllerLockGuard::ControllerLockGuard( ChartModel& rModel ) : + mrModel( rModel ) +{ + mrModel.lockControllers(); +} + +ControllerLockGuard::~ControllerLockGuard() +{ + mrModel.unlockControllers(); +} + +ControllerLockHelper::ControllerLockHelper( const Reference< frame::XModel > & xModel ) : + m_xModel( 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 000000000..c90a356bf --- /dev/null +++ b/chart2/source/tools/DataSeriesHelper.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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +class lcl_MatchesRole +{ +public: + explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) : + m_aRole( 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; +}; + +Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( + const Reference< chart2::data::XDataSource > & xDataSource ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + + for( auto const & labeledData : aSequences ) + { + 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; +} + +void lcl_getCooSysAndChartTypeOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram, + Reference< chart2::XCoordinateSystem > & xOutCooSys, + Reference< chart2::XChartType > & xOutChartType ) +{ + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( !xCooSysCnt.is()) + return; + + const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + for( Reference< chart2::XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< chart2::XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); + for( Reference< chart2::XChartType > const & chartType : aChartTypes ) + { + Reference< chart2::XDataSeriesContainer > xSeriesCnt( chartType, uno::UNO_QUERY ); + if( xSeriesCnt.is()) + { + const Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); + for( Reference< chart2::XDataSeries > const & dataSeries : aSeries ) + { + if( dataSeries == xSeries ) + { + xOutCooSys.set( coords ); + xOutChartType.set( chartType ); + } + } + } + } + } +} + +void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert ) +{ + try + { + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + DataPointLabel aLabelAtSeries; + xSeriesProperties->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabelAtSeries; + aLabelAtSeries.ShowNumber = bInsert; + if( !bInsert ) + { + aLabelAtSeries.ShowNumberInPercent = false; + aLabelAtSeries.ShowCategoryName = false; + } + xSeriesProperties->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabelAtSeries)); + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= 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; + } + xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel)); + } + } + } + } + } + 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; +} + +Reference< chart2::data::XLabeledDataSequence > + getDataSequenceByRole( + const Reference< chart2::data::XDataSource > & xSource, + const OUString& aRole, + bool bMatchPrefix /* = false */ ) +{ + Reference< chart2::data::XLabeledDataSequence > aNoResult; + if( ! xSource.is()) + return aNoResult; + Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences()); + + const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray(); + const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength(); + const Reference< chart2::data::XLabeledDataSequence > * pMatch = + std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix )); + + if( pMatch != pEnd ) + return *pMatch; + + return aNoResult; +} + +std::vector< Reference< chart2::data::XLabeledDataSequence > > + getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences, + const OUString& aRole ) +{ + std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec; + std::copy_if( aDataSequences.begin(), aDataSequences.end(), + std::back_inserter( aResultVec ), + lcl_MatchesRole(aRole, /*bMatchPrefix*/true) ); + return aResultVec; +} + +std::vector > +getAllDataSequences( const uno::Sequence >& aSeries ) +{ + std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec; + + for( uno::Reference const & dataSeries : aSeries ) + { + Reference< chart2::data::XDataSource > xSource( dataSeries, uno::UNO_QUERY ); + if( xSource.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); + std::copy( aSeq.begin(), aSeq.end(), + std::back_inserter( aSeqVec )); + } + } + + return aSeqVec; +} + +Reference< chart2::data::XDataSource > + getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries ) +{ + return Reference< chart2::data::XDataSource >( + new DataSource(comphelper::containerToSequence(getAllDataSequences(aSeries)))); +} + +namespace +{ +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; +} +} + +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 getDataSeriesLabel( + const Reference< chart2::XDataSeries > & xSeries, + const OUString & rLabelSequenceRole ) +{ + OUString aResult; + + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( xSource.is()) + { + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, 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( xSource )); + if( xLabeledSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); + if( xSeq.is()) + aResult = lcl_getDataSequenceLabel( xSeq ); + } + } + + } + + return aResult; +} + +void setStackModeAtSeries( + const Sequence< Reference< chart2::XDataSeries > > & aSeries, + const Reference< chart2::XCoordinateSystem > & 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( Reference< chart2::XDataSeries > const & dataSeries : aSeries ) + { + try + { + Reference< beans::XPropertySet > xProp( dataSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + xProp->setPropertyValue( "StackingDirection", aPropValue ); + + sal_Int32 nAxisIndex; + xProp->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) + { + Reference< chart2::XAxis > xAxis( + xCorrespondingCoordinateSystem->getAxisByDimension(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 Reference< chart2::XDataSeries > & xSeries ) +{ + sal_Int32 nRet = 0; + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nRet; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return nRet; +} + +sal_Int32 getNumberFormatKeyFromAxis( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, + sal_Int32 nDimensionIndex, + sal_Int32 nAxisIndex /* = -1 */ ) +{ + sal_Int32 nResult = 0; + if( nAxisIndex == -1 ) + nAxisIndex = getAttachedAxisIndex( xSeries ); + try + { + Reference< beans::XPropertySet > xAxisProp( + xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); + if( xAxisProp.is()) + xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nResult; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return nResult; +} + +Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram ) +{ + Reference< chart2::XCoordinateSystem > xResult; + Reference< chart2::XChartType > xDummy; + lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy ); + + return xResult; +} + +Reference< chart2::XChartType > getChartTypeOfSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XDiagram > & xDiagram ) +{ + Reference< chart2::XChartType > xResult; + Reference< chart2::XCoordinateSystem > xDummy; + lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult ); + + return xResult; +} + +void deleteSeries( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::XChartType > & xChartType ) +{ + try + { + Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW ); + auto aSeries( + comphelper::sequenceToContainer > >( xSeriesCnt->getDataSeries())); + std::vector< Reference< chart2::XDataSeries > >::iterator aIt = + std::find( aSeries.begin(), aSeries.end(), xSeries ); + if( aIt != aSeries.end()) + { + aSeries.erase( aIt ); + xSeriesCnt->setDataSeries( comphelper::containerToSequence( aSeries )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, + bool bSymbolsOn, sal_Int32 nSeriesIndex ) +{ + if( !xSeriesProperties.is() ) + return; + + chart2::Symbol aSymbProp; + if( xSeriesProperties->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; + } + xSeriesProperties->setPropertyValue( "Symbol", uno::Any( aSymbProp )); + } + //todo: check attributed data points +} + +void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn ) +{ + if( !xSeriesProperties.is() ) + return; + + if( bLinesOn ) + { + // keep line-styles that are not NONE + drawing::LineStyle eLineStyle; + if( (xSeriesProperties->getPropertyValue( "LineStyle") >>= eLineStyle ) && + eLineStyle == drawing::LineStyle_NONE ) + { + xSeriesProperties->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) ); + } + } + else + xSeriesProperties->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) ); +} + +void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick ) +{ + if( !xSeriesProperties.is() ) + return; + + sal_Int32 nNewValue = bThick ? 80 : 0; + sal_Int32 nOldValue = 0; + if( (xSeriesProperties->getPropertyValue( "LineWidth") >>= nOldValue ) && + nOldValue != nNewValue ) + { + if( !(bThick && nOldValue>0)) + xSeriesProperties->setPropertyValue( "LineWidth", uno::Any( nNewValue ) ); + } +} + +void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( !xSeriesProperties.is() ) + return; + + xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue ); + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= 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 Reference< chart2::XDataSeries >& xSeries, + const OUString& rPropertyName, const uno::Any& rPropertyValue ) +{ + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( !xSeriesProperties.is() ) + return false; + + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= 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 +{ + +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 hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries ) +{ + uno::Reference< chart2::data::XDataSource > xDataSource( xSeries, uno::UNO_QUERY ); + + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences(); + + for(sal_Int32 nN = aDataSequences.getLength();nN--;) + { + if( !aDataSequences[nN].is() ) + continue; + if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) ) + return true; + if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) ) + return true; + } + return false; +} + +sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate ) +{ + if( !bTranslate ) + return nIndex; + + try + { + uno::Reference xProp( xDataSequence, uno::UNO_QUERY ); + if( xProp.is()) + { + Sequence aHiddenIndicesSeq; + xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenIndicesSeq; + if( aHiddenIndicesSeq.hasElements() ) + { + auto aHiddenIndices( comphelper::sequenceToContainer>( aHiddenIndicesSeq ) ); + std::sort( aHiddenIndices.begin(), aHiddenIndices.end() ); + + sal_Int32 nHiddenCount = static_cast(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 Reference< chart2::XDataSeries >& xSeries ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if( xProp.is() ) + { + DataPointLabel aLabel; + if( xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= 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; + if( bRet ) + break; + } + } + } + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex ) +{ + bool bRet = false; + try + { + Reference< beans::XPropertySet > xProp; + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + { + auto aIndices( comphelper::sequenceToContainer>( aAttributedDataPointIndexList ) ); + std::vector< sal_Int32 >::iterator aIt = std::find( aIndices.begin(), aIndices.end(), nPointIndex ); + if( aIt != aIndices.end()) + xProp = xSeries->getDataPointByIndex(nPointIndex); + else + xProp = xSeriesProperties; + } + if( xProp.is() ) + { + DataPointLabel aLabel; + if( xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) + bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; + } + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return bRet; +} + +void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries ) +{ + lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ ); +} + +void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& 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; + xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel)); + } + } + 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 000000000..bdcac98ef --- /dev/null +++ b/chart2/source/tools/DataSource.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 +#include + +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() +{} + +// ____ 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 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 000000000..50fd37347 --- /dev/null +++ b/chart2/source/tools/DataSourceHelper.cxx @@ -0,0 +1,532 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +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 uno::Reference< XDataSeries > & xDataSeries ) +{ + uno::Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + if( !xSeriesProp.is()) + return; + + try + { + uno::Reference< beans::XPropertySet > xErrorBarProp; + if( ( xSeriesProp->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( ( xSeriesProp->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::XDataSource > DataSourceHelper::createDataSource( + const Sequence< Reference< chart2::data::XLabeledDataSequence > >& rSequences ) +{ + return new DataSource(rSequences); +} + +Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence() +{ + return new ::chart::CachedDataSequence(); +} + +Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence( const OUString& rSingleText ) +{ + return new ::chart::CachedDataSequence( rSingleText ); +} + +Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence( + const Reference< chart2::data::XDataSequence >& xValues , + const Reference< chart2::data::XDataSequence >& xLabels ) +{ + return new ::chart::LabeledDataSequence( xValues, xLabels ); +} + +Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence( + const Reference< chart2::data::XDataSequence >& xValues ) +{ + return new ::chart::LabeledDataSequence( xValues ); +} + +Reference< chart2::data::XLabeledDataSequence > 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; + + uno::Sequence< beans::PropertyValue > aArguments(3); + aArguments[0] = beans::PropertyValue( "DataRowSource" + , -1, uno::Any( eRowSource ) + , beans::PropertyState_DIRECT_VALUE ); + aArguments[1] = beans::PropertyValue( "FirstCellAsLabel" + , -1, uno::Any( bFirstCellAsLabel ) + , beans::PropertyState_DIRECT_VALUE ); + aArguments[2] = beans::PropertyValue( "HasCategories" + , -1, uno::Any( bHasCategories ) + , beans::PropertyState_DIRECT_VALUE ); + + return aArguments; +} + +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[aArguments.getLength() - 1] = + beans::PropertyValue( "CellRangeRepresentation" + , -1, uno::Any( rRangeRepresentation ) + , beans::PropertyState_DIRECT_VALUE ); + if( rSequenceMapping.hasElements() ) + { + aArguments.realloc( aArguments.getLength() + 1 ); + aArguments[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; + } + } +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::pressUsedDataIntoRectangularFormat( + const uno::Reference< chart2::XChartDocument >& xChartDoc ) +{ + std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVector; + + //categories are always the first sequence + Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); + + Reference< chart2::data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + aResultVector.push_back( xCategories ); + + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + uno::Reference< chart2::data::XDataSource > xSeriesSource( + DataSeriesHelper::getDataSource( comphelper::containerToSequence(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( comphelper::containerToSequence(aResultVector) ); +} + +uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges( + const uno::Reference< chart2::XDiagram > & xDiagram ) +{ + std::vector< OUString > aResult; + + if( xDiagram.is()) + { + uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + lcl_addRanges( aResult, xCategories ); + + std::vector< uno::Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + for (auto const& series : aSeriesVector) + { + uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY); + lcl_addDataSourceRanges( aResult, xDataSource ); + lcl_addErrorBarRanges( aResult, series ); + } + } + + return comphelper::containerToSequence( aResult ); +} + +uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges( const uno::Reference< frame::XModel > & xChartModel ) +{ + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + return getUsedDataRanges( xDiagram ); +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( + const uno::Reference< chart2::XChartDocument >& xChartDoc ) +{ + return pressUsedDataIntoRectangularFormat( xChartDoc ); +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( + const uno::Reference< frame::XModel >& xChartModel ) +{ + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult; + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + aResult.push_back( xCategories ); + + std::vector< uno::Reference< XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartModel ) ); + for (auto const& series : aSeriesVector) + { + uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY); + if( !xDataSource.is() ) + continue; + uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + std::copy( aDataSequences.begin(), aDataSequences.end(), + std::back_inserter( aResult )); + } + + return uno::Reference< chart2::data::XDataSource >( + new DataSource( comphelper::containerToSequence( aResult ))); +} + +uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData( + ChartModel& rModel ) +{ + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult; + + uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() ); + uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) ); + if( xCategories.is() ) + aResult.push_back( xCategories ); + + std::vector< uno::Reference< XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( rModel ) ); + for (auto const& series : aSeriesVector) + { + uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY); + if( !xDataSource.is() ) + continue; + uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + std::copy( aDataSequences.begin(), aDataSequences.end(), + std::back_inserter( aResult )); + } + + return uno::Reference< chart2::data::XDataSource >( + new DataSource( comphelper::containerToSequence( aResult ))); +} + +bool DataSourceHelper::detectRangeSegmentation( + const uno::Reference< + frame::XModel >& xChartModel + , OUString& rOutRangeString + , css::uno::Sequence< sal_Int32 >& rSequenceMapping + , bool& rOutUseColumns + , bool& rOutFirstCellAsLabel + , bool& rOutHasCategories ) +{ + bool bSomethingDetected = false; + + uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( !xChartDocument.is() ) + return bSomethingDetected; + uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() ); + if( !xDataProvider.is() ) + return bSomethingDetected; + + try + { + DataSourceHelper::readArguments( + xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument ) ), + rOutRangeString, rSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); + bSomethingDetected = !rOutRangeString.isEmpty(); + + uno::Reference< chart2::data::XLabeledDataSequence > xCategories( + DiagramHelper::getCategoriesFromDiagram( xChartDocument->getFirstDiagram() )); + rOutHasCategories = xCategories.is(); + } + catch( uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return bSomethingDetected; +} + +bool DataSourceHelper::allArgumentsForRectRangeDetected( + const uno::Reference< chart2::XChartDocument >& 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::get())); + } + else if ( rProperty.Name == "FirstCellAsLabel" ) + { + bHasFirstCellAsLabel = + (rProperty.Value.hasValue() && rProperty.Value.isExtractableTo(cppu::UnoType::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 uno::Reference< frame::XModel >& xChartModel + , const css::uno::Sequence< sal_Int32 >& rSequenceMapping + , bool bUseColumns , bool bFirstCellAsLabel, bool bUseCategories ) +{ + uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( !xChartDocument.is() ) + return; + uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() ); + if( !xDataProvider.is() ) + return; + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + if( !xDiagram.is() ) + return; + uno::Reference< chart2::XChartTypeManager > xChartTypeManager( xChartDocument->getChartTypeManager() ); + if( !xChartTypeManager.is() ) + return; + uno::Reference< lang::XMultiServiceFactory > xTemplateFactory( xChartTypeManager, uno::UNO_QUERY ); + if( !xTemplateFactory.is() ) + return; + + OUString aRangeString; + bool bDummy; + uno::Sequence< sal_Int32 > aDummy; + readArguments( xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument )), + 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.realloc( 2 ); + aResult[0] = xLabel->getSourceRangeRepresentation(); + aResult[1] = xValues->getSourceRangeRepresentation(); + } + else + { + aResult.realloc( 1 ); + aResult[0] = xLabel->getSourceRangeRepresentation(); + } + } + else if( xValues.is()) + { + aResult.realloc( 1 ); + aResult[0] = 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 000000000..213d1787d --- /dev/null +++ b/chart2/source/tools/DiagramHelper.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +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 +{ + +DiagramHelper::tTemplateWithServiceName + DiagramHelper::getTemplateForDiagram( + const Reference< XDiagram > & xDiagram, + const Reference< lang::XMultiServiceFactory > & xChartTypeManager ) +{ + DiagramHelper::tTemplateWithServiceName aResult; + + if( ! (xChartTypeManager.is() && xDiagram.is())) + 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 + { + Reference< XChartTypeTemplate > xTempl( + xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW ); + + if (xTempl.is() && xTempl->matchesTemplate(xDiagram, true)) + { + aResult.first = xTempl; + aResult.second = aServiceNames[ i ]; + bTemplateFound = true; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +void DiagramHelper::setVertical( + const Reference< XDiagram > & xDiagram, + bool bVertical /* = true */ ) +{ + try + { + Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY ); + if (!xCnt.is()) + return; + + const Sequence< Reference > aCooSys = xCnt->getCoordinateSystems(); + uno::Any aValue; + aValue <<= bVertical; + for( uno::Reference< XCoordinateSystem > const & xCooSys : aCooSys ) + { + Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY ); + bool bChanged = false; + if (xProp.is()) + { + bool bOldSwap = false; + if( !(xProp->getPropertyValue("SwapXAndYAxis") >>= bOldSwap) + || bVertical != bOldSwap ) + bChanged = true; + + if( bChanged ) + xProp->setPropertyValue("SwapXAndYAxis", aValue); + } + + if (!xCooSys.is()) + continue; + + 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) + { + Reference xAxis = xCooSys->getAxisByDimension(nDimIndex,nI); + if (!xAxis.is()) + continue; + + //adapt title rotation only when axis swapping has changed + if (!bChanged) + continue; + + Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY ); + if (!xTitled.is()) + continue; + + Reference< beans::XPropertySet > xTitleProps( xTitled->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 DiagramHelper::getVertical( const uno::Reference< chart2::XDiagram > & xDiagram, + bool& rbFound, bool& rbAmbiguous ) +{ + bool bValue = false; + rbFound = false; + rbAmbiguous = false; + + Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY ); + if (!xCnt.is()) + return false; + + const Sequence< Reference > aCooSys = xCnt->getCoordinateSystems(); + + for (Reference const & coords : aCooSys) + { + Reference xProp(coords, uno::UNO_QUERY); + if (!xProp.is()) + continue; + + bool bCurrent = false; + if (xProp->getPropertyValue("SwapXAndYAxis") >>= bCurrent) + { + if (!rbFound) + { + bValue = bCurrent; + rbFound = true; + } + else if (bCurrent != bValue) + { + // ambiguous -> choose always first found + rbAmbiguous = true; + } + } + } + return bValue; +} + +void DiagramHelper::setStackMode( + const Reference< XDiagram > & xDiagram, + StackMode eStackMode +) +{ + try + { + bool bValueFound = false; + bool bIsAmbiguous = false; + StackMode eOldStackMode = DiagramHelper::getStackMode( xDiagram, bValueFound, bIsAmbiguous ); + + if( eStackMode == eOldStackMode && !bIsAmbiguous ) + return; + + StackingDirection eNewDirection = StackingDirection_NO_STACKING; + if( eStackMode == StackMode::YStacked || eStackMode == StackMode::YStackedPercent ) + eNewDirection = StackingDirection_Y_STACKING; + else if( eStackMode == StackMode::ZStacked ) + eNewDirection = StackingDirection_Z_STACKING; + + uno::Any aNewDirection( eNewDirection ); + + bool bPercent = false; + if( eStackMode == StackMode::YStackedPercent ) + bPercent = true; + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is() ) + return; + const uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( uno::Reference< XCoordinateSystem > const & xCooSys : aCooSysList ) + { + //set correct percent stacking + const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1); + for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI) + { + Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI )); + if( xAxis.is()) + { + chart2::ScaleData aScaleData = xAxis->getScaleData(); + if( (aScaleData.AxisType==AxisType::PERCENT) != bPercent ) + { + if( bPercent ) + aScaleData.AxisType = AxisType::PERCENT; + else + aScaleData.AxisType = AxisType::REALNUMBER; + xAxis->setScaleData( aScaleData ); + } + } + } + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + if (!aChartTypeList.hasElements()) + continue; + + uno::Reference< XChartType > xChartType( aChartTypeList[0] ); + + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + const uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( uno::Reference< XDataSeries > const & dataSeries : aSeriesList ) + { + Reference< beans::XPropertySet > xProp( dataSeries, uno::UNO_QUERY ); + if(xProp.is()) + xProp->setPropertyValue( "StackingDirection", aNewDirection ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +StackMode DiagramHelper::getStackMode( const Reference< XDiagram > & xDiagram, bool& rbFound, bool& rbAmbiguous ) +{ + rbFound=false; + rbAmbiguous=false; + + StackMode eGlobalStackMode = StackMode::NONE; + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is() ) + return eGlobalStackMode; + const uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( uno::Reference< XCoordinateSystem > const & xCooSys : aCooSysList ) + { + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > 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; +} + +StackMode DiagramHelper::getStackModeFromChartType( + const Reference< XChartType > & xChartType, + bool& rbFound, bool& rbAmbiguous, + const Reference< XCoordinateSystem > & xCorrespondingCoordinateSystem ) +{ + StackMode eStackMode = StackMode::NONE; + rbFound = false; + rbAmbiguous = false; + + try + { + Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW ); + Sequence< Reference< chart2::XDataSeries > > aSeries( xDSCnt->getDataSeries()); + + 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.getLength(); + sal_Int32 i = (nSeriesCount == 1) ? 0: 1; + for( ; i xProp( aSeries[i], uno::UNO_QUERY_THROW ); + chart2::StackingDirection eCurrentDirection = eCommonDirection; + // property is not MAYBEVOID + bool bSuccess = ( xProp->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]); + + Reference< chart2::XAxis > xAxis( + xCorrespondingCoordinateSystem->getAxisByDimension( 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; +} + +sal_Int32 DiagramHelper::getDimension( const Reference< XDiagram > & xDiagram ) +{ + // -1: not yet set + sal_Int32 nResult = -1; + + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( xCooSysCnt.is() ) + { + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + + for( Reference< XCoordinateSystem > const & xCooSys : aCooSysSeq ) + { + if(xCooSys.is()) + { + nResult = xCooSys->getDimension(); + break; + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return nResult; +} + +void DiagramHelper::setDimension( + const Reference< XDiagram > & xDiagram, + sal_Int32 nNewDimensionCount ) +{ + if( ! xDiagram.is()) + return; + + if( DiagramHelper::getDimension( xDiagram ) == nNewDimensionCount ) + return; + + try + { + bool rbFound = false; + bool rbAmbiguous = true; + StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous ); + bool bIsSupportingOnlyDeepStackingFor3D=false; + + //change all coordinate systems: + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( Reference const & xOldCooSys : aCooSysList ) + { + Reference< XCoordinateSystem > xNewCooSys; + + Reference< XChartTypeContainer > xChartTypeContainer( xOldCooSys, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + + const Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( Reference< XChartType > const & xChartType : aChartTypeList ) + { + bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType ); + if(!xNewCooSys.is()) + { + xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount ); + 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 + DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys ); + } + + //correct stack mode if necessary + if( nNewDimensionCount==3 && eStackMode != StackMode::ZStacked && bIsSupportingOnlyDeepStackingFor3D ) + DiagramHelper::setStackMode( xDiagram, StackMode::ZStacked ); + else if( nNewDimensionCount==2 && eStackMode == StackMode::ZStacked ) + DiagramHelper::setStackMode( xDiagram, StackMode::NONE ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void DiagramHelper::replaceCoordinateSystem( + const Reference< XDiagram > & xDiagram, + const Reference< XCoordinateSystem > & xCooSysToReplace, + const Reference< XCoordinateSystem > & xReplacement ) +{ + OSL_ASSERT( xDiagram.is()); + if( ! xDiagram.is()) + return; + + // update the coordinate-system container + Reference< XCoordinateSystemContainer > xCont( xDiagram, uno::UNO_QUERY ); + if( !xCont.is()) + return; + + try + { + Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + + // move chart types of xCooSysToReplace to xReplacement + Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW ); + Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW ); + xCTCntReplacement->setChartTypes( xCTCntCooSys->getChartTypes()); + + xCont->removeCoordinateSystem( xCooSysToReplace ); + xCont->addCoordinateSystem( xReplacement ); + + if( xCategories.is() ) + DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool DiagramHelper::isSeriesAttachedToMainAxis( + const uno::Reference< chart2::XDataSeries >& xDataSeries ) +{ + sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + return (nAxisIndex==0); +} + +bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis + , const uno::Reference< chart2::XDataSeries >& xDataSeries + , const uno::Reference< chart2::XDiagram >& xDiagram + , const uno::Reference< uno::XComponentContext > & xContext + , bool bAdaptAxes ) +{ + bool bChanged = false; + + //set property at axis + Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW ); + + sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1; + sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + uno::Reference< chart2::XAxis > xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries, xDiagram ) ); + + if( nOldAxisIndex != nNewAxisIndex ) + { + try + { + xProp->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex ) ); + bChanged = true; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + if( bChanged && xDiagram.is() ) + { + uno::Reference< XAxis > xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis, xDiagram ) ); + if(!xAxis.is()) //create an axis if necessary + xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, xDiagram, xContext ); + if( bAdaptAxes ) + { + AxisHelper::makeAxisVisible( xAxis ); + AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, xDiagram ); + } + } + + return bChanged; +} + +uno::Reference< XAxis > DiagramHelper::getAttachedAxis( + const uno::Reference< XDataSeries >& xSeries, + const uno::Reference< XDiagram >& xDiagram ) +{ + return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), xDiagram ); +} + +uno::Reference< XChartType > DiagramHelper::getChartTypeOfSeries( + const uno::Reference< chart2::XDiagram >& xDiagram + , const uno::Reference< XDataSeries >& xGivenDataSeries ) +{ + if( !xGivenDataSeries.is() ) + return nullptr; + if(!xDiagram.is()) + return nullptr; + + //iterate through the model to find the given xSeries + //the found parent indicates the charttype + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is()) + return nullptr; + + const uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( uno::Reference< XCoordinateSystem > const & xCooSys : aCooSysList ) + { + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + const uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( uno::Reference< XChartType > const & xChartType : aChartTypeList ) + { + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + const uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( uno::Reference< XDataSeries > const & dataSeries : aSeriesList ) + { + if( xGivenDataSeries==dataSeries ) + return xChartType; + } + } + } + return nullptr; +} + +std::vector< Reference< XDataSeries > > + DiagramHelper::getDataSeriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + std::vector< Reference< XDataSeries > > aResult; + + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( Reference< XChartType> const & chartType : aChartTypeSeq ) + { + Reference< XDataSeriesContainer > xDSCnt( chartType, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() ); + std::copy( aSeriesSeq.begin(), aSeriesSeq.end(), + std::back_inserter( aResult )); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +Sequence< Sequence< Reference< XDataSeries > > > + DiagramHelper::getDataSeriesGroups( const Reference< XDiagram > & xDiagram ) +{ + vector< Sequence< Reference< XDataSeries > > > aResult; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + const Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( Reference< XCoordinateSystem > const & coords : aCooSysList ) + { + //iterate through all chart types in the current coordinate system + Reference< XChartTypeContainer > xChartTypeContainer( coords, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + const Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( Reference< XChartType > const & chartType : aChartTypeList ) + { + Reference< XDataSeriesContainer > xDataSeriesContainer( chartType, uno::UNO_QUERY ); + if( !xDataSeriesContainer.is() ) + continue; + aResult.push_back( xDataSeriesContainer->getDataSeries() ); + } + } + } + return comphelper::containerToSequence( aResult ); +} + +Reference< XChartType > + DiagramHelper::getChartTypeByIndex( const Reference< XDiagram >& xDiagram, sal_Int32 nIndex ) +{ + Reference< XChartType > xChartType; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( ! xCooSysContainer.is()) + return xChartType; + + const Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + sal_Int32 nTypesSoFar = 0; + for( Reference< XCoordinateSystem > const & coords : aCooSysList ) + { + Reference< XChartTypeContainer > xChartTypeContainer( coords, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + if( nIndex >= 0 && nIndex < (nTypesSoFar + aChartTypeList.getLength()) ) + { + xChartType.set( aChartTypeList[nIndex - nTypesSoFar] ); + break; + } + nTypesSoFar += aChartTypeList.getLength(); + } + + return xChartType; +} + +namespace +{ + +std::vector< Reference< XAxis > > lcl_getAxisHoldingCategoriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + std::vector< Reference< XAxis > > aRet; + + // return first x-axis as fall-back + Reference< XAxis > xFallBack; + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & xCooSys : aCooSysSeq ) + { + 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) + { + Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI ); + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.Categories.is() || (aScaleData.AxisType == AxisType::CATEGORY) ) + { + aRet.push_back(xAxis); + } + if( (nN == 0) && !xFallBack.is()) + xFallBack.set( xAxis ); + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } + + if( aRet.empty() ) + aRet.push_back(xFallBack); + + return aRet; +} + +} // anonymous namespace + +bool DiagramHelper::isCategoryDiagram( + const Reference< XDiagram >& xDiagram ) +{ + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & xCooSys : aCooSysSeq ) + { + 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) + { + Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI ); + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE ) + return true; + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return false; +} + +void DiagramHelper::setCategoriesToDiagram( + const Reference< chart2::data::XLabeledDataSequence >& xCategories, + const Reference< XDiagram >& xDiagram, + bool bSetAxisType /* = false */, + bool bCategoryAxis /* = true */ ) +{ + std::vector< Reference< chart2::XAxis > > aCatAxes( + lcl_getAxisHoldingCategoriesFromDiagram( xDiagram )); + + for (const Reference< chart2::XAxis >& xCatAxis : aCatAxes) + { + if( xCatAxis.is()) + { + ScaleData aScaleData( xCatAxis->getScaleData()); + aScaleData.Categories = xCategories; + if( bSetAxisType ) + { + if( bCategoryAxis ) + aScaleData.AxisType = AxisType::CATEGORY; + else if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE ) + aScaleData.AxisType = AxisType::REALNUMBER; + } + xCatAxis->setScaleData( aScaleData ); + } + } +} + +Reference< data::XLabeledDataSequence > + DiagramHelper::getCategoriesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + Reference< data::XLabeledDataSequence > xResult; + + try + { + std::vector< Reference< chart2::XAxis > > aCatAxes( + lcl_getAxisHoldingCategoriesFromDiagram( xDiagram )); + //search for first categories + if (!aCatAxes.empty()) + { + Reference< chart2::XAxis > xCatAxis(aCatAxes[0]); + if( xCatAxis.is()) + { + ScaleData aScaleData( xCatAxis->getScaleData()); + if( aScaleData.Categories.is() ) + { + xResult.set( aScaleData.Categories ); + uno::Reference xProp(aScaleData.Categories->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; +} + +static void lcl_generateAutomaticCategoriesFromChartType( + Sequence< OUString >& rRet, + const Reference< XChartType >& xChartType ) +{ + if(!xChartType.is()) + return; + OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() ); + Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY ); + if( !xSeriesCnt.is() ) + return; + + const Sequence< Reference< XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries() ); + for( Reference< XDataSeries > const & dataSeries : aSeriesSeq ) + { + Reference< data::XDataSource > xDataSource( dataSeries, uno::UNO_QUERY ); + if( !xDataSource.is() ) + continue; + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, 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 Reference< XCoordinateSystem > & xCooSys ) +{ + Sequence< OUString > aRet; + + Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY ); + if( xTypeCntr.is() ) + { + const Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() ); + for( Reference< XChartType > const & chartType : aChartTypes ) + { + lcl_generateAutomaticCategoriesFromChartType( aRet, chartType ); + if( aRet.hasElements() ) + return aRet; + } + } + return aRet; +} + +Sequence< OUString > DiagramHelper::getExplicitSimpleCategories( + ChartModel& rModel ) +{ + uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( rModel ) ); + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel ); + return aExplicitCategoriesProvider.getSimpleCategories(); +} + +namespace +{ +void lcl_switchToDateCategories( const Reference< XChartDocument >& 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() ); + double fTest = 0.0; + double fNan = 0.0; + ::rtl::math::setNan( & fNan ); + sal_Int32 nN = aAnyCategories.getLength(); + for( ; nN--; ) + { + Sequence< Any >& rCat = aAnyCategories[nN]; + if( rCat.getLength() > 1 ) + rCat.realloc(1); + if( rCat.getLength() == 1 ) + { + Any& rAny = rCat[0]; + if( !(rAny>>=fTest) ) + { + rAny <<= fNan; + } + } + } + xDataAccess->setAnyRowDescriptions( aAnyCategories ); + } + //check the numberformat at the axis + Reference< beans::XPropertySet > xAxisProps( xAxis, uno::UNO_QUERY ); + Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartDoc, uno::UNO_QUERY ); + if( xAxisProps.is() && xNumberFormatsSupplier.is() ) + { + sal_Int32 nNumberFormat = -1; + xAxisProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat; + + Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->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 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 Reference< XChartDocument >& 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 Reference< XChartDocument >& xChartDoc ) +{ + if(xChartDoc.is()) + { + ControllerLockGuardUNO aCtrlLockGuard( xChartDoc ); + + Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartDoc ) ); + if( xCooSys.is() ) + { + Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) ); + lcl_switchToDateCategories( xChartDoc, xAxis ); + } + } +} + +void DiagramHelper::switchToTextCategories( const Reference< XChartDocument >& xChartDoc ) +{ + if(xChartDoc.is()) + { + ControllerLockGuardUNO aCtrlLockGuard( xChartDoc ); + + Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartDoc ) ); + if( xCooSys.is() ) + { + Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) ); + lcl_switchToTextCategories( xChartDoc, xAxis ); + } + } +} + +bool DiagramHelper::isSupportingDateAxis( const Reference< chart2::XDiagram >& xDiagram ) +{ + return ::chart::ChartTypeHelper::isSupportingDateAxis( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), 0 ); +} + +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 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, LANGUAGE_SYSTEM, 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 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; +} + +Sequence< Reference< XChartType > > + DiagramHelper::getChartTypesFromDiagram( + const Reference< XDiagram > & xDiagram ) +{ + std::vector< Reference< XChartType > > aResult; + + if(xDiagram.is()) + { + try + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + std::copy( aChartTypeSeq.begin(), aChartTypeSeq.end(), + std::back_inserter( aResult )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return comphelper::containerToSequence( aResult ); +} + +bool DiagramHelper::areChartTypesCompatible( const Reference< ::chart2::XChartType >& xFirstType, + const Reference< ::chart2::XChartType >& xSecondType ) +{ + if( !xFirstType.is() || !xSecondType.is() ) + return false; + + auto aFirstRoles( comphelper::sequenceToContainer>( xFirstType->getSupportedMandatoryRoles() ) ); + auto aSecondRoles( comphelper::sequenceToContainer>( xSecondType->getSupportedMandatoryRoles() ) ); + std::sort( aFirstRoles.begin(), aFirstRoles.end() ); + std::sort( aSecondRoles.begin(), aSecondRoles.end() ); + return ( aFirstRoles == aSecondRoles ); +} + +namespace +{ + /** + * 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 + * + */ + +bool lcl_moveSeriesOrCheckIfMoveIsAllowed( + const Reference< XDiagram >& xDiagram, + const Reference< XDataSeries >& xGivenDataSeries, + bool bForward, + bool bDoMove ) +{ + bool bMovedOrMoveAllowed = false; + + try + { + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + + if( xGivenDataSeries.is() && xCooSysContainer.is() ) + { + //find position of series. + bool bFound = false; + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + + for( sal_Int32 nCS = 0; !bFound && nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + uno::Reference< XChartType > xFormerChartType; + + for( sal_Int32 nT = 0; !bFound && nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > xCurrentChartType( aChartTypeList[nT] ); + + //iterate through all series in this chart type + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xCurrentChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + + for( sal_Int32 nS = 0; !bFound && nS < aSeriesList.getLength(); ++nS ) + { + + // We found the series we are interested in! + if( xGivenDataSeries==aSeriesList[nS] ) + { + sal_Int32 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 && nNewSeriesIndex < aSeriesList.getLength() ) + { + //move series in the same charttype + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ]; + aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries; + xDataSeriesContainer->setDataSeries( aSeriesList ); + } + } + else if( nNewSeriesIndex<0 ) + { + //exchange series with former charttype + if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) ) + { + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xFormerChartType, uno::UNO_QUERY ); + if( xOtherDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() ); + sal_Int32 nOtherSeriesIndex = aOtherSeriesList.getLength()-1; + if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() ) + { + uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] ); + aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries; + xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList); + + aSeriesList[nOldSeriesIndex]=xExchangeSeries; + xDataSeriesContainer->setDataSeries(aSeriesList); + } + } + } + } + } + else if( nT+1 < aChartTypeList.getLength() ) + { + //exchange series with next charttype + uno::Reference< XChartType > xOtherChartType( aChartTypeList[nT+1] ); + if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) ) + { + bMovedOrMoveAllowed = true; + if( bDoMove ) + { + uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xOtherChartType, uno::UNO_QUERY ); + if( xOtherDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() ); + if( aOtherSeriesList.hasElements() ) + { + uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[0] ); + aOtherSeriesList[0] = xGivenDataSeries; + xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList); + + aSeriesList[nOldSeriesIndex]=xExchangeSeries; + xDataSeriesContainer->setDataSeries(aSeriesList); + } + } + } + } + } + } + catch( const util::CloseVetoException& ) + { + } + catch( const uno::RuntimeException& ) + { + } + } + } + xFormerChartType = xCurrentChartType; + } + } + } + } + catch( const util::CloseVetoException& ) + { + } + catch( const uno::RuntimeException& ) + { + } + return bMovedOrMoveAllowed; +} +} // anonymous namespace + +bool DiagramHelper::isSeriesMoveable( + const Reference< XDiagram >& xDiagram, + const Reference< XDataSeries >& xGivenDataSeries, + bool bForward ) +{ + const bool bDoMove = false; + + bool bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed( + xDiagram, xGivenDataSeries, bForward, bDoMove ); + + return bIsMoveable; +} + +bool DiagramHelper::moveSeries( const Reference< XDiagram >& xDiagram, const Reference< XDataSeries >& xGivenDataSeries, bool bForward ) +{ + const bool bDoMove = true; + + bool bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed( + xDiagram, xGivenDataSeries, bForward, bDoMove ); + + return bMoved; +} + +bool DiagramHelper::isSupportingFloorAndWall( const Reference< + chart2::XDiagram >& xDiagram ) +{ + //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 Sequence< Reference< chart2::XChartType > > aTypes( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) ); + for( Reference< chart2::XChartType > const & xType : aTypes ) + { + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + return false; + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) + return false; + if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + return false; + } + return true; +} + +bool DiagramHelper::isPieOrDonutChart( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) +{ + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( + xDiagram, 0 ) ); + + if( xChartType .is() ) + { + OUString aChartType = xChartType->getChartType(); + if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE ) + return true; + } + return false; +} + +sal_Int32 DiagramHelper::getGeometry3D( + const uno::Reference< chart2::XDiagram > & xDiagram, + bool& rbFound, bool& rbAmbiguous ) +{ + sal_Int32 nCommonGeom( DataPointGeometry3D::CUBOID ); + rbFound = false; + rbAmbiguous = false; + + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + if( aSeriesVec.empty()) + rbAmbiguous = true; + + for (auto const& series : aSeriesVec) + { + try + { + sal_Int32 nGeom = 0; + Reference< beans::XPropertySet > xProp(series, uno::UNO_QUERY_THROW); + if( xProp->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; +} + +void DiagramHelper::setGeometry3D( + const Reference< chart2::XDiagram > & xDiagram, + sal_Int32 nNewGeometry ) +{ + std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& series : aSeriesVec) + { + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( + series, "Geometry3D", uno::Any( nNewGeometry )); + } +} + +sal_Int32 DiagramHelper::getCorrectedMissingValueTreatment( + const Reference< chart2::XDiagram > & xDiagram, + const Reference< chart2::XChartType >& xChartType ) +{ + sal_Int32 nResult = css::chart::MissingValueTreatment::LEAVE_GAP; + const uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments( + ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) ); + + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY ); + if( xDiaProp.is() && (xDiaProp->getPropertyValue( "MissingValueTreatment" ) >>= 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; +} + +DiagramPositioningMode DiagramHelper::getDiagramPositioningMode( const uno::Reference< + chart2::XDiagram > & xDiagram ) +{ + DiagramPositioningMode eMode = DiagramPositioningMode_AUTO; + uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY ); + if( xDiaProps.is() ) + { + RelativePosition aRelPos; + RelativeSize aRelSize; + if( (xDiaProps->getPropertyValue("RelativePosition") >>= aRelPos ) && + (xDiaProps->getPropertyValue("RelativeSize") >>= aRelSize ) ) + { + bool bPosSizeExcludeAxes=false; + xDiaProps->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxes; + if( bPosSizeExcludeAxes ) + eMode = DiagramPositioningMode_EXCLUDING; + else + eMode = DiagramPositioningMode_INCLUDING; + } + } + return eMode; +} + +static void lcl_ensureRange0to1( double& rValue ) +{ + if(rValue<0.0) + rValue=0.0; + if(rValue>1.0) + rValue=1.0; +} + +bool DiagramHelper::setDiagramPositioning( const uno::Reference< frame::XModel >& xChartModel, + const awt::Rectangle& rPosRect /*100th mm*/ ) +{ + ControllerLockGuardUNO aCtrlLockGuard( xChartModel ); + + bool bChanged = false; + awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) ); + uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + if( !xDiaProps.is() ) + return bChanged; + + RelativePosition aOldPos; + RelativeSize aOldSize; + xDiaProps->getPropertyValue("RelativePosition" ) >>= aOldPos; + xDiaProps->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; + + xDiaProps->setPropertyValue( "RelativePosition", uno::Any(aNewPos) ); + xDiaProps->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 uno::Reference< frame::XModel >& xChartModel ) +{ + awt::Rectangle aRet(-1,-1,-1,-1); + + uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + if( !xDiaProps.is() ) + return aRet; + + awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) ); + + RelativePosition aRelPos; + RelativeSize aRelSize; + xDiaProps->getPropertyValue("RelativePosition" ) >>= aRelPos; + xDiaProps->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(SvtSaveOptions().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 000000000..5191e4f3d --- /dev/null +++ b/chart2/source/tools/ErrorBar.cxx @@ -0,0 +1,485 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace +{ + +static const char lcl_aServiceName[] = "com.sun.star.comp.chart2.ErrorBar"; + +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[] = + { + {OUString("ShowPositiveError"),0,cppu::UnoType::get(), 0, 0}, + {OUString("ShowNegativeError"),1,cppu::UnoType::get(), 0, 0}, + {OUString("PositiveError"),2,cppu::UnoType::get(),0,0}, + {OUString("NegativeError"),3,cppu::UnoType::get(), 0, 0}, + {OUString("PercentageError"),4,cppu::UnoType::get(), 0, 0}, + {OUString("ErrorBarStyle"),5,cppu::UnoType::get(),0,0}, + {OUString("ErrorBarRangePositive"),6,cppu::UnoType::get(),0,0}, // read-only for export + {OUString("ErrorBarRangeNegative"),7,cppu::UnoType::get(),0,0}, // read-only for export + {OUString("Weight"),8,cppu::UnoType::get(),0,0}, + {OUString("LineStyle"),9,cppu::UnoType::get(),0,0}, + {OUString("LineDash"),10,cppu::UnoType::get(),0,0}, + {OUString("LineWidth"),11,cppu::UnoType::get(),0,0}, + {OUString("LineColor"),12,cppu::UnoType::get(),0,0}, + {OUString("LineTransparence"),13,cppu::UnoType::get(),0,0}, + {OUString("LineJoint"),14,cppu::UnoType::get(),0,0}, + { OUString(), 0, css::uno::Type(), 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( ModifyListenerHelper::createModifyEventForwarder()) +{} + +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( ModifyListenerHelper::createModifyEventForwarder()) +{ + 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() ); + for(sal_Int32 i = 0; i < rPropNames.getLength(); ++i) + { + aRet[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 ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL ErrorBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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( 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 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 000000000..bf65f58ec --- /dev/null +++ b/chart2/source/tools/ExplicitCategoriesProvider.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 Reference< chart2::XCoordinateSystem >& xCooSysModel + , ChartModel& rModel ) + : m_bDirty(true) + , m_xCooSysModel( xCooSysModel ) + , mrModel(rModel) + , m_xOriginalCategories() + , 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. + uno::Reference< XAxis > xAxis( xCooSysModel->getAxisByDimension(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< Reference< XDataSeries > > aSeries( ChartModelHelper::getDataSeries( mrModel ) ); + if( !aSeries.empty() ) + { + uno::Reference< data::XDataSource > xSeriesSource( aSeries.front(), uno::UNO_QUERY ); + OUString aStringDummy; + bool bDummy; + uno::Sequence< sal_Int32 > aSeqDummy; + DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource), + aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy ); + } + if( bSeriesUsesColumns ) + m_aSplitCategoriesList=aColumns; + else + m_aSplitCategoriesList=aRows; + } + } + } + if( !m_aSplitCategoriesList.hasElements() ) + { + m_aSplitCategoriesList.realloc(1); + m_aSplitCategoriesList[0]=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.getLength() > 1; +} + +sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const +{ + sal_Int32 nCount = m_aSplitCategoriesList.getLength(); + if(!nCount) + nCount = 1; + return nCount; +} + +static std::vector lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories ) +{ + std::vector 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); + + sal_Int32 nAxisNumberFormat = 0; + Reference< XCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( rModel ) ); + if( xCooSysModel.is() ) + { + Reference< chart2::XAxis > xAxis( xCooSysModel->getAxisByDimension(0,0) ); + nAxisNumberFormat = AxisHelper::getExplicitNumberFormatKeyForAxis( + xAxis, xCooSysModel, uno::Reference(static_cast< ::cppu::OWeakObject* >(&rModel), uno::UNO_QUERY), false ); + } + + Color nLabelColor; + bool bColorChanged = false; + + NumberFormatterWrapper aNumberFormatterWrapper( rModel.getNumberFormatsSupplier() ); + + for(sal_Int32 nN=0;nN>=fDouble ) + { + if( !std::isnan(fDouble) ) + aText = aNumberFormatterWrapper.getFormattedString( + nAxisNumberFormat, fDouble, nLabelColor, bColorChanged ); + } + else + { + aAny>>=aText; + } + } + rOutTexts[nN] = aText; + } +} + +SplitCategoriesProvider::~SplitCategoriesProvider() +{ +} + +namespace { + +class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider +{ +public: + + explicit SplitCategoriesProvider_ForLabeledDataSequences( + const css::uno::Sequence< + css::uno::Reference< css::chart2::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 css::uno::Sequence< css::uno::Reference< + css::chart2::data::XLabeledDataSequence> >& m_rSplitCategoriesList; + + ChartModel& mrModel; +}; + +} + +sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const +{ + return m_rSplitCategoriesList.getLength(); +} +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& rLimitingBorders, bool bCreateSingleCategories ) +{ + std::vector< ComplexCategory > aResult; + + sal_Int32 nMaxCount = rStrings.getLength(); + OUString aPrevious; + sal_Int32 nCurrentCount=0; + for( sal_Int32 nN=0; nN& 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 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); + for(sal_Int32 nN=0; nN 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; + Reference< XCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( rModel ) ); + if( xCooSysModel.is() ) + { + if( rModel.hasInternalDataProvider() ) + { + bOwnData = true; + Reference< beans::XPropertySet > xAxisProps( xCooSysModel->getAxisByDimension(0,0), uno::UNO_QUERY ); + 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;nNgetNumberFormatKeyByIndex( 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; + ::rtl::math::setNan( &aDate ); + rDateCategories.push_back( aDate ); + } + } + 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, 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 ); + m_bIsExplicitCategoriesInited = true; + } + return m_aExplicitCategories; +} + +const std::vector* 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 Reference< XCoordinateSystem >& 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 000000000..7d85b19b5 --- /dev/null +++ b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +ExponentialRegressionCurveCalculator::ExponentialRegressionCurveCalculator() + : m_fLogSlope(0.0) + , m_fLogIntercept(0.0) + , m_fSign(1.0) +{ + ::rtl::math::setNan( & m_fLogSlope ); + ::rtl::math::setNan( & m_fLogIntercept ); +} + +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 ) + { + ::rtl::math::setNan( & m_fLogSlope ); + ::rtl::math::setNan( & m_fLogIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoefficient );// 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 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 ) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( std::isnan( m_fLogSlope ) || + std::isnan( m_fLogIntercept ))) + { + fResult = m_fSign * exp(m_fLogIntercept + x * m_fLogSlope); + } + + return fResult; +} + +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( 2 ); + aResult[0].X = min; + aResult[0].Y = getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = 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) ).append( " " ); + 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 ).append( " " ); + 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) ? OUStringLiteral(" ") : OUStringLiteral(" + ") ); + } + } + } + if ( m_fLogSlope < 0.0 ) + aTmpBuf.append( OUStringChar(aMinusSign) ).append( " " ); + 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 ).append( " " ); + } + } + aTmpBuf.append( mXName ).append(" )"); + 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 000000000..d0c888d74 --- /dev/null +++ b/chart2/source/tools/FillProperties.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillColor", + FillProperties::PROP_FILL_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID // "maybe auto" + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillTransparence", + FillProperties::PROP_FILL_TRANSPARENCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillTransparenceGradientName", + FillProperties::PROP_FILL_TRANSPARENCE_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillGradientName", + FillProperties::PROP_FILL_GRADIENT_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillGradientStepCount", + FillProperties::PROP_FILL_GRADIENT_STEPCOUNT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "FillHatchName", + FillProperties::PROP_FILL_HATCH_NAME, + cppu::UnoType::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::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapOffsetX", + FillProperties::PROP_FILL_BITMAP_OFFSETX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapOffsetY", + FillProperties::PROP_FILL_BITMAP_OFFSETY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetX", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapPositionOffsetY", + FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapRectanglePoint", + FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapLogicalSize", + FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeX", + FillProperties::PROP_FILL_BITMAP_SIZEX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapSizeY", + FillProperties::PROP_FILL_BITMAP_SIZEY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "FillBitmapMode", + FillProperties::PROP_FILL_BITMAP_MODE, + cppu::UnoType::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< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_COLOR, 0xd9d9d9 ); // gray85 + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_TRANSPARENCE, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BACKGROUND, false ); +} + +void lcl_AddDefaultsToMap_only_BitmapProperties( + ::chart::tPropertyValueMap & rOutMap ) +{ + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, 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< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, 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 000000000..ff885494d --- /dev/null +++ b/chart2/source/tools/FormattedStringHelper.cxx @@ -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 . + */ + +#include +#include +#include +#include + +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; + +Sequence< Reference< chart2::XFormattedString2 > > + FormattedStringHelper::createFormattedStringSequence( + const Reference< uno::XComponentContext > & xContext + , const OUString & rString + , const Reference< beans::XPropertySet > & xTextProperties ) throw() +{ + Reference< XFormattedString2 > xFormStr; + try + { + if( xContext.is() ) + { + xFormStr = chart2::FormattedString::create(xContext); + + xFormStr->setString( rString ); + + // set character properties + comphelper::copyProperties( + xTextProperties, Reference< beans::XPropertySet >( xFormStr, uno::UNO_QUERY_THROW ) ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return Sequence< Reference< XFormattedString2 > >( & xFormStr, 1 ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ImplOPropertySet.cxx b/chart2/source/tools/ImplOPropertySet.cxx new file mode 100644 index 000000000..d5f30096e --- /dev/null +++ b/chart2/source/tools/ImplOPropertySet.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 "ImplOPropertySet.hxx" +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; + +namespace +{ + +struct lcl_getPropertyStateByHandle +{ + explicit lcl_getPropertyStateByHandle( + const ::property::impl::ImplOPropertySet::tPropertyMap & rMap ) + : m_rMap( rMap ) + {} + + beans::PropertyState operator() ( sal_Int32 nHandle ) + { + if( m_rMap.end() == m_rMap.find( nHandle )) + return beans::PropertyState_DEFAULT_VALUE; + return beans::PropertyState_DIRECT_VALUE; + } + +private: + const ::property::impl::ImplOPropertySet::tPropertyMap & m_rMap; +}; + +template< typename K, typename V > +struct lcl_eraseMapEntry +{ + explicit lcl_eraseMapEntry( std::map< K, V > & rMap ) + : m_rMap( rMap ) + {} + + void operator() ( const K & aKey ) + { + m_rMap.erase( aKey ); + } + +private: + std::map< K, V > m_rMap; +}; + +struct lcl_replaceInterfacePropertiesByClones +{ + void operator() ( ::property::impl::ImplOPropertySet::tPropertyMap::value_type & rProp ) + { + if( rProp.second.hasValue() && + rProp.second.getValueType().getTypeClass() == uno::TypeClass_INTERFACE ) + { + Reference< util::XCloneable > xCloneable; + if( rProp.second >>= xCloneable ) + rProp.second <<= xCloneable->createClone(); + } + } +}; + +} // anonymous namespace + +namespace property::impl +{ + +ImplOPropertySet::ImplOPropertySet() +{} + +ImplOPropertySet::ImplOPropertySet( const ImplOPropertySet & rOther ) +{ + std::copy( rOther.m_aProperties.begin(), rOther.m_aProperties.end(), + std::inserter( m_aProperties, m_aProperties.begin() )); + + // clone interface properties + std::for_each( m_aProperties.begin(), m_aProperties.end(), + lcl_replaceInterfacePropertiesByClones()); + + m_xStyle.set( ::chart::CloneHelper::CreateRefClone< style::XStyle >()( rOther.m_xStyle )); +} + +beans::PropertyState ImplOPropertySet::GetPropertyStateByHandle( sal_Int32 nHandle ) const +{ + return lcl_getPropertyStateByHandle( m_aProperties ) ( nHandle ); +} + +Sequence< beans::PropertyState > ImplOPropertySet::GetPropertyStatesByHandle( + const std::vector< sal_Int32 > & aHandles ) const +{ + Sequence< beans::PropertyState > aResult( aHandles.size()); + + std::transform( aHandles.begin(), aHandles.end(), + aResult.getArray(), + lcl_getPropertyStateByHandle( m_aProperties )); + + return aResult; +} + +void ImplOPropertySet::SetPropertyToDefault( sal_Int32 nHandle ) +{ + tPropertyMap::iterator aFoundIter( m_aProperties.find( nHandle ) ); + + if( m_aProperties.end() != aFoundIter ) + { + m_aProperties.erase( aFoundIter ); + } +} + +void ImplOPropertySet::SetPropertiesToDefault( + const std::vector< sal_Int32 > & aHandles ) +{ + std::for_each( aHandles.begin(), aHandles.end(), + lcl_eraseMapEntry< sal_Int32, Any >( m_aProperties ) ); +} + +void ImplOPropertySet::SetAllPropertiesToDefault() +{ + m_aProperties.clear(); +} + +bool ImplOPropertySet::GetPropertyValueByHandle( + Any & rValue, + sal_Int32 nHandle ) const +{ + bool bResult = false; + + tPropertyMap::const_iterator aFoundIter( m_aProperties.find( nHandle ) ); + + if( m_aProperties.end() != aFoundIter ) + { + rValue = (*aFoundIter).second; + bResult = true; + } + + return bResult; +} + +void ImplOPropertySet::SetPropertyValueByHandle( + sal_Int32 nHandle, const Any & rValue ) +{ + m_aProperties[ nHandle ] = rValue; +} + +bool ImplOPropertySet::SetStyle( const Reference< style::XStyle > & xStyle ) +{ + if( ! xStyle.is()) + return false; + + m_xStyle = xStyle; + return true; +} + +} // namespace property::impl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ImplOPropertySet.hxx b/chart2/source/tools/ImplOPropertySet.hxx new file mode 100644 index 000000000..98dc53b00 --- /dev/null +++ b/chart2/source/tools/ImplOPropertySet.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_TOOLS_IMPLOPROPERTYSET_HXX +#define INCLUDED_CHART2_SOURCE_TOOLS_IMPLOPROPERTYSET_HXX + +#include +#include +#include + +#include +#include + +namespace com::sun::star::style { class XStyle; } + +namespace property +{ +namespace impl +{ + +class ImplOPropertySet +{ +public: + ImplOPropertySet(); + explicit ImplOPropertySet( const ImplOPropertySet & rOther ); + + /** 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 ); + const css::uno::Reference< css::style::XStyle >& + GetStyle() const { return m_xStyle;} + + typedef + std::map< sal_Int32, css::uno::Any > + tPropertyMap; + +private: + tPropertyMap m_aProperties; + css::uno::Reference< css::style::XStyle > + m_xStyle; +}; + +} // namespace impl +} // namespace chart + +// INCLUDED_CHART2_SOURCE_TOOLS_IMPLOPROPERTYSET_HXX +#endif + +/* 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 000000000..5fc4d1724 --- /dev/null +++ b/chart2/source/tools/InternalData.cxx @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#ifdef DEBUG_CHART2_TOOLS +#define DEBUG_INTERNAL_DATA 1 +#endif + +#ifdef DEBUG_INTERNAL_DATA +#include +#endif + +#include +#include + +using ::com::sun::star::uno::Sequence; + +using namespace ::com::sun::star; +using namespace ::std; + +namespace chart +{ + +namespace +{ +struct lcl_NumberedStringGenerator +{ + lcl_NumberedStringGenerator( const OUString & rStub, const OUString & rWildcard ) : + m_aStub( rStub ), + m_nCounter( 0 ), + m_nStubStartIndex( rStub.indexOf( rWildcard )), + m_nWildcardLength( rWildcard.getLength()) + { + } + vector< uno::Any > operator()() + { + vector< uno::Any > aRet(1); + aRet[0] <<= m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::number( ++m_nCounter )); + return aRet; + } +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 ) +{ + // is there a more elegant way of conversion? + Sequence< T > aResult( rValarray.size()); + for( size_t i = 0; i < rValarray.size(); ++i ) + aResult[i] = rValarray[i]; + return aResult; +} + +} // anonymous namespace + +InternalData::InternalData() + : m_nColumnCount( 0 ) + , m_nRowCount( 0 ) + , m_aRowLabels( 0 ) + , m_aColumnLabels( 0 ) +{} + +static 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 >& 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 ); + double fNan; + ::rtl::math::setNan( & fNan ); + // set all values to Nan + m_aData = fNan; + + for( sal_Int32 nRow=0; nRow > InternalData::getData() const +{ + Sequence< Sequence< double > > aResult( m_nRowCount ); + + for( sal_Int32 i=0; i( + 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 vector< double > & rNewData ) +{ + if( nColumnIndex < 0 ) + return; + enlargeData( nColumnIndex + 1, rNewData.size() ); + + tDataType aSlice = m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ]; + for( 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 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( 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, const vector< uno::Any >& rComplexLabel ) +{ + if( nColumnIndex < 0 ) + return; + if( nColumnIndex >= static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + { + m_aColumnLabels.resize(nColumnIndex+1); + enlargeData( nColumnIndex+1, 0 ); + } + m_aColumnLabels[nColumnIndex]=rComplexLabel; + + dump(); +} + +void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::Any >& rComplexLabel ) +{ + if( nRowIndex < 0 ) + return; + if( nRowIndex >= static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + { + m_aRowLabels.resize(nRowIndex+1); + enlargeData( 0, nRowIndex+1 ); + } + sal_Int32 nSize = static_cast( 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] = rComplexLabel; + } +} + +vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) ) + return m_aColumnLabels[nColumnIndex]; + else + return vector< uno::Any >(); +} +vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const +{ + if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) ) + return m_aRowLabels[nRowIndex]; + else + return 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 aTemp( m_aRowLabels[nRowIndex] ); + m_aRowLabels[nRowIndex] = m_aRowLabels[nRowIndex + 1]; + m_aRowLabels[nRowIndex + 1] = aTemp; +} + +void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex ) +{ + if( nColumnIndex >= m_nColumnCount - 1 ) + return; + + const sal_Int32 nMax = m_nRowCount; + for( sal_Int32 nRowIdx=0; nRowIdx 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( m_nColumnCount, nColumnCount ) ); + sal_Int32 nNewRowCount( std::max( m_nRowCount, nRowCount ) ); + sal_Int32 nNewSize( nNewColumnCount*nNewRowCount ); + + bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount); + + if( bGrow ) + { + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + // copy old data + for( int nCol=0; nCol( + 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 ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, 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( + 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), 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 ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, 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, 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 ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, nNewSize ); + + // copy old data + int nCol=0; + for( ; nCol( + m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ] ); + for( ; nCol( + 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 ); + + double fNan; + ::rtl::math::setNan( &fNan ); + tDataType aNewData( fNan, 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( const tVecVecAny& rNewRowLabels ) +{ + m_aRowLabels = 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( const tVecVecAny& rNewColumnLabels ) +{ + m_aColumnLabels = 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(1, m_aColumnLabels.size(), true); + for (size_t nCol = 0; nCol < m_aColumnLabels.size(); ++nCol) + { + if (m_aColumnLabels[nCol].empty()) + continue; + + OUString aStr; + if (m_aColumnLabels[nCol][0] >>= aStr) + aPrinter.set(0, nCol, aStr); + } + aPrinter.print("Header"); + } + + if (!m_aRowLabels.empty()) + { + svl::GridPrinter aPrinter(m_aRowLabels.size(), m_aRowLabels[0].size()); + 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); + + 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 000000000..7c826e8f6 --- /dev/null +++ b/chart2/source/tools/InternalDataProvider.cxx @@ -0,0 +1,1530 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace com::sun::star::chart2 { class XChartDocument; } + +using namespace ::com::sun::star; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +namespace +{ + +static const char lcl_aCategoriesRangeName[] = "categories"; +static const char lcl_aCategoriesLevelRangeNamePrefix[] = "categoriesL "; //L <-> level +static const char lcl_aCategoriesPointRangeNamePrefix[] = "categoriesP "; //P <-> point +static const char lcl_aCategoriesRoleName[] = "categories"; +static const char lcl_aLabelRangePrefix[] = "label "; +static const char lcl_aCompleteRange[] = "all"; + +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()(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 Reference< chart2::XDataSeries > & xSeries ) + { + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + if( !(xSource.is() && xSink.is()) ) + return; + + Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences(); + Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() ); + for( sal_Int32 i=0; i 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>( 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 ) + xSink->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 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 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 ) + {} + + vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const uno::Any& rNewValue ) + { + 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 ) + {} + + vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const OUString& rNewValue ) + { + 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() ( 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() ( vector< uno::Any >& rVector ) + { + if( m_nLevel < static_cast(rVector.size()) ) + { + rVector.erase(rVector.begin() + m_nLevel); + } + } + +private: + sal_Int32 m_nLevel; +}; + +} // anonymous namespace + +InternalDataProvider::InternalDataProvider() + : m_bDataInColumns( true ) +{} + +InternalDataProvider::InternalDataProvider( + const Reference< chart2::XChartDocument > & xChartDoc, + bool bConnectToModel, + bool bDefaultDataInColumns) +: m_bDataInColumns( bDefaultDataInColumns ) +{ + try + { + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) ); + if( xDiagram.is()) + { + Reference< frame::XModel > xChartModel = xChartDoc; + + //data in columns? + { + OUString aRangeString; + bool bFirstCellAsLabel = true; + bool bHasCategories = true; + uno::Sequence< sal_Int32 > aSequenceMapping; + const bool bSomethingDetected( + DataSourceHelper::detectRangeSegmentation( + xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories )); + + // #i120559# if no data was available, restore default + if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns) + { + m_bDataInColumns = bDefaultDataInColumns; + } + } + + // categories + { + vector< vector< uno::Any > > aNewCategories;//inner count is level + { + ChartModel& rModel = dynamic_cast(*xChartModel); + ExplicitCategoriesProvider aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xChartModel), rModel); + + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL 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 aVector(1); + aVector[0] <<= aSimplecategories[nN]; + aNewCategories.push_back( aVector ); + } + } + } + + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabels( aNewCategories ); + else + m_aInternalData.setComplexColumnLabels( aNewCategories ); + if( bConnectToModel ) + DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence( + createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram ); + } + + // data series + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc )); + 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 + std::copy( aNewElements.begin(), aNewElements.end(), + std::inserter( m_aSequenceMap, + m_aSequenceMap.upper_bound( rNewRangeRepresentation ))); +} + +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 )); + } +} + +Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap( + const OUString & rRangeRepresentation ) +{ + Reference xSeq = createDataSequenceFromArray(rRangeRepresentation, OUString()); + if (xSeq.is()) + return xSeq; + + xSeq.set(new UncachedDataSequence(this, rRangeRepresentation)); + addDataSequenceToMap(rRangeRepresentation, xSeq); + return xSeq; +} + +uno::Reference +InternalDataProvider::createDataSequenceFromArray( const OUString& rArrayStr, const OUString& rRole ) +{ + if (rArrayStr.indexOf('{') != 0 || rArrayStr[rArrayStr.getLength()-1] != '}') + { + // Not an array string. + return uno::Reference(); + } + + bool bAllNumeric = true; + uno::Reference xSeq; + + const sal_Unicode* p = rArrayStr.getStr(); + const sal_Unicode* pEnd = p + rArrayStr.getLength(); + const sal_Unicode* pElem = nullptr; + OUString aElem; + + std::vector aRawElems; + ++p; // Skip the first '{'. + --pEnd; // Skip the last '}'. + bool bInQuote = false; + for (; p != pEnd; ++p) + { + 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; + aRawElems.push_back(aElem); + 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 == "values-y" || rRole == "values-first" || rRole == "values-last" || + rRole == "values-min" || rRole == "values-max" || rRole == "values-size") + { + // Column values. Append a new data column and populate it. + + std::vector 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 == "values-x") + { + std::vector 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 == "categories") + { + // Category labels. + + for (size_t i = 0; i < aRawElems.size(); ++i) + { + std::vector aLabels(1, uno::Any(aRawElems[i])); + m_aInternalData.setComplexRowLabel(i, aLabels); + } + + xSeq.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName)); + addDataSequenceToMap(lcl_aCategoriesRangeName, xSeq); + } + else if (rRole == "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) + { + std::vector aLabels(1, uno::Any(aRawElems[0])); + m_aInternalData.setComplexColumnLabel(nColSize-1, 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 ) +{ + Reference< chart2::data::XDataSequence > 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 vector< vector< uno::Any > >& rLabels ) +{ + sal_Int32 nCount = 1;//minimum is 1! + for (auto const& elemLabel : rLabels) + { + nCount = std::max( 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; + vector< 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 > 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( 4 ); + aArguments[0] = beans::PropertyValue( + "CellRangeRepresentation", -1, uno::Any( OUString(lcl_aCompleteRange) ), + beans::PropertyState_DIRECT_VALUE ); + aArguments[1] = 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 + aArguments[2] = beans::PropertyValue( + "FirstCellAsLabel", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE ); + aArguments[3] = 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 = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32(); + 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 SAL_CALL +InternalDataProvider::createDataSequenceByValueArray( + const OUString& aRole, const OUString& aRangeRepresentation ) +{ + return createDataSequenceFromArray(aRangeRepresentation, aRole); +} + +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 = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32(); + 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 = aRange.copy( strlen(lcl_aLabelRangePrefix)).toUInt32(); + 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 = aRange.copy( strlen(lcl_aCategoriesPointRangeNamePrefix) ).toUInt32(); + 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 = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix) ).toInt32(); + vector< 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 ) + { + vector< 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. + Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions(); + aResult.realloc( aLabels.getLength() ); + transform( aLabels.begin(), aLabels.end(), + aResult.getArray(), CommonFunctors::makeAny< OUString >() ); + } + } + else + { + sal_Int32 nIndex = aRange.toInt32(); + if( nIndex >= 0 ) + { + Sequence< double > aData; + if( m_bDataInColumns ) + aData = m_aInternalData.getColumnValues(nIndex); + else + aData = m_aInternalData.getRowValues(nIndex); + if( aData.hasElements() ) + { + aResult.realloc( aData.getLength()); + 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>(aNewData) ); + if( aRange.match( lcl_aLabelRangePrefix ) ) + { + sal_uInt32 nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexColumnLabel( nIndex, aNewVector ); + else + m_aInternalData.setComplexRowLabel( nIndex, aNewVector ); + } + else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) ) + { + sal_Int32 nPointIndex = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32(); + if( m_bDataInColumns ) + m_aInternalData.setComplexRowLabel( nPointIndex, aNewVector ); + else + m_aInternalData.setComplexColumnLabel( nPointIndex, aNewVector ); + } + else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) ) + { + sal_Int32 nLevel = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32(); + vector< 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( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + } + else if( aRange == lcl_aCategoriesRangeName ) + { + vector< 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( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( aComplexCategories ); + } + else + { + sal_Int32 nIndex = aRange.toInt32(); + if( nIndex>=0 ) + { + 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 ) + { + vector< 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( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( 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 ) + { + vector< 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( aComplexCategories ); + else + m_aInternalData.setComplexColumnLabels( 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 = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32(); + 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 ) +{ + const OUString aPivotTableID("PT@"); + 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 vector< vector< Type > >& rIn ) +{ + Sequence< Sequence< Type > > aRet; + sal_Int32 nOuterCount = rIn.size(); + if( nOuterCount ) + { + aRet.realloc(nOuterCount); + for( sal_Int32 nN=0; nN +vector< vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn ) +{ + vector< vector< Type > > aRet; + sal_Int32 nOuterCount = rIn.getLength(); + if( nOuterCount ) + { + aRet.resize(nOuterCount); + for( sal_Int32 nN=0; nN>( rIn[nN] ); + } + return aRet; +} + +std::vector< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const vector< 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 > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn ) +{ + vector< 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() +{ + double fNan = InternalDataProvider::getNotANumber(); + double fValue = fNan; + vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels()); + sal_Int32 nCount = aCategories.size(); + Sequence< double > aDoubles( nCount ); + sal_Int32 nN=0; + for (auto const& category : aCategories) + { + if( !( !category.empty() && (category[0]>>=fValue) ) ) + fValue = fNan; + aDoubles[nN++]=fValue; + } + return aDoubles; +} + +void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates ) +{ + sal_Int32 nCount = rDates.getLength(); + vector< vector< uno::Any > > aNewCategories; + aNewCategories.reserve(nCount); + vector< uno::Any > aSingleLabel(1); + + for(sal_Int32 nN=0; nN > 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 ) +{ + vector< vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) ); + m_aInternalData.setComplexRowLabels( aComplexDescriptions ); +} + +void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions ) +{ + vector< vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() ); + transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(), + aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) ); + m_aInternalData.setComplexColumnLabels( aComplexDescriptions ); +} + +Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions() +{ + vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexRowLabels() ); + SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels ); + return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider ); +} + +Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions() +{ + vector< 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() +{ + double fNan; + ::rtl::math::setNan( & fNan ); + return fNan; +} + +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 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 000000000..c3a896b22 --- /dev/null +++ b/chart2/source/tools/LabeledDataSequence.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +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( ModifyListenerHelper::createModifyEventForwarder()) +{} + +LabeledDataSequence::LabeledDataSequence( + const uno::Reference< chart2::data::XDataSequence > & rValues ) : + m_xData( rValues ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder ); +} + +LabeledDataSequence::LabeledDataSequence( + const uno::Reference< chart2::data::XDataSequence > & rValues, + const uno::Reference< chart2::data::XDataSequence > & rLabel ) : + m_xData( rValues ), + m_xLabel( rLabel ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + 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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL LabeledDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +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 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 000000000..6fbd6bf63 --- /dev/null +++ b/chart2/source/tools/LegendHelper.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 +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +Reference< chart2::XLegend > LegendHelper::showLegend( ChartModel& rModel + , const uno::Reference< uno::XComponentContext >& xContext ) +{ + uno::Reference< chart2::XLegend > xLegend = LegendHelper::getLegend( rModel, xContext, true ); + uno::Reference< beans::XPropertySet > xProp( xLegend, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( "Show", uno::Any(true) ); + + chart2::RelativePosition aRelativePosition; + if( !(xProp->getPropertyValue( "RelativePosition") >>= aRelativePosition) ) + { + chart2::LegendPosition ePos = chart2::LegendPosition_LINE_END; + if( !(xProp->getPropertyValue( "AnchorPosition") >>= ePos ) ) + xProp->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( !(xProp->getPropertyValue( "Expansion") >>= eExpansion ) ) + xProp->setPropertyValue( "Expansion", uno::Any( eExpansion )); + + xProp->setPropertyValue( "RelativePosition", uno::Any()); + } + + } + return xLegend; +} + +void LegendHelper::hideLegend( ChartModel& rModel ) +{ + uno::Reference< chart2::XLegend > xLegend = LegendHelper::getLegend( rModel, nullptr ); + uno::Reference< beans::XPropertySet > xProp( xLegend, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( "Show", uno::Any(false) ); + } +} + +uno::Reference< chart2::XLegend > LegendHelper::getLegend( + ChartModel& rModel + , const uno::Reference< uno::XComponentContext >& xContext + , bool bCreate ) +{ + uno::Reference< chart2::XLegend > xResult; + + try + { + uno::Reference< chart2::XDiagram > xDia( rModel.getFirstDiagram()); + if( xDia.is() ) + { + xResult.set( xDia->getLegend() ); + if( bCreate && !xResult.is() && xContext.is() ) + { + xResult.set( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.Legend", xContext ), uno::UNO_QUERY ); + 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 uno::Reference< chart2::XDiagram > & 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 000000000..5817db73a --- /dev/null +++ b/chart2/source/tools/LifeTime.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 +#include + +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace apphelper +{ + +LifeTimeManager::LifeTimeManager( lang::XComponent* pComponent ) + : m_aListenerContainer( m_aAccessMutex ) + , 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(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(); + + } +} + +bool LifeTimeManager::dispose() +{ + //hold no mutex + { + osl::MutexGuard 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 + } + //no mutex is acquired + + //--do the disposing of listeners after calling this method + { + uno::Reference< lang::XComponent > xComponent(m_pComponent); + if(xComponent.is()) + { + // notify XCLoseListeners + lang::EventObject aEvent( xComponent ); + m_aListenerContainer.disposeAndClear( aEvent ); + } + } + + //no mutex is acquired + { + osl::MutexGuard aGuard( m_aAccessMutex ); + 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 + { + osl::MutexGuard 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()) + { + //--call queryClosing on all registered close listeners + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( + cppu::UnoType::get()); + if( pIC ) + { + lang::EventObject aEvent( xCloseable ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XCloseListener > xCloseListener( aIt.next(), uno::UNO_QUERY ); + if(xCloseListener.is()) + xCloseListener->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 + osl::MutexGuard 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(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 + + osl::MutexGuard 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(false); + + throw ex; +} + +void CloseableLifeTimeManager::g_close_endTryClose_doClose() +{ + //this method is called, if the try to close was successful + osl::MutexGuard 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(false); + impl_doClose(); +} + +void CloseableLifeTimeManager::impl_setOwnership( bool bDeliverOwnership, bool bMyVeto ) +{ + m_bOwnership = bDeliverOwnership && bMyVeto; +} + +void CloseableLifeTimeManager::impl_apiCallCountReachedNull() +{ + //Mutex needs to be acquired exactly once + //mutex will be released inbetween in impl_doClose() + if( m_pCloseable && m_bOwnership ) + impl_doClose(); +} + +void CloseableLifeTimeManager::impl_doClose() +{ + //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; + + NegativeGuard< osl::Mutex > aNegativeGuard( m_aAccessMutex ); + //mutex is not acquired, mutex will be reacquired at the end of this method automatically + + uno::Reference< util::XCloseable > xCloseable; + try + { + xCloseable.set(m_pCloseable); + if(xCloseable.is()) + { + //--call notifyClosing on all registered close listeners + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer.getContainer( + cppu::UnoType::get()); + if( pIC ) + { + lang::EventObject aEvent( xCloseable ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XCloseListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->notifyClosing( aEvent ); + } + } + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + 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(); + } + } + //mutex will be reacquired in destructor of aNegativeGuard +} + +void CloseableLifeTimeManager::g_addCloseListener( const uno::Reference< util::XCloseListener > & xListener ) +{ + osl::MutexGuard aGuard( m_aAccessMutex ); + //Mutex needs to be acquired exactly once; will be released inbetween + if( !impl_canStartApiCall() ) + return; + //mutex is acquired + + m_aListenerContainer.addInterface( cppu::UnoType::get(),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.release(); + m_aEndTryClosingCondition.wait(); //@todo??? this may block??? try closing + m_aAccessMutex.acquire(); + 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 + osl::MutexGuard g(m_rManager.m_aAccessMutex); + 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_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 000000000..7e6d28860 --- /dev/null +++ b/chart2/source/tools/LinePropertiesHelper.cxx @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineDash", + PROP_LINE_DASH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + +//not in service description + rOutProperties.emplace_back( "LineDashName", + PROP_LINE_DASH_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "LineColor", + PROP_LINE_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineTransparence", + PROP_LINE_TRANSPARENCE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineWidth", + PROP_LINE_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineJoint", + PROP_LINE_JOINT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "LineCap", + PROP_LINE_CAP, + cppu::UnoType::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< sal_Int32 >( rOutMap, PROP_LINE_WIDTH, 0 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_LINE_COLOR, 0x000000 ); // black + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int16 >( rOutMap, PROP_LINE_TRANSPARENCE, 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 000000000..9cf3492d8 --- /dev/null +++ b/chart2/source/tools/LinearRegressionCurveCalculator.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 + +using namespace ::com::sun::star; + +namespace chart +{ + +LinearRegressionCurveCalculator::LinearRegressionCurveCalculator() : + PolynomialRegressionCurveCalculator() +{} + +LinearRegressionCurveCalculator::~LinearRegressionCurveCalculator() +{} + +void LinearRegressionCurveCalculator::setRegressionProperties( + sal_Int32 /*aDegree*/, + sal_Bool aForceIntercept, + double aInterceptValue, + sal_Int32 aPeriod ) +{ + PolynomialRegressionCurveCalculator::setRegressionProperties( + 1, + aForceIntercept, + aInterceptValue, + aPeriod); +} + +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( 2 ); + aResult[0].X = min; + aResult[0].Y = getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = 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 000000000..c09eab509 --- /dev/null +++ b/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +LogarithmicRegressionCurveCalculator::LogarithmicRegressionCurveCalculator() : + m_fSlope( 0.0 ), + m_fIntercept( 0.0 ) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +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 + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoefficient ); + 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 ) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( std::isnan( m_fSlope ) || + std::isnan( m_fIntercept ))) + { + fResult = m_fSlope * log( x ) + m_fIntercept; + } + + return fResult; +} + +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( 2 ); + aResult[0].X = min; + aResult[0].Y = getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = 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) ).append( " " ); + } + 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 ).append( " " ); + } + } + aTmpBuf.append( "ln(" ).append( mXName ).append( ") " ); + 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) ).append( " " ); + 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 ( aBuf.toString() == (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 000000000..c9821343b --- /dev/null +++ b/chart2/source/tools/MeanValueRegressionCurveCalculator.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 + +#include +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +MeanValueRegressionCurveCalculator::MeanValueRegressionCurveCalculator() : + m_fMeanValue( 0.0 ) +{ + ::rtl::math::setNan( & m_fMeanValue ); +} + +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 ) + { + ::rtl::math::setNan( & m_fMeanValue ); + } + 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( 2 ); + aResult[0].X = min; + aResult[0].Y = m_fMeanValue; + aResult[1].X = max; + aResult[1].Y = 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 000000000..73c326fdc --- /dev/null +++ b/chart2/source/tools/MediaDescriptorHelper.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 +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace apphelper +{ + +MediaDescriptorHelper::MediaDescriptorHelper( const uno::Sequence< + beans::PropertyValue > & rMediaDescriptor ) + : m_aModelProperties(rMediaDescriptor.getLength()) +{ + 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 + impl_init(); + sal_Int32 nRegularCount = 0; + sal_Int32 nModelCount = 0; + + auto addRegularProp = [&aRegularProperties, &nRegularCount](const beans::PropertyValue& rRegularProp) + { + aRegularProperties[nRegularCount] = rRegularProp; + ++nRegularCount; + }; + auto addModelProp = [this, &nModelCount, &addRegularProp](const beans::PropertyValue& rModelProp) + { + addRegularProp(rModelProp); + m_aModelProperties[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/ModifyListenerHelper.cxx b/chart2/source/tools/ModifyListenerHelper.cxx new file mode 100644 index 000000000..3266af1d0 --- /dev/null +++ b/chart2/source/tools/ModifyListenerHelper.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 +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace +{ + +void lcl_fireModifyEvent( + ::cppu::OBroadcastHelper const & rBroadcastHelper, + const Reference< uno::XWeak > & xEventSource, + const lang::EventObject * pEvent ) +{ + ::cppu::OInterfaceContainerHelper * pCntHlp = rBroadcastHelper.getContainer( + cppu::UnoType::get()); + if( !pCntHlp ) + return; + + lang::EventObject aEventToSend; + if( pEvent ) + aEventToSend = *pEvent; + else + aEventToSend.Source.set( xEventSource ); + OSL_ENSURE( aEventToSend.Source.is(), "Sending event without source" ); + + ::cppu::OInterfaceIteratorHelper aIt( *pCntHlp ); + + while( aIt.hasMoreElements()) + { + Reference< util::XModifyListener > xModListener( aIt.next(), uno::UNO_QUERY ); + if( xModListener.is()) + xModListener->modified( aEventToSend ); + } +} + +struct lcl_weakReferenceToSame +{ + explicit lcl_weakReferenceToSame( const Reference< util::XModifyListener > & xModListener ) : + m_xHardRef( xModListener ) + {} + + // argument type is same as tListenerMap::value_type& + bool operator() ( const std::pair, + css::uno::Reference< css::util::XModifyListener> > & xElem ) + { + Reference< util::XModifyListener > xWeakAsHard( xElem.first ); + if( xWeakAsHard.is()) + return (xWeakAsHard == m_xHardRef); + return false; + } + +private: + Reference< util::XModifyListener > m_xHardRef; +}; + +} // anonymous namespace + +namespace chart::ModifyListenerHelper +{ + +uno::Reference< util::XModifyListener > createModifyEventForwarder() +{ + return new ModifyEventForwarder(); +} + +ModifyEventForwarder::ModifyEventForwarder() : + ::cppu::WeakComponentImplHelper< + css::util::XModifyBroadcaster, + css::util::XModifyListener >( m_aMutex ), + m_aModifyListeners( m_aMutex ) +{ +} + +void ModifyEventForwarder::AddListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyListener > xListenerToAdd( aListener ); + + Reference< uno::XWeak > xWeak( aListener, uno::UNO_QUERY ); + if( xWeak.is()) + { + // remember the helper class for later remove + uno::WeakReference< util::XModifyListener > xWeakRef( aListener ); + xListenerToAdd.set( new WeakModifyListenerAdapter( xWeakRef )); + m_aListenerMap.emplace_back( xWeakRef, xListenerToAdd ); + } + + m_aModifyListeners.addListener( cppu::UnoType::get(), xListenerToAdd ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ModifyEventForwarder::RemoveListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + // look up fitting helper class that has been added + Reference< util::XModifyListener > xListenerToRemove( aListener ); + tListenerMap::iterator aIt( + std::find_if( m_aListenerMap.begin(), m_aListenerMap.end(), lcl_weakReferenceToSame( aListener ))); + if( aIt != m_aListenerMap.end()) + { + xListenerToRemove.set( (*aIt).second ); + // map entry is no longer needed + m_aListenerMap.erase( aIt ); + } + + m_aModifyListeners.removeListener( cppu::UnoType::get(), xListenerToRemove ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ModifyEventForwarder::DisposeAndClear( const Reference< uno::XWeak > & xSource ) +{ + ::cppu::OInterfaceContainerHelper * pCntHlp = m_aModifyListeners.getContainer( + cppu::UnoType::get()); + if( pCntHlp ) + pCntHlp->disposeAndClear( lang::EventObject( xSource ) ); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL ModifyEventForwarder::addModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + AddListener( aListener ); +} + +void SAL_CALL ModifyEventForwarder::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + RemoveListener( aListener ); +} + +// ____ XModifyListener ____ +void SAL_CALL ModifyEventForwarder::modified( const lang::EventObject& aEvent ) +{ + lcl_fireModifyEvent( m_aModifyListeners, Reference< uno::XWeak >(), &aEvent ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ModifyEventForwarder::disposing( const lang::EventObject& /* Source */ ) +{ + // nothing +} + +// ____ WeakComponentImplHelperBase ____ +void SAL_CALL ModifyEventForwarder::disposing() +{ + // dispose was called at this + DisposeAndClear( 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 000000000..7774bec02 --- /dev/null +++ b/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx @@ -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 . + */ + +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +MovingAverageRegressionCurveCalculator::MovingAverageRegressionCurveCalculator() +{} + +MovingAverageRegressionCurveCalculator::~MovingAverageRegressionCurveCalculator() +{} + +// ____ XRegressionCurveCalculator ____ +void SAL_CALL MovingAverageRegressionCurveCalculator::recalculateRegression( + const uno::Sequence< double >& aXValues, + const uno::Sequence< double >& aYValues ) +{ + ::rtl::math::setNan( & m_fCorrelationCoefficient ); + + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValid())); + + const size_t aSize = aValues.first.size(); + + aYList.clear(); + aXList.clear(); + + for( size_t i = mPeriod - 1; i < aSize; ++i ) + { + double yAvg; + yAvg = 0.0; + + for (sal_Int32 j = 0; j < mPeriod; j++) + { + yAvg += aValues.second[i - j]; + } + yAvg /= mPeriod; + + double x = aValues.first[i]; + aYList.push_back(yAvg); + aXList.push_back(x); + } +} + +double SAL_CALL MovingAverageRegressionCurveCalculator::getCurveValue( double /*x*/ ) +{ + double fResult; + rtl::math::setNan(&fResult); + return fResult; +} + +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*/ ) +{ + uno::Sequence< geometry::RealPoint2D > aResult( aYList.size() ); + + for( size_t i = 0; i < aYList.size(); ++i ) + { + aResult[i].X = aXList[i]; + aResult[i].Y = aYList[i]; + } + return aResult; +} + +OUString MovingAverageRegressionCurveCalculator::ImplGetRepresentation( + const uno::Reference< util::XNumberFormatter >& /*xNumFormatter*/, + sal_Int32 /*nNumberFormatKey*/, sal_Int32* /*pFormulaLength = nullptr */ ) const +{ + return SchResId( STR_OBJECT_MOVING_AVERAGE_WITH_PARAMETERS ); +} + +} // 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 000000000..b5e730ba5 --- /dev/null +++ b/chart2/source/tools/NameContainer.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 + +#include + #include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; + +namespace chart +{ + +uno::Reference< container::XNameContainer > createNameContainer( + const css::uno::Type& rType, const OUString& rServicename, const OUString& rImplementationName ) +{ + return new NameContainer( rType, rServicename, rImplementationName ); +} + +NameContainer::NameContainer( const css::uno::Type& rType, const OUString& rServicename, const OUString& rImplementationName ) + : m_aType( rType ) + , m_aServicename( rServicename ) + , m_aImplementationName( rImplementationName ) + , m_aMap() +{ +} + +NameContainer::NameContainer( + const NameContainer & rOther ) + : impl::NameContainer_Base(rOther) + , m_aType( rOther.m_aType ) + , m_aServicename( rOther.m_aServicename ) + , m_aImplementationName( rOther.m_aImplementationName ) + , m_aMap( rOther.m_aMap ) +{ +} + +NameContainer::~NameContainer() +{ +} + +//XServiceInfo +OUString SAL_CALL NameContainer::getImplementationName() +{ + return m_aImplementationName; +} + +sal_Bool SAL_CALL NameContainer::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString > SAL_CALL NameContainer::getSupportedServiceNames() +{ + return { m_aServicename }; +} + +// 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() +{ + sal_Int32 nCount = m_aMap.size(); + Sequence< OUString > aSeq(nCount); + sal_Int32 nN = 0; + for (auto const& elem : m_aMap) + { + aSeq[nN++]=elem.first; + } + return aSeq; +} + +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 m_aType; +} + +// 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 000000000..50f6dc7fb --- /dev/null +++ b/chart2/source/tools/NumberFormatterWrapper.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +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 xProp(m_xNumberFormatsSupplier,uno::UNO_QUERY); + OUString sNullDate( "NullDate" ); + if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(sNullDate) ) + m_aNullDate = xProp->getPropertyValue(sNullDate); + SvNumberFormatsSupplierObj* pSupplierObj = comphelper::getUnoTunnelImplementation( xSupplier ); + if( pSupplierObj ) + m_pNumberFormatter = pSupplierObj->GetNumberFormatter(); + SAL_WARN_IF(!m_pNumberFormatter,"chart2.tools","need a numberformatter"); +} + +NumberFormatterWrapper::~NumberFormatterWrapper() +{ +} + +Date NumberFormatterWrapper::getNullDate() const +{ + Date aRet(30,12,1899); + + util::Date aUtilDate; + if( m_aNullDate.hasValue() && (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; + 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; + 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 000000000..252cfb605 --- /dev/null +++ b/chart2/source/tools/OPropertySet.cxx @@ -0,0 +1,372 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "ImplOPropertySet.hxx" +#include + +#include +#include + +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( ::osl::Mutex & par_rMutex ) : + OBroadcastHelper( par_rMutex ), + // the following causes a warning; there seems to be no way to avoid it + OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )), + m_rMutex( par_rMutex ), + m_pImplProperties( new impl::ImplOPropertySet() ), + m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false) +{ +} + +OPropertySet::OPropertySet( const OPropertySet & rOther, ::osl::Mutex & par_rMutex ) : + OBroadcastHelper( par_rMutex ), + // the following causes a warning; there seems to be no way to avoid it + OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )), + m_rMutex( par_rMutex ), + m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false) +{ + MutexGuard aGuard( m_rMutex ); + if (rOther.m_pImplProperties) + m_pImplProperties.reset(new impl::ImplOPropertySet(*rOther.m_pImplProperties)); +} + +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::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get() }; + + return aTypeList; +} + +Sequence< sal_Int8 > SAL_CALL + OPropertySet::getImplementationId() +{ + return css::uno::Sequence(); +} + +// ____ XPropertyState ____ +beans::PropertyState SAL_CALL + OPropertySet::getPropertyState( const OUString& PropertyName ) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + return m_pImplProperties->GetPropertyStateByHandle( + rPH.getHandleByName( PropertyName )); +} + +Sequence< beans::PropertyState > SAL_CALL + OPropertySet::getPropertyStates( const Sequence< OUString >& aPropertyName ) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + std::unique_ptr 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 m_pImplProperties->GetPropertyStatesByHandle( aHandles ); +} + +void SAL_CALL + OPropertySet::setPropertyToDefault( const OUString& PropertyName ) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + m_pImplProperties->SetPropertyToDefault( rPH.getHandleByName( PropertyName )); + firePropertyChangeEvent(); +} + +Any SAL_CALL + OPropertySet::getPropertyDefault( const OUString& aPropertyName ) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + return GetDefaultValue( rPH.getHandleByName( aPropertyName ) ); +} + +// ____ XMultiPropertyStates ____ + +// Note: getPropertyStates() is already implemented in XPropertyState with the +// same signature + +void SAL_CALL + OPropertySet::setAllPropertiesToDefault() +{ + m_pImplProperties->SetAllPropertiesToDefault(); + firePropertyChangeEvent(); +} + +void SAL_CALL + OPropertySet::setPropertiesToDefault( const Sequence< OUString >& aPropertyNames ) +{ + cppu::IPropertyArrayHelper & rPH = getInfoHelper(); + + std::unique_ptr pHandles(new sal_Int32[ aPropertyNames.getLength() ]); + rPH.fillHandles( pHandles.get(), aPropertyNames ); + + std::vector< sal_Int32 > aHandles( pHandles.get(), pHandles.get() + aPropertyNames.getLength()); + pHandles.reset(); + + m_pImplProperties->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 ) + { + pResultArray[ nI ] = GetDefaultValue( + rPH.getHandleByName( aPropertyNames[ 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(n32Value); + return true; + } + + sal_Int64 n64Value = 0; + if( rValue>>=n64Value ) + { + rConvertedValue <<= static_cast(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 + { + aDefault = GetDefaultValue( nHandle ); + } + catch( const beans::UnknownPropertyException& ) + { + aDefault.clear(); + } + m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue ); + if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && aDefault.hasValue() && aDefault == rValue ) //#i98893# don't export defaults to file + m_pImplProperties->SetPropertyToDefault( nHandle ); + else + m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue ); +} + +void SAL_CALL OPropertySet::getFastPropertyValue + ( Any& rValue, + sal_Int32 nHandle ) const +{ + if( m_pImplProperties->GetPropertyValueByHandle( rValue, nHandle )) + return; + + // property was not set -> try style + uno::Reference< beans::XFastPropertySet > xStylePropSet( m_pImplProperties->GetStyle(), 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 + { + rValue = GetDefaultValue( nHandle ); + } + catch( const beans::UnknownPropertyException& ) + { + rValue.clear(); + } + } +} + +void OPropertySet::firePropertyChangeEvent() +{ + // nothing in base class +} + +// ____ XStyleSupplier ____ +Reference< style::XStyle > SAL_CALL OPropertySet::getStyle() +{ + return m_pImplProperties->GetStyle(); +} + +void SAL_CALL OPropertySet::setStyle( const Reference< style::XStyle >& xStyle ) +{ + if( ! m_pImplProperties->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(); +} + +} // 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 000000000..be592b952 --- /dev/null +++ b/chart2/source/tools/ObjectIdentifier.cxx @@ -0,0 +1,1502 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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; + +static const char m_aMultiClick[] = "MultiClick"; +static const char m_aDragMethodEquals[] = "DragMethod="; +static const char m_aDragParameterEquals[] = "DragParameter="; +static const char m_aProtocol[] = "CID/"; +static const OUString m_aPieSegmentDragMethodServiceName("PieSegmentDragging"); + +namespace +{ + +OUString lcl_createClassificationStringForType( ObjectType eObjectType + , const OUString& rDragMethodServiceName + , const OUString& 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.isEmpty() ) + { + if( !aRet.isEmpty() ) + aRet.append(":"); + aRet.append( m_aDragMethodEquals ); + aRet.append( rDragMethodServiceName ); + + if( !rDragParameterString.isEmpty() ) + { + if( !aRet.isEmpty() ) + aRet.append(":"); + aRet.append( m_aDragParameterEquals ); + aRet.append( 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; +} + +Reference lcl_getFirstStockChartType( const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + if(!xDiagram.is()) + return nullptr; + + //iterate through all coordinate systems + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( !xCooSysContainer.is()) + return nullptr; + + const uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( Reference< XCoordinateSystem > const & coords : aCooSysList ) + { + //iterate through all chart types in the current coordinate system + Reference< XChartTypeContainer > xChartTypeContainer( coords, uno::UNO_QUERY ); + if( !xChartTypeContainer.is() ) + continue; + + const uno::Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( Reference< XChartType > const & xChartType : aChartTypeList ) + { + if(!xChartType.is()) + continue; + OUString aChartType = xChartType->getChartType(); + if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + return xChartType; + } + } + return nullptr; +} + +OUString lcl_getIndexStringAfterString( const OUString& rString, const OUString& rSearchString ) +{ + OUStringBuffer aRet; + + sal_Int32 nIndexStart = rString.lastIndexOf( rSearchString ); + if( nIndexStart != -1 ) + { + nIndexStart += rSearchString.getLength(); + sal_Int32 nIndexEnd = rString.getLength(); + sal_Int32 nNextColon = rString.indexOf( ':', nIndexStart ); + if( nNextColon != -1 ) + nIndexEnd = nNextColon; + aRet = rString.copy(nIndexStart,nIndexEnd-nIndexStart); + } + + return aRet.makeStringAndClear(); +} + +sal_Int32 lcl_StringToIndex( const OUString& rIndexString ) +{ + sal_Int32 nRet = -1; + if( !rIndexString.isEmpty() ) + { + nRet = rIndexString.toInt32(); + if( nRet < -1 ) + nRet = -1; + } + return nRet; +} + +void lcl_parseCooSysIndices( sal_Int32& rnDiagram, sal_Int32& rnCooSys, const OUString& rString ) +{ + rnDiagram = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, "D=" ) ); + rnCooSys = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, "CS=" ) ); +} + +void lcl_parseAxisIndices( sal_Int32& rnDimensionIndex, sal_Int32& rnAxisIndex, const OUString& rString ) +{ + OUString aAxisIndexString = lcl_getIndexStringAfterString( rString, ":Axis=" ); + sal_Int32 nCharacterIndex=0; + rnDimensionIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) ); + rnAxisIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) ); +} + +void lcl_parseGridIndices( sal_Int32& rnSubGridIndex, const OUString& rString ) +{ + rnSubGridIndex = -1; + rnSubGridIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, ":SubGrid=" ) ); +} + +void lcl_parseSeriesIndices( sal_Int32& rnChartTypeIndex, sal_Int32& rnSeriesIndex, sal_Int32& rnPointIndex, const OUString& rString ) +{ + rnChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, "CT=" ) ); + rnSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, "Series=" ) ); + rnPointIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, "Point=" ) ); +} + +void lcl_getDiagramAndCooSys( const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel + , Reference< XDiagram >& xDiagram + , Reference< XCoordinateSystem >& xCooSys ) +{ + sal_Int32 nDiagramIndex = -1; + sal_Int32 nCooSysIndex = -1; + lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rObjectCID ); + xDiagram = ChartModelHelper::findDiagram( xChartModel );//todo use nDiagramIndex when more than one diagram is possible in future + if( !xDiagram.is() ) + return; + + if( nCooSysIndex > -1 ) + { + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + if( nCooSysIndex < aCooSysList.getLength() ) + xCooSys = aCooSysList[nCooSysIndex]; + } + } +} + +} //anonymous namespace + +ObjectIdentifier::ObjectIdentifier() + :m_aObjectCID( OUString() ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const OUString& rObjectCID ) + :m_aObjectCID( rObjectCID ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const Reference< drawing::XShape >& rxShape ) + :m_aObjectCID( OUString() ) + ,m_xAdditionalShape( rxShape ) +{ +} + +ObjectIdentifier::ObjectIdentifier( const Any& rAny ) + :m_aObjectCID( OUString() ) +{ + const uno::Type& rType = rAny.getValueType(); + if ( rType == cppu::UnoType::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 Reference< uno::XInterface >& xObject + , ChartModel& rModel) +{ + OUString aRet; + + enum ObjectType eObjectType = OBJECTTYPE_UNKNOWN; + OUString aObjectID; + OUString aParentParticle; + OUString aDragMethodServiceName; + OUString aDragParameterString; + + try + { + //title + Reference< XTitle > xTitle( xObject, uno::UNO_QUERY ); + if( xTitle.is() ) + { + TitleHelper::eTitleType aTitleType; + if( TitleHelper::getTitleType( aTitleType, xTitle, rModel ) ) + { + eObjectType = OBJECTTYPE_TITLE; + aParentParticle = lcl_getTitleParentParticle( aTitleType ); + aRet = ObjectIdentifier::createClassifiedIdentifierWithParent( + eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString ); + } + return aRet; + + } + + //axis + Reference< XAxis > xAxis( xObject, uno::UNO_QUERY ); + if( xAxis.is() ) + { + Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, rModel.getFirstDiagram() ) ); + OUString aCooSysParticle( createParticleForCoordinateSystem( xCooSys, rModel ) ); + 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( rModel ) ); + } + + //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 Reference< uno::XInterface >& xObject + , const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + enum ObjectType eObjectType = OBJECTTYPE_UNKNOWN; + OUString aObjectID; + OUString aParentParticle; + OUString aDragMethodServiceName; + OUString aDragParameterString; + + try + { + //title + Reference< XTitle > xTitle( xObject, uno::UNO_QUERY ); + if( xTitle.is() ) + { + TitleHelper::eTitleType aTitleType; + if( TitleHelper::getTitleType( aTitleType, xTitle, xChartModel ) ) + { + eObjectType = OBJECTTYPE_TITLE; + aParentParticle = lcl_getTitleParentParticle( aTitleType ); + aRet = ObjectIdentifier::createClassifiedIdentifierWithParent( + eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString ); + } + return aRet; + + } + + //axis + Reference< XAxis > xAxis( xObject, uno::UNO_QUERY ); + if( xAxis.is() ) + { + Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ) ) ); + 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::createClassifiedIdentifierForParticle( + const OUString& rParticle ) +{ + return ObjectIdentifier::createClassifiedIdentifierForParticles( rParticle, OUString() ); +} + +OUString ObjectIdentifier::createClassifiedIdentifierForParticles( + const OUString& rParentParticle + , const OUString& rChildParticle + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString ) +{ + ObjectType eObjectType( ObjectIdentifier::getObjectType( rChildParticle ) ); + if( eObjectType == OBJECTTYPE_UNKNOWN ) + eObjectType = ObjectIdentifier::getObjectType( rParentParticle ); + + OUStringBuffer aRet( m_aProtocol ); + aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString )); + if(aRet.getLength() > static_cast(strlen(m_aProtocol))) + aRet.append("/"); + + if(!rParentParticle.isEmpty()) + { + aRet.append(rParentParticle); + if( !rChildParticle.isEmpty() ) + 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 Reference< XCoordinateSystem >& xCooSys + , ChartModel& rModel ) +{ + OUStringBuffer aRet; + + Reference< XDiagram > xDiagram( rModel.getFirstDiagram() ); + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + sal_Int32 nCooSysIndex = 0; + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( ; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex ) + { + Reference< XCoordinateSystem > xCurrentCooSys( aCooSysList[nCooSysIndex] ); + if( xCooSys == xCurrentCooSys ) + { + aRet = ObjectIdentifier::createParticleForDiagram(); + aRet.append(":CS="); + aRet.append( OUString::number( nCooSysIndex ) ); + break; + } + } + } + + return aRet.makeStringAndClear(); +} + +OUString ObjectIdentifier::createParticleForCoordinateSystem( + const Reference< XCoordinateSystem >& xCooSys + , const Reference< frame::XModel >& xChartModel ) +{ + OUStringBuffer aRet; + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + sal_Int32 nCooSysIndex = 0; + uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( ; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex ) + { + Reference< XCoordinateSystem > xCurrentCooSys( aCooSysList[nCooSysIndex] ); + if( xCooSys == xCurrentCooSys ) + { + aRet = ObjectIdentifier::createParticleForDiagram(); + aRet.append(":CS="); + aRet.append( OUString::number( nCooSysIndex ) ); + break; + } + } + } + + return aRet.makeStringAndClear(); +} + +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 Reference< frame::XModel >& 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 ) +{ + OUStringBuffer aRet; + + aRet.append("D="); + aRet.append( OUString::number( nDiagramIndex ) ); + aRet.append(":CS="); + aRet.append( OUString::number( nCooSysIndex ) ); + aRet.append(":CT="); + aRet.append( OUString::number( nChartTypeIndex ) ); + aRet.append(":"); + aRet.append(getStringForType( OBJECTTYPE_DATA_SERIES )); + aRet.append("="); + aRet.append( OUString::number( nSeriesIndex ) ); + + return aRet.makeStringAndClear(); +} + +OUString ObjectIdentifier::createParticleForLegend( ChartModel& ) +{ + OUStringBuffer aRet; + + //todo: if more than one diagram is implemented, find the correct diagram which is owner of the given legend + + aRet.append( ObjectIdentifier::createParticleForDiagram() ); + aRet.append(":"); + aRet.append(getStringForType( OBJECTTYPE_LEGEND )); + aRet.append("="); + + return aRet.makeStringAndClear(); +} + +OUString ObjectIdentifier::createParticleForLegend( + const Reference< frame::XModel >& ) +{ + OUStringBuffer aRet; + + //todo: if more than one diagram is implemented, find the correct diagram which is owner of the given legend + + aRet.append( ObjectIdentifier::createParticleForDiagram() ); + aRet.append(":"); + aRet.append(getStringForType( OBJECTTYPE_LEGEND )); + aRet.append("="); + + return aRet.makeStringAndClear(); +} + +OUString ObjectIdentifier::createClassifiedIdentifier( + enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES + , const OUString& rParticleID )//e.g. SeriesID +{ + return createClassifiedIdentifierWithParent( + eObjectType, rParticleID, OUString() ); +} + +OUString ObjectIdentifier::createClassifiedIdentifierWithParent( + enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID + , const OUString& rParticleID //e.g. Point Index or SubGrid Index + , const OUString& rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId" + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString + ) + //, bool bIsMultiClickObject ) //e.g. true +{ + //e.g. "MultiClick/Series=2:Point=34" + + OUStringBuffer aRet( m_aProtocol ); + aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString )); + if(aRet.getLength() > static_cast(strlen(m_aProtocol))) + aRet.append("/"); + aRet.append(rParentPartical); + if(!rParentPartical.isEmpty()) + aRet.append(":"); + + aRet.append(getStringForType( eObjectType )); + aRet.append("="); + aRet.append(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( + const OUString& rDragParameterString + , sal_Int32& rOffsetPercent + , awt::Point& rMinimumPosition + , awt::Point& rMaximumPosition ) +{ + sal_Int32 nCharacterIndex = 0; + + OUString aValueString( rDragParameterString.getToken( 0, ',', nCharacterIndex ) ); + rOffsetPercent = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMinimumPosition.X = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMinimumPosition.Y = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMaximumPosition.X = aValueString.toInt32(); + if( nCharacterIndex < 0 ) + return false; + + aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex ); + rMaximumPosition.Y = aValueString.toInt32(); + return nCharacterIndex >= 0; +} + +OUString ObjectIdentifier::getDragMethodServiceName( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nIndexStart = rCID.indexOf( m_aDragMethodEquals ); + if( nIndexStart != -1 ) + { + nIndexStart = rCID.indexOf( '=', nIndexStart ); + if( nIndexStart != -1 ) + { + nIndexStart++; + sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart ); + if( nNextSlash != -1 ) + { + sal_Int32 nIndexEnd = nNextSlash; + sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart ); + if( nNextColon < nNextSlash ) + nIndexEnd = nNextColon; + aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart); + } + } + } + return aRet; +} + +OUString ObjectIdentifier::getDragParameterString( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nIndexStart = rCID.indexOf( m_aDragParameterEquals ); + if( nIndexStart != -1 ) + { + nIndexStart = rCID.indexOf( '=', nIndexStart ); + if( nIndexStart != -1 ) + { + nIndexStart++; + sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart ); + if( nNextSlash != -1 ) + { + sal_Int32 nIndexEnd = nNextSlash; + sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart ); + if( nNextColon < nNextSlash ) + nIndexEnd = nNextColon; + aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart); + } + } + } + return aRet; +} + +bool ObjectIdentifier::isDragableObject( const OUString& 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: + OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( rClassifiedIdentifier ) ); + bReturn = !aDragMethodServiceName.isEmpty(); + 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( const OUString& 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( const OUString& 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 = rClassifiedIdentifier.match( m_aMultiClick, strlen(m_aProtocol) ); + return bRet; +} + +bool ObjectIdentifier::areSiblings( const OUString& rCID1, const OUString& rCID2 ) +{ + bool bRet=false; + sal_Int32 nLastSign1 = rCID1.lastIndexOf( '=' ); + sal_Int32 nLastSign2 = rCID2.lastIndexOf( '=' ); + if( nLastSign1 == rCID1.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs + bRet=false; + else if( nLastSign2 == rCID2.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs + bRet=false; + else if( ObjectIdentifier::areIdenticalObjects( rCID1, rCID2 ) ) + bRet=false; + else + { + OUString aParent1( ObjectIdentifier::getFullParentParticle( rCID1 ) ); + if( !aParent1.isEmpty() ) + { + OUString 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( const OUString& rCID1, const OUString& rCID2 ) +{ + if( rCID1 == rCID2 ) + return true; + //draggable pie or donut segments need special treatment, as their CIDs do change with offset + { + if( rCID1.indexOf( m_aPieSegmentDragMethodServiceName ) < 0 + || rCID2.indexOf( m_aPieSegmentDragMethodServiceName ) < 0 ) + 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; + default: //OBJECTTYPE_UNKNOWN + ; + } + return aRet; +} + +ObjectType ObjectIdentifier::getObjectType( const OUString& rCID ) +{ + ObjectType eRet; + sal_Int32 nLastSign = rCID.lastIndexOf( ':' );//last sign before the type string + if(nLastSign==-1) + nLastSign = rCID.lastIndexOf( '/' ); + if(nLastSign==-1) + { + sal_Int32 nEndIndex = rCID.lastIndexOf( '=' ); + if(nEndIndex==-1) + return OBJECTTYPE_UNKNOWN; + nLastSign = 0; + } + if( nLastSign>0 ) + nLastSign++; + + if( rCID.match("Page",nLastSign) ) + eRet = OBJECTTYPE_PAGE; + else if( rCID.match("Title",nLastSign) ) + eRet = OBJECTTYPE_TITLE; + else if( rCID.match("LegendEntry",nLastSign) ) + eRet = OBJECTTYPE_LEGEND_ENTRY; + else if( rCID.match("Legend",nLastSign) ) + eRet = OBJECTTYPE_LEGEND; + else if( rCID.match("DiagramWall",nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM_WALL; + else if( rCID.match("DiagramFloor",nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM_FLOOR; + else if( rCID.match("D=",nLastSign) ) + eRet = OBJECTTYPE_DIAGRAM; + else if( rCID.match("AxisUnitLabel",nLastSign) ) + eRet = OBJECTTYPE_AXIS_UNITLABEL; + else if( rCID.match("Axis",nLastSign) ) + eRet = OBJECTTYPE_AXIS; + else if( rCID.match("Grid",nLastSign) ) + eRet = OBJECTTYPE_GRID; + else if( rCID.match("SubGrid",nLastSign) ) + eRet = OBJECTTYPE_SUBGRID; + else if( rCID.match("Series",nLastSign) ) + eRet = OBJECTTYPE_DATA_SERIES; + else if( rCID.match("Point",nLastSign) ) + eRet = OBJECTTYPE_DATA_POINT; + else if( rCID.match("DataLabels",nLastSign) ) + eRet = OBJECTTYPE_DATA_LABELS; + else if( rCID.match("DataLabel",nLastSign) ) + eRet = OBJECTTYPE_DATA_LABEL; + else if( rCID.match("ErrorsX",nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_X; + else if( rCID.match("ErrorsY",nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_Y; + else if( rCID.match("ErrorsZ",nLastSign) ) + eRet = OBJECTTYPE_DATA_ERRORS_Z; + else if( rCID.match("Curve",nLastSign) ) + eRet = OBJECTTYPE_DATA_CURVE; + else if( rCID.match("Equation",nLastSign) ) + eRet = OBJECTTYPE_DATA_CURVE_EQUATION; + else if( rCID.match("Average",nLastSign) ) + eRet = OBJECTTYPE_DATA_AVERAGE_LINE; + else if( rCID.match("StockRange",nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_RANGE; + else if( rCID.match("StockLoss",nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_LOSS; + else if( rCID.match("StockGain",nLastSign) ) + eRet = OBJECTTYPE_DATA_STOCK_GAIN; + 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( + const OUString& 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( + const OUString& rSeriesParticle + , sal_Int32 nCurveIndex ) +{ + OUString aParticleID( OUString::number( nCurveIndex ) ); + return createClassifiedIdentifierWithParent( OBJECTTYPE_DATA_CURVE_EQUATION, aParticleID, rSeriesParticle ); +} + +OUString ObjectIdentifier::addChildParticle( const OUString& rParticle, const OUString& rChildParticle ) +{ + OUStringBuffer aRet(rParticle); + + if( !aRet.isEmpty() && !rChildParticle.isEmpty() ) + aRet.append(":"); + if( !rChildParticle.isEmpty() ) + aRet.append(rChildParticle); + + return aRet.makeStringAndClear(); +} + +OUString ObjectIdentifier::createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex ) +{ + OUStringBuffer aRet( getStringForType( eObjectType ) ); + if( !aRet.isEmpty() ) + { + aRet.append("="); + aRet.append(OUString::number(nIndex)); + } + return aRet.makeStringAndClear(); +} + +sal_Int32 ObjectIdentifier::getIndexFromParticleOrCID( const OUString& rParticleOrCID ) +{ + const OUString aIndexString = lcl_getIndexStringAfterString( rParticleOrCID, "=" ); + return lcl_StringToIndex( aIndexString.getToken( 0, ',' ) ); +} + +OUString ObjectIdentifier::createSeriesSubObjectStub( ObjectType eSubObjectType + , const OUString& rSeriesParticle + , const OUString& rDragMethodServiceName + , const OUString& rDragParameterString ) +{ + OUString aChildParticle = getStringForType( eSubObjectType ) + "="; + + return createClassifiedIdentifierForParticles( + rSeriesParticle, aChildParticle + , rDragMethodServiceName, rDragParameterString ); +} + +OUString ObjectIdentifier::createPointCID( const OUString& rPointCID_Stub, sal_Int32 nIndex ) +{ + return rPointCID_Stub + OUString::number( nIndex ); +} + +OUString ObjectIdentifier::getParticleID( const OUString& rCID ) +{ + OUString aRet; + sal_Int32 nLast = rCID.lastIndexOf('='); + if(nLast>=0) + aRet = rCID.copy(++nLast); + return aRet; +} + +OUString ObjectIdentifier::getFullParentParticle( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nStartPos = rCID.lastIndexOf('/'); + if( nStartPos>=0 ) + { + nStartPos++; + sal_Int32 nEndPos = rCID.lastIndexOf(':'); + if( nEndPos>=0 && nStartPos < nEndPos ) + { + aRet = rCID.copy(nStartPos,nEndPos-nStartPos); + } + } + + return aRet; +} + +OUString ObjectIdentifier::getObjectID( const OUString& rCID ) +{ + OUString aRet; + + sal_Int32 nStartPos = rCID.lastIndexOf('/'); + if( nStartPos>=0 ) + { + nStartPos++; + sal_Int32 nEndPos = rCID.getLength(); + aRet = rCID.copy(nStartPos,nEndPos-nStartPos); + } + + return aRet; +} + +bool ObjectIdentifier::isCID( const OUString& rName ) +{ + return !rName.isEmpty() && rName.match( m_aProtocol ); +} + +Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet( + const OUString& rObjectCID, + const Reference< chart2::XChartDocument >& xChartDocument ) +{ + return ObjectIdentifier::getObjectPropertySet( + rObjectCID, Reference< frame::XModel >( xChartDocument )); +} + +Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + //return the model object that is indicated by rObjectCID + if(rObjectCID.isEmpty()) + return nullptr; + if(!xChartModel.is()) + return nullptr; + + Reference< beans::XPropertySet > xObjectProperties; + try + { + ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID ); + OUString aParticleID = ObjectIdentifier::getParticleID( rObjectCID ); + + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + switch(eObjectType) + { + case OBJECTTYPE_PAGE: + { + Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY ); + if( xChartDocument.is()) + xObjectProperties.set( xChartDocument->getPageBackground() ); + } + break; + case OBJECTTYPE_TITLE: + { + TitleHelper::eTitleType aTitleType = getTitleTypeForCID( rObjectCID ); + Reference< XTitle > xTitle( TitleHelper::getTitle( aTitleType, xChartModel ) ); + xObjectProperties.set( xTitle, uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_LEGEND: + { + if( xDiagram.is() ) + xObjectProperties.set( xDiagram->getLegend(), uno::UNO_QUERY ); + } + break; + case OBJECTTYPE_LEGEND_ENTRY: + break; + case OBJECTTYPE_DIAGRAM: + { + xObjectProperties.set( xDiagram, uno::UNO_QUERY ); + } + 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 ); + + Reference< chart2::XAxis > xAxis( + AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) ); + if( xAxis.is() ) + xObjectProperties.set( xAxis, uno::UNO_QUERY ); + } + 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.set( AxisHelper::getGridProperties( xCooSys , nDimensionIndex, nAxisIndex, nSubGridIndex ) ); + } + break; + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_SERIES: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if( xSeries.is() ) + xObjectProperties.set( xSeries, uno::UNO_QUERY ); + + break; + } + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_POINT: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if(xSeries.is()) + { + sal_Int32 nIndex = aParticleID.toInt32(); + xObjectProperties = xSeries->getDataPointByIndex( nIndex ); + } + break; + } + case OBJECTTYPE_DATA_ERRORS_X: + case OBJECTTYPE_DATA_ERRORS_Y: + case OBJECTTYPE_DATA_ERRORS_Z: + { + Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ) ); + if(xSeries.is()) + { + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBarProp; + if( xSeriesProp.is() ) + { + 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"; + + xSeriesProp->getPropertyValue( errorBar ) >>= xErrorBarProp; + xObjectProperties = xErrorBarProp; + } + } + break; + } + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_CURVE: + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + Reference< XRegressionCurveContainer > xRegressionContainer( ObjectIdentifier::getDataSeriesForCID( + rObjectCID, xChartModel ), uno::UNO_QUERY ); + if(xRegressionContainer.is()) + { + sal_Int32 nIndex = aParticleID.toInt32(); + uno::Sequence< Reference< XRegressionCurve > > aCurveList = + xRegressionContainer->getRegressionCurves(); + if( nIndex >= 0 && nIndex getEquationProperties()); + else + xObjectProperties.set( aCurveList[nIndex], uno::UNO_QUERY ); + } + } + break; + } + case OBJECTTYPE_DATA_STOCK_RANGE: + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + { + Reference xChartType( lcl_getFirstStockChartType( xChartModel ) ); + Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); + if(xChartTypeProps.is()) + xChartTypeProps->getPropertyValue( "BlackDay" ) >>= xObjectProperties; + } + break; + case OBJECTTYPE_DATA_STOCK_GAIN: + { + Reference xChartType( lcl_getFirstStockChartType( xChartModel ) ); + Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY ); + if(xChartTypeProps.is()) + xChartTypeProps->getPropertyValue( "WhiteDay" ) >>= xObjectProperties; + } + break; + default: //OBJECTTYPE_UNKNOWN + break; + } + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xObjectProperties; +} + +Reference< XAxis > ObjectIdentifier::getAxisForCID( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > 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 ); +} + +Reference< XDataSeries > ObjectIdentifier::getDataSeriesForCID( + const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + Reference< XDataSeries > xSeries; + + Reference< XDiagram > xDiagram; + Reference< XCoordinateSystem > 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 ); + + Reference< XDataSeriesContainer > xDataSeriesContainer( DiagramHelper::getChartTypeByIndex( xDiagram, nChartTypeIndex ), uno::UNO_QUERY ); + if( xDataSeriesContainer.is() ) + { + uno::Sequence< uno::Reference< XDataSeries > > aDataSeriesSeq( xDataSeriesContainer->getDataSeries() ); + if( nSeriesIndex >= 0 && nSeriesIndex < aDataSeriesSeq.getLength() ) + xSeries.set( aDataSeriesSeq[nSeriesIndex] ); + } + + return xSeries; +} + +Reference< XDiagram > ObjectIdentifier::getDiagramForCID( + const OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + Reference< XDiagram > xDiagram; + + Reference< XCoordinateSystem > xCooSys; + lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys ); + + return xDiagram; +} + +TitleHelper::eTitleType ObjectIdentifier::getTitleTypeForCID( const OUString& rCID ) +{ + TitleHelper::eTitleType eRet( TitleHelper::MAIN_TITLE ); + + OUString 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( const OUString& 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( const OUString& rObjectCID, bool bForward ) +{ + sal_Int32 nDiagramIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, "CID/D=" ) ); + sal_Int32 nCooSysIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, "CS=" ) ); + sal_Int32 nChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, "CT=" ) ); + sal_Int32 nSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, "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 000000000..b3585b71f --- /dev/null +++ b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx @@ -0,0 +1,396 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +#include + +using namespace com::sun::star; + +namespace chart +{ + +static double lcl_GetDotProduct(std::vector& aVec1, std::vector& 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 ) +{ + rtl::math::setNan(&m_fCorrelationCoefficient); + + 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 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 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 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(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 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 ) +{ + double fResult; + rtl::math::setNan(&fResult); + + if (mCoefficients.empty()) + { + return fResult; + } + + sal_Int32 aNoCoefficients = static_cast(mCoefficients.size()); + + // Horner's method + 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) ).append(" "); + 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 ( aBuf.toString() == ( 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 000000000..1d3a36d5c --- /dev/null +++ b/chart2/source/tools/PopupRequest.cxx @@ -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/. + * + */ + +#include + +using namespace css; + +namespace chart +{ + +PopupRequest::PopupRequest() + : impl::PopupRequest_Base(m_aMutex) +{ +} + +PopupRequest::~PopupRequest() +{} + +// ____ XRequestCallback ____ + +void SAL_CALL PopupRequest::addCallback(const uno::Reference& xCallback, + const uno::Any& /*aData*/) +{ + m_xCallback = xCallback; +} + +// ____ WeakComponentImplHelperBase ____ +// is called when dispose() is called at this component +void SAL_CALL PopupRequest::disposing() +{ +} + +} // 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 000000000..eb054bd8d --- /dev/null +++ b/chart2/source/tools/PotentialRegressionCurveCalculator.cxx @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace chart +{ + +PotentialRegressionCurveCalculator::PotentialRegressionCurveCalculator() + : m_fSlope(0.0) + , m_fIntercept(0.0) + , m_fSign(1.0) +{ + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); +} + +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 ) + { + ::rtl::math::setNan( & m_fSlope ); + ::rtl::math::setNan( & m_fIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoefficient ); + 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 ) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if( ! ( std::isnan( m_fSlope ) || + std::isnan( m_fIntercept ))) + { + fResult = m_fIntercept * pow( x, m_fSlope ); + } + + return fResult; +} + +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( 2 ); + aResult[0].X = min; + aResult[0].Y = getCurveValue( min ); + aResult[1].X = max; + aResult[1].Y = 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) ).append( " " ); + 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 ).append( " " ); + } + } + if( m_fSlope != 0.0 ) // add slope value + { + aTmpBuf.append( mXName ).append( "^" ); + aTmpBuf.append( 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 000000000..cb3e860c0 --- /dev/null +++ b/chart2/source/tools/PropertyHelper.cxx @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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( const Any & rValue, const Reference< container::XNameAccess > & xAccess ) + : m_aValue( 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( const OUString & rCmpStr ) : + m_aCmpStr( rCmpStr ) + {} + + bool operator() ( const OUString & rStr ) + { + return rStr.match( m_aCmpStr ); + } + +private: + OUString m_aCmpStr; +}; + +struct lcl_OUStringRestToInt32 +{ + explicit lcl_OUStringRestToInt32( sal_Int32 nPrefixLength ) : + m_nPrefixLength( nPrefixLength ) + {} + sal_Int32 operator() ( const OUString & rStr ) + { + if( m_nPrefixLength > rStr.getLength() ) + return 0; + return rStr.copy( m_nPrefixLength ).toInt32(); + } +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() || + ( rValue.getValueType() != xNameContainer->getElementType())) + return rPreferredName; + + try + { + Reference< container::XNameAccess > xNameAccess( xNameContainer, uno::UNO_QUERY_THROW ); + auto aNames( comphelper::sequenceToContainer>( xNameAccess->getElementNames())); + std::vector< OUString >::const_iterator aIt( + std::find_if( aNames.begin(), aNames.end(), lcl_EqualsElement( rValue, xNameAccess ))); + + // element not found in container + if( aIt == aNames.end()) + { + OUString aUniqueName; + + // check if preferred name is already used + if( !rPreferredName.isEmpty()) + { + aIt = std::find( aNames.begin(), aNames.end(), rPreferredName ); + if( aIt == aNames.end()) + aUniqueName = rPreferredName; + } + + if( aUniqueName.isEmpty()) + { + // 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, rValue ); + return aUniqueName; + } + else + // element found => return name + return *aIt; + } + 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 000000000..b326d0bac --- /dev/null +++ b/chart2/source/tools/RangeHighlighter.cxx @@ -0,0 +1,398 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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()); + for( sal_Int32 i=0; i & xSelectionSupplier ) : + impl::RangeHighlighter_Base( m_aMutex ), + m_xSelectionSupplier( xSelectionSupplier ), + 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_xSelectionSupplier.is()) + return; + + try + { + Reference< frame::XController > xController( m_xSelectionSupplier, uno::UNO_QUERY ); + Reference< frame::XModel > xChartModel; + if( xController.is()) + xChartModel.set( xController->getModel()); + + m_bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( xChartModel ); + + uno::Any aSelection( m_xSelectionSupplier->getSelection()); + const uno::Type& rType = aSelection.getValueType(); + + if ( rType == cppu::UnoType::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 ); + Reference< chart2::XDataSeries > xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID, 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, 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, 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 + Reference< chart2::XDiagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, 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 + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY_THROW ); + fillRangesForDiagram( xChartDoc->getFirstDiagram() ); + return; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void RangeHighlighter::fillRangesForDiagram( const Reference< chart2::XDiagram > & xDiagram ) +{ + Sequence< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram )); + m_aSelectedRanges.realloc( aSelectedRanges.getLength()); + // @todo: merge ranges + for( sal_Int32 i=0; i & 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 Reference< uno::XInterface > & xDataSeries, sal_Int32 nIndex ) +{ + if( !xDataSeries.is()) + return; + + Reference< chart2::data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY ); + if( !xSource.is() ) + return; + + Color nPreferredColor = defaultPreferredColor; + std::vector< chart2::data::HighlightedRange > aHilightedRanges; + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences()); + for( 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(); + rBHelper.addListener( cppu::UnoType::get(), 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 ) +{ + rBHelper.removeListener( cppu::UnoType::get(), 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() +{ + ::cppu::OInterfaceContainerHelper* pIC = rBHelper.getContainer( + cppu::UnoType< view::XSelectionChangeListener >::get() ); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + 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 SAL_CALL RangeHighlighter::disposing() +{ + // @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 000000000..441095005 --- /dev/null +++ b/chart2/source/tools/ReferenceSizeProvider.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 +{ + +ReferenceSizeProvider::ReferenceSizeProvider( + awt::Size aPageSize, + const Reference< XChartDocument > & 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() +{ + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDoc )); + + // DataSeries/Points + std::vector< Reference< XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& elem : aSeries) + { + Reference< beans::XPropertySet > xSeriesProp(elem, uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + // data points + Sequence< sal_Int32 > aPointIndexes; + try + { + if( xSeriesProp->getPropertyValue( "AttributedDataPoints") >>= aPointIndexes ) + { + for( sal_Int32 idx : 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( xSeriesProp ); + } + } +} + +void ReferenceSizeProvider::setValuesAtPropertySet( + const Reference< beans::XPropertySet > & xProp, + bool bAdaptFontSizes /* = true */ ) +{ + if( ! xProp.is()) + return; + + static const char aRefSizeName[] = "ReferencePageSize"; + + 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 Reference< XChartDocument > & xChartDoc ) +{ + AutoResizeState eResult = AUTO_RESIZE_UNKNOWN; + + // Main Title + Reference< XTitled > xDocTitled( xChartDoc, uno::UNO_QUERY ); + if( xDocTitled.is()) + impl_getAutoResizeFromTitled( xDocTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // diagram is needed by the rest of the objects + Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartDoc ); + if( ! xDiagram.is()) + return eResult; + + // Sub Title + Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY ); + if( xDiaTitled.is()) + impl_getAutoResizeFromTitled( xDiaTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // Legend + Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + getAutoResizeFromPropSet( xLegendProp, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // Axes (incl. Axis Titles) + const Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( Reference< XAxis > const & axis : aAxes ) + { + Reference< beans::XPropertySet > xProp( axis, uno::UNO_QUERY ); + if( xProp.is()) + getAutoResizeFromPropSet( xProp, eResult ); + Reference< XTitled > xTitled( axis, uno::UNO_QUERY ); + if( xTitled.is()) + { + impl_getAutoResizeFromTitled( xTitled, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + } + } + + // DataSeries/Points + std::vector< Reference< XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for (auto const& elem : aSeries) + { + Reference< beans::XPropertySet > xSeriesProp(elem, uno::UNO_QUERY); + if( xSeriesProp.is()) + { + getAutoResizeFromPropSet( xSeriesProp, eResult ); + if( eResult == AUTO_RESIZE_AMBIGUOUS ) + return eResult; + + // data points + Sequence< sal_Int32 > aPointIndexes; + try + { + if( xSeriesProp->getPropertyValue( "AttributedDataPoints") >>= aPointIndexes ) + { + for( sal_Int32 idx : 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( Reference< XTitled >( m_xChartDoc, uno::UNO_QUERY )); + + // diagram is needed by the rest of the objects + Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( m_xChartDoc ); + if( ! xDiagram.is()) + return; + + // Sub Title + impl_setValuesAtTitled( Reference< XTitled >( xDiagram, uno::UNO_QUERY )); + + // Legend + Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + setValuesAtPropertySet( xLegendProp ); + + // Axes (incl. Axis Titles) + const Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( Reference< XAxis > const & axis : aAxes ) + { + Reference< beans::XPropertySet > xProp( axis, uno::UNO_QUERY ); + if( xProp.is()) + setValuesAtPropertySet( xProp ); + impl_setValuesAtTitled( Reference< XTitled >( axis, uno::UNO_QUERY )); + } + + // 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 000000000..5b65375b0 --- /dev/null +++ b/chart2/source/tools/RegressionCurveCalculator.cxx @@ -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 . + */ + +#include + +#include +#include + +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +RegressionCurveCalculator::RegressionCurveCalculator() : + m_fCorrelationCoefficient(0.0), + mDegree(2), + mForceIntercept(false), + mInterceptValue(0.0), + mPeriod(2), + mXName("x"), mYName("f(x)") +{ + rtl::math::setNan( &m_fCorrelationCoefficient ); + rtl::math::setNan( &mInterceptValue ); +} + +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 ) +{ + mDegree = aDegree; + mForceIntercept = aForceIntercept; + mInterceptValue = aInterceptValue; + mPeriod = aPeriod; +} + +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 = OStringToOUString( + ::rtl::math::doubleToString( fNumber, rtl_math_StringFormat_G1, nSignificantDigit, '.', true ), + RTL_TEXTENCODING_ASCII_US ); + // 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 = OStringToOUString( + ::rtl::math::doubleToString( fNumber, rtl_math_StringFormat_G1, nSignificantDigit, '.', true ), + RTL_TEXTENCODING_ASCII_US ); + } + fNumber = ::rtl::math::stringToDouble( aResult, '.', ',' ); + } + aResult = xNumFormatter->convertNumberToString( nNumberFormatKey, fNumber ); + } + else + { + sal_Int32 nStringLength = 4; // default length + if ( pStringLength ) + nStringLength = *pStringLength; + aResult = OStringToOUString( + ::rtl::math::doubleToString( fNumber, rtl_math_StringFormat_G1, nStringLength, '.', true ), + RTL_TEXTENCODING_ASCII_US ); + } + 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(); + + // 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 ); + + 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; nPdoScaling( x ); + aResult[nP].X = x; + aResult[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 000000000..47f6a4b0e --- /dev/null +++ b/chart2/source/tools/RegressionCurveHelper.cxx @@ -0,0 +1,764 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "RegressionCurveModel.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 +{ + +Reference< XRegressionCurve > RegressionCurveHelper::createMeanValueLine() +{ + return Reference< XRegressionCurve >( new MeanValueRegressionCurve ); +} + +Reference< XRegressionCurve > RegressionCurveHelper::createRegressionCurveByServiceName( + const OUString& aServiceName ) +{ + Reference< XRegressionCurve > xResult; + + // todo: use factory methods with service name + if( aServiceName == "com.sun.star.chart2.LinearRegressionCurve" ) + { + xResult.set( new LinearRegressionCurve ); + } + else if( aServiceName == "com.sun.star.chart2.LogarithmicRegressionCurve" ) + { + xResult.set( new LogarithmicRegressionCurve ); + } + else if( aServiceName == "com.sun.star.chart2.ExponentialRegressionCurve" ) + { + xResult.set( new ExponentialRegressionCurve ); + } + else if( aServiceName == "com.sun.star.chart2.PotentialRegressionCurve" ) + { + xResult.set( new PotentialRegressionCurve ); + } + else if( aServiceName == "com.sun.star.chart2.PolynomialRegressionCurve" ) + { + xResult.set( new PolynomialRegressionCurve ); + } + else if( aServiceName == "com.sun.star.chart2.MovingAverageRegressionCurve" ) + { + xResult.set( new MovingAverageRegressionCurve ); + } + + return xResult; +} + +Reference< XRegressionCurveCalculator > RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( + const OUString& aServiceName ) +{ + Reference< XRegressionCurveCalculator > xResult; + + // todo: use factory methods with service name + if( aServiceName == "com.sun.star.chart2.MeanValueRegressionCurve" ) + { + xResult.set( new MeanValueRegressionCurveCalculator() ); + } + if( aServiceName == "com.sun.star.chart2.LinearRegressionCurve" ) + { + xResult.set( new LinearRegressionCurveCalculator() ); + } + else if( aServiceName == "com.sun.star.chart2.LogarithmicRegressionCurve" ) + { + xResult.set( new LogarithmicRegressionCurveCalculator() ); + } + else if( aServiceName == "com.sun.star.chart2.ExponentialRegressionCurve" ) + { + xResult.set( new ExponentialRegressionCurveCalculator() ); + } + else if( aServiceName == "com.sun.star.chart2.PotentialRegressionCurve" ) + { + xResult.set( new PotentialRegressionCurveCalculator() ); + } + else if( aServiceName == "com.sun.star.chart2.PolynomialRegressionCurve" ) + { + xResult.set( new PolynomialRegressionCurveCalculator() ); + } + else if( aServiceName == "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 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()); + for( i=0; irecalculateRegression( aXValues, aYValues ); +} + +void RegressionCurveHelper::initializeCurveCalculator( + const Reference< XRegressionCurveCalculator > & xOutCurveCalculator, + const Reference< XDataSeries > & xSeries, + const Reference< frame::XModel > & xModel ) +{ + sal_Int32 nAxisType = ChartTypeHelper::getAxisType( + ChartModelHelper::getChartTypeOfSeries( xModel, xSeries ), 0 ); // x-axis + + initializeCurveCalculator( xOutCurveCalculator, + uno::Reference< data::XDataSource >( xSeries, uno::UNO_QUERY ), + (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::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"; +} + +uno::Reference< chart2::XRegressionCurve > + 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 curve; + } + } + catch( const Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return uno::Reference< chart2::XRegressionCurve >(); +} + +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::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"); + } +} + +uno::Reference< chart2::XRegressionCurve > RegressionCurveHelper::addRegressionCurve( + SvxChartRegress eType, + uno::Reference< XRegressionCurveContainer > const & xRegressionCurveContainer, + const uno::Reference< beans::XPropertySet >& xPropertySource, + const uno::Reference< beans::XPropertySet >& xEquationProperties ) +{ + uno::Reference< chart2::XRegressionCurve > 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.set( createRegressionCurveByServiceName( aServiceName ) ); + + if( xEquationProperties.is()) + xCurve->setEquationProperties( xEquationProperties ); + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + if( xProperties.is()) + { + if( xPropertySource.is()) + comphelper::copyProperties( xPropertySource, xProperties ); + else + { + uno::Reference< XPropertySet > xSeriesProp( xRegressionCurveContainer, uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + xProperties->setPropertyValue( "LineColor", + xSeriesProp->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( + uno::Reference< chart2::XRegressionCurveContainer > const & xRegCnt ) +{ + bool bRemovedSomething = false; + if( xRegCnt.is()) + { + try + { + const uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + std::vector< uno::Reference< chart2::XRegressionCurve > > aCurvesToDelete; + for( uno::Reference< chart2::XRegressionCurve > const & curve : aCurves ) + { + 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( + uno::Reference< chart2::XRegressionCurveContainer > const & xRegCnt ) +{ + if( !xRegCnt.is()) + return; + + try + { + const uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves( + xRegCnt->getRegressionCurves()); + for( uno::Reference< chart2::XRegressionCurve > const & curve : aCurves ) + { + if( !isMeanValueLine( curve ) ) + { + uno::Reference< chart2::XRegressionCurve > xRegCurve( curve ); + if( xRegCurve.is() ) + { + uno::Reference< beans::XPropertySet > xEqProp( xRegCurve->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"); + } +} + +uno::Reference< XRegressionCurve > 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()); +} + +uno::Reference< chart2::XRegressionCurve > 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 curve; + } + } + } + catch( const Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return nullptr; +} + +uno::Reference< chart2::XRegressionCurve > RegressionCurveHelper::getRegressionCurveAtIndex( + const Reference< XRegressionCurveContainer >& xCurveContainer, + sal_Int32 aIndex ) +{ + if( !xCurveContainer.is()) + return nullptr; + + try + { + uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves(xCurveContainer->getRegressionCurves()); + if(0 <= aIndex && aIndex < aCurves.getLength()) + { + 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 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; +} + +std::vector< Reference< chart2::XRegressionCurve > > + RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine( + const Reference< chart2::XDiagram > & xDiagram ) +{ + std::vector< Reference< chart2::XRegressionCurve > > aResult; + std::vector< Reference< chart2::XDataSeries > > aSeries( DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + for (auto const& elem : aSeries) + { + Reference< chart2::XRegressionCurveContainer > xContainer(elem, uno::UNO_QUERY); + if(xContainer.is()) + { + const uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves(xContainer->getRegressionCurves()); + for( Reference< XRegressionCurve > const & curve : aCurves ) + { + if( ! isMeanValueLine( curve )) + aResult.push_back( curve ); + } + } + } + + return aResult; +} + +void RegressionCurveHelper::resetEquationPosition( + const Reference< chart2::XRegressionCurve > & xCurve ) +{ + if( !xCurve.is()) + return; + + try + { + const OUString aPosPropertyName( "RelativePosition" ); + 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 Reference< chart2::XRegressionCurveContainer >& xContainer, + const Reference< chart2::XRegressionCurve >& xCurve ) +{ + if( xContainer.is()) + { + uno::Sequence< uno::Reference< XRegressionCurve > > aCurves( + xContainer->getRegressionCurves()); + + for( sal_Int32 i = 0; i < aCurves.getLength(); ++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; +} + +} //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 000000000..649e93e27 --- /dev/null +++ b/chart2/source/tools/RegressionCurveModel.cxx @@ -0,0 +1,570 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include "RegressionEquation.hxx" +#include +#include +#include +#include +#include +#include + +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 +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "PolynomialDegree", + PROPERTY_DEGREE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "MovingAveragePeriod", + PROPERTY_PERIOD, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ExtrapolateForward", + PROPERTY_EXTRAPOLATE_FORWARD, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ExtrapolateBackward", + PROPERTY_EXTRAPOLATE_BACKWARD, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ForceIntercept", + PROPERTY_FORCE_INTERCEPT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "InterceptValue", + PROPERTY_INTERCEPT_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "CurveName", + PROPERTY_CURVE_NAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND ); +} + +struct StaticXXXDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + ::chart::LinePropertiesHelper::AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +}; + +struct StaticXXXDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticXXXDefaults_Initializer > +{ +}; + +struct StaticRegressionCurveInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } +}; + +struct StaticRegressionCurveInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticRegressionCurveInfoHelper_Initializer > +{ +}; + +struct StaticRegressionCurveInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticRegressionCurveInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticRegressionCurveInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticRegressionCurveInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +RegressionCurveModel::RegressionCurveModel( tCurveType eCurveType ) : + ::property::OPropertySet( m_aMutex ), + m_eRegressionCurveType( eCurveType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()), + 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_aMutex ), + m_eRegressionCurveType( rOther.m_eRegressionCurveType ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + 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 ); + ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder ); + fireModifyEvent(); + } +} + +// ____ 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 ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL RegressionCurveModel::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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() +{ + fireModifyEvent(); +} + +void RegressionCurveModel::fireModifyEvent() +{ + m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this ))); +} + +// ____ OPropertySet ____ +uno::Any RegressionCurveModel::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticXXXDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL RegressionCurveModel::getInfoHelper() +{ + return *StaticRegressionCurveInfoHelper::get(); +} + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL RegressionCurveModel::getPropertySetInfo() +{ + return *StaticRegressionCurveInfo::get(); +} + +// 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 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 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 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 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 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 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 const &) +{ + return cppu::acquire(new ::chart::MovingAverageRegressionCurve ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/RegressionCurveModel.hxx b/chart2/source/tools/RegressionCurveModel.hxx new file mode 100644 index 000000000..05257e2dc --- /dev/null +++ b/chart2/source/tools/RegressionCurveModel.hxx @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONCURVEMODEL_HXX +#define INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONCURVEMODEL_HXX + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +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 RegressionCurveModel : + public MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const override; + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + // ____ 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; + + // ____ 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; + css::uno::Reference< css::beans::XPropertySet > m_xEquationProperties; +}; + +// 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 + +// INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONCURVEMODEL_HXX +#endif + +/* 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 000000000..1c46dc69f --- /dev/null +++ b/chart2/source/tools/RegressionEquation.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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_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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "XName", + PROP_EQUATION_XNAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "YName", + PROP_EQUATION_YNAME, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ShowCorrelationCoefficient", + PROP_EQUATION_SHOW_CORRELATION_COEFF, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT ); + + rOutProperties.emplace_back( "ReferencePageSize", + PROP_EQUATION_REF_PAGE_SIZE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RelativePosition", + PROP_EQUATION_REL_POS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( CHART_UNONAME_NUMFMT, + PROP_EQUATION_NUMBER_FORMAT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + +struct StaticRegressionEquationDefaults_Initializer +{ + ::chart::tPropertyValueMap* operator()() + { + static ::chart::tPropertyValueMap aStaticDefaults; + lcl_AddDefaultsToMap( aStaticDefaults ); + return &aStaticDefaults; + } +private: + static void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap ) + { + ::chart::LinePropertiesHelper::AddDefaultsToMap( rOutMap ); + ::chart::FillProperties::AddDefaultsToMap( rOutMap ); + ::chart::CharacterProperties::AddDefaultsToMap( rOutMap ); + + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SHOW, false ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_XNAME, OUString("x") ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_YNAME, OUString("f(x)") ); + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SHOW_CORRELATION_COEFF, false ); + //::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_EQUATION_SEPARATOR, OUString( '\n' )); + + // override other defaults + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE ); + + float fDefaultCharHeight = 10.0; + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight ); + ::chart::PropertyHelper::setPropertyValue( rOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight ); + } +}; + +struct StaticRegressionEquationDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticRegressionEquationDefaults_Initializer > +{ +}; + +struct StaticRegressionEquationInfoHelper_Initializer +{ + ::cppu::OPropertyArrayHelper* operator()() + { + static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() ); + return &aPropHelper; + } + +private: + static uno::Sequence< Property > lcl_GetPropertySequence() + { + 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 ); + } + +}; + +struct StaticRegressionEquationInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticRegressionEquationInfoHelper_Initializer > +{ +}; + +struct StaticRegressionEquationInfo_Initializer +{ + uno::Reference< beans::XPropertySetInfo >* operator()() + { + static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticRegressionEquationInfoHelper::get() ) ); + return &xPropertySetInfo; + } +}; + +struct StaticRegressionEquationInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticRegressionEquationInfo_Initializer > +{ +}; + +} // anonymous namespace + +namespace chart +{ + +RegressionEquation::RegressionEquation() : + ::property::OPropertySet( m_aMutex ), + m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder()) +{} + +RegressionEquation::RegressionEquation( const RegressionEquation & rOther ) : + impl::RegressionEquation_Base(rOther), + ::property::OPropertySet( rOther, m_aMutex ), + m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder()) +{} + +RegressionEquation::~RegressionEquation() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL RegressionEquation::createClone() +{ + return uno::Reference< util::XCloneable >( new RegressionEquation( *this )); +} + +// ____ OPropertySet ____ +uno::Any RegressionEquation::GetDefaultValue( sal_Int32 nHandle ) const +{ + const tPropertyValueMap& rStaticDefaults = *StaticRegressionEquationDefaults::get(); + tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) ); + if( aFound == rStaticDefaults.end() ) + return uno::Any(); + return (*aFound).second; +} + +::cppu::IPropertyArrayHelper & SAL_CALL RegressionEquation::getInfoHelper() +{ + return *StaticRegressionEquationInfoHelper::get(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL RegressionEquation::getPropertySetInfo() +{ + return *StaticRegressionEquationInfo::get(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL RegressionEquation::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL RegressionEquation::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) +{ + try + { + uno::Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ 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 > >( m_aStrings ), + m_xModifyEventForwarder ); + m_aStrings = Strings; + ModifyListenerHelper::addListenerToAllElements( + comphelper::sequenceToContainer > >( 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 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 000000000..605dd115a --- /dev/null +++ b/chart2/source/tools/RegressionEquation.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONEQUATION_HXX +#define INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONEQUATION_HXX + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +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 MutexContainer, + 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 css::uno::Any GetDefaultValue( sal_Int32 nHandle ) 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; + + css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_TOOLS_REGRESSIONEQUATION_HXX +#endif + +/* 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 000000000..deb3e5ca5 --- /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 +#include +#include +#include +#include + +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 * rtl::math::cos( fAnglePi ) + fYDelta * rtl::math::sin( fAnglePi ) ) ); + aResult.Y += static_cast< sal_Int32 >( + ::rtl::math::round( - fXDelta * rtl::math::sin( fAnglePi ) + fYDelta * rtl::math::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 000000000..a142d5b29 --- /dev/null +++ b/chart2/source/tools/RelativeSizeHelper.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 +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::std; + +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 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( + const Reference< XPropertySet > & xTargetProperties, + const awt::Size & rOldReferenceSize, + const awt::Size & rNewReferenceSize ) +{ + if( ! xTargetProperties.is()) + return; + + float fFontHeight = 0; + + 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 000000000..850eb9b84 --- /dev/null +++ b/chart2/source/tools/ResId.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +namespace chart +{ + OUString SchResId(const char *pId) + { + return Translate::get(pId, 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 000000000..82ce8149b --- /dev/null +++ b/chart2/source/tools/Scaling.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 +#include +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +namespace +{ + +static const char lcl_aServiceName_Logarithmic[] = "com.sun.star.chart2.LogarithmicScaling"; +static const char lcl_aServiceName_Exponential[] = "com.sun.star.chart2.ExponentialScaling"; +static const char lcl_aServiceName_Linear[] = "com.sun.star.chart2.LinearScaling"; +static const char lcl_aServiceName_Power[] = "com.sun.star.chart2.PowerScaling"; + +} + +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 ) +{ + double fResult; + if( std::isnan( value ) || std::isinf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = log( value ) / m_fLogOfBase; + return fResult; +} + +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 ) +{ + double fResult; + if( std::isnan( value ) || std::isinf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = pow( m_fBase, value ); + return fResult; +} + +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 ) +{ + double fResult; + if( std::isnan( value ) || std::isinf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = m_fOffset + m_fSlope * value; + return fResult; +} + +uno::Reference< XScaling > SAL_CALL + LinearScaling::getInverseScaling() +{ + // ToDo: ApproxEqual ? + if( m_fSlope == 0 ) + throw uno::RuntimeException(); + + 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 ) +{ + double fResult; + if( std::isnan( value ) || std::isinf( value ) ) + ::rtl::math::setNan( & fResult ); + else + fResult = pow( value, m_fExponent ); + return fResult; +} + +uno::Reference< XScaling > SAL_CALL + PowerScaling::getInverseScaling() +{ + // ToDo: ApproxEqual ? + if( m_fExponent == 0 ) + throw uno::RuntimeException(); + + 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 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 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 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 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 000000000..9d5746ef6 --- /dev/null +++ b/chart2/source/tools/SceneProperties.cxx @@ -0,0 +1,332 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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::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::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // shadowSlant + rOutProperties.emplace_back( "D3DSceneShadowSlant", + PROP_SCENE_SHADOW_SLANT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // shadeMode + rOutProperties.emplace_back( "D3DSceneShadeMode", + PROP_SCENE_SHADE_MODE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // ambientColor + rOutProperties.emplace_back( "D3DSceneAmbientColor", + PROP_SCENE_AMBIENT_COLOR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // lightingMode + rOutProperties.emplace_back( "D3DSceneTwoSidedLighting", + PROP_SCENE_TWO_SIDED_LIGHTING, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // camera geometry + rOutProperties.emplace_back( "D3DCameraGeometry", + PROP_SCENE_CAMERA_GEOMETRY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + + // perspective + rOutProperties.emplace_back( "D3DScenePerspective", + PROP_SCENE_PERSPECTIVE, + cppu::UnoType::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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection1", + PROP_SCENE_LIGHT_DIRECTION_1, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn1", + PROP_SCENE_LIGHT_ON_1, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 2 + rOutProperties.emplace_back( "D3DSceneLightColor2", + PROP_SCENE_LIGHT_COLOR_2, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection2", + PROP_SCENE_LIGHT_DIRECTION_2, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn2", + PROP_SCENE_LIGHT_ON_2, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 3 + rOutProperties.emplace_back( "D3DSceneLightColor3", + PROP_SCENE_LIGHT_COLOR_3, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection3", + PROP_SCENE_LIGHT_DIRECTION_3, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn3", + PROP_SCENE_LIGHT_ON_3, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 4 + rOutProperties.emplace_back( "D3DSceneLightColor4", + PROP_SCENE_LIGHT_COLOR_4, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection4", + PROP_SCENE_LIGHT_DIRECTION_4, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn4", + PROP_SCENE_LIGHT_ON_4, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 5 + rOutProperties.emplace_back( "D3DSceneLightColor5", + PROP_SCENE_LIGHT_COLOR_5, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection5", + PROP_SCENE_LIGHT_DIRECTION_5, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn5", + PROP_SCENE_LIGHT_ON_5, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 6 + rOutProperties.emplace_back( "D3DSceneLightColor6", + PROP_SCENE_LIGHT_COLOR_6, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection6", + PROP_SCENE_LIGHT_DIRECTION_6, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn6", + PROP_SCENE_LIGHT_ON_6, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 7 + rOutProperties.emplace_back( "D3DSceneLightColor7", + PROP_SCENE_LIGHT_COLOR_7, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection7", + PROP_SCENE_LIGHT_DIRECTION_7, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn7", + PROP_SCENE_LIGHT_ON_7, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + // light source 8 + rOutProperties.emplace_back( "D3DSceneLightColor8", + PROP_SCENE_LIGHT_COLOR_8, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightDirection8", + PROP_SCENE_LIGHT_DIRECTION_8, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "D3DSceneLightOn8", + PROP_SCENE_LIGHT_ON_8, + cppu::UnoType::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< sal_Int32 >( rOutMap, PROP_SCENE_DISTANCE, 4200 ); + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_SCENE_FOCAL_LENGTH, 8000 ); + +// PROP_SCENE_SHADOW_SLANT; + ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_SHADE_MODE, drawing::ShadeMode_SMOOTH ); + + ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( + 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 000000000..02dab3b9b --- /dev/null +++ b/chart2/source/tools/StatisticsHelper.cxx @@ -0,0 +1,375 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + } + } + + double fResult; + if( rOutValidCount == 0 ) + ::rtl::math::setNan( & fResult ); + else + { + const double fN = static_cast< double >( rOutValidCount ); + fResult = (fQuadSum - fSum*fSum/fN) / fN; + } + + return fResult; +} + +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 ); + aRole.append( '-' ); + + if( bPositiveValue ) + aRole.append( "positive" ); + else + aRole.append( "negative" ); + + OUString aLongRole = aRole.makeStringAndClear(); + Reference< chart2::data::XLabeledDataSequence > xLSeq( + ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole )); + // try role without "-negative" or "-positive" postfix + if( xLSeq.is()) + rOutRoleNameUsed = aLongRole; + else + { + xLSeq.set( ::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 ); + aSequences[ aSequences.getLength() - 1 ] = xLSeq; + xSink->setData( aSequences ); +} + +void lcl_setXMLRangePropertyAtDataSequence( + const Reference< chart2::data::XDataSequence > & xDataSequence, + const OUString & rXMLRange ) +{ + try + { + const OUString aXMLRangePropName( "CachedXMLRange"); + 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 ); + double fResult; + + if( nValCount == 0 || + std::isnan( fVar )) + { + ::rtl::math::setNan( & fResult ); + } + else + { + // standard-deviation / sqrt(n) + fResult = sqrt( fVar ) / sqrt( double(nValCount) ); + } + + return fResult; +} + +Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + bool bPositiveValue, + bool bYError /* = true */ ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + if( !xDataSource.is()) + return xResult; + + OUString aRole; + Reference< chart2::data::XLabeledDataSequence > xLSeq( + lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole )); + if( xLSeq.is()) + xResult.set( xLSeq ); + + return xResult; +} + +Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource( + const Reference< chart2::data::XDataSource > & xDataSource, + bool bPositiveValue, + bool bYError /* = true */ ) +{ + 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 = 0.0; + ::rtl::math::setNan( & fResult ); + + 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 Reference< chart2::XDataSeries > & xDataSeries, + sal_Int32 nStyle, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xErrorBar; + Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + if( !xSeriesProp.is()) + return xErrorBar; + + const OUString aPropName( + bYError ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X)); + if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) || + !xErrorBar.is()) + { + xErrorBar.set( new ErrorBar ); + } + + OSL_ASSERT( xErrorBar.is()); + if( xErrorBar.is()) + { + xErrorBar->setPropertyValue( "ErrorBarStyle", uno::Any( nStyle )); + } + + xSeriesProp->setPropertyValue( aPropName, uno::Any( xErrorBar )); + + return xErrorBar; +} + +Reference< beans::XPropertySet > StatisticsHelper::getErrorBars( + const Reference< chart2::XDataSeries > & xDataSeries, + bool bYError /* = true */ ) +{ + Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBar; + const OUString aPropName( + bYError ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X)); + + if ( xSeriesProp.is()) + xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar; + + return xErrorBar; +} + +bool StatisticsHelper::hasErrorBars( + const Reference< chart2::XDataSeries > & 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 Reference< chart2::XDataSeries > & 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 Reference< chart2::XDataSeries > & 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 000000000..fe788397d --- /dev/null +++ b/chart2/source/tools/ThreeDHelper.cxx @@ -0,0 +1,1460 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 Reference< beans::XPropertySet >& xSceneProperties ) +{ + if( xSceneProperties.is() ) + { + bool bRightAngledAxes = false; + xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes; + if(bRightAngledAxes) + { + uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + return true; + } + } + } + return false; +} + +void lcl_RotateLightSource( const Reference< beans::XPropertySet >& xSceneProperties + , const OUString& rLightSourceDirection + , const OUString& rLightSourceOn + , const ::basegfx::B3DHomMatrix& rRotationMatrix ) +{ + if( !xSceneProperties.is() ) + return; + + bool bLightOn = false; + if( !(xSceneProperties->getPropertyValue( rLightSourceOn ) >>= bLightOn) ) + return; + + if( bLightOn ) + { + drawing::Direction3D aLight; + if( xSceneProperties->getPropertyValue( rLightSourceDirection ) >>= aLight ) + { + ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) ); + aLightVector = rRotationMatrix*aLightVector; + + xSceneProperties->setPropertyValue( rLightSourceDirection + , uno::Any( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) ); + } + } +} + +void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRottion, const Reference< beans::XPropertySet >& xSceneProperties ) +{ + if(!xSceneProperties.is()) + return; + + ::basegfx::B3DHomMatrix aLightRottion( rLightRottion ); + BaseGFXHelper::ReduceToRotationMatrix( aLightRottion ); + + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection1", "D3DSceneLightOn1", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection2", "D3DSceneLightOn2", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection3", "D3DSceneLightOn3", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection4", "D3DSceneLightOn4", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection5", "D3DSceneLightOn5", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection6", "D3DSceneLightOn6", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection7", "D3DSceneLightOn7", aLightRottion ); + lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection8", "D3DSceneLightOn8", aLightRottion ); +} + +::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + ::basegfx::B3DHomMatrix aInverseRotation; + double fXAngleRad=0.0; + double fYAngleRad=0.0; + double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( + xSceneProperties, 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; +} + +::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + ::basegfx::B3DHomMatrix aCompleteRotation; + double fXAngleRad=0.0; + double fYAngleRad=0.0; + double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( + xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); + return aCompleteRotation; +} + +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); +} + +bool lcl_isLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, bool bRealistic ) +{ + if(!xDiagramProps.is()) + return false; + + bool bIsOn = false; + xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2 ) >>= bIsOn; + if(!bIsOn) + return false; + + uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + + sal_Int32 nColor = 0; + xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ) >>= nColor; + if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) ) + return false; + + sal_Int32 nAmbientColor = 0; + xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR ) >>= nAmbientColor; + if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) ) + return false; + + drawing::Direction3D aDirection(0,0,0); + xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_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; + xDiagramProps->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes; + if(!bRightAngledAxes) + { + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); + BaseGFXHelper::ReduceToRotationMatrix( aRotation ); + ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) ); + aLightVector = aRotation*aLightVector; + aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector ); + } + } + } + + return lcl_isEqual( aDirection, aDefaultDirection ); +} + +bool lcl_isRealisticLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) +{ + return lcl_isLightScheme( xDiagramProps, true /*bRealistic*/ ); +} +bool lcl_isSimpleLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) +{ + return lcl_isLightScheme( xDiagramProps, false /*bRealistic*/ ); +} +void lcl_setLightsForScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, const ThreeDLookScheme& rScheme ) +{ + if(!xDiagramProps.is()) + return; + if( rScheme == ThreeDLookScheme_Unknown) + return; + + xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2, uno::Any( true ) ); + + uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + uno::Any aADirection( rScheme == ThreeDLookScheme_Simple + ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) + : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) ); + + xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2, aADirection ); + //rotate light direction when right angled axes are off but supported + { + bool bRightAngledAxes = false; + xDiagramProps->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes; + if(!bRightAngledAxes) + { + if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) ) + { + ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); + BaseGFXHelper::ReduceToRotationMatrix( aRotation ); + lcl_RotateLightSource( xDiagramProps, "D3DSceneLightDirection2", "D3DSceneLightOn2", aRotation ); + } + } + } + + sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); + xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2, uno::Any( nColor ) ); + + sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); + xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR, uno::Any( nAmbientColor ) ); +} + +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; +} + +bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode + , sal_Int32 nRoundedEdges + , sal_Int32 nObjectLines + , const uno::Reference< XDiagram >& xDiagram ) +{ + if(aShadeMode!=drawing::ShadeMode_FLAT) + return false; + if(nRoundedEdges!=0) + return false; + if(nObjectLines==0) + { + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + return ChartTypeHelper::noBordersForSimpleScheme( xChartType ); + } + if(nObjectLines!=1) + return false; + return true; +} + +void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode + , sal_Int32& rnRoundedEdges + , sal_Int32& rnObjectLines ) +{ + rShadeMode = drawing::ShadeMode_SMOOTH; + rnRoundedEdges = 5; + rnObjectLines = 0; +} + +void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode + , sal_Int32& rnRoundedEdges + , sal_Int32& rnObjectLines + , const uno::Reference< XDiagram >& xDiagram ) +{ + rShadeMode = drawing::ShadeMode_FLAT; + rnRoundedEdges = 0; + + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1; +} + +} //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 +{ +::basegfx::B3DHomMatrix lcl_getCameraMatrix( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + drawing::HomogenMatrix aCameraMatrix; + + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + if( xSceneProperties.is() ) + xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= aCG; + + ::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 ); +} + +double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad ) +{ + //valid range: ]-Pi,Pi] + while( fAngleRad<=-F_PI ) + fAngleRad+=(2*F_PI); + while( fAngleRad>F_PI ) + fAngleRad-=(2*F_PI); + return fAngleRad; +} + +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 = F_PI2; + else + x = -F_PI2; + y = R; + } + else if( ( nRotationDeg == 90 || nRotationDeg == 270 ) + && ( nElevationDeg == 90 || nElevationDeg == 270 ) ) + { + //cR==0 && cE==0 + z = F_PI2; + if( sin(R)>0 ) + x = F_PI2; + else + x = -F_PI2; + + if( (sin(R)*sin(E))>0 ) + y = 0.0; + else + y = F_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 = F_PI2; + else + y = -F_PI2; + + if( (cos(E))>0 ) + x = 0; + else + x = F_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 F_PI and x=+-F_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 = F_PI2; + else + x = -F_PI2; + //use element 21 for y + if( (sin(R)*sin(E)*sin(z))>0.0) + y = 0.0; + else + y = F_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 = +- F_PI/2; + //x = +- F_PI/2; + z = F_PI2; + x = F_PI2; + 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=(F_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=(F_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 = F_PI; + + //element 23 + double f23 = cos(z)*sin(x) / cos(R); + if( f23 > 0 ) + E = F_PI2; + else + E = -F_PI2; + } + 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 = F_PI2; + else + R = -F_PI2; + + //element 21 + double f21 = cos(y)*sin(z) / sin(R); + if( f21 > 0 ) + E = F_PI2; + else + E = -F_PI2; + } + 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+=F_PI; + + //element 23 + double f23 = cos(z)*sin(x); + if( f23/cos(R) > 0 ) + E = F_PI2; + else + E = -F_PI2; + } + } + else if( lcl_isSinZero(x) ) + { + //sinY==0 sinX==0 + //element 13+11 + if( f11 > 0 ) + R = 0.0; + else + R = F_PI; + + double f22 = cos(x)*cos(z); + if( f22 > 0 ) + E = 0.0; + else + E = F_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 = F_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+=F_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 = F_PI2; + else + R = -F_PI2; + + //element 21+22 + double f21 = cos(y)*sin(z); + if( f21/sin(R) > 0 ) + E = F_PI2; + else + E = -F_PI2; + } + else + { + //sinY == 0 && all other !=0 + double f13 = sin(x)*sin(z); + R = atan( f13/f11 ); + if( (f11*cos(R))<0.0 ) + R+=F_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+=F_PI; + } + } + else if( lcl_isCosZero(y) ) + { + //cosY==0 + + double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y); + if( f13 >= 0 ) + R = F_PI2; + else + R = -F_PI2; + + double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z); + if( f22 >= 0 ) + E = 0.0; + else + E = F_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+=F_PI; + + double f22 = cos(x)*cos(z); + if( f22>0 ) + E = 0.0; + else + E = F_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+=F_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+=F_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 F_PI + if( f11<0.0 ) + R=F_PI; + E=F_PI2;//22 -> E=+-F_PI/2 + //use element 11 and 23 for sign + double f23 = cos(z)*sin(x); + if( (f11*f23*sin(E))<0.0 ) + E=-F_PI2; + } + else if( lcl_isCosZero(z) ) + { + //cosY!=0 sinY!=0 cosX=0 cosZ=0 + //element 11 & 13: + if( (sin(x)*sin(z))>0.0 ) + R=F_PI2; + else + R=-F_PI2; + //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 += F_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+=F_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+=F_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+=F_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+=F_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::getRotationAngleFromDiagram( + const Reference< beans::XPropertySet >& xSceneProperties, double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad ) +{ + //takes the camera and the transformation matrix into account + + rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0; + + if( !xSceneProperties.is() ) + return; + + //get camera rotation + ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( xSceneProperties ) ); + BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix ); + + //get scene rotation + ::basegfx::B3DHomMatrix aSceneRotation; + { + drawing::HomogenMatrix aHomMatrix; + if( xSceneProperties->getPropertyValue( "D3DTransformMatrix") >>= 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<-F_PI2 || rfZAngleRad>F_PI2) + { + rfZAngleRad-=F_PI; + rfXAngleRad-=F_PI; + rfYAngleRad=(F_PI-rfYAngleRad); + + rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad); + rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad); + rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad); + } +} + +void ThreeDHelper::switchRightAngledAxes( const Reference< beans::XPropertySet >& xSceneProperties, bool bRightAngledAxes ) +{ + try + { + if( xSceneProperties.is() ) + { + bool bOldRightAngledAxes = false; + xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bOldRightAngledAxes; + if( bOldRightAngledAxes!=bRightAngledAxes) + { + xSceneProperties->setPropertyValue( "RightAngledAxes", uno::Any( bRightAngledAxes )); + if(bRightAngledAxes) + { + ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); + lcl_rotateLights( aInverseRotation, xSceneProperties ); + } + else + { + ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( xSceneProperties ) ); + lcl_rotateLights( aCompleteRotation, xSceneProperties ); + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ThreeDHelper::setRotationAngleToDiagram( + const Reference< beans::XPropertySet >& xSceneProperties + , 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 + + if( !xSceneProperties.is() ) + return; + + try + { + //remind old rotation for adaptation of light directions + ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); + + ::basegfx::B3DHomMatrix aInverseCameraRotation; + { + ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix( + lcl_getCameraMatrix( xSceneProperties ) ) ); + 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 + xSceneProperties->setPropertyValue( + "D3DTransformMatrix", uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); + + //rotate lights if RightAngledAxes are not set or not supported + bool bRightAngledAxes = false; + xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes; + uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); + if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + { + ::basegfx::B3DHomMatrix aNewRotation; + aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); + lcl_rotateLights( aNewRotation*aInverseOldRotation, xSceneProperties ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void ThreeDHelper::getRotationFromDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties + , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree ) +{ + double fXAngle, fYAngle, fZAngle; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); + + if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + 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 ThreeDHelper::setRotationToDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties + , 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( xSceneProperties ) ) + ThreeDHelper::convertElevationRotationDegToXYZAngleRad( + nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle ); + + ThreeDHelper::setRotationAngleToDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); +} + +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::getCameraDistance( + const Reference< beans::XPropertySet >& xSceneProperties ) +{ + double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; + + if( !xSceneProperties.is() ) + return fCameraDistance; + + try + { + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= aCG; + ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) ); + fCameraDistance = aVRP.getLength(); + + ensureCameraDistanceRange( fCameraDistance ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return fCameraDistance; +} + +void ThreeDHelper::setCameraDistance( + const Reference< beans::XPropertySet >& xSceneProperties, double fCameraDistance ) +{ + if( !xSceneProperties.is() ) + return; + + try + { + if( fCameraDistance <= 0 ) + fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; + + drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); + xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= 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 ); + + xSceneProperties->setPropertyValue( "D3DCameraGeometry", uno::Any( aCG )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +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; +} + +ThreeDLookScheme ThreeDHelper::detectScheme( const uno::Reference< XDiagram >& xDiagram ) +{ + ThreeDLookScheme aScheme = ThreeDLookScheme_Unknown; + + sal_Int32 nRoundedEdges; + sal_Int32 nObjectLines; + ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); + + //get shade mode and light settings: + drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); + uno::Reference< beans::XPropertySet > xDiagramProps( xDiagram, uno::UNO_QUERY ); + try + { + if( xDiagramProps.is() ) + xDiagramProps->getPropertyValue( "D3DSceneShadeMode" )>>= aShadeMode; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, xDiagram ) ) + { + if( lcl_isSimpleLightScheme(xDiagramProps) ) + aScheme = ThreeDLookScheme_Simple; + } + else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) ) + { + if( lcl_isRealisticLightScheme(xDiagramProps) ) + aScheme = ThreeDLookScheme_Realistic; + } + + return aScheme; +} + +void ThreeDHelper::setScheme( const uno::Reference< XDiagram >& xDiagram, ThreeDLookScheme aScheme ) +{ + if( aScheme == ThreeDLookScheme_Unknown ) + return; + + drawing::ShadeMode aShadeMode; + sal_Int32 nRoundedEdges; + sal_Int32 nObjectLines; + + if( aScheme == ThreeDLookScheme_Simple ) + lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,xDiagram); + else + lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines); + + try + { + ThreeDHelper::setRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); + + uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY ); + if( xProp.is() ) + { + drawing::ShadeMode aOldShadeMode; + if( ! ( (xProp->getPropertyValue( "D3DSceneShadeMode" )>>=aOldShadeMode) && + aOldShadeMode == aShadeMode )) + { + xProp->setPropertyValue( "D3DSceneShadeMode", uno::Any( aShadeMode )); + } + } + + lcl_setLightsForScheme( xProp, aScheme ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + +} + +void ThreeDHelper::set3DSettingsToDefault( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + Reference< beans::XPropertyState > xState( xSceneProperties, uno::UNO_QUERY ); + if(xState.is()) + { + xState->setPropertyToDefault( "D3DSceneDistance"); + xState->setPropertyToDefault( "D3DSceneFocalLength"); + } + ThreeDHelper::setDefaultRotation( xSceneProperties ); + ThreeDHelper::setDefaultIllumination( xSceneProperties ); +} + +void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties, bool bPieOrDonut ) +{ + if( !xSceneProperties.is() ) + return; + + drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) ); + xSceneProperties->setPropertyValue( "D3DCameraGeometry", uno::Any( aCameraGeo )); + + ::basegfx::B3DHomMatrix aSceneRotation; + if( bPieOrDonut ) + aSceneRotation.rotate( -F_PI/3.0, 0, 0 ); + xSceneProperties->setPropertyValue( "D3DTransformMatrix", + uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); +} + +void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + bool bPieOrDonut( DiagramHelper::isPieOrDonutChart( uno::Reference< XDiagram >(xSceneProperties, uno::UNO_QUERY) ) ); + ThreeDHelper::setDefaultRotation( xSceneProperties, bPieOrDonut ); +} + +void ThreeDHelper::setDefaultIllumination( const uno::Reference< beans::XPropertySet >& xSceneProperties ) +{ + if( !xSceneProperties.is() ) + return; + + drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); + try + { + xSceneProperties->getPropertyValue( "D3DSceneShadeMode" )>>= aShadeMode; + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7, uno::Any( false ) ); + xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8, uno::Any( false ) ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + ThreeDLookScheme aScheme = (aShadeMode==drawing::ShadeMode_FLAT) ? ThreeDLookScheme_Simple : ThreeDLookScheme_Realistic; + lcl_setLightsForScheme( xSceneProperties, aScheme ); +} + +void ThreeDHelper::getRoundedEdgesAndObjectLines( + const uno::Reference< XDiagram > & 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< uno::Reference< XDataSeries > > aSeriesList( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesCount = static_cast( aSeriesList.size() ); + + OUString aPercentDiagonalPropertyName( "PercentDiagonal" ); + OUString aBorderStylePropertyName( "BorderStyle" ); + + for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) + { + uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); + uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); + if(!nS) + { + rnRoundedEdges = 0; + try + { + sal_Int16 nPercentDiagonal = 0; + + xProp->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 + { + xProp->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; + xProp->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; + xProp->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 uno::Reference< XDiagram > & 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< uno::Reference< XDataSeries > > aSeriesList( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesCount = static_cast( aSeriesList.size() ); + for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) + { + uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); + + if( nRoundedEdges>=0 && nRoundedEdges<=100 ) + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "PercentDiagonal", aARoundedEdges ); + + if( nObjectLines==0 || nObjectLines==1 ) + DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", aALineStyle ); + } +} + +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Left); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); + } + if( sin(fYAngleRad)>0.0 ) + eRet = CuboidPlanePosition_Right; + return eRet; +} + +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Back); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); + } + if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 ) + eRet = CuboidPlanePosition_Front; + return eRet; +} + +CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const Reference< beans::XPropertySet >& xSceneProperties ) +{ + CuboidPlanePosition eRet(CuboidPlanePosition_Bottom); + + double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; + ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); + if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) + { + 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 000000000..3cdddbbee --- /dev/null +++ b/chart2/source/tools/TitleHelper.cxx @@ -0,0 +1,452 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 uno::Reference< XDiagram >& 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 = DiagramHelper::getVertical( xDiagram, 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.set( xDiagram, uno::UNO_QUERY ); + break; + case TitleHelper::X_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 0, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::Y_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 1, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::Z_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 2, true, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::SECONDARY_X_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 0, false, xDiagram ), uno::UNO_QUERY ); + break; + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + if( xDiagram.is()) + xResult.set( AxisHelper::getAxis( 1, false, xDiagram ), uno::UNO_QUERY ); + break; + + case TitleHelper::MAIN_TITLE: + default: + OSL_FAIL( "Unsupported Title-Type requested" ); + break; + } + + return xResult; +} + +uno::Reference< XTitled > lcl_getTitleParent( TitleHelper::eTitleType nTitleIndex + , const uno::Reference< XDiagram >& 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 uno::Reference< frame::XModel >& xModel ) +{ + if(nTitleIndex == TitleHelper::MAIN_TITLE) + { + uno::Reference< XTitled > xTitled( xModel, uno::UNO_QUERY ); + return xTitled; + } + + uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram; + + if( xChartDoc.is()) + xDiagram.set( xChartDoc->getFirstDiagram()); + + return lcl_getTitleParent( nTitleIndex, xDiagram ); +} + +} + +uno::Reference< XTitle > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex + , ChartModel& rModel ) +{ + if(nTitleIndex == TitleHelper::MAIN_TITLE) + return rModel.getTitleObject(); + + uno::Reference< XDiagram > xDiagram = rModel.getFirstDiagram(); + uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xDiagram ) ); + if( xTitled.is()) + return xTitled->getTitleObject(); + return nullptr; +} + +uno::Reference< XTitle > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex + , const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XTitled > xTitled; + if(nTitleIndex == TitleHelper::MAIN_TITLE) + { + xTitled.set( xModel, uno::UNO_QUERY ); + } + else + { + uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram; + if( xChartDoc.is()) + xDiagram.set( xChartDoc->getFirstDiagram()); + xTitled = lcl_getTitleParent( nTitleIndex, xDiagram ); + } + if( xTitled.is()) + return xTitled->getTitleObject(); + return nullptr; +} + +uno::Reference< XTitle > TitleHelper::createOrShowTitle( + TitleHelper::eTitleType eTitleType + , const OUString& rTitleText + , const uno::Reference< frame::XModel >& xModel + , const uno::Reference< uno::XComponentContext > & xContext ) +{ + uno::Reference< chart2::XTitle > xTitled( TitleHelper::getTitle( eTitleType, xModel ) ); + if( xTitled.is()) + { + css::uno::Reference xProps(xTitled, css::uno::UNO_QUERY_THROW); + xProps->setPropertyValue("Visible",css::uno::Any(true)); + return xTitled; + } + else + { + return createTitle(eTitleType, rTitleText, xModel, xContext, nullptr/*pRefSizeProvider*/); + } +} + +uno::Reference< XTitle > TitleHelper::createTitle( + TitleHelper::eTitleType eTitleType + , const OUString& rTitleText + , const uno::Reference< frame::XModel >& xModel + , const uno::Reference< uno::XComponentContext > & xContext + , ReferenceSizeProvider * pRefSizeProvider ) +{ + uno::Reference< XTitle > xTitle; + uno::Reference< XTitled > xTitled( lcl_getTitleParent( eTitleType, xModel ) ); + + if( !xTitled.is() ) + { + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< chart2::XAxis > 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; + } + uno::Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY ); + if( xProps.is() ) + { + xProps->setPropertyValue( "Show", uno::Any( false ) ); + xTitled = lcl_getTitleParent( eTitleType, xModel ); + } + } + + if(xTitled.is()) + { + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) ); + + xTitle.set( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.Title", + xContext ), uno::UNO_QUERY ); + + if(xTitle.is()) + { + // 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 = DiagramHelper::getVertical( xDiagram, bDummy, bDummy ); + + Reference< beans::XPropertySet > xTitleProps( xTitle, uno::UNO_QUERY ); + if( xTitleProps.is() ) + { + 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) ) + { + xTitleProps->setPropertyValue( "TextRotation", uno::Any( 90.0 )); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + return xTitle; + +} + +OUString TitleHelper::getCompleteString( const uno::Reference< XTitle >& 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 uno::Reference< XTitle >& 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; + uno::Reference< beans::XPropertySet > xTitleProperties( xTitle, uno::UNO_QUERY ); + if( xTitleProperties.is() ) + xTitleProperties->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(1); + + uno::Sequence< uno::Reference< XFormattedString > > aOldStringList = xTitle->getText(); + if( aOldStringList.hasElements() ) + { + aNewStringList[0].set( aOldStringList[0] ); + aNewStringList[0]->setString( aNewText ); + } + else + { + uno::Reference< chart2::XFormattedString2 > xFormattedString = + chart2::FormattedString::create( xContext ); + + xFormattedString->setString( aNewText ); + aNewStringList[0].set( 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 css::uno::Reference< css::frame::XModel >& xModel ) +{ + uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) ); + if( xTitled.is()) + { + xTitled->setTitleObject(nullptr); + } +} + +void TitleHelper::hideTitle( TitleHelper::eTitleType nTitleIndex + , const css::uno::Reference< css::frame::XModel >& xModel ) +{ + uno::Reference< chart2::XTitle > xTitled( TitleHelper::getTitle( nTitleIndex, xModel ) ); + if( xTitled.is()) + { + css::uno::Reference xProps(xTitled, css::uno::UNO_QUERY_THROW); + xProps->setPropertyValue("Visible",css::uno::Any(false)); + } +} + +bool TitleHelper::getTitleType( eTitleType& rType + , const css::uno::Reference< css::chart2::XTitle >& xTitle + , ChartModel& rModel ) +{ + if( !xTitle.is() ) + return false; + + Reference< chart2::XTitle > xCurrentTitle; + for( sal_Int32 nTitleType = TITLE_BEGIN; nTitleType < NORMAL_TITLE_END; nTitleType++ ) + { + xCurrentTitle = TitleHelper::getTitle( static_cast(nTitleType), rModel ); + if( xCurrentTitle == xTitle ) + { + rType = static_cast(nTitleType); + return true; + } + } + + return false; +} + +bool TitleHelper::getTitleType( eTitleType& rType + , const css::uno::Reference< css::chart2::XTitle >& xTitle + , const css::uno::Reference< css::frame::XModel >& xModel ) +{ + if( !xTitle.is() || !xModel.is() ) + return false; + + Reference< chart2::XTitle > xCurrentTitle; + for( sal_Int32 nTitleType = TITLE_BEGIN; nTitleType < NORMAL_TITLE_END; nTitleType++ ) + { + xCurrentTitle = TitleHelper::getTitle( static_cast(nTitleType), xModel ); + if( xCurrentTitle == xTitle ) + { + rType = static_cast(nTitleType); + return true; + } + } + + return false; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/TrueGuard.cxx b/chart2/source/tools/TrueGuard.cxx new file mode 100644 index 000000000..f4acf3574 --- /dev/null +++ b/chart2/source/tools/TrueGuard.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 + +namespace chart +{ + +TrueGuard::TrueGuard( bool& rbTrueDuringGuardedTime ) + : m_rbTrueDuringGuardedTime( rbTrueDuringGuardedTime ) +{ + m_rbTrueDuringGuardedTime = true; +} + +TrueGuard::~TrueGuard() +{ + m_rbTrueDuringGuardedTime = 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 000000000..59fc826d3 --- /dev/null +++ b/chart2/source/tools/UncachedDataSequence.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 +{ +static const char lcl_aServiceName[] = "com.sun.star.comp.chart.UncachedDataSequence"; + +enum +{ + PROP_NUMBERFORMAT_KEY, + PROP_PROPOSED_ROLE, + PROP_XML_RANGE +}; +} // anonymous namespace + +namespace chart +{ + +UncachedDataSequence::UncachedDataSequence( + const Reference< chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation ) + : OPropertyContainer( GetBroadcastHelper()), + UncachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey(0), + m_xDataProvider( xIntDataProv ), + m_aSourceRepresentation( rRangeRepresentation ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} + +UncachedDataSequence::UncachedDataSequence( + const Reference< chart2::XInternalDataProvider > & xIntDataProv, + const OUString & rRangeRepresentation, + const OUString & rRole ) + : OPropertyContainer( GetBroadcastHelper()), + UncachedDataSequence_Base( GetMutex()), + m_nNumberFormatKey(0), + m_xDataProvider( xIntDataProv ), + m_aSourceRepresentation( rRangeRepresentation ), + m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); + setFastPropertyValue_NoBroadcast( PROP_PROPOSED_ROLE, uno::Any( rRole )); +} + +UncachedDataSequence::UncachedDataSequence( const UncachedDataSequence & rSource ) + : ::comphelper::OMutexAndBroadcastHelper(), + OPropertyContainer( GetBroadcastHelper()), + ::comphelper::OPropertyArrayUsageHelper< UncachedDataSequence >(), + 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( ModifyListenerHelper::createModifyEventForwarder()) +{ + registerProperties(); +} + +UncachedDataSequence::~UncachedDataSequence() +{} + +void UncachedDataSequence::registerProperties() +{ + registerProperty( "NumberFormatKey", + PROP_NUMBERFORMAT_KEY, + 0, // PropertyAttributes + & m_nNumberFormatKey, + cppu::UnoType::get() ); + + registerProperty( "Role", + PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + & m_sRole, + cppu::UnoType::get() ); + + registerProperty( "CachedXMLRange", + PROP_XML_RANGE, + 0, // PropertyAttributes + & m_aXMLRange, + cppu::UnoType::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()) + { + 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()) + { + 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)); + const OUString aReplacementStr("%NUMBER"); + 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[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::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() +{ + UncachedDataSequence * pNewSeq = new UncachedDataSequence( *this ); + return Reference< util::XCloneable >( pNewSeq ); +} + +// ____ 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 ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->addModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void SAL_CALL UncachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener ) +{ + try + { + Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW ); + xBroadcaster->removeModifyListener( aListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +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 000000000..f610ae0f7 --- /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 +#include +#include +#include +#include + +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::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "TextUserDefinedAttributes", + PROP_XML_USERDEF_TEXT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ParaUserDefinedAttributes", + PROP_XML_USERDEF_PARA, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + // UserDefinedAttributesSupplier + rOutProperties.emplace_back( "UserDefinedAttributes", + PROP_XML_USERDEF, + cppu::UnoType::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 000000000..85b2f3b39 --- /dev/null +++ b/chart2/source/tools/WeakListenerAdapter.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 + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +WeakModifyListenerAdapter::WeakModifyListenerAdapter( + const uno::WeakReference< util::XModifyListener > & xListener ) : + WeakListenerAdapter< css::util::XModifyListener >( xListener ) +{} + +WeakModifyListenerAdapter::~WeakModifyListenerAdapter() +{} + +void SAL_CALL WeakModifyListenerAdapter::modified( const lang::EventObject& aEvent ) +{ + Reference< util::XModifyListener > xModListener( getListener() ); + if( xModListener.is()) + xModListener->modified( aEvent ); +} + +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 000000000..74d2b4b0a --- /dev/null +++ b/chart2/source/tools/WrappedDefaultProperty.cxx @@ -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 . + */ + +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +WrappedDefaultProperty::WrappedDefaultProperty( + const OUString& rOuterName, const OUString& rInnerName, + const uno::Any& rNewOuterDefault ) : + WrappedProperty( rOuterName, rInnerName ), + m_aOuterDefaultValue( rNewOuterDefault ) +{} + +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 000000000..ff74fac8c --- /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 + +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 000000000..4e62dca5b --- /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 +#include +#include +#include +#include +#include + +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 >& 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 >& rList ) +{ + addIgnoreFillProperties_without_BitmapProperties( rList ); + addIgnoreFillProperties_only_BitmapProperties( rList ); +} + +void WrappedIgnoreProperties::addIgnoreFillProperties_without_BitmapProperties( std::vector< std::unique_ptr >& 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 >& 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 000000000..ee28aba86 --- /dev/null +++ b/chart2/source/tools/WrappedProperty.cxx @@ -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 . + */ + +#include +#include +#include +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +WrappedProperty::WrappedProperty( const OUString& rOuterName, const OUString& rInnerName) + : m_aOuterName( rOuterName ) + , m_aInnerName( rInnerName ) +{ +} +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 000000000..26344a578 --- /dev/null +++ b/chart2/source/tools/WrappedPropertySet.cxx @@ -0,0 +1,442 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +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(); + OSL_FAIL("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(); + OSL_FAIL("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 SAL_CALL WrappedPropertySet::getPropertyValues( const Sequence< OUString >& rNameSeq ) +{ + Sequence< Any > aRetSeq; + if( rNameSeq.hasElements() ) + { + aRetSeq.realloc( rNameSeq.getLength() ); + for(sal_Int32 nN=0; nN& /* 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() ); + for(sal_Int32 nN=0; nN 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() ); + for(sal_Int32 nN=0; nN > 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 000000000..cc4749dee --- /dev/null +++ b/chart2/source/tools/XMLRangeHelper.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 +#include +#include +#include + +#include + +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('A' + nCol) ); + else if( nCol < 702 ) + { + output->append( static_cast('A' + nCol / 26 - 1 )); + output->append( static_cast('A' + nCol % 26) ); + } + else // works for nCol <= 18,278 + { + output->append( static_cast('A' + nCol / 702 - 1 )); + output->append( static_cast('A' + (nCol % 702) / 26 )); + output->append( static_cast('A' + nCol % 26) ); + } + + // write row number as number + if( ! rCell.bRelativeRow ) + output->append( '$' ); + output->append( rCell.nRow + sal_Int32(1) ); +} + +void lcl_getSingleCellAddressFromXMLString( + const OUString& 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 = rXMLString.copy( 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 = (aCellStr.copy( i + 1 )).toInt32() - 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 000000000..f705a7346 --- /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 +#include +#include + +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(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, 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 000000000..292f24b7e --- /dev/null +++ b/chart2/source/view/axes/DateScaling.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 "DateScaling.hxx" +#include +#include +#include + +namespace +{ + +static const char lcl_aServiceName_DateScaling[] = "com.sun.star.chart2.DateScaling"; +static const char lcl_aServiceName_InverseDateScaling[] = "com.sun.star.chart2.InverseDateScaling"; + +static 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 ) ) + ::rtl::math::setNan( & fResult ); + else + { + Date aDate(m_aNullDate); + aDate.AddDays(::rtl::math::approxFloor(value)); + switch( m_nTimeUnit ) + { + case DAY: + fResult = value; + if(m_bShifted) + fResult+=0.5; + break; + case YEAR: + case MONTH: + default: + 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 ) ) + ::rtl::math::setNan( & fResult ); + 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(fYear) ); + aDate.SetMonth( static_cast(fMonth) ); + aDate.SetDay( 1 ); + double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth; + double fDay = (value-fMonthCount)*aDate.GetDaysInMonth(); + fDay += 1.0; + aDate.SetDay( static_cast(::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 000000000..2c2f34dd6 --- /dev/null +++ b/chart2/source/view/axes/DateScaling.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_VIEW_AXES_DATESCALING_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_DATESCALING_HXX + +#include +#include +#include +#include +#include + +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 +#endif + +/* 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 000000000..2bb936567 --- /dev/null +++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.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 + +#include + +#include + +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; + ::rtl::math::setInf(&fGlobalExtremum, false); + for (auto const& elem : m_aMinimumAndMaximumSupplierList) + { + double fLocalExtremum = elem->getMinimumX(); + if(fLocalExtremumgetMaximumX(); + if(fLocalExtremum>fGlobalExtremum) + fGlobalExtremum=fLocalExtremum; + } + if(std::isinf(fGlobalExtremum)) + ::rtl::math::setNan(&fGlobalExtremum); + return fGlobalExtremum; +} + +double MergedMinimumAndMaximumSupplier::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) +{ + double fGlobalExtremum; + ::rtl::math::setInf(&fGlobalExtremum, false); + for (auto const& elem : m_aMinimumAndMaximumSupplierList) + { + double fLocalExtremum = elem->getMinimumYInRange( fMinimumX, fMaximumX, nAxisIndex ); + if(fLocalExtremumgetMaximumYInRange( fMinimumX, fMaximumX, nAxisIndex ); + if(fLocalExtremum>fGlobalExtremum) + fGlobalExtremum=fLocalExtremum; + } + if(std::isinf(fGlobalExtremum)) + ::rtl::math::setNan(&fGlobalExtremum); + return fGlobalExtremum; +} + +double MergedMinimumAndMaximumSupplier::getMinimumZ() +{ + double fGlobalExtremum; + ::rtl::math::setInf(&fGlobalExtremum, false); + for (auto const& elem : m_aMinimumAndMaximumSupplierList) + { + double fLocalExtremum = elem->getMinimumZ(); + if(fLocalExtremumgetMaximumZ(); + if(fLocalExtremum>fGlobalExtremum) + fGlobalExtremum=fLocalExtremum; + } + if(std::isinf(fGlobalExtremum)) + ::rtl::math::setNan(&fGlobalExtremum); + 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(); +} + +long MergedMinimumAndMaximumSupplier::calculateTimeResolutionOnXAxis() +{ + long nRet = css::chart::TimeUnit::YEAR; + for (auto const& elem : m_aMinimumAndMaximumSupplierList) + { + long nCurrent = elem->calculateTimeResolutionOnXAxis(); + if(nRet>nCurrent) + nRet=nCurrent; + } + return nRet; +} + +void MergedMinimumAndMaximumSupplier::setTimeResolutionOnXAxis( 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 000000000..10fc3ccd4 --- /dev/null +++ b/chart2/source/view/axes/ScaleAutomatism.cxx @@ -0,0 +1,990 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "Tickmarks_Equidistant.hxx" +#include +#include "DateScaling.hxx" +#include +#include +#include + +#include +#include + +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) + , Scaling() + , AxisType(css::chart2::AxisType::REALNUMBER) + , ShiftedCategoryPosition(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) + , SubIncrements() +{ +} + +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( ) +{ + ::rtl::math::setNan( &m_fValueMinimum ); + ::rtl::math::setNan( &m_fValueMaximum ); +} + +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.ShiftedCategoryPosition = 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.ShiftedCategoryPosition ) + 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>=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>=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.ShiftedCategoryPosition ) + ++aMaxDate; //for explicit scales we need one interval more (maximum excluded) + break; + case MONTH: + aMinDate.SetDay(1); + aMaxDate.SetDay(1); + if( rExplicitScale.ShiftedCategoryPosition ) + 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.ShiftedCategoryPosition ) + 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: + long nDayCount = aMaxDate - aMinDate; + long nMainIncrementCount = 1; + if( !bAutoMajor ) + { + 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 ) + { + long nNumer = 1; + 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( rtl::math::approxCeil( 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( rtl::math::approxCeil( nIntervalDays/nDaysPerInterval ) ); + if(nNumer<=0) + nNumer=1; + } + } + rExplicitIncrement.MajorTimeInterval.Number = nNumer; + nMainIncrementCount = static_cast(nDayCount/(nNumer*nDaysPerInterval)); + } + + //choose minor time interval: + if( !bAutoMinor ) + { + if( rExplicitIncrement.MinorTimeInterval.TimeUnit > rExplicitIncrement.MajorTimeInterval.TimeUnit ) + rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit; + 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::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>=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 000000000..07dc62399 --- /dev/null +++ b/chart2/source/view/axes/TickmarkProperties.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKPROPERTIES_HXX + +#include + +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 +#endif + +/* 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 000000000..8332f01ff --- /dev/null +++ b/chart2/source/view/axes/Tickmarks.cxx @@ -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 . + */ + +#include "Tickmarks.hxx" +#include "Tickmarks_Equidistant.hxx" +#include "Tickmarks_Dates.hxx" +#include +#include "VAxisProperties.hxx" +#include +#include + +using namespace ::com::sun::star; +using ::basegfx::B2DVector; + +namespace chart { + +TickInfo::TickInfo( const uno::Reference& xInverse ) +: fScaledTickValue( 0.0 ) +, xInverseScaling( xInverse ) +, aTickScreenPosition(0.0,0.0) +, bPaintIt( true ) +, nFactorForLimitedTextWidth(1) +{ +} + +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(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( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_rScale( rScale ) + , m_rIncrement( rIncrement ) +{ + //@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 < F_PI4 || fInclination > (F_PI-F_PI4); +} +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 < F_PI4 || fInclination > (F_PI-F_PI4); +} +//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::getXaxisStartPos() const +{ + return m_aAxisStartScreenPosition2D; +} + +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[nSequenceIndex].realloc(2); + rPoints[nSequenceIndex][0].X = static_cast(aStart.getX()); + rPoints[nSequenceIndex][0].Y = static_cast(aStart.getY()); + rPoints[nSequenceIndex][1].X = static_cast(aEnd.getX()); + rPoints[nSequenceIndex][1].Y = static_cast(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[0].realloc(2); + rPoints[0][0].X = static_cast(m_aAxisStartScreenPosition2D.getX()); + rPoints[0][0].Y = static_cast(m_aAxisStartScreenPosition2D.getY()); + rPoints[0][1].X = static_cast(m_aAxisEndScreenPosition2D.getX()); + rPoints[0][1].Y = static_cast(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 000000000..cab62aaa4 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_HXX + +#include +#include +#include + +#include + +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 xInverseScaling; + + ::basegfx::B2DVector aTickScreenPosition; + bool bPaintIt; + + css::uno::Reference xTextShape; + + OUString aText;//used only for complex categories so far + sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category + +//methods: + TickInfo() = delete; + explicit TickInfo( const css::uno::Reference& 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 TickInfoArrayType; +typedef std::vector 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( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + 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; + ::basegfx::B2DVector getXaxisStartPos() const; + +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 + +#endif + +/* 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 000000000..854e661f6 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Dates.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +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( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_aScale( rScale ) + , m_aIncrement( rIncrement ) +{ + //@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(::rtl::math::approxFloor(m_aScale.Minimum)); + Date aMaxDate = aNull + static_cast(::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(::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 000000000..2e4e3b35b --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Dates.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_DATES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_DATES_HXX + +#include "Tickmarks.hxx" + +namespace chart +{ + +class DateTickFactory +{ +public: + DateTickFactory( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + ~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 +#endif + +/* 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 000000000..60f6e6331 --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Equidistant.cxx @@ -0,0 +1,621 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include + +#include + +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( + const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) + : m_rScale( rScale ) + , m_rIncrement( rIncrement ) +{ + //@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(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); + 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(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::max()) + // Interval count too high! Bail out. + return 0; + + sal_Int32 nIntervalCount = static_cast(fIntervalCount); + + nIntervalCount+=3; + for(sal_Int32 nN=0; nN1 ) + 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]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(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(fScaledValuem_fScaledVisibleMax) + { + if( !approxEqual(fScaledValue,m_fScaledVisibleMax) ) + return false; + } + if(fScaledValue > aAllTicks(nDepthCount); + aAllTicks[0].realloc(nMaxMajorTickCount); + + sal_Int32 nRealMajorTickCount = 0; + for( sal_Int32 nMajorTick=0; nMajorTick1 ) + nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount; + } + uno::Sequence< double >& rTicks = aAllTicks[nDepth]; + sal_Int32 nCount = rTicks.getLength(); + //check lower border + for( nTick=0; nTicknCount-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); + for(nTick = 0; nTick >& 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; nNstatic_cast(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_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 000000000..55263c05b --- /dev/null +++ b/chart2/source/view/axes/Tickmarks_Equidistant.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_EQUIDISTANT_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_EQUIDISTANT_HXX + +#include "Tickmarks.hxx" +#include + +#include + +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::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 + m_pnPositions; //current positions in the different sequences + std::unique_ptr + 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 + m_pbIntervalFinished; + sal_Int32 m_nCurrentDepth; + sal_Int32 m_nCurrentPos; + double m_fCurrentValue; +}; + +class EquidistantTickFactory +{ +public: + EquidistantTickFactory( + const ExplicitScaleData& rScale + , const ExplicitIncrementData& rIncrement ); + ~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 + 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 +#endif + +/* 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 000000000..6e6f40b65 --- /dev/null +++ b/chart2/source/view/axes/VAxisBase.cxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include "Tickmarks.hxx" +#include +#include +#include +#include +#include + +#include + +#include + +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.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.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( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) +{ + if( m_bRecordMaximumTextSize && xShape.is() ) + { + 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_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); + if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + return false; + + uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); + if( xProps.is() ) + { + bool bShow = false; + xProps->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.ShiftedCategoryPosition ) + 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 = m_pShapeFactory->createGroup2D( m_xFinalTarget, m_aCID ); + + return true; +} + +size_t VAxisBase::getIndexOfLongestLabel( const uno::Sequence& rLabels ) +{ + sal_Int32 nRet = 0; + sal_Int32 nLength = 0; + sal_Int32 nN = 0; + for( nN=0; nN 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 ); + } +} + +} //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 000000000..bddba67f9 --- /dev/null +++ b/chart2/source/view/axes/VAxisBase.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISBASE_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISBASE_HXX + +#include "VAxisOrGridBase.hxx" +#include "VAxisProperties.hxx" +#include "Tickmarks.hxx" + +namespace com::sun::star::util { class XNumberFormatsSupplier; } + +namespace chart +{ + +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 ); + +protected: //methods + static size_t getIndexOfLongestLabel( const css::uno::Sequence& rLabels ); + void removeTextShapesFromTicks(); + void updateUnscaledValuesAtTicks( TickIter& rIter ); + + virtual bool prepareShapeCreation(); + void recordMaximumTextSize( const css::uno::Reference< css::drawing::XShape >& 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; + + css::uno::Reference< css::drawing::XShapes > m_xGroupShape_Shapes; + css::uno::Reference< css::drawing::XShapes > m_xTextTarget; + + /** + * 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 +#endif + +/* 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 000000000..290f3a368 --- /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 +#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 000000000..8bcaf898c --- /dev/null +++ b/chart2/source/view/axes/VAxisOrGridBase.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISORGRIDBASE_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISORGRIDBASE_HXX + +#include +#include +#include + +#include + +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 +#endif + +/* 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 000000000..27a4950a8 --- /dev/null +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -0,0 +1,400 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +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(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(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(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( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) ); + return aTickmarkProperties; +} + +AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel + , ExplicitCategoriesProvider* pExplicitCategoriesProvider ) + : m_xAxisModel(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_bDisplayLabels( true ) + , m_bTryStaggeringFirst( false ) + , m_nNumberFormatKey(0) + , m_nMajorTickmarks(1) + , m_nMinorTickmarks(1) + , m_aTickmarkPropertiesList() + , m_aLineProperties() + //for category axes + , m_nAxisType(AxisType::REALNUMBER) + , m_bComplexCategories(false) + , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider) + , m_bLimitSpaceForLabels(false) +{ +} + +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 ) +{ + uno::Reference< beans::XPropertySet > xProp = + uno::Reference::query( m_xAxisModel ); + if( !xProp.is() ) + return; + + if( m_nDimensionIndex<2 ) + initAxisPositioning( xProp ); + + ScaleData aScaleData = m_xAxisModel->getScaleData(); + if( m_nDimensionIndex==0 ) + AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian ); + m_nAxisType = aScaleData.AxisType; + + if( bCartesian ) + { + 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; + } + + if( bIsYAxisPosition ) + maLabelAlignment.meAlignment = lcl_getLabelAlignmentForYAxis(*this); + else + maLabelAlignment.meAlignment = lcl_getLabelAlignmentForXAxis(*this); + } + } + + try + { + //init LineProperties + m_aLineProperties.initFromPropertySet( xProp ); + + //init display labels + xProp->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. + xProp->getPropertyValue( "TryStaggeringFirst" ) >>= m_bTryStaggeringFirst; + + //init TickmarkProperties + xProp->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks; + xProp->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& xAxisModel ) +{ + uno::Reference< beans::XPropertySet > xProp = + uno::Reference::query( xAxisModel ); + if(!xProp.is()) + return; + + try + { + xProp->getPropertyValue( "TextBreak" ) >>= bLineBreakAllowed; + xProp->getPropertyValue( "TextOverlap" ) >>= bOverlapAllowed; + xProp->getPropertyValue( "StackCharacters" ) >>= bStackCharacters; + xProp->getPropertyValue( "TextRotation" ) >>= fRotationAngleDegree; + + css::chart::ChartAxisArrangeOrderType eArrangeOrder; + xProp->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder; + switch(eArrangeOrder) + { + case css::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE: + eStaggering = AxisLabelStaggering::SideBySide; + break; + case css::chart::ChartAxisArrangeOrderType_STAGGER_EVEN: + eStaggering = AxisLabelStaggering::StaggerEven; + break; + case css::chart::ChartAxisArrangeOrderType_STAGGER_ODD: + eStaggering = AxisLabelStaggering::StaggerOdd; + break; + default: + eStaggering = AxisLabelStaggering::StaggerAuto; + break; + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } +} + +bool AxisLabelProperties::isStaggered() const +{ + return ( eStaggering == AxisLabelStaggering::StaggerOdd || eStaggering == AxisLabelStaggering::StaggerEven ); +} + +void AxisLabelProperties::autoRotate45() +{ + fRotationAngleDegree = 45; + bLineBreakAllowed = false; + 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 000000000..d087e5064 --- /dev/null +++ b/chart2/source/view/axes/VAxisProperties.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISPROPERTIES_HXX + +#include "TickmarkProperties.hxx" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +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 nNumberFormatKey; + + AxisLabelStaggering eStaggering; + + bool bLineBreakAllowed; + bool bOverlapAllowed; + + bool bStackCharacters; + double fRotationAngleDegree; + + sal_Int32 nRhythm; //show only each nth label with n==nRhythm + + //methods: + void init( const css::uno::Reference< css::chart2::XAxis >& 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 +{ + css::uno::Reference 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 m_pfMainLinePositionAtOtherAxis; + std::optional m_pfExrtaLinePositionAtOtherAxis; + + bool m_bCrossingAxisHasReverseDirection; + bool m_bCrossingAxisIsCategoryAxes; + + AxisLabelAlignment maLabelAlignment; + + 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 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 m_xAxisTextProvider; //for categories or series names + //<- category axes + + bool m_bLimitSpaceForLabels; + + //methods: + + AxisProperties( const css::uno::Reference< css::chart2::XAxis >& xAxisModel + , ExplicitCategoriesProvider* pExplicitCategoriesProvider ); + + 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 +#endif + +/* 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 000000000..1c62bfb93 --- /dev/null +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -0,0 +1,1980 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "Tickmarks_Equidistant.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +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( Reference< drawing::XShape > const & xShape2DText, + const AxisLabelProperties& rAxisLabelProperties, + const OUString& rLabel, + const tNameSequence& rPropNames, + const tAnySequence& rPropValues, + const bool bIsHorizontalAxis ) +{ + uno::Reference< text::XTextRange > xTextRange( xShape2DText, uno::UNO_QUERY ); + + if( !xTextRange.is() ) + return; + + const sal_Int32 nFullSize = bIsHorizontalAxis ? rAxisLabelProperties.m_aFontReferenceSize.Height : rAxisLabelProperties.m_aFontReferenceSize.Width; + + if( !nFullSize || !rLabel.getLength() ) + return; + + sal_Int32 nMaxLabelsSize = bIsHorizontalAxis ? rAxisLabelProperties.m_aMaximumSpaceForLabels.Height : rAxisLabelProperties.m_aMaximumSpaceForLabels.Width; + const sal_Int32 nAvgCharWidth = xShape2DText->getSize().Width / rLabel.getLength(); + const sal_Int32 nTextSize = bIsHorizontalAxis ? ShapeFactory::getSizeAfterRotation(xShape2DText, rAxisLabelProperties.fRotationAngleDegree).Height : + ShapeFactory::getSizeAfterRotation(xShape2DText, rAxisLabelProperties.fRotationAngleDegree).Width; + + if( !nAvgCharWidth ) + return; + + const OUString sDots = "..."; + const sal_Int32 nCharsToRemove = ( nTextSize - nMaxLabelsSize ) / nAvgCharWidth + 1; + sal_Int32 nNewLen = rLabel.getLength() - nCharsToRemove - sDots.getLength(); + // Prevent from showing only dots + if (nNewLen < 0) + nNewLen = ( rLabel.getLength() >= sDots.getLength() ) ? sDots.getLength() : rLabel.getLength(); + + bool bCrop = nCharsToRemove > 0; + if( !bCrop ) + return; + + OUString aNewLabel = rLabel.copy( 0, nNewLen ); + if( nNewLen > sDots.getLength() ) + aNewLabel += sDots; + xTextRange->setString( aNewLabel ); + + uno::Reference< beans::XPropertySet > xProp( xTextRange, uno::UNO_QUERY ); + if( xProp.is() ) + { + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + } +} + +static Reference< drawing::XShape > createSingleLabel( + const Reference< lang::XMultiServiceFactory>& xShapeFactory + , const Reference< drawing::XShapes >& 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.fRotationAngleDegree)); + uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi ); + OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.bStackCharacters ); + + Reference< drawing::XShape > xShape2DText = ShapeFactory::getOrCreateShapeFactory(xShapeFactory) + ->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.fRotationAngleDegree, rAxisProperties.m_bComplexCategories ); + + return xShape2DText; +} + +static bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape + , double fRotationAngleDegree + , const basegfx::B2DVector& rTickScreenPosition ) +{ + if(!xShape.is()) + return false; + + ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(), ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree )); + + basegfx::B2IVector aPosition( + static_cast( rTickScreenPosition.getX() ) + , static_cast( 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 Reference< drawing::XShape >& xShape1 + , const Reference< drawing::XShape >& 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 Reference< drawing::XShapes >& 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( rDistanceTickToText.getLength() ); + if( nDistanceTickToText==0.0) + return aRet; + + B2DVector aStaggerDirection(rDistanceTickToText); + aStaggerDirection.normalize(); + + sal_Int32 nDistance=0; + Reference< drawing::XShape > 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; + Reference< drawing::XShape > xShape2DText; + for( TickInfo* pTickInfo = rIter.firstInfo() + ; pTickInfo + ; pTickInfo = rIter.nextInfo() ) + { + xShape2DText = pTickInfo->xTextShape; + if( xShape2DText.is() ) + { + awt::Point aPos = xShape2DText->getPosition(); + aPos.X += static_cast(rStaggerDistance.getX()); + aPos.Y += static_cast(rStaggerDistance.getY()); + xShape2DText->setPosition( aPos ); + } + } +} + +static bool lcl_hasWordBreak( const Reference& xShape ) +{ + if (!xShape.is()) + return false; + + SvxShape* pShape = comphelper::getUnoTunnelImplementation(xShape); + SvxShapeText* pShapeText = dynamic_cast(pShape); + if (!pShapeText) + return false; + + SvxTextEditSource* pTextEditSource = dynamic_cast(pShapeText->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* 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(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0 + if( nIndex>=0 && nIndexgetLength() ) + 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 xProps(rAxisProp.m_xAxisModel, uno::UNO_QUERY); + + 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 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.bLineBreakAllowed ) + return false; + if( rAxisLabelProperties.bStackCharacters ) + return false; + //no break for value axis + if( !m_bUseTextLabels ) + return false; + if( !( rAxisLabelProperties.fRotationAngleDegree == 0.0 || + rAxisLabelProperties.fRotationAngleDegree == 90.0 || + rAxisLabelProperties.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.bOverlapAllowed ) + return false; + if( rAxisLabelProperties.bLineBreakAllowed ) // auto line break may conflict with... + return false; + if( rAxisLabelProperties.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.bStackCharacters; + if( bIsVerticalAxis ) + return rAxisLabelProperties.bStackCharacters; + return false; +} + +bool isAutoStaggeringOfLabelsAllowed( + const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis ) +{ + if( rAxisLabelProperties.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* 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(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* 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 && nTextLevel < static_cast< sal_Int32 >(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 Reference& 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(); + } + } + + if (!isBreakOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) && + !isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) && + !rAxisLabelProperties.isStaggered()) + return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory); + + FixedNumberFormatter aFixedNumberFormatter( + m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + + bool bIsStaggered = rAxisLabelProperties.isStaggered(); + B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true); + sal_Int32 nLimitedSpaceForText = -1; + + if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) + { + 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.fRotationAngleDegree == 90.0 || rAxisLabelProperties.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.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* 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,"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.nRhythm != 0 ) + continue; + + //don't create labels for invisible ticks + if( !pTickInfo->bPaintIt ) + continue; + + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.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.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.eStaggering = AxisLabelStaggering::StaggerEven; + pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo; + if( !pLastVisibleNeighbourTickInfo || + !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.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.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.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(aTickScreenPos2D.getX()) + ,static_cast(aTickScreenPos2D.getY())); + + //create single label + if(!pTickInfo->xTextShape.is()) + pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget + , aAnchorScreenPosition2D, aLabel + , rAxisLabelProperties, m_aAxisProperties + , aPropNames, aPropValues, bIsHorizontalAxis ); + if(!pTickInfo->xTextShape.is()) + continue; + + recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + + // Label has multiple lines and the words are broken + if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed + && rAxisLabelProperties.fRotationAngleDegree == 0.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.fRotationAngleDegree = 90; + } + rAxisLabelProperties.bLineBreakAllowed = false; + m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; + removeTextShapesFromTicks(); + return false; + } + + //if NO OVERLAP -> remove overlapping shapes + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + { + // Check if the label still overlaps with its neighbor. + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.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.eStaggering = AxisLabelStaggering::StaggerEven; + pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo; + if( !pLastVisibleNeighbourTickInfo || + !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.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.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs. + removeTextShapesFromTicks(); + rAxisLabelProperties.nRhythm = 1; + return false; + } + + // Try incrementing the tick interval and start over. + rAxisLabelProperties.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + return false; + } + } + } + + pPREPreviousVisibleTickInfo = pPreviousVisibleTickInfo; + pPreviousVisibleTickInfo = pTickInfo; + } + return true; +} + +bool VCartesianAxis::createTextShapesSimple( + const Reference& xTarget, TickIter& rTickIter, + AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory ) +{ + FixedNumberFormatter aFixedNumberFormatter( + m_xNumberFormatsSupplier, rAxisLabelProperties.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* 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,"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.nRhythm != 0 ) + continue; + + //don't create labels for invisible ticks + if( !pTickInfo->bPaintIt ) + continue; + + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.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.fRotationAngleDegree + , pTickInfo->aTickScreenPosition ) ) + { + // This tick overlaps with its neighbor. Increment the visible + // tick intervals (if that's allowed) and start over. + + rAxisLabelProperties.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.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(aTickScreenPos2D.getX()) + ,static_cast(aTickScreenPos2D.getY())); + + //create single label + if(!pTickInfo->xTextShape.is()) + pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget + , aAnchorScreenPosition2D, aLabel + , rAxisLabelProperties, m_aAxisProperties + , aPropNames, aPropValues, bIsHorizontalAxis ); + if(!pTickInfo->xTextShape.is()) + continue; + + recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + + //if NO OVERLAP -> remove overlapping shapes + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + { + // Check if the label still overlaps with its neighbor. + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.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.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs. + removeTextShapesFromTicks(); + rAxisLabelProperties.nRhythm = 1; + return false; + } + + // Try incrementing the tick interval and start over. + rAxisLabelProperties.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.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 +{ + double fNan; + rtl::math::setNan(&fNan); + + if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis ) + return fNan; + + 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 fNan; + + 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() && m_pShapeFactory) + { + tPropertyNameMap aDummyPropertyNameMap; + Reference< drawing::XShape > xShape3DAnchor = m_pShapeFactory->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; + aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ) ); + aPosList.push_back( 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; + aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ) ); + aPosList.push_back( 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; + aPosList.push_back( getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ) ); + aPosList.push_back( 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(fabs(aEnd.getY()-aStart.getY())); + sal_Int32 nMaxWidth = static_cast(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.nNumberFormatKey); + OUString sPreviousValueLabel; + sal_Int32 nSameLabel = 0; + for (sal_Int32 nLabel = 0; nLabel < static_cast(m_aAllTickInfos[0].size()); ++nLabel) + { + Color nColor = COL_AUTO; + bool bHasColor = false; + OUString sValueLabel = aFixedNumberFormatterTest.getFormattedString(m_aAllTickInfos[0][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 aCummulatedLabelsDistance(0,0); + for( sal_Int32 nTextLevel=0; nTextLevel apTickIter(createLabelTickIterator(nTextLevel)); + if (apTickIter) + { + double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + if( nTextLevel>0 ) + { + lcl_shiftLabels(*apTickIter, aCummulatedLabelsDistance); + //multilevel labels: 0 or 90 by default + if( m_aAxisProperties.m_bSwapXAndY ) + fRotationAngleDegree = 90.0; + else + fRotationAngleDegree = 0.0; + } + aCummulatedLabelsDistance += lcl_getLabelsDistance( + *apTickIter, pTickFactory2D->getDistanceAxisTickToText(m_aAxisProperties), + fRotationAngleDegree); + } + } + } + else if (rAxisLabelProperties.isStaggered()) + { + if( !m_aAllTickInfos.empty() ) + { + LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, true ); + LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, false ); + + lcl_shiftLabels( aOuterIter + , lcl_getLabelsDistance( aInnerIter + , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ), 0.0 ) ); + } + } +} + +void VCartesianAxis::createLabels() +{ + if( !prepareShapeCreation() ) + return; + + //create labels + if (!m_aAxisProperties.m_bDisplayLabels) + return; + + std::unique_ptr apTickFactory2D(createTickFactory2D()); // throws on failure + 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 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.bLineBreakAllowed = true; + aComplexProps.bOverlapAllowed = aComplexProps.fRotationAngleDegree != 0.0; + if( nTextLevel > 0 ) + { + //multilevel labels: 0 or 90 by default + if( m_aAxisProperties.m_bSwapXAndY ) + aComplexProps.fRotationAngleDegree = 90.0; + else + aComplexProps.fRotationAngleDegree = 0.0; + } + } + AxisLabelProperties& rAxisLabelProperties = m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties; + while (!createTextShapes(m_xTextTarget, *apTickIter, rAxisLabelProperties, + pTickFactory2D, nScreenDistanceBetweenTicks)) + { + }; + } + } + doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D ); +} + +void VCartesianAxis::createMaximumLabels() +{ + TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize); + + if( !prepareShapeCreation() ) + return; + + //create labels + if (!m_aAxisProperties.m_bDisplayLabels) + return; + + std::unique_ptr 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.eStaggering = AxisLabelStaggering::StaggerEven; + + aAxisLabelProperties.bOverlapAllowed = true; + aAxisLabelProperties.bLineBreakAllowed = false; + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel 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 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) + { + Reference< drawing::XShape > xShape2DText(tickInfo.xTextShape); + if( xShape2DText.is() ) + { + B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + B2DVector aTickScreenPos2D(tickInfo.aTickScreenPosition); + aTickScreenPos2D += aTextToTickDistance; + awt::Point aAnchorScreenPosition2D( + static_cast(aTickScreenPos2D.getX()) + ,static_cast(aTickScreenPos2D.getY())); + + double fRotationAngleDegree = m_aAxisLabelProperties.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 + uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); + if( xProp.is() ) + { + try + { + xProp->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); + m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints + , &rTickmarkProperties.aLineProperties ); +} + +void VCartesianAxis::createShapes() +{ + if( !prepareShapeCreation() ) + return; + + std::unique_ptr apTickFactory2D(createTickFactory2D()); // throws on failure + TickFactory2D* pTickFactory2D = apTickFactory2D.get(); + + //create line shapes + if(m_nDimension==2) + { + //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 aTickmarkPropertiesList; + static const bool bIncludeSpaceBetweenTickAndText = false; + sal_Int32 nOffset = static_cast(pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength()); + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel apTickIter(createLabelTickIterator( nTextLevel )); + if( apTickIter ) + { + double fRotationAngleDegree = m_aAxisLabelProperties.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(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.ShiftedCategoryPosition )// if ShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted + { + pTickFactory2D->getAllTicks( aUnshiftedTickInfos ); + pTickFactory2D->updateScreenValues( aUnshiftedTickInfos ); + hideIdenticalScreenValues( aUnshiftedTickInfos ); + } + TickInfoArraysType& rAllTickInfos = m_aScale.ShiftedCategoryPosition ? 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 ); + Reference< drawing::XShape > xShape = m_pShapeFactory->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(aStart.getX()), static_cast(aStart.getY())}, + {static_cast(aEnd.getX()), static_cast(aEnd.getY())} }}; + m_pShapeFactory->createLine2D( + m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties ); + } + } + } + + createLabels(); +} + +} //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 000000000..1c020bc41 --- /dev/null +++ b/chart2/source/view/axes/VCartesianAxis.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANAXIS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANAXIS_HXX + +#include "VAxisBase.hxx" +#include + +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; + }; + +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 css::uno::Reference& 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 css::uno::Reference& 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; +}; + +} //namespace chart +#endif + +/* 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 000000000..e7fe42a87 --- /dev/null +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.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 "VCartesianCoordinateSystem.hxx" +#include "VCartesianGrid.hxx" +#include "VCartesianAxis.hxx" +#include +#include +#include +#include +#include +#include +#include + +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 Reference< XCoordinateSystem >& 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; + Reference< XAxis > 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,m_xShapeFactory + , createCIDForGrid( nDimensionIndex,nAxisIndex ) ); + if(nDimensionCount==2) + aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + aGrid.setScales( getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY ); + aGrid.createShapes(); + } +} + +void VCartesianCoordinateSystem::createVAxisList( + const uno::Reference & xChartDoc + , const awt::Size& rFontReferenceSize + , const awt::Rectangle& rMaximumSpaceForLabels + , bool bLimitSpaceForLabels + ) +{ + // note: using xChartDoc itself as XNumberFormatsSupplier would cause + // a leak from VCartesianAxis due to cyclic reference + uno::Reference const xNumberFormatsSupplier( + dynamic_cast(*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++ ) + { + Reference< XAxis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex); + if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) + continue; + + AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider()); + aAxisProperties.m_nDimensionIndex = nDimensionIndex; + aAxisProperties.m_bSwapXAndY = bSwapXAndY; + aAxisProperties.m_bIsMainAxis = (nAxisIndex==0); + aAxisProperties.m_bLimitSpaceForLabels = bLimitSpaceForLabels; + Reference< XAxis > 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) + Reference< XAxis > xSisterAxis( AxisHelper::getCrossingMainAxis( xCrossingMainAxis, m_xCooSysModel ) ); + aAxisProperties.initAxisPositioning( Reference< beans::XPropertySet >( xSisterAxis, uno::UNO_QUERY) ); + } + aAxisProperties.init(true); + if(aAxisProperties.m_bDisplayLabels) + aAxisProperties.m_nNumberFormatKey = getNumberFormatKeyForAxis(xAxis, xChartDoc); + + auto apVAxis = std::make_shared(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount); + tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); + m_aAxisMap[aFullAxisIndex] = apVAxis; + apVAxis->set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos ); + + apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels); + } + } +} + +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& 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,m_xShapeFactory + , 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& 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 ) ); + 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 000000000..e959dbc5d --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANCOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANCOORDINATESYSTEM_HXX + +#include + +namespace chart +{ + +class VCartesianCoordinateSystem : public VCoordinateSystem +{ +public: + VCartesianCoordinateSystem() = delete; + explicit VCartesianCoordinateSystem( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + virtual ~VCartesianCoordinateSystem() override; + + virtual void createVAxisList( + const css::uno::Reference< css::chart2::XChartDocument> &ChartDoc + , const css::awt::Size& rFontReferenceSize + , const css::awt::Rectangle& rMaximumSpaceForLabels + , bool bLimitSpaceForLabels ) override; + + virtual void initVAxisInList() override; + virtual void updateScalesAndIncrementsOnAxes() override; + + virtual void createGridShapes() override; +}; + +} //namespace chart +#endif + +/* 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 000000000..eda61d9b8 --- /dev/null +++ b/chart2/source/view/axes/VCartesianGrid.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 "VCartesianGrid.hxx" +#include "Tickmarks.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 ) + : P0(3) + , P1(3) + , P2(3) + , 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()) + { + double fHelp = MinX; + MinX = MaxX; + MaxX = fHelp; + } + if(!pPosHelper->isMathematicalOrientationY()) + { + double fHelp = MinY; + MinY = MaxY; + MaxY = fHelp; + } + if(pPosHelper->isMathematicalOrientationZ())//z axis in draw is reverse to mathematical + { + double fHelp = MinZ; + MinZ = MaxZ; + MaxZ = fHelp; + } + 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 + + P0[0]=P1[0]=P2[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MinX : MaxX; + P0[1]=P1[1]=P2[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MinY : MaxY; + P0[2]=P1[2]=P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MinZ : MaxZ; + + if(m_nDimensionIndex==0) + { + P0[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; + P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; + if( eBottomPos != CuboidPlanePosition_Bottom && !bSwapXY ) + P2=P1; + } + else if(m_nDimensionIndex==1) + { + P0[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; + P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; + if( eBottomPos != CuboidPlanePosition_Bottom && bSwapXY ) + P2=P1; + } + else if(m_nDimensionIndex==2) + { + P0[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; + P2[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; + if( eBottomPos != CuboidPlanePosition_Bottom ) + { + if( !bSwapXY ) + P0=P1; + else + P2=P1; + } + } +} + +void GridLinePoints::update( double fScaledTickValue ) +{ + P0[m_nDimensionIndex] = P1[m_nDimensionIndex] = P2[m_nDimensionIndex] = fScaledTickValue; +} + +static void addLine2D( drawing::PointSequenceSequence& rPoints, sal_Int32 nIndex + , const GridLinePoints& rScaledLogicPoints + , const Reference< XTransformation > & xTransformation + ) +{ + drawing::Position3D aPA = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P0 ) ); + drawing::Position3D aPB = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P1 ) ); + + rPoints[nIndex].realloc(2); + rPoints[nIndex][0].X = static_cast(aPA.PositionX); + rPoints[nIndex][0].Y = static_cast(aPA.PositionY); + rPoints[nIndex][1].X = static_cast(aPB.PositionX); + rPoints[nIndex][1].Y = static_cast(aPB.PositionY); +} + +static void addLine3D( drawing::PolyPolygonShape3D& rPoints, sal_Int32 nIndex + , const GridLinePoints& rBasePoints + , const Reference< XTransformation > & xTransformation ) +{ + drawing::Position3D aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P0 ) ); + AddPointToPoly( rPoints, aPoint, nIndex ); + aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P1 ) ); + AddPointToPoly( rPoints, aPoint, nIndex ); + aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P2 ) ); + AddPointToPoly( rPoints, aPoint, nIndex ); +} + +VCartesianGrid::VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount + , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) + : VAxisOrGridBase( nDimensionIndex, nDimensionCount ) + , m_aGridPropertiesList( rGridPropertiesList ) +{ + m_pPosHelper = new PlottingPositionHelper(); +} + +VCartesianGrid::~VCartesianGrid() +{ + delete m_pPosHelper; + m_pPosHelper = nullptr; +} + +void VCartesianGrid::fillLinePropertiesFromGridModel( std::vector& rLinePropertiesList + , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) +{ + rLinePropertiesList.clear(); + if( !rGridPropertiesList.hasElements() ) + 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.hasElements()) + return; + //somehow equal to axis tickmarks + + //create named group shape + Reference< drawing::XShapes > xGroupShape_Shapes( + createGroupShape( m_xLogicTarget, m_aCID ) ); + + if(!xGroupShape_Shapes.is()) + return; + + std::vector 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; + + Reference< drawing::XShapes > xTarget( xGroupShape_Shapes ); + if( nDepth > 0 ) + { + xTarget.set( createGroupShape( m_xLogicTarget + , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) ) + ) ); + if(!xTarget.is()) + xTarget.set( 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); + m_pShapeFactory->createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] ); + + //prepare polygon for handle shape: + drawing::PointSequenceSequence aHandlesPoints(1); + sal_Int32 nOldHandleCount = aHandlesPoints[0].getLength(); + aHandlesPoints[0].realloc(nOldHandleCount+nRealPointCount); + for( sal_Int32 nN = 0; nN xHandleShape = + m_pShapeFactory->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(); + drawing::PolyPolygonShape3D aPoints; + aPoints.SequenceX.realloc(nPointCount); + aPoints.SequenceY.realloc(nPointCount); + aPoints.SequenceZ.realloc(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.SequenceX.realloc(nRealPointCount); + aPoints.SequenceY.realloc(nRealPointCount); + aPoints.SequenceZ.realloc(nRealPointCount); + m_pShapeFactory->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 000000000..d655e0e87 --- /dev/null +++ b/chart2/source/view/axes/VCartesianGrid.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANGRID_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANGRID_HXX + +#include "VAxisOrGridBase.hxx" +#include + +namespace chart { struct VLineProperties; } + +namespace chart +{ + +class VCartesianGrid : public VAxisOrGridBase +{ +// public methods +public: + VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount + , const css::uno::Sequence< + css::uno::Reference< css::beans::XPropertySet > >& rGridPropertiesList //main grid, subgrid, subsubgrid etc + ); + virtual ~VCartesianGrid() override; + + virtual void createShapes() override; + + static void fillLinePropertiesFromGridModel( std::vector& rLinePropertiesList + , const css::uno::Sequence< + css::uno::Reference< css::beans::XPropertySet > >& rGridPropertiesList ); + +private: + css::uno::Sequence< + css::uno::Reference< css::beans::XPropertySet > > m_aGridPropertiesList; //main grid, subgrid, subsubgrid etc +}; + +} //namespace chart +#endif + +/* 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 000000000..1c900b392 --- /dev/null +++ b/chart2/source/view/axes/VCoordinateSystem.cxx @@ -0,0 +1,560 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "VCartesianCoordinateSystem.hxx" +#include "VPolarCoordinateSystem.hxx" +#include +#include +#include +#include +#include +#include "VAxisBase.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::createCoordinateSystem( + const Reference< XCoordinateSystem >& xCooSysModel ) +{ + if( !xCooSysModel.is() ) + return nullptr; + + OUString aViewServiceName = xCooSysModel->getViewServiceName(); + + //@todo: in future the coordinatesystems should be instantiated via service factory + std::unique_ptr 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( const Reference< XCoordinateSystem >& xCooSys ) + : m_xCooSysModel(xCooSys) + , m_aMatrixSceneToScreen() + , m_eLeftWallPos(CuboidPlanePosition_Left) + , m_eBackWallPos(CuboidPlanePosition_Back) + , m_eBottomPos(CuboidPlanePosition_Bottom) + , m_aMergedMinMaxSupplier() + , 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 Reference< drawing::XShapes >& xLogicTarget + , const Reference< drawing::XShapes >& xFinalTarget + , const Reference< lang::XMultiServiceFactory >& xShapeFactory + , Reference< drawing::XShapes >& xLogicTargetForSeriesBehindAxis ) +{ + OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.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 + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + if(nDimensionCount==2) + { + //create and add to target + m_xLogicTargetForGrids = pShapeFactory->createGroup2D( xLogicTarget ); + xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup2D( xLogicTarget ); + m_xLogicTargetForAxes = pShapeFactory->createGroup2D( xLogicTarget ); + } + else + { + //create and added to target + m_xLogicTargetForGrids = pShapeFactory->createGroup3D( xLogicTarget ); + xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup3D( xLogicTarget ); + m_xLogicTargetForAxes = pShapeFactory->createGroup3D( xLogicTarget ); + } + m_xFinalTarget = xFinalTarget; + m_xShapeFactory = xShapeFactory; +} + +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 aResolution( + std::max(m_xCooSysModel->getDimension(), 2)); + + for( auto& i : aResolution ) + 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(2.0*static_cast(rPageResolution.Width)*fCoosysWidth/fPageWidth); + sal_Int32 nYResolution = static_cast(2.0*static_cast(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 ) + { + aResolution[0]=nXResolution; + aResolution[1]=nYResolution; + } + else + { + //this maybe can be optimized further ... + sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution ); + nMaxResolution*=2; + for( auto& i : aResolution ) + i = nMaxResolution; + } + + return aResolution; +} + +Reference< XAxis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const +{ + if( m_xCooSysModel.is() ) + return m_xCooSysModel->getAxisByDimension( nDimensionIndex, nAxisIndex ); + return nullptr; +} + +Sequence< Reference< beans::XPropertySet > > VCoordinateSystem::getGridListFromAxis( const Reference< XAxis >& xAxis ) +{ + std::vector< Reference< beans::XPropertySet > > aRet; + + if( xAxis.is() ) + { + aRet.push_back( xAxis->getGridProperties() ); + auto aSubGrids( comphelper::sequenceToContainer > >( xAxis->getSubGridProperties() ) ); + aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() ); + } + + return comphelper::containerToSequence( aRet ); +} + +void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex ) +{ + if( rDimensionIndex<0 ) + rDimensionIndex=0; + if( rDimensionIndex>2 ) + rDimensionIndex=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 uno::Reference & /* xChartDoc */ + , const awt::Size& /* rFontReferenceSize */ + , const awt::Rectangle& /* rMaximumSpaceForLabels */ + , bool /* bLimitSpaceForLabels */ + ) +{ +} + +void VCoordinateSystem::initVAxisInList() +{ +} +void VCoordinateSystem::updateScalesAndIncrementsOnAxes() +{ +} + +void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) +{ + if( rScaleAutomatism.getScale().AxisType==AxisType::DATE && nDimIndex==0 ) + { + // 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 = 0.0; + double fMax = 0.0; + ::rtl::math::setInf(&fMin, false); + ::rtl::math::setInf(&fMax, true); + if( nDimIndex == 0 ) + { + // x dimension + fMin = m_aMergedMinMaxSupplier.getMinimumX(); + fMax = m_aMergedMinMaxSupplier.getMaximumX(); + } + else if( nDimIndex == 1 ) + { + // y dimension + ExplicitScaleData aScale = getExplicitScale( 0, 0 ); + fMin = m_aMergedMinMaxSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex); + fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum,aScale.Maximum, 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 ) ); + + 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.end() ) + 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& elem : m_aAxisMap) + { + VAxisBase* pVAxis = elem.second.get(); + if( pVAxis ) + { + if(pVAxis->getDimensionCount()==2) + pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + pVAxis->createMaximumLabels(); + } + } +} +void VCoordinateSystem::createAxesLabels() +{ + for (auto const& elem : m_aAxisMap) + { + VAxisBase* pVAxis = elem.second.get(); + if( pVAxis ) + { + if(pVAxis->getDimensionCount()==2) + pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + pVAxis->createLabels(); + } + } +} + +void VCoordinateSystem::updatePositions() +{ + for (auto const& elem : m_aAxisMap) + { + VAxisBase* pVAxis = elem.second.get(); + if( pVAxis ) + { + if(pVAxis->getDimensionCount()==2) + pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + pVAxis->updatePositions(); + } + } +} + +void VCoordinateSystem::createAxesShapes() +{ + for (auto const& elem : m_aAxisMap) + { + VAxisBase* pVAxis = elem.second.get(); + if( pVAxis ) + { + if(pVAxis->getDimensionCount()==2) + pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + + tFullAxisIndex aFullAxisIndex = elem.first; + if( aFullAxisIndex.second == 0 ) + { + if( aFullAxisIndex.first == 0 ) + { + if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY ) + pVAxis->setExtraLinePositionAtOtherAxis( + m_aExplicitScales[1].Origin ); + } + else if( aFullAxisIndex.first == 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 +{ + Reference xProp(m_xCooSysModel, uno::UNO_QUERY ); + bool bSwapXAndY = false; + if( xProp.is()) try + { + xProp->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 Reference< chart2::XAxis >& xAxis + , const Reference& 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 000000000..1a93888b7 --- /dev/null +++ b/chart2/source/view/axes/VPolarAngleAxis.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 + +#include "VPolarAngleAxis.hxx" +#include "VPolarGrid.hxx" +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::rtl::math; + +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 uno::Reference< drawing::XShapes >& xTarget + , EquidistantTickIter& rTickIter + , AxisLabelProperties const & rAxisLabelProperties + , double fLogicRadius + , double fLogicZ ) +{ + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + + FixedNumberFormatter aFixedNumberFormatter( + m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + + //prepare text properties for multipropertyset-interface of shape + tNameSequence aPropNames; + tAnySequence aPropValues; + + uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); + PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false, -1, false, false ); + LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps + , rAxisLabelProperties.m_aFontReferenceSize ); + + uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"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.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 && nIndexgetLength() ) + 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, pShapeFactory); + 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.fRotationAngleDegree)); + + uno::Any aATransformation = ShapeFactory::makeTransformation( aAnchorScreenPosition2D, fRotationAnglePi ); + OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.bStackCharacters ); + + pTickInfo->xTextShape = pShapeFactory->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.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 ); + uno::Reference< drawing::XShape > xShape = m_pShapeFactory->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 000000000..3ee9e7e15 --- /dev/null +++ b/chart2/source/view/axes/VPolarAngleAxis.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARANGLEAXIS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARANGLEAXIS_HXX + +#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 css::uno::Reference< css::drawing::XShapes >& xTarget + , EquidistantTickIter& rTickIter + , AxisLabelProperties const & rAxisLabelProperties + , double fLogicRadius, double fLogicZ ); +}; + +} //namespace chart +#endif + +/* 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 000000000..9e41857c2 --- /dev/null +++ b/chart2/source/view/axes/VPolarAxis.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 "VPolarAxis.hxx" +#include "VPolarAngleAxis.hxx" +#include "VPolarRadiusAxis.hxx" +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +std::shared_ptr VPolarAxis::createAxis( const AxisProperties& rAxisProperties + , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier + , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ) +{ + if( nDimensionIndex==0 ) + return std::make_shared( rAxisProperties, xNumberFormatsSupplier, nDimensionCount ); + return std::make_shared( 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() ) + , m_aIncrements() +{ + PlotterBase::m_pPosHelper = m_pPosHelper.get(); +} + +VPolarAxis::~VPolarAxis() +{ +} + +void VPolarAxis::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) +{ + m_aIncrements = 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 000000000..0a7056be7 --- /dev/null +++ b/chart2/source/view/axes/VPolarAxis.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARAXIS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARAXIS_HXX + +#include "VAxisBase.hxx" +#include + +namespace chart +{ + +class PolarPlottingPositionHelper; + +class VPolarAxis : public VAxisBase +{ +public: + static std::shared_ptr createAxis( const AxisProperties& rAxisProperties + , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier + , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ); + + void setIncrements( const 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 m_pPosHelper; + std::vector< ExplicitIncrementData > m_aIncrements; +}; + +} //namespace chart +#endif + +/* 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 000000000..1fee84175 --- /dev/null +++ b/chart2/source/view/axes/VPolarCoordinateSystem.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 "VPolarCoordinateSystem.hxx" +#include "VPolarGrid.hxx" +#include "VPolarAxis.hxx" +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; + +VPolarCoordinateSystem::VPolarCoordinateSystem( const Reference< XCoordinateSystem >& 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 ) + { + if( getPropertySwapXAndYAxis() ) + { + aResolution[0]/=2;//radius + aResolution[1]*=4;//outer circle resolution + } + else + { + aResolution[0]*=4;//outer circle resolution + aResolution[1]/=2;//radius + } + } + + return aResolution; +} + +void VPolarCoordinateSystem::createVAxisList( + const uno::Reference & xChartDoc + , const awt::Size& rFontReferenceSize + , const awt::Rectangle& rMaximumSpaceForLabels + , bool //bLimitSpaceForLabels + ) +{ + // note: using xChartDoc itself as XNumberFormatsSupplier would cause + // a leak from VPolarAxis due to cyclic reference + uno::Reference const xNumberFormatsSupplier( + dynamic_cast(*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++ ) + { + Reference< XAxis > xAxis( getAxisByDimension(nDimensionIndex,nAxisIndex) ); + if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) + continue; + AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider()); + 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,m_xShapeFactory + , 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; + + Reference< XAxis > 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,m_xShapeFactory + , 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 000000000..497667296 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARCOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARCOORDINATESYSTEM_HXX + +#include + +namespace chart +{ + +class VPolarCoordinateSystem : public VCoordinateSystem +{ +public: + VPolarCoordinateSystem() = delete; + explicit VPolarCoordinateSystem( const css::uno::Reference< css::chart2::XCoordinateSystem >& 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 css::uno::Reference< css::chart2::XChartDocument> & xChartDoc + , const css::awt::Size& rFontReferenceSize + , const css::awt::Rectangle& rMaximumSpaceForLabels + , bool bLimitSpaceForLabels ) override; + + virtual void initVAxisInList() override; + virtual void updateScalesAndIncrementsOnAxes() override; + + virtual void createGridShapes() override; +}; + +} //namespace chart +#endif + +/* 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 000000000..46d176b6d --- /dev/null +++ b/chart2/source/view/axes/VPolarGrid.cxx @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include "Tickmarks_Equidistant.hxx" + +#include + +#include + +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 + , const uno::Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) + : VAxisOrGridBase( nDimensionIndex, nDimensionCount ) + , m_aGridPropertiesList( rGridPropertiesList ) + , m_pPosHelper( new PolarPlottingPositionHelper() ) + , m_aIncrements() +{ + PlotterBase::m_pPosHelper = m_pPosHelper.get(); +} + +VPolarGrid::~VPolarGrid() +{ +} + +void VPolarGrid::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) +{ + m_aIncrements = rIncrements; +} + +void VPolarGrid::getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const +{ + const std::vector& 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 ); + for( TickInfo* pTickInfo = aIter.firstInfo() + ; pTickInfo + ; pTickInfo = aIter.nextInfo(), nTick++ ) + { + if(nTick>=rPoints[0].getLength()) + rPoints[0].realloc(rPoints[0].getLength()+30); + + //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); + double fLogicAngle = pTickInfo->getUnscaledTickValue(); + + drawing::Position3D aScenePosition3D( pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicRadius, fLogicZ ) ); + rPoints[0][nTick].X = static_cast(aScenePosition3D.PositionX); + rPoints[0][nTick].Y = static_cast(aScenePosition3D.PositionY); + } + if(rPoints[0].getLength()>1) + { + rPoints[0].realloc(nTick+1); + rPoints[0][nTick].X = rPoints[0][0].X; + rPoints[0][nTick].Y = rPoints[0][0].Y; + } + else + rPoints[0].realloc(0); +} +#ifdef NOTYET +void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicTarget + , TickInfoArraysType& /* rRadiusTickInfos */ + , TickInfoArraysType& rAngleTickInfos + , const std::vector& rLinePropertiesList ) +{ + Reference< drawing::XShapes > xMainTarget( + createGroupShape( xLogicTarget, m_aCID ) ); + + const std::vector& 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(aScenePositionStart.PositionX); + aPoints[0][0].Y = static_cast(aScenePositionStart.PositionY); + aPoints[0][1].X = static_cast(aScenePositionEnd.PositionX); + aPoints[0][1].Y = static_cast(aScenePositionEnd.PositionY); + appendPointSequence( aAllPoints, aPoints ); + } + + Reference< drawing::XShape > xShape = m_pShapeFactory->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 Reference< drawing::XShapes >& xLogicTarget + , TickInfoArraysType& rRadiusTickInfos + , TickInfoArraysType& rAngleTickInfos + , const std::vector& rLinePropertiesList ) +{ + Reference< drawing::XShapes > xMainTarget( + createGroupShape( xLogicTarget, m_aCID ) ); + + const std::vector& 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; + + Reference< drawing::XShapes > xTarget( xMainTarget ); + if( nDepth > 0 ) + { + xTarget.set( createGroupShape( xLogicTarget + , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) ) + ) ); + if(!xTarget.is()) + xTarget.set( 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 ); + } + + Reference< drawing::XShape > xShape = m_pShapeFactory->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_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); + if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + return; + if(!m_aGridPropertiesList.hasElements()) + return; + + //create all scaled tickmark values + TickInfoArraysType aAngleTickInfos; + TickInfoArraysType aRadiusTickInfos; + getAllTickInfos( 0, aAngleTickInfos ); + getAllTickInfos( 1, aRadiusTickInfos ); + + std::vector 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 000000000..29fa8b270 --- /dev/null +++ b/chart2/source/view/axes/VPolarGrid.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARGRID_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARGRID_HXX + +#include "VAxisOrGridBase.hxx" +#include "Tickmarks.hxx" +#include +#include + +namespace chart { struct VLineProperties; } + +namespace chart +{ + +class PolarPlottingPositionHelper; + +class VPolarGrid : public VAxisOrGridBase +{ +// public methods +public: + VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount + , const css::uno::Sequence< + css::uno::Reference< css::beans::XPropertySet > > & rGridPropertiesList //main grid, subgrid, subsubgrid etc + ); + virtual ~VPolarGrid() override; + + virtual void createShapes() override; + + void setIncrements( const 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 + css::uno::Sequence< + css::uno::Reference< css::beans::XPropertySet > > m_aGridPropertiesList;//main grid, subgrid, subsubgrid etc + std::unique_ptr m_pPosHelper; + std::vector< ExplicitIncrementData > m_aIncrements; + + void getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const; + + void create2DRadiusGrid( const css::uno::Reference& xLogicTarget + , TickInfoArraysType& rRadiusTickInfos + , TickInfoArraysType& rAngleTickInfos + , const std::vector& rLinePropertiesList ); +}; + +} //namespace chart +#endif + +/* 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 000000000..6bf0b0f47 --- /dev/null +++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include "Tickmarks_Equidistant.hxx" + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::rtl::math; + +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 uno::Reference< drawing::XShapes >& xLogicTarget + , const uno::Reference< drawing::XShapes >& xFinalTarget + , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory + , const OUString& rCID ) +{ + VPolarAxis::initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID ); + m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID ); +} + +void VPolarRadiusAxis::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +{ + VPolarAxis::setScales( rScales, bSwapXAndYAxis ); + m_apAxisWithLabels->setScales( 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_xShapeFactory, m_aCID ); + aAxis.setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( m_aMatrixScreenToScene ) ); + aAxis.setScales( 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 000000000..38ebd7b29 --- /dev/null +++ b/chart2/source/view/axes/VPolarRadiusAxis.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARRADIUSAXIS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARRADIUSAXIS_HXX + +#include "VPolarAxis.hxx" +#include + +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 css::uno::Reference< css::drawing::XShapes >& xLogicTarget + , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + , const OUString& rCID + ) override; + + virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix ) override; + + virtual void setScales( const 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 m_apAxisWithLabels; +}; + +} //namespace chart +#endif + +/* 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 000000000..a658a26d0 --- /dev/null +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -0,0 +1,994 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include "Splines.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +AreaChart::AreaChart( const uno::Reference& 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_xChartTypeModelProps.is() ) + { + m_xChartTypeModelProps->getPropertyValue(CHART_UNONAME_CURVE_STYLE) >>= m_eCurveStyle; + m_xChartTypeModelProps->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) >>= m_nCurveResolution; + m_xChartTypeModelProps->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 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( drawing::PolyPolygonShape3D& rPolyPoly, PlottingPositionHelper& rPosHelper ) +{ + sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength(); + if(!nPolyCount) + return; + + drawing::PolyPolygonShape3D aTmp; + aTmp.SequenceX.realloc(nPolyCount); + aTmp.SequenceY.realloc(nPolyCount); + aTmp.SequenceZ.realloc(nPolyCount); + + for( sal_Int32 nPolygonIndex = 0; nPolygonIndexgetLength(); + if( !nPointCount ) + continue; + + pOuterTargetX->realloc(nPointCount); + pOuterTargetY->realloc(nPointCount); + pOuterTargetZ->realloc(nPointCount); + + double* pSourceX = pOuterSourceX->getArray(); + double* pSourceY = pOuterSourceY->getArray(); + double* pSourceZ = pOuterSourceZ->getArray(); + + double* pTargetX = pOuterTargetX->getArray(); + double* pTargetY = pOuterTargetY->getArray(); + double* pTargetZ = pOuterTargetZ->getArray(); + + //copy first point + *pTargetX=*pSourceX++; + *pTargetY=*pSourceY++; + *pTargetZ=*pSourceZ++; + sal_Int32 nTargetPointCount=1; + + for( sal_Int32 nSource=1; nSourcerealloc(nTargetPointCount); + pOuterTargetY->realloc(nTargetPointCount); + pOuterTargetZ->realloc(nTargetPointCount); + } + + pOuterSourceX->realloc(0); + pOuterSourceY->realloc(0); + pOuterSourceZ->realloc(0); + } + + //free space + rPolyPoly.SequenceX.realloc(nPolyCount); + rPolyPoly.SequenceY.realloc(nPolyCount); + rPolyPoly.SequenceZ.realloc(nPolyCount); + + rPolyPoly=aTmp; +} + +bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, chart2::CurveStyle eCurveStyle, PlottingPositionHelper const * pPosHelper, drawing::PolyPolygonShape3D &aPoly ) +{ + sal_uInt32 nOuterCount = aStartPoly.SequenceX.getLength(); + if ( !nOuterCount ) + return false; + + drawing::PolyPolygonShape3D aSteppedPoly; + aSteppedPoly.SequenceX.realloc(nOuterCount); + aSteppedPoly.SequenceY.realloc(nOuterCount); + aSteppedPoly.SequenceZ.realloc(nOuterCount); + + for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) + { + if( aStartPoly.SequenceX[nOuter].getLength() <= 1 ) + continue; //we need at least two points + + sal_uInt32 nMaxIndexPoints = aStartPoly.SequenceX[nOuter].getLength()-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 double* pOldX = aStartPoly.SequenceX[nOuter].getConstArray(); + const double* pOldY = aStartPoly.SequenceY[nOuter].getConstArray(); + const double* pOldZ = aStartPoly.SequenceZ[nOuter].getConstArray(); + + aSteppedPoly.SequenceX[nOuter].realloc( nNewIndexPoints ); + aSteppedPoly.SequenceY[nOuter].realloc( nNewIndexPoints ); + aSteppedPoly.SequenceZ[nOuter].realloc( nNewIndexPoints ); + + double* pNewX = aSteppedPoly.SequenceX[nOuter].getArray(); + double* pNewY = aSteppedPoly.SequenceY[nOuter].getArray(); + double* pNewZ = aSteppedPoly.SequenceZ[nOuter].getArray(); + + pNewX[0] = pOldX[0]; + pNewY[0] = pOldY[0]; + pNewZ[0] = pOldZ[0]; + for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ ) + { + switch ( eCurveStyle ) + { + case CurveStyle_STEP_START: + /** O + | + | + | + O-----+ + */ + // create the intermediate point + pNewX[1+oi*2] = pOldX[oi+1]; + pNewY[1+oi*2] = pOldY[oi]; + pNewZ[1+oi*2] = pOldZ[oi]; + // and now the normal one + pNewX[1+oi*2+1] = pOldX[oi+1]; + pNewY[1+oi*2+1] = pOldY[oi+1]; + pNewZ[1+oi*2+1] = pOldZ[oi+1]; + break; + case CurveStyle_STEP_END: + /** +------O + | + | + | + O + */ + // create the intermediate point + pNewX[1+oi*2] = pOldX[oi]; + pNewY[1+oi*2] = pOldY[oi+1]; + pNewZ[1+oi*2] = pOldZ[oi]; + // and now the normal one + pNewX[1+oi*2+1] = pOldX[oi+1]; + pNewY[1+oi*2+1] = pOldY[oi+1]; + pNewZ[1+oi*2+1] = pOldZ[oi+1]; + break; + case CurveStyle_STEP_CENTER_X: + /** +--O + | + | + | + O--+ + */ + // create the first intermediate point + pNewX[1+oi*3] = (pOldX[oi]+pOldX[oi+1])/2; + pNewY[1+oi*3] = pOldY[oi]; + pNewZ[1+oi*3] = pOldZ[oi]; + // create the second intermediate point + pNewX[1+oi*3+1] = (pOldX[oi]+pOldX[oi+1])/2; + pNewY[1+oi*3+1] = pOldY[oi+1]; + pNewZ[1+oi*3+1] = pOldZ[oi]; + // and now the normal one + pNewX[1+oi*3+2] = pOldX[oi+1]; + pNewY[1+oi*3+2] = pOldY[oi+1]; + pNewZ[1+oi*3+2] = pOldZ[oi+1]; + break; + case CurveStyle_STEP_CENTER_Y: + /** O + | + +-----+ + | + O + */ + // create the first intermediate point + pNewX[1+oi*3] = pOldX[oi]; + pNewY[1+oi*3] = (pOldY[oi]+pOldY[oi+1])/2; + pNewZ[1+oi*3] = pOldZ[oi]; + // create the second intermediate point + pNewX[1+oi*3+1] = pOldX[oi+1]; + pNewY[1+oi*3+1] = (pOldY[oi]+pOldY[oi+1])/2; + pNewZ[1+oi*3+1] = pOldZ[oi]; + // and now the normal one + pNewX[1+oi*3+2] = pOldX[oi+1]; + pNewY[1+oi*3+2] = pOldY[oi+1]; + pNewZ[1+oi*3+2] = pOldZ[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 + , drawing::PolyPolygonShape3D const * pSeriesPoly + , PlottingPositionHelper* pPosHelper ) +{ + //return true if a line was created successfully + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + + drawing::PolyPolygonShape3D aPoly; + if(m_eCurveStyle==CurveStyle_CUBIC_SPLINES) + { + drawing::PolyPolygonShape3D aSplinePoly; + SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution ); + lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper ); + Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly ); + } + else if(m_eCurveStyle==CurveStyle_B_SPLINES) + { + drawing::PolyPolygonShape3D 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: + uno::Reference< drawing::XShape > xShape; + if(m_nDimension==3) + { + double fDepth = getTransformedDepth(); + sal_Int32 nPolyCount = aPoly.SequenceX.getLength(); + for(sal_Int32 nPoly=0;nPolycreateStripe(xSeriesGroupShape_Shapes + , Stripe( aPoint1, aPoint2, fDepth ) + , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 ); + } + } + } + else //m_nDimension!=3 + { + xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes + , PolyToPointSequence( aPoly ) ); + 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 + , drawing::PolyPolygonShape3D const * pSeriesPoly + , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , PlottingPositionHelper const * pPosHelper ) +{ + //return true if an area was created successfully + + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + double zValue = pSeries->m_fLogicZPos; + + drawing::PolyPolygonShape3D 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(fMaxXgetLogicMinX() || 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 + { + drawing::PolyPolygonShape3D 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: + uno::Reference< drawing::XShape > xShape; + if(m_nDimension==3) + { + xShape = m_pShapeFactory->createArea3D( xSeriesGroupShape_Shapes + , aPoly, getTransformedDepth() ); + } + else //m_nDimension!=3 + { + xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes + , aPoly ); + } + 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, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex + drawing::PolyPolygonShape3D* pSeriesPoly = nullptr; + + //iterate through all series + for( std::unique_ptr 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() + { + ::rtl::math::setNan( &m_fX ); + ::rtl::math::setNan( &m_fY ); + ::rtl::math::setNan( &m_fZ ); + } + + 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_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized"); + if(!(m_pShapeFactory&&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 = m_pShapeFactory->createGroup2D( m_xFinalTarget ); + m_xRegressionCurveEquationTarget = m_pShapeFactory->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 > 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 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(); + if( rLogicYSumMap.find(nAttachedAxisIndex)==rLogicYSumMap.end() ) + rLogicYSumMap[nAttachedAxisIndex]=0.0; + + m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex); + + double fAdd = pSeries->getYValue( nIndex ); + if( !std::isnan(fAdd) && !std::isinf(fAdd) ) + rLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd ); + } + } + } + } + + 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 > aLogicYForNextSeriesMapByX(nEndIndex); //one for each different nAttachedAxisIndex + //iterate through all series + for( std::unique_ptr const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget); + + sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); + 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)) + 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 ) + { + drawing::PolyPolygonShape3D& rPolygon = pSeries->m_aPolyPolygonShape3D; + sal_Int32& rIndex = pSeries->m_nPolygonIndex; + if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() ) + { + if( rPolygon.SequenceX[ rIndex ].hasElements() ) + 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||fLogicXm_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; + + //create a group shape for this point and add to the series shape: + OUString aPointCID = ObjectIdentifier::createPointCID( + pSeries->getPointCID_Stub(), nIndex ); + uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); + uno::Reference xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); + + { + nCreatedPoints++; + + //create data point + drawing::Direction3D aSymbolSize(0,0,0); + if( bCreateSymbol ) + { + if(m_nDimension!=3) + { + 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; + m_pShapeFactory->createSymbol2D( + xPointGroupShape_Shapes, aScenePosition, aSymbolSize, + nSymbol, pSymbolProperties->BorderColor, + pSymbolProperties->FillColor); + } + else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC) + { + m_pShapeFactory->createGraphic2D(xPointGroupShape_Shapes, + aScenePosition, aSymbolSize, + pSymbolProperties->Graphic); + } + //@todo other symbol styles + } + } + //create error bars or rectangles, depending on configuration + if ( ConfigAccess::getUseErrorRectangle() ) + { + 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,m_pShapeFactory) + .transformSceneToScreenPosition( aScenePosition3D ); + } + + createDataLabel( m_xTextTarget, *pSeries, nIndex + , fLogicValueForLabeDisplay + , rLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset ); + } + } + + //remove PointGroupShape if empty + if(!xPointGroupShape_Shapes->getCount()) + xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape); + } + + }//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 000000000..786fcba83 --- /dev/null +++ b/chart2/source/view/charttypes/AreaChart.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_AREACHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_AREACHART_HXX + +#include +#include +#include + +namespace chart +{ + +class AreaChart : public VSeriesPlotter +{ + // public methods +public: + AreaChart() = delete; + + AreaChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount + , bool bCategoryXAxis, bool bNoArea=false + ); + virtual ~AreaChart() override; + + virtual void createShapes() override; + virtual void addSeries( std::unique_ptr 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 + , css::drawing::PolyPolygonShape3D const * pSeriesPoly + , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , PlottingPositionHelper const * pPosHelper ); + bool impl_createLine( VDataSeries* pSeries + , css::drawing::PolyPolygonShape3D const * pSeriesPoly + , PlottingPositionHelper* pPosHelper ); + static bool create_stepped_line( css::drawing::PolyPolygonShape3D aStartPoly + , css::chart2::CurveStyle eCurveStyle + , PlottingPositionHelper const * pPosHelper + , css::drawing::PolyPolygonShape3D &aPoly ); + +private: //member + std::unique_ptr + 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; + + css::uno::Reference< css::drawing::XShapes > m_xSeriesTarget; + css::uno::Reference< css::drawing::XShapes > m_xErrorBarTarget; + css::uno::Reference< css::drawing::XShapes > m_xTextTarget; + css::uno::Reference< css::drawing::XShapes > m_xRegressionCurveEquationTarget; +}; +} //namespace chart +#endif + +/* 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 000000000..3641e67b4 --- /dev/null +++ b/chart2/source/view/charttypes/BarChart.cxx @@ -0,0 +1,985 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +BarChart::BarChart( const uno::Reference& 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_xChartTypeModelProps.is() ) + { + m_xChartTypeModelProps->getPropertyValue( "OverlapSequence" ) >>= m_aOverlapSequence; + m_xChartTypeModelProps->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(&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(&( 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() ) + { + double fTemp = aRet.DirectionX; + aRet.DirectionX = aRet.DirectionY; + aRet.DirectionY = fTemp; + } + } + 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,m_pShapeFactory) + .transformSceneToScreenPosition( aScenePosition3D ); +} + +uno::Reference< drawing::XShape > BarChart::createDataPoint3D_Bar( + const uno::Reference< drawing::XShapes >& 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", "" ); + } + + uno::Reference< drawing::XShape > xShape; + switch( nGeometry3D ) + { + case DataPointGeometry3D::CYLINDER: + xShape = m_pShapeFactory->createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree ); + break; + case DataPointGeometry3D::CONE: + xShape = m_pShapeFactory->createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree ); + break; + case DataPointGeometry3D::PYRAMID: + xShape = m_pShapeFactory->createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0 + , xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + break; + case DataPointGeometry3D::CUBOID: + default: + xShape = m_pShapeFactory->createCube( xTarget, rPosition, rSize + , nRotateZAngleHundredthDegree, xObjectProperties + , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges ); + return xShape; + } + if( nGeometry3D != DataPointGeometry3D::PYRAMID ) + 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 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(m_aZSlots.size())) + m_aZSlots.resize(zSlot+1); + } + VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot ); +} + +namespace { + +//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() + { + ::rtl::math::setNan( &m_fX ); + ::rtl::math::setNan( &m_fUpperY ); + ::rtl::math::setNan( &m_fLowerY ); + ::rtl::math::setNan( &m_fZ ); + } + + double m_fX; + double m_fUpperY; + double m_fLowerY; + double m_fZ; +}; + +} + +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; + for( nN = 0; nN < m_aOverlapSequence.getLength(); nN++ ) + { + if(nN!=nUseThisIndex) + m_aOverlapSequence[nN] = m_aOverlapSequence[nUseThisIndex]; + } + + nUseThisIndex = nAxisIndex; + if( nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength() ) + nUseThisIndex = 0; + for( nN = 0; nN < m_aGapwidthSequence.getLength(); nN++ ) + { + if(nN!=nUseThisIndex) + m_aGapwidthSequence[nN] = m_aGapwidthSequence[nUseThisIndex]; + } +} + +static E3dScene* lcl_getE3dScene(uno::Reference const & xInterface) +{ + E3dScene* pScene = nullptr; + + SvxShape* pSvxShape = comphelper::getUnoTunnelImplementation(xInterface); + if (pSvxShape) + { + SdrObject* pObject = pSvxShape->GetSdrObject(); + pScene = dynamic_cast(pObject); + } + return pScene; +} + +void BarChart::createShapes() +{ + if( m_aZSlots.empty() ) //no series + return; + + OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized"); + if(!(m_pShapeFactory&&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 + + uno::Reference< drawing::XShapes > xSeriesTarget( + createGroupShape( m_xLogicTarget )); + uno::Reference< drawing::XShapes > xRegressionCurveTarget( + createGroupShape( m_xLogicTarget )); + uno::Reference< drawing::XShapes > xTextTarget( + m_pShapeFactory->createGroup2D( m_xFinalTarget )); + + uno::Reference< drawing::XShapes > xRegressionCurveEquationTarget( + m_pShapeFactory->createGroup2D( m_xFinalTarget )); + //check necessary here that different Y axis can not be stacked in the same group? ... hm? + + double fLogicZ = 1.0;//as defined + + bool bDrawConnectionLines = false; + bool bDrawConnectionLinesInited = false; + bool bOnlyConnectionLinesForThisPoint = false; + + std::unordered_set> aShapeSet; + + const comphelper::ScopeGuard aGuard([aShapeSet]() { + + std::unordered_set aSceneSet; + + for (uno::Reference const & rShape : aShapeSet) + { + E3dScene* pScene = lcl_getE3dScene(rShape); + if(nullptr != pScene) + { + 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 nSkippedPoints = 0; + sal_Int32 nCreatedPoints = 0; + + 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(); + if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() ) + aLogicYSumMap[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 ) + { + //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(&( 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; + } + + 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 const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + + bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); + + 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; + } + + uno::Reference xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget)); + uno::Reference xSeriesGroupShape(xSeriesGroupShape_Shapes, uno::UNO_QUERY); + // Suspend setting rects dirty for the duration of this call + aShapeSet.insert(xSeriesGroupShape); + E3dScene* pScene = lcl_getE3dScene(xSeriesGroupShape); + 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(fUnscaledLogicXgetLogicMinX()) + 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; + + 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 xPointGroupShape_Shape = + // uno::Reference( 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 ) + ) + { + nSkippedPoints++; + 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 ); + + nCreatedPoints++; + //create partial point + if( !approxEqual(fLowerYValue,fUpperYValue) ) + { + uno::Reference< drawing::XShape > 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); + + uno::Reference< XTransformation > xTransformation = pSubPosHelper->getTransformationScaledLogicToScene(); + + //transformation 3) -> 4) + drawing::Position3D aTransformedBottom ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicBottom) ) ) ); + drawing::Position3D aTransformedLeftBottomFront ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicLeftBottomFront) ) ) ); + drawing::Position3D aTransformedRightDeepTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicRightDeepTop) ) ) ); + drawing::Position3D aTransformedTopTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(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 + { + // performance improvement: alloc the sequence before the rendering + // otherwise we have 2 realloc calls + drawing::PolyPolygonShape3D aPoly; + aPoly.SequenceX.realloc(1); + aPoly.SequenceY.realloc(1); + aPoly.SequenceZ.realloc(1); + drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); + drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); + + AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); + AddPointToPoly( aPoly, drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); + AddPointToPoly( aPoly, aRightUpperPoint ); + AddPointToPoly( aPoly, aLeftUpperPoint ); + AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); + pPosHelper->transformScaledLogicToScene( aPoly ); + xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes, aPoly ); + setMappedProperties( xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + } + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor"); + if(!std::isnan(nPropVal)) + { + uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); + xProps->setPropertyValue("FillColor", uno::Any(static_cast(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) + fSlotX+=1.0; + }//next x slot + ++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(&( 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 const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + drawing::PolyPolygonShape3D* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D; + if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly)) + continue; + + drawing::PolyPolygonShape3D aPoly; + Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly ); + + if(!ShapeFactory::hasPolygonAnyLines(aPoly)) + continue; + + //transformation 3) -> 4) + pPosHelper->transformScaledLogicToScene( aPoly ); + + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes( + getSeriesGroupShape(pSeries.get(), xSeriesTarget) ); + uno::Reference< drawing::XShape > xShape( m_pShapeFactory->createLine2D( + xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) ) ); + setMappedProperties( xShape, pSeries->getPropertiesOfSeries() + , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + } + } + } + } + + /* @todo remove series shapes if empty + */ + + 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/BarChart.hxx b/chart2/source/view/charttypes/BarChart.hxx new file mode 100644 index 000000000..ed4457aff --- /dev/null +++ b/chart2/source/view/charttypes/BarChart.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARCHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARCHART_HXX + +#include +#include + +namespace chart +{ +class BarPositionHelper; + +class BarChart : public VSeriesPlotter +{ + // public methods +public: + BarChart() = delete; + + BarChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount ); + virtual ~BarChart() override; + + virtual void createShapes() override; + virtual void addSeries( std::unique_ptr pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override; + + virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; + +private: //methods + css::uno::Reference< css::drawing::XShape > + createDataPoint3D_Bar( + const css::uno::Reference< css::drawing::XShapes >& 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(); + +private: //member + std::unique_ptr m_pMainPosHelper; + css::uno::Sequence< sal_Int32 > m_aOverlapSequence; + css::uno::Sequence< sal_Int32 > m_aGapwidthSequence; +}; +} //namespace chart +#endif + +/* 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 000000000..f8ac3e7d6 --- /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 + +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 BarPositionHelper::clone() const +{ + return std::make_unique(*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 000000000..e63fa8837 --- /dev/null +++ b/chart2/source/view/charttypes/BarPositionHelper.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARPOSITIONHELPER_HXX + +#include +#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 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 +#endif + +/* 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 000000000..9ad349b9f --- /dev/null +++ b/chart2/source/view/charttypes/BubbleChart.cxx @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +BubbleChart::BubbleChart( const uno::Reference& 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 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,m_pShapeFactory).transformSceneToScreenPosition( aSceneMinPos ) ); + awt::Point aScreenMaxPos( LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory).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 / F_PI ); + double fRadius = sqrt( fLogicSize / F_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() + { + ::rtl::math::setNan( &m_fX ); + ::rtl::math::setNan( &m_fY ); + ::rtl::math::setNan( &m_fZ ); + } + + double m_fX; + double m_fY; + double m_fZ; +}; + +} + +void BubbleChart::createShapes() +{ + if( m_aZSlots.empty() ) //no series + return; + + OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized"); + if(!(m_pShapeFactory&&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) + uno::Reference< drawing::XShapes > xSeriesTarget( + createGroupShape( m_xLogicTarget )); + uno::Reference< drawing::XShapes > xTextTarget( + m_pShapeFactory->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 const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + + bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); + bool bHasBorderColorMapping = pSeries->hasPropertyMapping("LineColor"); + + uno::Reference< drawing::XShapes > 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 ); + uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); + uno::Reference xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); + + { + nCreatedPoints++; + + //create data point + drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize ); + uno::Reference xShape = m_pShapeFactory->createCircle2D( xPointGroupShape_Shapes + , aScenePosition, aSymbolSize ); + + setMappedProperties( xShape + , pSeries->getPropertiesOfPoint( nIndex ) + , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nIndex, "FillColor"); + if(!std::isnan(nPropVal)) + { + uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); + xProps->setPropertyValue("FillColor", uno::Any(static_cast(nPropVal))); + } + } + if(bHasBorderColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nIndex, "LineColor"); + if(!std::isnan(nPropVal)) + { + uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); + xProps->setPropertyValue("LineColor", uno::Any(static_cast(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,m_pShapeFactory) + .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_Shape); + + }//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 000000000..a4e9f7a75 --- /dev/null +++ b/chart2/source/view/charttypes/BubbleChart.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BUBBLECHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BUBBLECHART_HXX + +#include +#include + +namespace chart +{ + +class BubbleChart : public VSeriesPlotter +{ + // public methods +public: + BubbleChart() = delete; + + BubbleChart( const css::uno::Reference< css::chart2::XChartType >& 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 +#endif + +/* 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 000000000..a82c88965 --- /dev/null +++ b/chart2/source/view/charttypes/CandleStickChart.cxx @@ -0,0 +1,326 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include "BarPositionHelper.hxx" +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +CandleStickChart::CandleStickChart( const uno::Reference& 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 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_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized"); + if(!(m_pShapeFactory&&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) + + uno::Reference< drawing::XShapes > xSeriesTarget( + createGroupShape( m_xLogicTarget )); + uno::Reference< drawing::XShapes > xLossTarget( + createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier( + OBJECTTYPE_DATA_STOCK_LOSS, OUString() ))); + uno::Reference< drawing::XShapes > xGainTarget( + createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier( + OBJECTTYPE_DATA_STOCK_GAIN, OUString() ))); + uno::Reference< drawing::XShapes > xTextTarget( + m_pShapeFactory->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_xChartTypeModelProps.is() ) + { + m_xChartTypeModelProps->getPropertyValue( "ShowFirst" ) >>= bShowFirst; + + uno::Reference< beans::XPropertySet > xWhiteDayProps; + uno::Reference< beans::XPropertySet > xBlackDayProps; + m_xChartTypeModelProps->getPropertyValue( "Japanese" ) >>= bJapaneseStyle; + m_xChartTypeModelProps->getPropertyValue( "WhiteDay" ) >>= xWhiteDayProps; + m_xChartTypeModelProps->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 ) + { + sal_Int32 nAttachedAxisIndex = 0; + BarPositionHelper* pPosHelper = m_pMainPosHelper.get(); + if( !rZSlot.empty() ) + { + 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(&( 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 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(fUnscaledXgetLogicMinX() || 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 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 ) ); + + uno::Reference< drawing::XShapes > xLossGainTarget( xGainTarget ); + if(bBlack) + xLossGainTarget = xLossTarget; + + uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint( nIndex )); + uno::Reference< drawing::XShapes > xPointGroupShape_Shapes; + { + OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex ); + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) ); + xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID); + } + + //create min-max line + if( isValidPosition(aPosMiddleMinimum) && isValidPosition(aPosMiddleMaximum) ) + { + drawing::PolyPolygonShape3D aPoly; + sal_Int32 nLineIndex =0; + AddPointToPoly( aPoly, aPosMiddleMinimum, nLineIndex); + AddPointToPoly( aPoly, aPosMiddleMaximum, nLineIndex); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createLine2D( xPointGroupShape_Shapes, + PolyToPointSequence(aPoly)); + 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; + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createRectangle( xLossGainTarget, + aAWTSize, Position3DToAWTPoint( aPosLeftFirst ), + aNames, aValues); + + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if(xProp.is()) + { + if(bBlack) + PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, xProp ); + else + PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, xProp ); + } + } + else + { + drawing::PolyPolygonShape3D 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.SequenceX.hasElements() ) + { + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createLine2D( xPointGroupShape_Shapes, + PolyToPointSequence(aPoly) ); + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if(xProp.is()) + { + 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 000000000..2d2891318 --- /dev/null +++ b/chart2/source/view/charttypes/CandleStickChart.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CANDLESTICKCHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CANDLESTICKCHART_HXX + +#include +#include + +namespace chart +{ +class BarPositionHelper; + +class CandleStickChart : public VSeriesPlotter +{ + // public methods +public: + CandleStickChart() = delete; + + CandleStickChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount ); + virtual ~CandleStickChart() override; + + virtual void createShapes() override; + virtual void addSeries( std::unique_ptr 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 m_pMainPosHelper; +}; +} //namespace chart +#endif + +/* 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 000000000..d7412d3cb --- /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 000000000..2fd0d3d0a --- /dev/null +++ b/chart2/source/view/charttypes/CategoryPositionHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CATEGORYPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CATEGORYPOSITIONHELPER_HXX + +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 +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/ConfigAccess.cxx b/chart2/source/view/charttypes/ConfigAccess.cxx new file mode 100644 index 000000000..964e58ce4 --- /dev/null +++ b/chart2/source/view/charttypes/ConfigAccess.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 + +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +namespace +{ +class ChartConfigItem : public ::utl::ConfigItem +{ +private: + virtual void ImplCommit() override; + +public: + ChartConfigItem(); + + bool getUseErrorRectangle(); + virtual void Notify(const uno::Sequence& aPropertyNames) override; +}; +} + +ChartConfigItem::ChartConfigItem() + : ConfigItem("Office.Chart/ErrorProperties") +{ +} + +void ChartConfigItem::ImplCommit() {} +void ChartConfigItem::Notify(const uno::Sequence&) {} + +bool ChartConfigItem::getUseErrorRectangle() +{ + uno::Sequence aNames(1); + aNames[0] = "ErrorRectangle"; + + auto b = o3tl::tryAccess(GetProperties(aNames)[0]); + return b && *b; +} + +namespace +{ +//a ChartConfigItem Singleton +struct theChartConfigItem : public rtl::Static +{ +}; +} + +namespace ConfigAccess +{ +bool getUseErrorRectangle() +{ + bool bResult(theChartConfigItem::get().getUseErrorRectangle()); + return bResult; +} +} //namespace ConfigAccess + +} //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 000000000..a8a0f776d --- /dev/null +++ b/chart2/source/view/charttypes/NetChart.cxx @@ -0,0 +1,643 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +NetChart::NetChart( const uno::Reference& xChartTypeModel + , sal_Int32 nDimensionCount + , bool bNoArea + , std::unique_ptr 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 + , drawing::PolyPolygonShape3D* pSeriesPoly + , PlottingPositionHelper const * pPosHelper ) +{ + //return true if a line was created successfully + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + + drawing::PolyPolygonShape3D 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() ); + drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly); + drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]); + // add connector line to last polygon + AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->SequenceX.getLength() - 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: + uno::Reference< drawing::XShape > xShape; + { + xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes + , PolyToPointSequence( aPoly ) ); + 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 + , drawing::PolyPolygonShape3D* pSeriesPoly + , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , PlottingPositionHelper const * pPosHelper ) +{ + //return true if an area was created successfully + + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + double zValue = pSeries->m_fLogicZPos; + + drawing::PolyPolygonShape3D 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(fMaxXgetLogicMinX() || 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 + { + drawing::PolyPolygonShape3D 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: + uno::Reference< drawing::XShape > + xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes + , aPoly ); + 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, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex + drawing::PolyPolygonShape3D* pSeriesPoly = nullptr; + + //iterate through all series + for( std::unique_ptr 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() + { + ::rtl::math::setNan( &m_fX ); + ::rtl::math::setNan( &m_fY ); + ::rtl::math::setNan( &m_fZ ); + } + + 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_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"NetChart is not proper initialized"); + if(!(m_pShapeFactory&&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 = m_pShapeFactory->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 const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + + if (bDateCategory) + pSeries->doSortByXValues(); + + sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); + if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() ) + aLogicYSumMap[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 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; + + uno::Reference< drawing::XShapes > 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 ) + { + drawing::PolyPolygonShape3D& rPolygon = pSeries->m_aPolyPolygonShape3D; + sal_Int32& rIndex = pSeries->m_nPolygonIndex; + if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() ) + { + if( rPolygon.SequenceX[ rIndex ].hasElements() ) + 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||fLogicXm_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 ); + uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); + uno::Reference xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); + + { + //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; + m_pShapeFactory->createSymbol2D( + xPointGroupShape_Shapes, aScenePosition, aSymbolSize, nSymbol, + pSymbolProperties->BorderColor, pSymbolProperties->FillColor); + } + else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC) + { + m_pShapeFactory->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(m_pPosHelper); + if( pPolarPosHelper ) + { + PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory); + aScreenPosition2D = aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues( + eAlignment, fLogicX, fLogicY, fLogicZ, nOffset ); + } + } + else + { + if(eAlignment==LABEL_ALIGN_CENTER ) + nOffset = 0; + aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory) + .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_Shape); + + }//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 000000000..2d948d2e2 --- /dev/null +++ b/chart2/source/view/charttypes/NetChart.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_NETCHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_NETCHART_HXX + +#include +#include + +namespace chart +{ + +class NetChart : public VSeriesPlotter +{ + // public methods +public: + NetChart() = delete; + + NetChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount + , bool bNoArea + , std::unique_ptr 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 + , css::drawing::PolyPolygonShape3D* pSeriesPoly + , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , PlottingPositionHelper const * pPosHelper ); + bool impl_createLine( VDataSeries* pSeries + , css::drawing::PolyPolygonShape3D* pSeriesPoly + , PlottingPositionHelper const * pPosHelper ); + +private: //member + std::unique_ptr m_pMainPosHelper; + + bool m_bArea;//false -> line or symbol only + bool m_bLine; + + css::uno::Reference< css::drawing::XShapes > m_xSeriesTarget; + css::uno::Reference< css::drawing::XShapes > m_xTextTarget; +}; +} //namespace chart +#endif + +/* 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 000000000..5ab60729c --- /dev/null +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -0,0 +1,1621 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "PieChart.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +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) {} +}; + +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 uno::Reference& 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) +{ + ::rtl::math::setNan(&m_fMaxOffset); + + PlotterBase::m_pPosHelper = m_pPosHelper.get(); + VSeriesPlotter::m_pMainPosHelper = m_pPosHelper.get(); + m_pPosHelper->m_fRadiusOffset = 0.0; + m_pPosHelper->m_fRingDistance = 0.0; + + uno::Reference< beans::XPropertySet > xChartTypeProps( xChartTypeModel, uno::UNO_QUERY ); + if( !xChartTypeProps.is() ) + return; + + try + { + xChartTypeProps->getPropertyValue( "UseRings") >>= m_bUseRings; + 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( const std::vector< ExplicitScaleData >& rScales, bool /* bSwapXAndYAxis */ ) +{ + OSL_ENSURE(m_nDimension<=static_cast(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence"); + m_pPosHelper->setScales( 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; +} + +uno::Reference< drawing::XShape > PieChart::createDataPoint( + const uno::Reference& xTarget, + const uno::Reference& xObjectProperties, + tPropertyNameValueMap const * pOverwritePropertiesMap, + const ShapeParam& rParam ) +{ + //transform position: + drawing::Direction3D aOffset; + if (rParam.mfExplodePercentage != 0.0) + { + double fAngle = rParam.mfUnitCircleStartAngleDegree + rParam.mfUnitCircleWidthAngleDegree/2.0; + double fRadius = (rParam.mfUnitCircleOuterRadius-rParam.mfUnitCircleInnerRadius)*rParam.mfExplodePercentage; + 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 + uno::Reference< drawing::XShape > xShape; + if(m_nDimension==3) + { + xShape = m_pShapeFactory->createPieSegment( xTarget + , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree + , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius + , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) + , rParam.mfDepth ); + } + else + { + xShape = m_pShapeFactory->createPieSegment2D( xTarget + , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree + , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius + , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) ); + } + setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), pOverwritePropertiesMap ); + return xShape; +} + +void PieChart::createTextLabelShape( + const uno::Reference& 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 ); + 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,m_pShapeFactory); + 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_pShapeFactory, m_nDimension ); + basegfx::B2IVector aRadiusVector( + aOuterCirclePoint.X - aPieLabelInfo.aOrigin.getX(), + aOuterCirclePoint.Y - aPieLabelInfo.aOrigin.getY() ); + double fSquaredPieRadius = aRadiusVector.scalar(aRadiusVector); + double fPieRadius = sqrt( fSquaredPieRadius ); + + // set the maximum text width to be used when text wrapping is enabled + double fTextMaximumFrameWidth = 0.8 * 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; + uno::Reference< container::XChild > xChild( aPieLabelInfo.xTextShape, uno::UNO_QUERY ); + + ///text shape could be empty; in that case there is no need to add label info + if( !xChild.is() ) + return; + + aPieLabelInfo.xLabelGroupShape.set( xChild->getParent(), uno::UNO_QUERY ); + + aPieLabelInfo.fValue = nVal; + aPieLabelInfo.bMovementAllowed = bMovementAllowed; + aPieLabelInfo.bMoved= false; + aPieLabelInfo.xTextTarget = xTextTarget; + + if (bMovementAllowed) + { + performLabelBestFit(rParam, aPieLabelInfo); + } + + m_aLabelInfoList.push_back(aPieLabelInfo); +} + +void PieChart::addSeries( std::unique_ptr 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 >& rSeriesList( m_aZSlots.front().front().m_aSeriesVector ); + if(rSeriesList.empty()) + return m_fMaxOffset; + + VDataSeries* pSeries = rSeriesList.front().get(); + uno::Reference< beans::XPropertySet > xSeriesProp( pSeries->getPropertiesOfSeries() ); + if( !xSeriesProp.is() ) + return m_fMaxOffset; + + double fExplodePercentage=0.0; + xSeriesProp->getPropertyValue( "Offset") >>= fExplodePercentage; + if(fExplodePercentage>m_fMaxOffset) + m_fMaxOffset=fExplodePercentage; + + if(!m_bSizeExcludesLabelsAndExplodedSegments) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= 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_pShapeFactory && m_xLogicTarget.is() && m_xFinalTarget.is(), "PieChart is not properly initialized."); + if (!m_pShapeFactory || !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) + uno::Reference< drawing::XShapes > xSeriesTarget( + createGroupShape( m_xLogicTarget )); + uno::Reference< drawing::XShapes > xTextTarget( + m_pShapeFactory->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(); + ::rtl::math::setNan(&m_fMaxOffset); + sal_Int32 n3DRelativeHeight = 100; + uno::Reference< beans::XPropertySet > xPropertySet( m_xChartTypeModel, uno::UNO_QUERY ); + if ( (m_nDimension==3) && xPropertySet.is()) + { + try + { + uno::Any aAny = xPropertySet->getPropertyValue( "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 >* 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); + + uno::Reference< drawing::XShapes > 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 ); + + ///point color: + std::unique_ptr< tPropertyNameValueMap > apOverwritePropertiesMap; + if (!pSeries->hasPointOwnColor(nPointIndex) && m_xColorScheme.is()) + { + apOverwritePropertiesMap.reset( new tPropertyNameValueMap ); + (*apOverwritePropertiesMap)["FillColor"] <<= + m_xColorScheme->getColorByIndex( nPointIndex ); + } + + ///create data point + aParam.mfLogicZ = -1.0; // For 3D pie chart label position + uno::Reference xPointShape = + createDataPoint( + xSeriesGroupShape_Shapes, xPointProperties, apOverwritePropertiesMap.get(), aParam); + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor"); + if(!std::isnan(nPropVal)) + { + uno::Reference< beans::XPropertySet > xProps( xPointShape, uno::UNO_QUERY_THROW ); + xProps->setPropertyValue("FillColor", uno::Any(static_cast( 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(aParam.mfExplodePercentage * 100.0) ); + + awt::Point aMinimumPosition( PlottingPositionHelper::transformSceneToScreenPosition( + aOrigin, m_xLogicTarget, m_pShapeFactory, m_nDimension ) ); + awt::Point aMaximumPosition( PlottingPositionHelper::transformSceneToScreenPosition( + aNewOrigin, m_xLogicTarget, m_pShapeFactory, 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 +} + +namespace +{ + +::basegfx::B2IRectangle lcl_getRect( const uno::Reference< drawing::XShape >& 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 + +PieChart::PieLabelInfo::PieLabelInfo() + : aFirstPosition(), aOrigin(), fValue(0.0) + , bMovementAllowed(false), bMoved(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() ) + { + //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(aOverlap.getWidth()) : static_cast(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 = sqrt( double(rPageSize.Width)*double(rPageSize.Width) + double(rPageSize.Height)*double(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 ) + { + sal_Int32 nX1 = labelInfo.aFirstPosition.getX(); + sal_Int32 nY1 = labelInfo.aFirstPosition.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(1); + aPoints[0].realloc(2); + aPoints[0][0].X = nX1; + aPoints[0][0].Y = nY1; + aPoints[0][1].X = nX2; + aPoints[0][1].Y = nY2; + + uno::Reference< beans::XPropertySet > xProp( labelInfo.xTextShape, uno::UNO_QUERY); + if( xProp.is() ) + { + sal_Int32 nColor = 0; + xProp->getPropertyValue("CharColor") >>= nColor; + if( nColor != -1 )//automatic font color does not work for lines -> fallback to black + aVLineProperties.Color <<= nColor; + } + m_pShapeFactory->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_pShapeFactory, 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 fSquaredDistancePF = fDistancePM * fDistancePM + fOrthogonalEdgeLength * fOrthogonalEdgeLength; + double fDistancePF = sqrt( fSquaredDistancePF ); + + 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; +} + +/** 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. + */ +void PieChart::performLabelBestFit(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo) +{ + if( m_bUseRings ) + return; + + if( performLabelBestFitInnerPlacement(rShapeParam, rPieLabelInfo) ) + return; + + // If it does not fit inside, let's put it outside + awt::Point aOldPos(rPieLabelInfo.xLabelGroupShape->getPosition()); + basegfx::B2IVector aTranslationVector = rPieLabelInfo.aFirstPosition - rPieLabelInfo.aOrigin; + awt::Point aScreenPosition2D(aOldPos.X + aTranslationVector.getX(), + aOldPos.Y + aTranslationVector.getY()); + + double fAngleDegree = rShapeParam.mfUnitCircleStartAngleDegree + rShapeParam.mfUnitCircleWidthAngleDegree / 2.0; + ::basegfx::B2IRectangle aBb(lcl_getRect(rPieLabelInfo.xLabelGroupShape)); + double fLabelWidth = aBb.getWidth(); + double fLabelHeight = aBb.getHeight(); + + while (fAngleDegree > 360.0) + fAngleDegree -= 360.0; + while (fAngleDegree < 0.0) + fAngleDegree += 360.0; + + if (fAngleDegree <= 22.5 || fAngleDegree >= 337.5) + aScreenPosition2D.X += fLabelWidth / 2; + else if (fAngleDegree < 67.5) + { + aScreenPosition2D.X += fLabelWidth / 2; + aScreenPosition2D.Y -= fLabelHeight / 2; + } + else if (fAngleDegree < 112.5) + aScreenPosition2D.Y -= fLabelHeight / 2; + else if (fAngleDegree <= 157.5) + { + aScreenPosition2D.X -= fLabelWidth / 2; + aScreenPosition2D.Y -= fLabelHeight / 2; + } + else if (fAngleDegree <= 202.5) + aScreenPosition2D.X -= fLabelWidth / 2; + else if (fAngleDegree < 247.5) + { + aScreenPosition2D.X -= fLabelWidth / 2; + aScreenPosition2D.Y += fLabelHeight / 2; + } + else if (fAngleDegree < 292.5) + aScreenPosition2D.Y += fLabelHeight / 2; + else + { + aScreenPosition2D.X += fLabelWidth / 2; + aScreenPosition2D.Y += fLabelHeight / 2; + } + + rPieLabelInfo.xLabelGroupShape->setPosition(aScreenPosition2D); +} + +} //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 000000000..a176adaaf --- /dev/null +++ b/chart2/source/view/charttypes/PieChart.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_PIECHART_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_PIECHART_HXX + +#include +#include +#include +#include + +namespace chart +{ +class PiePositionHelper; + +class PieChart : public VSeriesPlotter +{ + struct ShapeParam; + +public: + PieChart() = delete; + + PieChart( const css::uno::Reference< css::chart2::XChartType >& 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( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) override; + virtual void addSeries( std::unique_ptr 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 + css::uno::Reference + createDataPoint( + const css::uno::Reference& xTarget, + const css::uno::Reference& xObjectProperties, + tPropertyNameValueMap const * pOverWritePropertiesMap, + const ShapeParam& rParam ); + + /** 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 css::uno::Reference& 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); + void performLabelBestFit(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo); + +private: //member + std::unique_ptr + 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 ); + + css::uno::Reference< css::drawing::XShape > xTextShape; + css::uno::Reference< css::drawing::XShape > xLabelGroupShape; + ::basegfx::B2IVector aFirstPosition; + ::basegfx::B2IVector aOrigin; + double fValue; + bool bMovementAllowed; + bool bMoved; + css::uno::Reference< css::drawing::XShapes > 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 +#endif + +/* 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 000000000..5d5a02228 --- /dev/null +++ b/chart2/source/view/charttypes/Splines.cxx @@ -0,0 +1,931 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include + +#include +#include +#include + +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( const 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( const 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( + const tPointVecType & rSortedPoints, + double fY1FirstDerivation, + double fYnFirstDerivation ) + : m_aPoints( rSortedPoints ), + m_fYp1( fY1FirstDerivation ), + m_fYpN( fYnFirstDerivation ), + m_nKLow( 0 ), + m_nKHigh( rSortedPoints.size() - 1 ), + m_fLastInterpolatedValue(0.0) +{ + ::rtl::math::setInf( &m_fLastInterpolatedValue, false ); + Calculate(); +} + +lcl_SplineCalculation::lcl_SplineCalculation( + const tPointVecType & rSortedPoints) + : m_aPoints( rSortedPoints ), + m_fYp1( 0.0 ), /*dummy*/ + m_fYpN( 0.0 ), /*dummy*/ + m_nKLow( 0 ), + m_nKHigh( rSortedPoints.size() - 1 ), + m_fLastInterpolatedValue(0.0) +{ + ::rtl::math::setInf( &m_fLastInterpolatedValue, false ); + 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=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 dx = 0.0; + double dy = 0.0; + double fDiffMax = 1.0; //dummy values + double fDenominator = 0.0; // initialized for summing up + for (lcl_tSizeType i=1; i<=n ; ++i) + { // 4th root(dx^2+dy^2) + dx = rUniquePoints[i].first - rUniquePoints[i-1].first; + dy = rUniquePoints[i].second - rUniquePoints[i-1].second; + // scaling to avoid underflow or overflow + fDiffMax = std::max(fabs(dx), fabs(dy)); + if (fDiffMax == 0.0) + { + bIsSuccessful = false; + break; + } + else + { + dx /= fDiffMax; + dy /= fDiffMax; + fDenominator += sqrt(sqrt(dx * dx + dy * dy)) * sqrt(fDiffMax); + } + } + 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) + { + dx = rUniquePoints[i].first - rUniquePoints[i-1].first; + dy = rUniquePoints[i].second - rUniquePoints[i-1].second; + fDiffMax = std::max(fabs(dx), fabs(dy)); + // same as above, so should not be zero + dx /= fDiffMax; + dy /= fDiffMax; + fNumerator += sqrt(sqrt(dx * dx + dy * dy)) * sqrt(fDiffMax); + } + 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 drawing::PolyPolygonShape3D& rInput + , drawing::PolyPolygonShape3D& rResult + , sal_uInt32 nGranularity ) +{ + OSL_PRECOND( nGranularity > 0, "Granularity is invalid" ); + + sal_uInt32 nOuterCount = rInput.SequenceX.getLength(); + + rResult.SequenceX.realloc(nOuterCount); + rResult.SequenceY.realloc(nOuterCount); + rResult.SequenceZ.realloc(nOuterCount); + + if( !nOuterCount ) + return; + + for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) + { + if( rInput.SequenceX[nOuter].getLength() <= 1 ) + continue; //we need at least two points + + sal_uInt32 nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1 + const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); + const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); + const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); + + 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=pOldX[ nN ]; + aInputY[ nN ].first=aParameter[nN]; + aInputY[ nN ].second=pOldY[ nN ]; + aInputZ[ nN ].first=aParameter[nN]; + aInputZ[ nN ].second=pOldZ[ nN ]; + } + + // generate a spline for each coordinate. It holds the complete + // information to calculate each point of the curve + std::unique_ptr aSplineX; + std::unique_ptr 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( pOldX[ 0 ] == pOldX[nMaxIndexPoints] && + pOldY[ 0 ] == pOldY[nMaxIndexPoints] && + pOldZ[ 0 ] == pOldZ[nMaxIndexPoints] && + nMaxIndexPoints >=2 ) + { // periodic spline + aSplineX.reset(new lcl_SplineCalculation( aInputX)); + aSplineY.reset(new lcl_SplineCalculation( aInputY)); + // aSplineZ = new lcl_SplineCalculation( aInputZ) ; + } + else // generate the kind "natural spline" + { + double fInfty; + ::rtl::math::setInf( &fInfty, false ); + double fXDerivation = fInfty; + double fYDerivation = fInfty; + aSplineX.reset(new lcl_SplineCalculation( aInputX, fXDerivation, fXDerivation )); + aSplineY.reset(new lcl_SplineCalculation( aInputY, fYDerivation, fYDerivation )); + } + + // fill result polygon with calculated values + rResult.SequenceX[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + rResult.SequenceY[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + rResult.SequenceZ[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + + double* pNewX = rResult.SequenceX[nOuter].getArray(); + double* pNewY = rResult.SequenceY[nOuter].getArray(); + double* pNewZ = rResult.SequenceZ[nOuter].getArray(); + + sal_uInt32 nNewPointIndex = 0; // Index in result points + + for( sal_uInt32 ni = 0; ni < nMaxIndexPoints; ni++ ) + { + // given point is surely a curve point + pNewX[nNewPointIndex] = pOldX[ni]; + pNewY[nNewPointIndex] = pOldY[ni]; + pNewZ[nNewPointIndex] = pOldZ[ni]; + 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 ) ); + + pNewX[nNewPointIndex]=aSplineX->GetInterpolatedValue( fParam ); + pNewY[nNewPointIndex]=aSplineY->GetInterpolatedValue( fParam ); + // pNewZ[nNewPointIndex]=aSplineZ->GetInterpolatedValue( fParam ); + pNewZ[nNewPointIndex] = pOldZ[ni]; + nNewPointIndex++; + } + } + // add last point + pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints]; + pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints]; + pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints]; + } +} + +// The implementation follows closely ODF1.2 spec, chapter chart:interpolation +// using the same names as in spec as far as possible, without prefix. +// More details can be found on +// Dr. C.-K. Shene: CS3621 Introduction to Computing with Geometry Notes +// Unit 9: Interpolation and Approximation/Curve Global Interpolation +// Department of Computer Science, Michigan Technological University +// http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/ +// [last called 2011-05-20] +void SplineCalculater::CalculateBSplines( + const css::drawing::PolyPolygonShape3D& rInput + , css::drawing::PolyPolygonShape3D& 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(nDegree, 15); + + sal_Int32 nOuterCount = rInput.SequenceX.getLength(); + + rResult.SequenceX.realloc(nOuterCount); + rResult.SequenceY.realloc(nOuterCount); + rResult.SequenceZ.realloc(nOuterCount); + + if( !nOuterCount ) + return; // no input + + for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) + { + if( rInput.SequenceX[nOuter].getLength() <= 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.SequenceX[nOuter].getLength()-1; // is >=1 + const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); + const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); + const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); + double fZCoordinate = pOldZ[0]; + tPointVecType aPointsIn; + aPointsIn.resize(nMaxIndexPoints+1); + for (lcl_tSizeType i = 0; i <= nMaxIndexPoints; ++i ) + { + aPointsIn[ i ].first = pOldX[i]; + aPointsIn[ i ].second = pOldY[i]; + } + 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::unique_ptr t(new double [n+1]); + if (!createParameterT(aPointsIn, t.get())) + { + continue; // next piece of series + } + + lcl_tSizeType m = n + p + 1; + std::unique_ptr u(new double [m+1]); + createKnotVector(n, p, t.get(), u.get()); + + // 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::unique_ptr aMatN(new double*[n+1]); + for (lcl_tSizeType row = 0; row <=n; ++row) + { + aMatN[row] = new double[p+1]; + for (sal_uInt32 col = 0; col <= p; ++col) + aMatN[row][col] = 0.0; + } + std::unique_ptr aShift(new lcl_tSizeType[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= 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 aP(new double[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]; + } + } + pNewX[nNewIndex] = 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]; + } + } + pNewY[nNewIndex] = aP[nLow]; + pNewZ[nNewIndex] = fZCoordinate; + } + } + } + for (lcl_tSizeType row = 0; row <=n; ++row) + { + delete[] aMatN[row]; + } + } // 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 000000000..af0d82ea7 --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_SPLINES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_SPLINES_HXX + +#include + +namespace com::sun::star::drawing { struct PolyPolygonShape3D; } + +namespace chart +{ + +class SplineCalculater +{ +public: + static void CalculateCubicSplines( + const css::drawing::PolyPolygonShape3D& rPoints + , css::drawing::PolyPolygonShape3D& rResult + , sal_uInt32 nGranularity ); + + static void CalculateBSplines( + const css::drawing::PolyPolygonShape3D& rPoints + , css::drawing::PolyPolygonShape3D& rResult + , sal_uInt32 nGranularity + , sal_uInt32 nSplineDepth ); +}; + +} //namespace chart +#endif + +/* 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 000000000..bbc1788ec --- /dev/null +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -0,0 +1,2865 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace chart { + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart; +using namespace ::com::sun::star::chart2; +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 pSeries ) + : m_aSeriesVector(1) + , m_bMaxPointCountDirty(true) + , m_nMaxPointCount(0) + , m_aListOfCachedYValues() +{ + 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 pSeries ) +{ + m_aSeriesVector.push_back(std::move(pSeries)); + m_bMaxPointCountDirty=true; +} + +sal_Int32 VDataSeriesGroup::getSeriesCount() const +{ + return m_aSeriesVector.size(); +} + +VSeriesPlotter::VSeriesPlotter( const uno::Reference& xChartTypeModel + , sal_Int32 nDimensionCount, bool bCategoryXAxis ) + : PlotterBase( nDimensionCount ) + , m_pMainPosHelper( nullptr ) + , m_xChartTypeModel(xChartTypeModel) + , m_xChartTypeModelProps( uno::Reference< beans::XPropertySet >::query( xChartTypeModel )) + , m_aZSlots() + , m_bCategoryXAxis(bCategoryXAxis) + , m_nTimeResolution(css::chart::TimeUnit::DAY) + , m_aNullDate(30,12,1899) + , m_xColorScheme() + , m_pExplicitCategoriesProvider(nullptr) + , m_bPointsWereSkipped(false) + , m_bPieLabelsAllowToMove(false) +{ + 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 & 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 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 || zSlot>=static_cast(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 || xSlot>=static_cast(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 const & rGroupVector : m_aZSlots) + { + for (VDataSeriesGroup const & rGroup : rGroupVector) + { + //iterate through all series in this x slot + for (std::unique_ptr const & pSeries : rGroup.m_aSeriesVector) + { + pSeries->releaseShapes(); + } + } + } +} + +uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries + , const uno::Reference< drawing::XShapes >& xTarget ) +{ + uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xGroupShape ); + if( !xShapes.is() ) + { + //create a group shape for this series and add to logic target: + xShapes = createGroupShape( xTarget,pDataSeries->getCID() ); + pDataSeries->m_xGroupShape = xShapes; + } + return xShapes; +} + +uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries + , const uno::Reference< drawing::XShapes >& xTarget ) +{ + uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xFrontSubGroupShape ); + if(!xShapes.is()) + { + //ensure that the series group shape is already created + uno::Reference< drawing::XShapes > 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 + xShapes = createGroupShape( xSeriesShapes ); + pDataSeries->m_xFrontSubGroupShape = xShapes; + } + return xShapes; +} + +uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries + , const uno::Reference< drawing::XShapes >& xTarget ) +{ + uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xBackSubGroupShape ); + if(!xShapes.is()) + { + //ensure that the series group shape is already created + uno::Reference< drawing::XShapes > xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) ); + //use series group shape as parent for the new created back group shape + xShapes = createGroupShape( xSeriesShapes ); + pDataSeries->m_xBackSubGroupShape = xShapes; + } + return xShapes; +} + +uno::Reference< drawing::XShapes > VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries + , const uno::Reference< drawing::XShapes >& xTextTarget ) +{ + //xTextTarget needs to be a 2D shape container always! + + uno::Reference< drawing::XShapes > xShapes( rDataSeries.m_xLabelsGroupShape ); + if(!xShapes.is()) + { + //create a 2D group shape for texts of this series and add to text target: + xShapes = m_pShapeFactory->createGroup2D( xTextTarget, rDataSeries.getLabelsCID() ); + rDataSeries.m_xLabelsGroupShape = xShapes; + } + return xShapes; +} + +uno::Reference< drawing::XShapes > VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries + , const uno::Reference< drawing::XShapes >& xTarget + , bool bYError ) +{ + uno::Reference< css::drawing::XShapes > &rShapeGroup = + bYError ? rDataSeries.m_xErrorYBarsGroupShape : rDataSeries.m_xErrorXBarsGroupShape; + + uno::Reference< drawing::XShapes > xShapes( rShapeGroup ); + if(!xShapes.is()) + { + //create a group shape for this series and add to logic target: + xShapes = createGroupShape( xTarget,rDataSeries.getErrorBarsCID(bYError) ); + rShapeGroup = xShapes; + } + return xShapes; + +} + +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; +} + +uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Reference< drawing::XShapes >& xTarget + , VDataSeries& rDataSeries + , sal_Int32 nPointIndex + , double fValue + , double fSumValue + , const awt::Point& rScreenPosition2D + , LabelAlignment eAlignment + , sal_Int32 nOffset + , sal_Int32 nTextWidth ) +{ + uno::Reference< drawing::XShape > xTextShape; + Sequence> 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; + + uno::Reference< drawing::XShapes > xTarget_ = + m_pShapeFactory->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; + // pt -> 1/100th mm + fViewFontSize *= (2540.0f / 72.0f); + } + + // the font height is used for computing the size of an optional legend + // symbol to be prepended to the text label. + Reference< drawing::XShape > 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.set( VSeriesPlotter::createLegendSymbolForPoint( aMaxSymbolExtent, rDataSeries, nPointIndex, xTarget_, m_xShapeFactory ) ); + else + xSymbol.set( VSeriesPlotter::createLegendSymbolForSeries( aMaxSymbolExtent, rDataSeries, xTarget_, m_xShapeFactory ) ); + } + + //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 = 3; + 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 ); + for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i ) + { + switch( aCustomLabels[i]->getFieldType() ) + { + case DataPointCustomLabelFieldType_VALUE: + { + aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false ); + break; + } + case DataPointCustomLabelFieldType_CATEGORYNAME: + { + aTextList[i] = getCategoryName( nPointIndex ); + break; + } + case DataPointCustomLabelFieldType_SERIESNAME: + { + OUString aRole; + if ( m_xChartTypeModel ) + aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); + const uno::Reference< XDataSeries >& xSeries( rDataSeries.getModel() ); + aTextList[i] = DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ); + break; + } + case DataPointCustomLabelFieldType_PERCENTAGE: + { + aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, true ); + break; + } + case DataPointCustomLabelFieldType_CELLREF: + { + // TODO: for now doesn't show placeholder + aTextList[i] = OUString(); + break; + } + case DataPointCustomLabelFieldType_TEXT: + { + aTextList[i] = aCustomLabels[i]->getString(); + break; + } + case DataPointCustomLabelFieldType_NEWLINE: + { + aTextList[i] = "\n"; + break; + } + default: + break; + } + aCustomLabels[i]->setString( aTextList[i] ); + } + } + else + { + if( pLabel->ShowCategoryName ) + { + aTextList[0] = getCategoryName( nPointIndex ); + } + + if( pLabel->ShowNumber ) + { + aTextList[1] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false); + } + + if( pLabel->ShowNumberInPercent ) + { + if(fSumValue==0.0) + fSumValue=1.0; + fValue /= fSumValue; + if( fValue < 0 ) + fValue*=-1.0; + + aTextList[2] = 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( aCustomLabels.getLength() ); + for( int i = 0; i < aFormattedLabels.getLength(); i++ ) + { + aFormattedLabels[i] = aCustomLabels[i]; + } + + // center the text + sal_uInt32 nProperties = pPropNames->getLength(); + pPropNames->realloc( nProperties + 1 ); + pPropValues->realloc( nProperties + 1 ); + (*pPropNames)[ nProperties ] = UNO_NAME_EDIT_PARA_ADJUST; + (*pPropValues)[ nProperties ] <<= style::ParagraphAdjust_CENTER; + + // create text shape + xTextShape = ShapeFactory::getOrCreateShapeFactory( m_xShapeFactory )-> + createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues, + ShapeFactory::makeTransformation( aScreenPosition2D ) ); + } + else if( bMultiLineLabel ) + { + // prepare properties for each paragraph + // we want to have the value and percent value centered respect + // with the category name + Sequence< tNameSequence > aParaPropNames(3); + aParaPropNames[1].realloc(1); + aParaPropNames[1][0] = "ParaAdjust"; + aParaPropNames[2].realloc(1); + aParaPropNames[2][0] = "ParaAdjust"; + + Sequence< tAnySequence > aParaPropValues(3); + aParaPropValues[1].realloc(1); + aParaPropValues[1][0] <<= style::ParagraphAdjust_CENTER; + aParaPropValues[2].realloc(1); + aParaPropValues[2][0] <<= style::ParagraphAdjust_CENTER; + + //create text shape + xTextShape = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)-> + createText( xTarget_, aTextList, aParaPropNames, aParaPropValues + , *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::getOrCreateShapeFactory(m_xShapeFactory)-> + 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 ) + { + uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY ); + if( xProp.is() ) + { + // 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 ); + xProp->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) ); + uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY ); + if( xProp.is() ) + xProp->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) ) + { + 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 = sqrt(double(m_aPageReferenceSize.Width)*double(m_aPageReferenceSize.Width) + double(m_aPageReferenceSize.Height)*double(m_aPageReferenceSize.Height)); + if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01) + { + drawing::PointSequenceSequence aPoints(1); + aPoints[0].realloc(2); + aPoints[0][0].X = nX1; + aPoints[0][0].Y = nY1; + aPoints[0][1].X = nX2; + aPoints[0][1].Y = nY2; + + VLineProperties aVLineProperties; + m_pShapeFactory->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; + ::rtl::math::setNan( & fResult ); + 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; + ::rtl::math::setInf(&fMaxValue, true); + 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 + , drawing::PolyPolygonShape3D& 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 uno::Reference< drawing::XShapes >& 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 ); + } + bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ); + } + else + bShowNegative = false; + } + + if(!bShowPositive && !bShowNegative) + return; + + drawing::PolyPolygonShape3D 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 ); + } + + uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( xTarget, PolyToPointSequence( aPoly) ); + 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 uno::Reference< drawing::XShapes >& rTarget + ,const uno::Reference< beans::XPropertySet >& rErrorBorderProp ) +{ + drawing::PolyPolygonShape3D aPoly; + sal_Int32 nSequenceIndex = 0; + AddPointToPoly( aPoly, rPos0, nSequenceIndex ); + AddPointToPoly( aPoly, rPos1, nSequenceIndex ); + uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + rTarget, PolyToPointSequence( aPoly) ); + setMappedProperties( xShape, rErrorBorderProp, + PropertyMapper::getPropertyNameMapForLineProperties() ); +} + +void VSeriesPlotter::createErrorRectangle( + const drawing::Position3D& rUnscaledLogicPosition + ,VDataSeries& rVDataSeries + ,sal_Int32 nIndex + ,const uno::Reference< drawing::XShapes >& 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; + } + uno::Reference< drawing::XShapes > xErrorBorder_ShapesX( + getErrorBarsGroupShape( rVDataSeries, rTarget, false ) ); + + if ( bUseYErrorData ) + { + xErrorBorderPropY = rVDataSeries.getYErrorBarProperties( nIndex ); + if ( !xErrorBorderPropY.is() ) + return; + } + uno::Reference< drawing::XShapes > 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 uno::Reference< drawing::XShapes >& xTarget ) +{ + if(m_nDimension!=2) + return; + // error bars + uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getXErrorBarProperties(nPointIndex)); + if( xErrorBarProp.is()) + { + uno::Reference< drawing::XShapes > 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 uno::Reference< drawing::XShapes >& xTarget + , double const * pfScaledLogicX ) +{ + if(m_nDimension!=2) + return; + // error bars + uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getYErrorBarProperties(nPointIndex)); + if( xErrorBarProp.is()) + { + uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes( + getErrorBarsGroupShape(rVDataSeries, xTarget, true) ); + + createErrorBar( xErrorBarsGroup_Shapes + , rUnscaledLogicPosition, xErrorBarProp + , rVDataSeries, nPointIndex + , true /* bYError */ + , pfScaledLogicX ); + } +} + +void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSeries, + const uno::Reference< drawing::XShapes >& xTarget, + const uno::Reference< drawing::XShapes >& xEquationTarget, + bool bMaySkipPoints ) +{ + if(m_nDimension!=2) + return; + uno::Reference< XRegressionCurveContainer > xContainer( rVDataSeries.getModel(), uno::UNO_QUERY ); + if(!xContainer.is()) + return; + + if (!m_pPosHelper) + return; + + uno::Sequence< uno::Reference< XRegressionCurve > > aCurveList = xContainer->getRegressionCurves(); + + for(sal_Int32 nN=0; nN xCalculator( aCurveList[nN]->getCalculator() ); + if( !xCalculator.is()) + continue; + + uno::Reference< beans::XPropertySet > xProperties( aCurveList[nN], uno::UNO_QUERY ); + + bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurveList[nN] ); + + sal_Int32 aDegree = 2; + sal_Int32 aPeriod = 2; + double aExtrapolateForward = 0.0; + double aExtrapolateBackward = 0.0; + bool bForceIntercept = false; + double aInterceptValue = 0.0; + + if ( xProperties.is() && !bAverageLine ) + { + xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree; + xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; + xProperties->getPropertyValue( "ExtrapolateForward") >>= aExtrapolateForward; + xProperties->getPropertyValue( "ExtrapolateBackward") >>= aExtrapolateBackward; + xProperties->getPropertyValue( "ForceIntercept") >>= bForceIntercept; + if (bForceIntercept) + xProperties->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); + 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); + aRegressionPoly.SequenceX[0].realloc(nPointCount); + aRegressionPoly.SequenceY[0].realloc(nPointCount); + aRegressionPoly.SequenceZ[0].realloc(nPointCount); + + 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) ) + { + aRegressionPoly.SequenceX[0][nRealPointCount] = fLogicX; + aRegressionPoly.SequenceY[0][nRealPointCount] = fLogicY; + nRealPointCount++; + } + } + aRegressionPoly.SequenceX[0].realloc(nRealPointCount); + aRegressionPoly.SequenceY[0].realloc(nRealPointCount); + aRegressionPoly.SequenceZ[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( xProperties ); + + //create an extra group shape for each curve for selection handling + uno::Reference< drawing::XShapes > xRegressionGroupShapes = + createGroupShape( xTarget, rVDataSeries.getDataCurveCID( nN, bAverageLine ) ); + uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + xRegressionGroupShapes, PolyToPointSequence( aRegressionPoly ), &aVLineProperties ); + ShapeFactory::setShapeName( xShape, "MarkHandles" ); + aDefaultPos = xShape->getPosition(); + } + + // curve equation and correlation coefficient + uno::Reference< beans::XPropertySet > xEquationProperties( aCurveList[nN]->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 nMaxLineLength ) + nMaxLineLength = nLineLength; + i = indexSep; + } + + return nMaxLineLength; +} + +void VSeriesPlotter::createRegressionCurveEquationShapes( + const OUString & rEquationCID, + const uno::Reference< beans::XPropertySet > & xEquationProperties, + const uno::Reference< drawing::XShapes >& 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" ).append( OUStringChar( aSuperscriptFigures[2] ) ).append( " = " ); + 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 ); + + uno::Reference< drawing::XShape > xTextShape = m_pShapeFactory->createText( + xEquationTarget, aFormula.makeStringAndClear(), + aNames, aValues, ShapeFactory::makeTransformation( aScreenPosition2D )); + + OSL_ASSERT( xTextShape.is()); + if( xTextShape.is()) + { + 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::setMappedProperties( + const uno::Reference< drawing::XShape >& xTargetShape + , const uno::Reference< beans::XPropertySet >& xSource + , const tPropertyNameMap& rMap + , tPropertyNameValueMap const * pOverwriteMap ) +{ + uno::Reference< beans::XPropertySet > xTargetProp( xTargetShape, uno::UNO_QUERY ); + PropertyMapper::setMappedProperties(xTargetProp,xSource,rMap,pOverwriteMap); +} + +void VSeriesPlotter::setTimeResolutionOnXAxis( long TimeResolution, const Date& rNullDate ) +{ + m_nTimeResolution = TimeResolution; + m_aNullDate = rNullDate; +} + +// MinimumAndMaximumSupplier +long VSeriesPlotter::calculateTimeResolutionOnXAxis() +{ + long nRet = css::chart::TimeUnit::YEAR; + if (!m_pExplicitCategoriesProvider) + return nRet; + + const std::vector& rDateCategories = m_pExplicitCategoriesProvider->getDateCategories(); + if (rDateCategories.empty()) + return nRet; + + std::vector::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; + getMinimumAndMaximiumX( fMinimum, fMaximum ); + return fMinimum; +} +double VSeriesPlotter::getMaximumX() +{ + double fMinimum, fMaximum; + getMinimumAndMaximiumX( 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; + getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); + return fMinY; + } + + double fMinimum, fMaximum; + ::rtl::math::setInf(&fMinimum, false); + ::rtl::math::setInf(&fMaximum, true); + for(std::vector & rXSlots : m_aZSlots) + { + for(VDataSeriesGroup & rXSlot : rXSlots) + { + double fLocalMinimum, fLocalMaximum; + rXSlot.calculateYMinAndMaxForCategoryRange( + static_cast(fMinimumX-1.0) //first category (index 0) matches with real number 1.0 + , static_cast(fMaximumX-1.0) //first category (index 0) matches with real number 1.0 + , isSeparateStackingForDifferentSigns( 1 ) + , fLocalMinimum, fLocalMaximum, nAxisIndex ); + if(fMaximumfLocalMinimum) + fMinimum=fLocalMinimum; + } + } + if(std::isinf(fMinimum)) + ::rtl::math::setNan(&fMinimum); + return fMinimum; +} + +double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) +{ + if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) ) + { + double fMinY, fMaxY; + getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); + return fMaxY; + } + + double fMinimum, fMaximum; + ::rtl::math::setInf(&fMinimum, false); + ::rtl::math::setInf(&fMaximum, true); + for( std::vector< VDataSeriesGroup > & rXSlots : m_aZSlots) + { + for(VDataSeriesGroup & rXSlot : rXSlots) + { + double fLocalMinimum, fLocalMaximum; + rXSlot.calculateYMinAndMaxForCategoryRange( + static_cast(fMinimumX-1.0) //first category (index 0) matches with real number 1.0 + , static_cast(fMaximumX-1.0) //first category (index 0) matches with real number 1.0 + , isSeparateStackingForDifferentSigns( 1 ) + , fLocalMinimum, fLocalMaximum, nAxisIndex ); + if(fMaximumfLocalMinimum) + fMinimum=fLocalMinimum; + } + } + if(std::isinf(fMaximum)) + ::rtl::math::setNan(&fMaximum); + 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::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const +{ + ::rtl::math::setInf(&rfMinimum, false); + ::rtl::math::setInf(&rfMaximum, true); + + for (auto const& ZSlot : m_aZSlots) + { + for (auto const& XSlot : ZSlot) + { + double fLocalMinimum, fLocalMaximum; + XSlot.getMinimumAndMaximiumX( fLocalMinimum, fLocalMaximum ); + if( !std::isnan(fLocalMinimum) && fLocalMinimum< rfMinimum ) + rfMinimum = fLocalMinimum; + if( !std::isnan(fLocalMaximum) && fLocalMaximum> rfMaximum ) + rfMaximum = fLocalMaximum; + } + } + if(std::isinf(rfMinimum)) + ::rtl::math::setNan(&rfMinimum); + if(std::isinf(rfMaximum)) + ::rtl::math::setNan(&rfMaximum); +} + +void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const +{ + ::rtl::math::setInf(&rfMinY, false); + ::rtl::math::setInf(&rfMaxY, true); + + for (auto const& ZSlot : m_aZSlots) + { + for (auto const& XSlot : ZSlot) + { + double fLocalMinimum, fLocalMaximum; + XSlot.getMinimumAndMaximiumYInContinuousXRange( 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)) + ::rtl::math::setNan(&rfMinY); + if(std::isinf(rfMaxY)) + ::rtl::math::setNan(&rfMaxY); +} + +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 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::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const +{ + + ::rtl::math::setInf(&rfMinimum, false); + ::rtl::math::setInf(&rfMaximum, true); + + for (std::unique_ptr const & pSeries : m_aSeriesVector) + { + sal_Int32 nPointCount = pSeries->getTotalPointCount(); + for(sal_Int32 nN=0;nNgetXValue( nN ); + if( std::isnan(fX) ) + continue; + if(rfMaximumfX) + rfMinimum=fX; + } + } + if(std::isinf(rfMinimum)) + ::rtl::math::setNan(&rfMinimum); + if(std::isinf(rfMaximum)) + ::rtl::math::setNan(&rfMaximum); +} + +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. + * + *

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.

+ * + *

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.

+ */ +class PerXMinMaxCalculator +{ + typedef std::pair MinMaxType; + typedef std::map SeriesMinMaxType; + typedef std::map> GroupMinMaxType; + typedef std::unordered_map 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 + { + rtl::math::setNan(&rfMin); + rtl::math::setNan(&rfMax); + + TotalStoreType aStore; + getTotalStore(aStore); + + if (aStore.empty()) + 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(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 r = + m_SeriesGroup.insert(std::make_pair(fX, std::make_unique())); + + if (!r.second) + // insertion failed. + return nullptr; + + it = r.first; + } + + return it->second.get(); + } +}; + +} + +void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( + double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const +{ + ::rtl::math::setNan(&rfMinY); + ::rtl::math::setNan(&rfMaxY); + + if (m_aSeriesVector.empty()) + // No data series. Bail out. + return; + + PerXMinMaxCalculator aRangeCalc; + for (const std::unique_ptr & 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 ) +{ + assert(nCategoryIndex >= 0); + assert(nCategoryIndex < getPointCount()); + + ::rtl::math::setInf(&rfMinimumY, false); + ::rtl::math::setInf(&rfMaximumY, true); + + 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, fPositiveSum, fNegativeSum, fFirstPositiveY, fFirstNegativeY; + ::rtl::math::setNan( &fTotalSum ); + ::rtl::math::setNan( &fPositiveSum ); + ::rtl::math::setNan( &fNegativeSum ); + ::rtl::math::setNan( &fFirstPositiveY ); + ::rtl::math::setNan( &fFirstNegativeY ); + + if( bSeparateStackingForDifferentSigns ) + { + for (const std::unique_ptr & 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 & 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 + ::rtl::math::setInf(&rfMinimumY, false); + ::rtl::math::setInf(&rfMaximumY, true); + + //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; ::rtl::math::setNan(&fMinimumY); + double fMaximumY; ::rtl::math::setNan(&fMaximumY); + + 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; + if(pRet) + pRet->setTimeResolution( m_nTimeResolution, m_aNullDate ); + return *pRet; +} + +void VSeriesPlotter::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& /*rPageSize*/ ) +{ +} + +VDataSeries* VSeriesPlotter::getFirstSeries() const +{ + for (std::vector 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(); +} + +uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const +{ + std::vector 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(); + uno::Reference< XDataSeries > xSeries( pSeries ? pSeries->getModel() : nullptr ); + if( xSeries.is() ) + { + OUString aSeriesName( DataSeriesHelper::getDataSeriesLabel( xSeries, 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 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 Reference< drawing::XShapes >& xTarget + , const Reference< lang::XMultiServiceFactory >& xShapeFactory + , const Reference< uno::XComponentContext >& xContext + , ChartModel& rModel + ) +{ + std::vector< ViewLegendEntry > aResult; + + if( xTarget.is() ) + { + uno::Reference< XCoordinateSystemContainer > xCooSysCnt( rModel.getFirstDiagram(), uno::UNO_QUERY ); + Reference< chart2::XCoordinateSystem > xCooSys(xCooSysCnt->getCoordinateSystems()[0]); + Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY ); + bool bSwapXAndY = false; + + if( xProp.is()) try + { + xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; + } + catch( const uno::Exception& ) + { + } + + //iterate through all series + bool bBreak = false; + bool bFirstSeries = true; + + + for (std::vector const & rGroupVector : m_aZSlots) + { + for (VDataSeriesGroup const & rGroup : rGroupVector) + { + for (std::unique_ptr const & pSeries : rGroup.m_aSeriesVector) + { + if (!pSeries) + continue; + + if (!pSeries->getPropertiesOfSeries()->getPropertyValue("ShowLegendEntry").get()) + { + continue; + } + + std::vector aSeriesEntries( + createLegendEntriesForSeries( + rEntryKeyAspectRatio, *pSeries, xTextProperties, + xTarget, xShapeFactory, 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 VSeriesPlotter::getAllSeries() +{ + std::vector aAllSeries; + for (std::vector const & rXSlot : m_aZSlots) + { + for(VDataSeriesGroup const & rGroup : rXSlot) + { + for (std::unique_ptr const & p : rGroup.m_aSeriesVector) + aAllSeries.push_back(p.get()); + } + } + return aAllSeries; +} + +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; + Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY ); + if( xRegrCont.is()) + { + Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves() ); + sal_Int32 i = 0, nCount = aCurves.getLength(); + for( i=0; i( aCurves[i], uno::UNO_QUERY ), 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(); +} + +Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForSeries( + const awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , const Reference< drawing::XShapes >& xTarget + , const Reference< lang::XMultiServiceFactory >& xShapeFactory ) +{ + + 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; + } + Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xTarget, eLegendSymbolStyle, xShapeFactory + , rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol )); + + return xShape; +} + +Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForPoint( + const awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , sal_Int32 nPointIndex + , const Reference< drawing::XShapes >& xTarget + , const Reference< lang::XMultiServiceFactory >& xShapeFactory ) +{ + + 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 ))); + } + } + + Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xTarget, eLegendSymbolStyle, xShapeFactory, xPointSet, ePropType, aExplicitSymbol )); + + return xShape; +} + +std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( + const awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , const Reference< beans::XPropertySet >& xTextProperties + , const Reference< drawing::XShapes >& xTarget + , const Reference< lang::XMultiServiceFactory >& xShapeFactory + , const Reference< uno::XComponentContext >& xContext + ) +{ + std::vector< ViewLegendEntry > aResult; + + if( ! ( xShapeFactory.is() && xTarget.is() && xContext.is() ) ) + return aResult; + + try + { + ViewLegendEntry aEntry; + OUString aLabelText; + bool bVaryColorsByPoint = rSeries.isVaryColorsByPoint(); + if( bVaryColorsByPoint ) + { + Sequence< OUString > aCategoryNames; + if( m_pExplicitCategoriesProvider ) + aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories(); + Sequence deletedLegendEntries; + try + { + rSeries.getPropertiesOfSeries()->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntries; + } + catch (const uno::Exception&) + { + } + for( sal_Int32 nIdx=0; nIdx xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); + + // create the symbol + Reference< drawing::XShape > xShape( createLegendSymbolForPoint( rEntryKeyAspectRatio, + rSeries, nIdx, xSymbolGroup, xShapeFactory ) ); + + // set CID to symbol for selection + if( xShape.is() ) + { + aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); + + 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.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties ); + aResult.push_back(aEntry); + } + } + } + else + { + // symbol + uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); + + // create the symbol + Reference< drawing::XShape > xShape( createLegendSymbolForSeries( + rEntryKeyAspectRatio, rSeries, xSymbolGroup, xShapeFactory ) ); + + // set CID to symbol for selection + if( xShape.is()) + { + aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); + + OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) ); + OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle ); + ShapeFactory::setShapeName( xShape, aCID ); + } + + // label + aLabelText = DataSeriesHelper::getDataSeriesLabel( rSeries.getModel(), m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : "values-y"); + aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, 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; + + Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY ); + if( xRegrCont.is()) + { + Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves()); + sal_Int32 i = 0, nCount = aCurves.getLength(); + for( i=0; i xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); + + // create the symbol + Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xSymbolGroup, LegendSymbolStyle::Line, xShapeFactory, + Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ), + VLegendSymbolFactory::PropertyType::Line, uno::Any() )); + + // set CID to symbol for selection + if( xShape.is()) + { + aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); + + 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; +} + +VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( + const uno::Reference& 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()); + else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) + pRet = new NetChart(xChartTypeModel,nDimensionCount,false,std::make_unique()); + 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 000000000..bf9b9b70d --- /dev/null +++ b/chart2/source/view/diagram/VDiagram.cxx @@ -0,0 +1,739 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +VDiagram::VDiagram( + const uno::Reference & xDiagram, const drawing::Direction3D& rPreferredAspectRatio, + sal_Int32 nDimension ) + : m_pShapeFactory(nullptr) + , m_nDimensionCount(nDimension) + , m_xDiagram(xDiagram) + , m_aPreferredAspectRatio(rPreferredAspectRatio) + , m_xAspectRatio3D() + , m_fXAnglePi(0) + , m_fYAnglePi(0) + , m_fZAnglePi(0) + , m_bRightAngledAxes(false) +{ + if( m_nDimensionCount != 3) + return; + + uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY ); + ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi ); + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) ) + { + if(xSourceProp.is()) + xSourceProp->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes; + if( m_bRightAngledAxes ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi ); + m_fZAnglePi=0.0; + } + } +} + +VDiagram::~VDiagram() +{ +} + +void VDiagram::init( + const uno::Reference< drawing::XShapes >& xTarget, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + OSL_PRECOND(xFactory.is(), "no proper initialization parameters"); + + m_xTarget = xTarget; + m_xShapeFactory = xFactory; + m_pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xFactory); +} + +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(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME), + static_cast(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_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized"); + if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is()) + return; + + //create group shape + uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xTarget); + m_xOuterGroupShape.set( xOuterGroup_Shapes, uno::UNO_QUERY ); + + uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"PlotAreaExcludingAxes") ); + + //create independent group shape as container for datapoints and such things + { + uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID"); + m_xCoordinateRegionShape.set( xShapes, uno::UNO_QUERY ); + } + + bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + + //add back wall + { + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + m_xWall2D = pShapeFactory->createRectangle( + xGroupForWall ); + + uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY ); + if( xProp.is()) + { + 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( xProp, 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, OUString() ) );//@todo read CID from model + xProp->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 uno::Reference< drawing::XShape >& xShape ) +{ + E3dScene* pRet=nullptr; + uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY ); + if(xTypeProvider.is()) + { + SvxShape* pSvxShape = comphelper::getUnoTunnelImplementation(xShape); + if(pSvxShape) + { + SdrObject* pObj = pSvxShape->GetSdrObject(); + pRet = dynamic_cast< E3dScene* >(pObj); + } + } + return pRet; +} + +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_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized"); + if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is()) + return; + + //create shape + m_xOuterGroupShape.set( m_pShapeFactory->createGroup3D( m_xTarget, "PlotAreaExcludingAxes" ), uno::UNO_QUERY); + + uno::Reference< drawing::XShapes > xOuterGroup_Shapes( m_xOuterGroupShape, uno::UNO_QUERY ); + + //create additional group to manipulate the aspect ratio of the whole diagram: + xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes ); + + m_xAspectRatio3D.set( xOuterGroup_Shapes, uno::UNO_QUERY ); + + bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + + 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, OUString() ) );//@todo read CID from model + if( !bAddFloorAndWall ) + aWallCID.clear(); + uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) ); + + CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + + //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); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->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); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->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 + { + uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW ); + + //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 + xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any( + static_cast(ThreeDHelper::getCameraDistance( xSourceProp )))); + xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE, + xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE)); + } + + //light + { + xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE, + xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE)); + xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR, + xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR)); + xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING, + xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING)); + lcl_setLightSources( xSourceProp, xDestProp ); + } + + //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)); + + xDestProp->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); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe + , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided ); + + CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + 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, OUString() ) );//@todo read CID from model + ShapeFactory::setShapeName( xShape, aFloorCID ); + } + } + + //create an additional scene for the smaller inner coordinate region: + { + uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" ); + m_xCoordinateRegionShape.set( xShapes, uno::UNO_QUERY ); + + uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY ); + OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet"); + if( xShapeProp.is()) + { + 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)); + + xShapeProp->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::reduceToMimimumSize() +{ + if( !m_xOuterGroupShape.is() ) + return; + + awt::Size aMaxSize( m_aAvailableSizeIncludingAxes ); + awt::Point aMaxPos( m_aAvailablePosIncludingAxes ); + + sal_Int32 nNewWidth = aMaxSize.Width/3; + sal_Int32 nNewHeight = aMaxSize.Height/3; + 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 000000000..4f9a33adb --- /dev/null +++ b/chart2/source/view/inc/Clipping.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_CLIPPING_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_CLIPPING_HXX + +#include + +namespace com::sun::star::drawing { struct PolyPolygonShape3D; } + +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 ); +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/ConfigAccess.hxx b/chart2/source/view/inc/ConfigAccess.hxx new file mode 100644 index 000000000..556b371f1 --- /dev/null +++ b/chart2/source/view/inc/ConfigAccess.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_CONFIGACCESS_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_CONFIGACCESS_HXX + +namespace chart +{ +namespace ConfigAccess +{ +/** @descr Retrieve the setting for showing errors in charts from the registry + settings of the Calc application. + + If this setting is not found, it is set to false (the default setting). + + @return boolean UseErrorRectangle. + */ +bool getUseErrorRectangle(); +} + +} //namespace chart +#endif + +/* 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 000000000..bfd549b22 --- /dev/null +++ b/chart2/source/view/inc/DateHelper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_DATEHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_DATEHELPER_HXX + +#include + +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, long TimeResolution ); +}; + +} //namespace chart +#endif + +/* 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 000000000..7d2eff4a6 --- /dev/null +++ b/chart2/source/view/inc/LabelAlignment.hxx @@ -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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LABELALIGNMENT_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_LABELALIGNMENT_HXX + +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 +}; + +} + +#endif + +/* 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 000000000..92b12d8d3 --- /dev/null +++ b/chart2/source/view/inc/LabelPositionHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LABELPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_LABELPOSITIONHELPER_HXX + +#include "LabelAlignment.hxx" +#include "PropertyMapper.hxx" +#include + +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 ShapeFactory; + +class LabelPositionHelper +{ +public: + LabelPositionHelper() = delete; + LabelPositionHelper( + sal_Int32 nDimensionCount + , const css::uno::Reference< css::drawing::XShapes >& xLogicTarget + , ShapeFactory* pShapeFactory ); + 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 css::uno::Reference< css::drawing::XShape >& 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 + css::uno::Reference< css::drawing::XShapes > m_xLogicTarget; + ShapeFactory* m_pShapeFactory; +}; + +} //namespace chart +#endif + +/* 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 000000000..8c7ae00fa --- /dev/null +++ b/chart2/source/view/inc/LegendEntryProvider.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX + +#include +#include +#include +#include +#include + +namespace chart { class ChartModel; } +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::chart2 { class XFormattedString2; } +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 +{ + +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 + BOX. + */ + Circle +}; + +struct ViewLegendEntry +{ + /** The legend symbol that represents a data series or other + information contained in the legend + */ + css::uno::Reference< css::drawing::XShape > aSymbol; + + /** The descriptive text for a legend entry. + */ + css::uno::Sequence< + css::uno::Reference< css::chart2::XFormattedString2 > > aLabel; +}; + +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 css::uno::Reference< css::drawing::XShapes >& xTarget, + const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + ChartModel& rModel + ) = 0; + +protected: + ~LegendEntryProvider() {} +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX +#endif + +/* 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 000000000..3572caab7 --- /dev/null +++ b/chart2/source/view/inc/Linear3DTransformation.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX + +#include +#include +#include + +namespace chart +{ + +class Linear3DTransformation : public ::cppu::WeakImplHelper< + css::chart2::XTransformation + > +{ +public: + Linear3DTransformation( const css::drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY ); + virtual ~Linear3DTransformation() override; + + // ____ XTransformation ____ + /// @see css::chart2::XTransformation + virtual css::uno::Sequence< double > SAL_CALL transform( + const css::uno::Sequence< double >& rSourceValues ) override; + /// @see css::chart2::XTransformation + virtual sal_Int32 SAL_CALL getSourceDimension() override; + /// @see css::chart2::XTransformation + virtual sal_Int32 SAL_CALL getTargetDimension() override; + +private: + css::drawing::HomogenMatrix m_Matrix; + bool m_bSwapXAndY; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX +#endif + +/* 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 000000000..b256f1b91 --- /dev/null +++ b/chart2/source/view/inc/MinimumAndMaximumSupplier.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_MINIMUMANDMAXIMUMSUPPLIER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_MINIMUMANDMAXIMUMSUPPLIER_HXX + +#include +#include +#include + +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 long calculateTimeResolutionOnXAxis() = 0; + virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) = 0; + +protected: + ~MinimumAndMaximumSupplier() {} +}; + +class MergedMinimumAndMaximumSupplier : 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 long calculateTimeResolutionOnXAxis() override; + virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) override; + +private: + typedef std::set< MinimumAndMaximumSupplier* > MinimumAndMaximumSupplierSet; + MinimumAndMaximumSupplierSet m_aMinimumAndMaximumSupplierList; +}; + +} //namespace chart +#endif + +/* 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 000000000..7fe205578 --- /dev/null +++ b/chart2/source/view/inc/PlotterBase.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTERBASE_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTERBASE_HXX + +#include +#include +#include + +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 css::uno::Reference< css::drawing::XShapes >& xLogicTarget + , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + , const OUString& rCID + ); + + virtual void setScales( const 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 + css::uno::Reference< css::drawing::XShapes > + createGroupShape( const css::uno::Reference< + css::drawing::XShapes >& xTarget + , const OUString& rName=OUString() ); + +protected: //member + css::uno::Reference< css::drawing::XShapes > m_xLogicTarget; + css::uno::Reference< css::drawing::XShapes > m_xFinalTarget; + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + ShapeFactory* m_pShapeFactory; + OUString m_aCID; + + const sal_Int32 m_nDimension; + // needs to be created and deleted by the derived class + PlottingPositionHelper* m_pPosHelper; +}; +} //namespace chart +#endif + +/* 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 000000000..198941330 --- /dev/null +++ b/chart2/source/view/inc/PlottingPositionHelper.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace com::sun::star::chart2 { class XTransformation; } +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; + +class PlottingPositionHelper +{ +public: + PlottingPositionHelper(); + PlottingPositionHelper( const PlottingPositionHelper& rSource ); + virtual ~PlottingPositionHelper(); + + virtual std::unique_ptr clone() const; + std::unique_ptr createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale ); + + virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix); + + virtual void setScales( const 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 css::uno::Reference< css::chart2::XTransformation > + 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; + + static css::awt::Point transformSceneToScreenPosition( + const css::drawing::Position3D& rScenePosition3D + , const css::uno::Reference< css::drawing::XShapes >& xSceneTarget + , ShapeFactory* pShapeFactory, 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( 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 css::uno::Reference< css::chart2::XTransformation > 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; + 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 clone() const override; + + virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix) override; + virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) override; + + const ::basegfx::B3DHomMatrix& getUnitCartesianToScene() const { return m_aUnitCartesianToScene;} + + virtual css::uno::Reference< css::chart2::XTransformation > + 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(m_nXResolution*(fX - fScaledMinX)/(fScaledMaxX-fScaledMinX)) + == static_cast(m_nXResolution*(fX2 - fScaledMinX)/(fScaledMaxX-fScaledMinX)) ); + + bool bSameY = ( static_cast(m_nYResolution*(fY - fScaledMinY)/(fScaledMaxY-fScaledMinY)) + == static_cast(m_nYResolution*(fY2 - fScaledMinY)/(fScaledMaxY-fScaledMinY)) ); + + bool bSameZ = ( static_cast(m_nZResolution*(fZ - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) + == static_cast(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].ShiftedCategoryPosition; + else if( 2==nDimensionIndex ) + return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition; + 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].ShiftedCategoryPosition ) + (*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].ShiftedCategoryPosition) + (*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 ) + { + double fHelp = rMin; + rMin = rMax; + rMax = fHelp; + } + 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 +#endif + +/* 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 000000000..2c6ed3a93 --- /dev/null +++ b/chart2/source/view/inc/PolarLabelPositionHelper.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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_POLARLABELPOSITIONHELPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_POLARLABELPOSITIONHELPER_HXX + +#include "LabelPositionHelper.hxx" +#include + +namespace chart +{ + +class PolarPlottingPositionHelper; + +class PolarLabelPositionHelper : public LabelPositionHelper +{ +public: + PolarLabelPositionHelper( + PolarPlottingPositionHelper* pPosHelper + , sal_Int32 nDimensionCount + , const css::uno::Reference< css::drawing::XShapes >& xLogicTarget + , ShapeFactory* pShapeFactory ); + 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 +#endif + +/* 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 000000000..5da914074 --- /dev/null +++ b/chart2/source/view/inc/PropertyMapper.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PROPERTYMAPPER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_PROPERTYMAPPER_HXX + +#include + +#include + +#include +#include + +namespace com::sun::star::beans { class XPropertySet; } + +namespace chart +{ + +typedef std::map< OUString, OUString > tPropertyNameMap; +typedef std::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 + , tPropertyNameValueMap const * pOverwriteMap=nullptr ); + + /** + * 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 getMultiPropertyLists( + tNameSequence& rNames + , tAnySequence& rValues + , const css::uno::Reference< css::beans::XPropertySet >& xProp + , const tPropertyNameMap& rMap + ); + + static void getMultiPropertyListsFromValueMap( + tNameSequence& rNames + , tAnySequence& rValues + , const tPropertyNameValueMap& rValueMap + ); + + static css::uno::Any* + getValuePointer( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , const OUString& rPropName ); + + static css::uno::Any* + getValuePointerForLimitedSpace( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , bool bLimitedHeight ); + + static void setMultiProperties( + const tNameSequence& rNames + , const tAnySequence& rValues + , const css::uno::Reference< css::beans::XPropertySet >& 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 +#endif + +/* 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 000000000..df2e203bc --- /dev/null +++ b/chart2/source/view/inc/ScaleAutomatism.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_SCALEAUTOMATISM_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_SCALEAUTOMATISM_HXX + +#include + +#include + +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 +#endif + +/* 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 000000000..7a698e4b9 --- /dev/null +++ b/chart2/source/view/inc/ShapeFactory.hxx @@ -0,0 +1,332 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_VIEW_INC_SHAPEFACTORY_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_SHAPEFACTORY_HXX + +#include "PropertyMapper.hxx" +#include +#include +#include +#include + +#include + +namespace chart { struct VLineProperties; } +namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::chart2 { class XFormattedString; } +namespace com::sun::star::drawing { class XDrawPage; } +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 +// +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 +{ + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + + ShapeFactory(css::uno::Reference< css::lang::XMultiServiceFactory> const & xFactory) + {m_xShapeFactory = xFactory;} + +public: + enum class StackPosition { Top, Bottom }; + + static ShapeFactory* getOrCreateShapeFactory(const css::uno::Reference< css::lang::XMultiServiceFactory>& xFactory); + + ShapeFactory() = delete; + css::uno::Reference< css::drawing::XShapes > + createGroup2D( + const css::uno::Reference< css::drawing::XShapes >& xTarget + , const OUString& aName = OUString() ); + + css::uno::Reference< css::drawing::XShapes > + createGroup3D( + const css::uno::Reference< css::drawing::XShapes >& xTarget + , const OUString& aName = OUString() ); + + css::uno::Reference< css::drawing::XShape > + createCube( const css::uno::Reference< css::drawing::XShapes >& 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); + + css::uno::Reference< css::drawing::XShape > + createCylinder( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPosition + , const css::drawing::Direction3D& rSize + , sal_Int32 nRotateZAngleHundredthDegree ); + + css::uno::Reference< css::drawing::XShape > + createPyramid( const css::uno::Reference< css::drawing::XShapes >& 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); + + css::uno::Reference< css::drawing::XShape > + createCone( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPosition + , const css::drawing::Direction3D& rSize + , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree ); + + css::uno::Reference< css::drawing::XShape > + createPieSegment2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree + , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius + , const css::drawing::Direction3D& rOffset + , const css::drawing::HomogenMatrix& rUnitCircleToScene ); + + css::uno::Reference< css::drawing::XShape > + createPieSegment( const css::uno::Reference< css::drawing::XShapes >& xTarget + , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree + , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius + , const css::drawing::Direction3D& rOffset + , const css::drawing::HomogenMatrix& rUnitCircleToScene + , double fDepth ); + + css::uno::Reference< css::drawing::XShape > + createStripe( const css::uno::Reference< css::drawing::XShapes >& 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 ); + + css::uno::Reference< css::drawing::XShape > + createArea3D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::PolyPolygonShape3D& rPolyPolygon + , double fDepth); + + css::uno::Reference< css::drawing::XShape > + createArea2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::PolyPolygonShape3D& rPolyPolygon); + + css::uno::Reference< css::drawing::XShape > + createSymbol2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPos + , const css::drawing::Direction3D& rSize + , sal_Int32 nStandardSymbol + , sal_Int32 nBorderColor + , sal_Int32 nFillColor ); + + css::uno::Reference< css::drawing::XShape > + createGraphic2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPos + , const css::drawing::Direction3D& rSize + , const css::uno::Reference< css::graphic::XGraphic >& xGraphic ); + + css::uno::Reference< css::drawing::XShape > + createLine2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::PointSequenceSequence& rPoints + , const VLineProperties* pLineProperties = nullptr ); + + css::uno::Reference< css::drawing::XShape > + createLine ( const css::uno::Reference< css::drawing::XShapes >& xTarget, + const css::awt::Size& rSize, const css::awt::Point& rPosition ); + + css::uno::Reference< css::drawing::XShape > + createLine3D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::PolyPolygonShape3D& rPoints + , const VLineProperties& rLineProperties ); + + css::uno::Reference< css::drawing::XShape > + createCircle2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPos + , const css::drawing::Direction3D& rSize ); + + css::uno::Reference< css::drawing::XShape > + createCircle( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::awt::Size& rSize + , const css::awt::Point& rPosition ); + + css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D + , const OUString& rText + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation + ); + + /** This method creates a text shape made up by a set of paragraphs. + * For each paragraph the related text style is passed to the method. + * + * @param xTarget + * where to append the new created text shape. + * + * @param rTextParagraphs + * the set of paragraphs which made up the text shape. + * + * @param rParaPropNames + * a collection of lists of text property names: + * there must be a list of text property names for each paragraph. + * + * @param rParaPropValues + * a collection of lists of text property values: + * there must be a list of text property values for each paragraph. + * + * @param rPropNames + * a list of text property names to be applied to the whole text shape. + * + * @param rPropValues + * a list of text property values to be applied to the whole text shape. + * + * @param rATransformation + * a transformation to be applied to the text shape as final step. + * + */ + css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::uno::Sequence< OUString >& rTextParagraphs + , const css::uno::Sequence< tNameSequence >& rParaPropNames + , const css::uno::Sequence< tAnySequence >& rParaPropValues + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation ); + + css::uno::Reference< css::drawing::XShape > + createText(const css::uno::Reference< css::drawing::XShapes >& xTarget + , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const css::uno::Any& rATransformation); + + css::uno::Reference< css::drawing::XShape > + createText( const css::uno::Reference< css::drawing::XShapes >& 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 ); + + css::uno::Reference< css::drawing::XShape > + createInvisibleRectangle( + const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::awt::Size& rSize ); + + css::uno::Reference< css::drawing::XShape > + createRectangle( + const css::uno::Reference< css::drawing::XShapes >& xTarget, + const css::awt::Size& rSize, + const css::awt::Point& rPosition, + const tNameSequence& rPropNames, + const tAnySequence& rPropValues, + StackPosition ePos = StackPosition::Top ); + + css::uno::Reference< css::drawing::XShape > + createRectangle( + const css::uno::Reference< css::drawing::XShapes >& xTarget ); + + css::uno::Reference< css::drawing::XShapes > + getOrCreateChartRootShape( const css::uno::Reference< + css::drawing::XDrawPage>& xPage ); + + static void setPageSize(const css::uno::Reference& xChartShapes, + const css::awt::Size& rSize); + + static css::uno::Reference< css::drawing::XShapes > + getChartRootShape( const css::uno::Reference< css::drawing::XDrawPage>& xPage ); + + static void makeShapeInvisible( const css::uno::Reference< css::drawing::XShape >& xShape ); + + static void setShapeName( const css::uno::Reference< css::drawing::XShape >& 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( css::drawing::PolyPolygonShape3D& rPoly ); + static bool isPolygonEmptyOrSinglePoint( css::drawing::PolyPolygonShape3D& rPoly ); + static void closePolygon( css::drawing::PolyPolygonShape3D& 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( + const css::uno::Reference< css::drawing::XShape >& xShape ); + + static css::awt::Size getSizeAfterRotation( + const css::uno::Reference< css::drawing::XShape >& xShape, double fRotationAngleDegree ); + + static void removeSubShapes( const css::uno::Reference< css::drawing::XShapes >& xShapes ); + + static sal_Int32 getSymbolCount() { return Symbol_COUNT; } + +private: + css::uno::Reference< css::drawing::XShape > + impl_createCube( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPosition + , const css::drawing::Direction3D& rSize, sal_Int32 nRotateZAngleHundredthDegree + , bool bRounded ); + + css::uno::Reference< css::drawing::XShape > + impl_createConeOrCylinder( const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::drawing::Position3D& rPosition + , const css::drawing::Direction3D& rSize + , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree + , bool bCylinder); +}; + +} //namespace chart +#endif + +/* 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 000000000..4c25af12a --- /dev/null +++ b/chart2/source/view/inc/Stripe.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_STRIPE_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_STRIPE_HXX + +#include +#include +#include + +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 +#endif + +/* 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 000000000..48f3f4aed --- /dev/null +++ b/chart2/source/view/inc/VCoordinateSystem.hxx @@ -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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VCOORDINATESYSTEM_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VCOORDINATESYSTEM_HXX + +#include "MinimumAndMaximumSupplier.hxx" +#include +#include +#include +#include + +#include +#include +#include + +namespace chart { class ExplicitCategoriesProvider; } +namespace chart { class ScaleAutomatism; } +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 chart +{ + +class VAxisBase; + +class VCoordinateSystem +{ +public: + virtual ~VCoordinateSystem(); + + static std::unique_ptr createCoordinateSystem( const css::uno::Reference< + css::chart2::XCoordinateSystem >& xCooSysModel ); + + /// @throws css::uno::RuntimeException + void initPlottingTargets( + const css::uno::Reference< css::drawing::XShapes >& xLogicTarget + , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + , css::uno::Reference< css::drawing::XShapes >& 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 css::uno::Reference< css::chart2::XCoordinateSystem >& + getModel() const { return m_xCooSysModel;} + + /** + * Create "view" axis obejcts 'VAxis' from the coordinate system model. + */ + virtual void createVAxisList( + const css::uno::Reference< css::chart2::XChartDocument> & xChartDoc + , const css::awt::Size& rFontReferenceSize + , const css::awt::Rectangle& rMaximumSpaceForLabels + , bool bLimitSpaceForLabels ); + + 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( const css::uno::Reference< + css::chart2::XCoordinateSystem >& xCooSys ); + + css::uno::Reference< css::chart2::XAxis > + getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const; + static css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > + getGridListFromAxis( const css::uno::Reference< css::chart2::XAxis >& 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 css::uno::Reference< + css::chart2::XAxis >& xAxis + , const css::uno::Reference< + css::chart2::XChartDocument>& xChartDoc); + +private: //methods + static void impl_adjustDimension( sal_Int32& rDimensionIndex ); + void impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const; + +protected: //member + css::uno::Reference< css::chart2::XCoordinateSystem > 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 + + css::uno::Reference< css::drawing::XShapes > m_xLogicTargetForGrids; + css::uno::Reference< css::drawing::XShapes > m_xLogicTargetForAxes; + css::uno::Reference< css::drawing::XShapes > m_xFinalTarget; + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + 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 +#endif + +/* 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 000000000..287415c27 --- /dev/null +++ b/chart2/source/view/inc/VDataSeries.hxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_VIEW_INC_VDATASERIES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VDATASERIES_HXX + +#include "PropertyMapper.hxx" + +#include +#include +#include +#include + +#include +#include + +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::chart2 { struct DataPointLabel; } +namespace com::sun::star::chart2 { struct Symbol; } +namespace com::sun::star::drawing { class XShapes; } + +namespace chart +{ + +class VDataSequence +{ +public: + void init( const css::uno::Reference& 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 Model; + + mutable css::uno::Sequence Doubles; +}; + +class VDataSeries final +{ +public: + VDataSeries( const css::uno::Reference& xDataSeries ); + + ~VDataSeries(); + + VDataSeries(const VDataSeries&) = delete; + const VDataSeries& operator=(const VDataSeries&) = delete; + + const css::uno::Reference& getModel() const; + + void setCategoryXAxis(); + void setXValues( const css::uno::Reference& xValues ); + void setXValuesIfNone( const css::uno::Reference& 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 css::uno::Reference& 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 getPropertiesOfPoint( sal_Int32 index ) const; + + css::uno::Reference getPropertiesOfSeries() const; + + css::chart2::Symbol* getSymbolProperties( sal_Int32 index ) const; + + css::uno::Reference getXErrorBarProperties( sal_Int32 index ) const; + + css::uno::Reference 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( const OUString& rRole ); + + //this is only temporarily here for area chart: + css::drawing::PolyPolygonShape3D 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 + css::uno::Reference m_xGroupShape; + css::uno::Reference m_xLabelsGroupShape; + css::uno::Reference m_xErrorXBarsGroupShape; + css::uno::Reference 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) + css::uno::Reference m_xFrontSubGroupShape; + css::uno::Reference m_xBackSubGroupShape; + +private: //member + css::uno::Reference m_xDataSeries; + + //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 m_PropertyMap; + + mutable double m_fXMeanValue; + mutable double m_fYMeanValue; + + css::uno::Sequence 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::unique_ptr + m_apLabel_Series; + mutable std::unique_ptr m_apLabelPropNames_Series; + mutable std::unique_ptr m_apLabelPropValues_Series; + mutable std::unique_ptr m_apSymbolProperties_Series; + + mutable std::unique_ptr + m_apLabel_AttributedPoint; + mutable std::unique_ptr m_apLabelPropNames_AttributedPoint; + mutable std::unique_ptr m_apLabelPropValues_AttributedPoint; + mutable std::unique_ptr m_apSymbolProperties_AttributedPoint; + mutable std::unique_ptr + m_apSymbolProperties_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 +#endif + +/* 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 000000000..15ea26434 --- /dev/null +++ b/chart2/source/view/inc/VDiagram.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VDIAGRAM_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VDIAGRAM_HXX + +#include +#include +#include +#include +#include + +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 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 css::uno::Reference& xDiagram, + const css::drawing::Direction3D& rPreferredAspectRatio, + sal_Int32 nDimension ); + ~VDiagram(); + + void init( + const css::uno::Reference& xTarget, + const css::uno::Reference& xFactory ); + + void createShapes( const css::awt::Point& rPos + , const css::awt::Size& rSize ); + + css::uno::Reference< css::drawing::XShapes > + getCoordinateRegion() const { return css::uno::Reference( m_xCoordinateRegionShape, css::uno::UNO_QUERY );} + + /** + * Get current bounding rectangle for the diagram without axes. + */ + basegfx::B2IRectangle getCurrentRectangle() const; + + void reduceToMimimumSize(); + + ::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; + + css::uno::Reference< css::drawing::XShapes > m_xTarget; + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + ShapeFactory* m_pShapeFactory; + + // this is the surrounding shape which contains floor, wall and coordinate + css::uno::Reference< css::drawing::XShape > m_xOuterGroupShape; + // this is an additional inner shape that represents the coordinate region - that is - where to place data points + css::uno::Reference< css::drawing::XShape > m_xCoordinateRegionShape; + css::uno::Reference< css::drawing::XShape > m_xWall2D; + + sal_Int32 m_nDimensionCount; + css::uno::Reference< css::chart2::XDiagram > 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 +#endif + +/* 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 000000000..96eb58782 --- /dev/null +++ b/chart2/source/view/inc/VLegendSymbolFactory.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX + +#include "LegendEntryProvider.hxx" +#include + +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 +{ + +namespace VLegendSymbolFactory +{ + enum class PropertyType + { + FilledSeries, + LineSeries, + Line, + }; + + css::uno::Reference< css::drawing::XShape > + createSymbol( + const css::awt::Size& rEntryKeyAspectRatio, + const css::uno::Reference< css::drawing::XShapes >& rSymbolContainer, + LegendSymbolStyle eStyle, + const css::uno::Reference< css::lang::XMultiServiceFactory > & xShapeFactory, + 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 + +// INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX +#endif + +/* 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 000000000..864e78316 --- /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 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VLINEPROPERTIES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VLINEPROPERTIES_HXX + +#include +#include + +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 propertey UNO_NAME_LINECAP + + VLineProperties(); + void initFromPropertySet( const css::uno::Reference< css::beans::XPropertySet >& xProp ); + + bool isLineVisible() const; +}; + +} //namespace chart +#endif + +/* 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 000000000..af9404ffc --- /dev/null +++ b/chart2/source/view/inc/VPolarTransformation.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX + +#include "PlottingPositionHelper.hxx" +#include +#include + +namespace chart +{ + +class VPolarTransformation : public ::cppu::WeakImplHelper< + css::chart2::XTransformation + > +{ +public: + VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper ); + virtual ~VPolarTransformation() override; + + // ____ XTransformation ____ + /// @see css::chart2::XTransformation + virtual css::uno::Sequence< double > SAL_CALL transform( + const css::uno::Sequence< double >& rSourceValues ) override; + /// @see css::chart2::XTransformation + virtual sal_Int32 SAL_CALL getSourceDimension() override; + /// @see css::chart2::XTransformation + virtual sal_Int32 SAL_CALL getTargetDimension() override; + +private: + PolarPlottingPositionHelper m_aPositionHelper; + ::basegfx::B3DHomMatrix m_aUnitCartesianToScene; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX +#endif + +/* 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 000000000..17215faae --- /dev/null +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -0,0 +1,440 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 INCLUDED_CHART2_SOURCE_VIEW_INC_VSERIESPLOTTER_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VSERIESPLOTTER_HXX + +#include +#include "PlotterBase.hxx" +#include "VDataSeries.hxx" +#include "LabelAlignment.hxx" +#include "MinimumAndMaximumSupplier.hxx" +#include "LegendEntryProvider.hxx" +#include + +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 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 pSeries ); + VDataSeriesGroup(VDataSeriesGroup&&) noexcept; + ~VDataSeriesGroup(); + + void addSeries( std::unique_ptr pSeries );//takes ownership of pSeries + sal_Int32 getSeriesCount() const; + void deleteSeries(); + + sal_Int32 getPointCount() const; + sal_Int32 getAttachedAxisIndexForFirstSeries() const; + + void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const; + void getMinimumAndMaximiumYInContinuousXRange( 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 ); + void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex + , bool bSeparateStackingForDifferentSigns + , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ); + + std::vector< std::unique_ptr > 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 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 long calculateTimeResolutionOnXAxis() override; + virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) override; + + void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const; + void getMinimumAndMaximiumYInContinuousXRange( 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 css::uno::Reference< css::drawing::XShapes >& xTarget, + const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + 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*/ ); + + css::uno::Reference< css::drawing::XShape > createLegendSymbolForSeries( + const css::awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory ); + + css::uno::Reference< css::drawing::XShape > createLegendSymbolForPoint( + const css::awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , sal_Int32 nPointIndex + , const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory ); + + std::vector< ViewLegendEntry > createLegendEntriesForSeries( + const css::awt::Size& rEntryKeyAspectRatio, + const VDataSeries& rSeries, + const css::uno::Reference< css::beans::XPropertySet >& xTextProperties, + const css::uno::Reference< css::drawing::XShapes >& xTarget, + const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + const css::uno::Reference< css::uno::XComponentContext >& xContext + ); + + std::vector< VDataSeries* > getAllSeries(); + + // This method creates a series plotter of the requested type; e.g. : return new PieChart... + static VSeriesPlotter* createSeriesPlotter( const css::uno::Reference< css::chart2::XChartType >& 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 ); + + //get series names for the z axis labels + css::uno::Sequence< OUString > getSeriesNames() 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; }; + + //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(); + +protected: + + VSeriesPlotter( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount + , bool bCategoryXAxis=true ); + + // Methods for group shapes. + + css::uno::Reference< css::drawing::XShapes > + getSeriesGroupShape( VDataSeries* pDataSeries + , const css:: uno::Reference< css::drawing::XShapes >& 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 + css::uno::Reference< css::drawing::XShapes > + getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries + , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); + css::uno::Reference< css::drawing::XShapes > + getSeriesGroupShapeBackChild( VDataSeries* pDataSeries + , const css:: uno::Reference< css::drawing::XShapes >& 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; + css::uno::Reference< css::drawing::XShapes > + getLabelsGroupShape( VDataSeries& rDataSeries + , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); + + css::uno::Reference< css::drawing::XShapes > + getErrorBarsGroupShape( VDataSeries& rDataSeries + , const css:: uno::Reference< css::drawing::XShapes >& 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. + */ + css::uno::Reference< css::drawing::XShape > + createDataLabel( const css::uno::Reference< css::drawing::XShapes >& 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 ); + + /// 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 ); + + /** 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 css::uno::Reference< css::drawing::XShapes >& 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 css::uno::Reference< css::drawing::XShapes >& rTarget + , bool bUseXErrorData + , bool bUseYErrorData + ); + + void addErrorBorder( + const css::drawing::Position3D& rPos0 + , const css::drawing::Position3D& rPos1 + , const css::uno::Reference< css::drawing::XShapes >& rTarget + , const css::uno::Reference< css::beans::XPropertySet >& rErrorBorderProp ); + + void createErrorBar_X( const css::drawing::Position3D& rUnscaledLogicPosition + , VDataSeries& rVDataSeries, sal_Int32 nPointIndex + , const css::uno::Reference< css::drawing::XShapes >& xTarget ); + + void createErrorBar_Y( const css::drawing::Position3D& rUnscaledLogicPosition + , VDataSeries& rVDataSeries, sal_Int32 nPointIndex + , const css::uno::Reference< css::drawing::XShapes >& xTarget + , double const * pfScaledLogicX ); + + void createRegressionCurvesShapes( VDataSeries const & rVDataSeries + , const css::uno::Reference< css::drawing::XShapes >& xTarget + , const css::uno::Reference< css::drawing::XShapes >& xEquationTarget + , bool bMaySkipPointsInRegressionCalculation ); + + void createRegressionCurveEquationShapes( const OUString & rEquationCID + , const css::uno::Reference< css::beans::XPropertySet > & xEquationProperties + , const css::uno::Reference< css::drawing::XShapes >& xEquationTarget + , const css::uno::Reference< css::chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator + , css::awt::Point aDefaultPos ); + + static void setMappedProperties( + const css::uno::Reference< css::drawing::XShape >& xTarget + , const css::uno::Reference< css::beans::XPropertySet >& xSource + , const tPropertyNameMap& rMap + , tPropertyNameValueMap const * pOverwriteMap=nullptr ); + + 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; + + css::uno::Reference< css::chart2::XChartType > m_xChartTypeModel; + css::uno::Reference< css::beans::XPropertySet > m_xChartTypeModelProps; + + 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) + 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; + +private: + typedef std::map< sal_Int32 , ExplicitScaleData > tSecondaryValueScales; + tSecondaryValueScales m_aSecondaryValueScales; + + typedef std::map< sal_Int32 , std::unique_ptr > tSecondaryPosHelperMap; + mutable tSecondaryPosHelperMap m_aSecondaryPosHelperMap; + css::awt::Size m_aPageReferenceSize; +}; + +} //namespace chart +#endif + +/* 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 000000000..d191efe48 --- /dev/null +++ b/chart2/source/view/inc/ViewDefines.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VIEWDEFINES_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_INC_VIEWDEFINES_HXX + +#include + +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 +#endif + +/* 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 000000000..7e428942f --- /dev/null +++ b/chart2/source/view/main/ChartItemPool.cxx @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chart +{ + +ChartItemPool::ChartItemPool(): + SfxItemPool( "ChartItemPool" , SCHATTR_START, SCHATTR_END, nullptr, nullptr ), + pItemInfos(new SfxItemInfo[SCHATTR_END - SCHATTR_START + 1]) +{ + /************************************************************************** + * PoolDefaults + **************************************************************************/ + std::vector* ppPoolDefaults = new std::vector(SCHATTR_END - SCHATTR_START + 1); + std::vector& 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_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_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 SfxInt32Item(SCHATTR_TEXT_DEGREES, 0); + 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 SfxInt32Item( SCHATTR_STARTING_ANGLE, 90 ); + 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)"); + + /************************************************************************** + * ItemInfos + **************************************************************************/ + const sal_uInt16 nMax = SCHATTR_END - SCHATTR_START + 1; + for( sal_uInt16 i = 0; i < nMax; i++ ) + { + pItemInfos[i]._nSID = 0; + pItemInfos[i]._bPoolable = 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); +} + +SfxItemPool* ChartItemPool::Clone() const +{ + return new ChartItemPool(*this); +} + +MapUnit ChartItemPool::GetMetric(sal_uInt16 /* nWhich */) const +{ + return MapUnit::Map100thMM; +} + +SfxItemPool* ChartItemPool::CreateChartItemPool() +{ + 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 000000000..b311b3050 --- /dev/null +++ b/chart2/source/view/main/ChartItemPool.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX + +#include +#include +#include + +namespace chart +{ +class ChartItemPool : public SfxItemPool +{ +private: + std::unique_ptr pItemInfos; + +public: + ChartItemPool(); + ChartItemPool(const ChartItemPool& rPool); +protected: + virtual ~ChartItemPool() override; +public: + + virtual SfxItemPool* Clone() const override; + MapUnit GetMetric( sal_uInt16 nWhich ) const override; + + /// creates a pure chart item pool + static SfxItemPool* CreateChartItemPool(); +}; + +} // namespace chart + +#endif +// 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 000000000..4b6b1fa9b --- /dev/null +++ b/chart2/source/view/main/ChartView.cxx @@ -0,0 +1,3101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include "VTitle.hxx" +#include "VButton.hxx" +#include +#include +#include +#include +#include +#include +#include "VLegend.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include + +#include +namespace com::sun::star::chart2 { class XChartDocument; } + +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 { + +class theExplicitValueProviderUnoTunnelId : public rtl::Static {}; + +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 +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`). + */ +struct AxisUsage +{ + AxisUsage(); + ~AxisUsage(); + + void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); + std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); + sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ); + + void prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ); + void setExplicitScaleAndIncrement( sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc ); + + ScaleAutomatism aAutoScaling; + +private: + tCoordinateSystemMap aCoordinateSystems; + std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension; +}; + +AxisUsage::AxisUsage() + : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM)) +{ +} + +AxisUsage::~AxisUsage() +{ + aCoordinateSystems.clear(); +} + +void AxisUsage::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 + std::map< sal_Int32, sal_Int32 >::const_iterator 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* > AxisUsage::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 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ) +{ + sal_Int32 nRet = -1; + std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex); + if( aIter != aMaxIndexPerDimension.end() ) + nRet = aIter->second; + return nRet; +} + +void AxisUsage::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) +{ + std::vector aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); + for (VCoordinateSystem * i : aVCooSysList) + i->prepareAutomaticAxisScaling(rScaleAutomatism, nDimIndex, nAxisIndex); +} + +void AxisUsage::setExplicitScaleAndIncrement( + sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc ) +{ + std::vector aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); + for (VCoordinateSystem* i : aVCooSysList) + i->setExplicitScaleAndIncrement(nDimIndex, nAxisIndex, rScale, rInc); +} + +typedef std::vector > SeriesPlottersType; + +/** 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 >& 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(); + drawing::Direction3D getPreferredAspectRatio(); + + SeriesPlottersType& getSeriesPlotterList() { return m_aSeriesPlotterList; } + std::vector< std::unique_ptr >& getCooSysList() { return m_rVCooSysList; } + std::vector< LegendEntryProvider* > getLegendEntryProviderList(); + + void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel ); + + static bool isCategoryPositionShifted( + const chart2::ScaleData& rSourceScale, bool bHasComplexCategories ); + +private: + /** A vector of series plotters. + */ + SeriesPlottersType m_aSeriesPlotterList; + + /** A vector of coordinate systems. + */ + std::vector< std::unique_ptr >& m_rVCooSysList; + + /** A map whose key is a `XAxis` interface and the related value is + * an object of `AxisUsage` type. + */ + std::map< uno::Reference< XAxis >, 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; + + sal_Int32 m_nDefaultDateNumberFormat; +}; + +SeriesPlotterContainer::SeriesPlotterContainer( std::vector< std::unique_ptr >& rVCooSysList ) + : m_rVCooSysList( rVCooSysList ) + , m_nMaxAxisIndex(0) + , 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& aPlotter : m_aSeriesPlotterList) + aRet[nN++] = aPlotter.get(); + return aRet; +} + +VCoordinateSystem* findInCooSysList( const std::vector< std::unique_ptr >& rVCooSysList + , const uno::Reference< XCoordinateSystem >& xCooSys ) +{ + for(auto & pVCooSys : rVCooSysList) + { + if(pVCooSys->getModel()==xCooSys) + return pVCooSys.get(); + } + return nullptr; +} + +VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< std::unique_ptr >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier ) +{ + if(!pMinimumAndMaximumSupplier) + return nullptr; + for(auto & pVCooSys : rVCooSysList) + { + if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier )) + return pVCooSys.get(); + } + return nullptr; +} + +VCoordinateSystem* addCooSysToList( std::vector< std::unique_ptr >& rVCooSysList + , const uno::Reference< XCoordinateSystem >& xCooSys + , ChartModel& rChartModel ) +{ + VCoordinateSystem* pExistingVCooSys = findInCooSysList( rVCooSysList, xCooSys ); + if( pExistingVCooSys ) + return pExistingVCooSys; + + std::unique_ptr 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 ) +{ + uno::Reference< XDiagram > xDiagram( rChartModel.getFirstDiagram() ); + if( !xDiagram.is()) + return; + + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( static_cast< ::cppu::OWeakObject* >( &rChartModel ), uno::UNO_QUERY ); + if( rChartModel.hasInternalDataProvider() && DiagramHelper::isSupportingDateAxis( xDiagram ) ) + m_nDefaultDateNumberFormat=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier ); + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + 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 + { + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW ); + xDiaProp->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues; + xDiaProp->getPropertyValue( "ConnectBars" ) >>= bConnectBars; + xDiaProp->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis; + xDiaProp->getPropertyValue( "IncludeHiddenCells" ) >>= bIncludeHiddenCells; + xDiaProp->getPropertyValue( "StartingAngle" ) >>= nStartingAngle; + + if (nDimensionCount == 3) + { + xDiaProp->getPropertyValue( "3DRelativeHeight" ) >>= n3DRelativeHeight; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } + + //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< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + OSL_ASSERT( xCooSysContainer.is()); + if( !xCooSysContainer.is()) + return; + uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,rChartModel); + // Let's check whether the secondary Y axis is visible + try + { + if (xCooSys->getMaximumAxisIndexByDimension(1) > 0) + { + Reference< beans::XPropertySet > xAxisProp(xCooSys->getAxisByDimension(1, 1), uno::UNO_QUERY); + xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible; + } + } + catch (const lang::IndexOutOfBoundsException&) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) + continue; + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) + { + uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); + if(nDimensionCount == 3 && xChartType->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE)) + { + uno::Reference< beans::XPropertySet > xPropertySet( xChartType, uno::UNO_QUERY ); + if (xPropertySet.is()) + { + try + { + sal_Int32 n3DRelativeHeightOldValue(100); + uno::Any aAny = xPropertySet->getPropertyValue( "3DRelativeHeight" ); + aAny >>= n3DRelativeHeightOldValue; + if (n3DRelativeHeightOldValue != n3DRelativeHeight) + xPropertySet->setPropertyValue( "3DRelativeHeight", uno::Any(n3DRelativeHeight) ); + } + catch (const uno::Exception&) { } + } + } + + bool bExcludingPositioning = DiagramHelper::getDiagramPositioningMode( xDiagram ) == DiagramPositioningMode_EXCLUDING; + VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount, bExcludingPositioning ); + if( !pPlotter ) + continue; + + m_aSeriesPlotterList.push_back( std::unique_ptr(pPlotter) ); + pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier ); + pPlotter->setColorScheme( xColorScheme ); + if(pVCooSys) + pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() ); + sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType ); + + if(pVCooSys) + pVCooSys->addMinimumAndMaximumSupplier(pPlotter); + + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + + sal_Int32 zSlot=-1; + sal_Int32 xSlot=-1; + sal_Int32 ySlot=-1; + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS ) + { + uno::Reference< XDataSeries > const & xDataSeries = aSeriesList[nS]; + if(!xDataSeries.is()) + continue; + if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) ) + continue; + + std::unique_ptr 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 (rSourceScale.AxisType == AxisType::CATEGORY) + return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition; + + 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) + { + uno::Reference 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) + { + uno::Reference xAxis = xCooSys->getAxisByDimension(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 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& aPlotter : m_aSeriesPlotterList ) + { + VSeriesPlotter* pSeriesPlotter = aPlotter.get(); + VCoordinateSystem* pVCooSys = lcl_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& aPlotter : m_aSeriesPlotterList ) + { + VSeriesPlotter* pSeriesPlotter = aPlotter.get(); + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter ); + if(pVCooSys) + { + AxesNumberFormats aAxesNumberFormats; + const uno::Reference< XCoordinateSystem >& xCooSys = pVCooSys->getModel(); + sal_Int32 nDimensionCount = xCooSys->getDimension(); + for(sal_Int32 nDimensionIndex=0; nDimensionIndexgetMaximumAxisIndexByDimension(nDimensionIndex); + for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) + { + try + { + Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); + 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 & axisUsage : m_aAxisUsageList) + { + AxisUsage& rAxisUsage = axisUsage.second; + + 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 & axisUsage : m_aAxisUsageList) + { + AxisUsage& rAxisUsage = axisUsage.second; + + 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 & axisUsage : m_aAxisUsageList) + { + AxisUsage& rAxisUsage = axisUsage.second; + std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex ); + if( aVCooSysList_Y.empty() ) + continue; + + uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() ); + if (!xDiagram.is()) + continue; + + bool bSeriesAttachedToThisAxis = false; + sal_Int32 nAttachedAxisIndex = -1; + { + std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + 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 & axisUsage : m_aAxisUsageList) + { + AxisUsage& rAxisUsage = axisUsage.second; + 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 ) ); + + Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() ); + Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); + Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY ); + + css::chart::ChartAxisPosition eCrossingMainAxisPos( css::chart::ChartAxisPosition_ZERO ); + if( xCrossingMainAxis.is() ) + { + 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& 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; +} + +} + +struct CreateShapeParam2D +{ + css::awt::Rectangle maRemainingSpace; + + std::shared_ptr mpSeriesPlotterContainer; + + std::shared_ptr mpVTitleX; + std::shared_ptr mpVTitleY; + std::shared_ptr mpVTitleZ; + + std::shared_ptr mpVTitleSecondX; + std::shared_ptr mpVTitleSecondY; + + css::uno::Reference mxMarkHandles; + css::uno::Reference mxPlotAreaWithAxes; + + css::uno::Reference 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) {} +}; + +const uno::Sequence& ExplicitValueProvider::getUnoTunnelId() +{ + return theExplicitValueProviderUnoTunnelId::get().getSeq(); +} + +ChartView::ChartView( + uno::Reference const & xContext, + ChartModel& rModel) + : m_aMutex() + , m_xCC(xContext) + , mrChartModel(rModel) + , m_xShapeFactory() + , m_xDrawPage() + , m_pDrawModelWrapper() + , m_aListenerContainer( m_aMutex ) + , 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 +{ +const OUString lcl_aGDIMetaFileMIMEType( + "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ); +const OUString lcl_aGDIMetaFileMIMETypeHighContrast( + "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ); +} // 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 > aProps(3); + aProps[0].Name = "FilterName"; + aProps[0].Value <<= OUString("SVM"); + + aProps[1].Name = "OutputStream"; + aProps[1].Value <<= xOutStream; + + uno::Sequence< beans::PropertyValue > aFilterData(8); + aFilterData[0].Name = "ExportOnlyBackground"; + aFilterData[0].Value <<= false; + aFilterData[1].Name = "HighContrast"; + aFilterData[1].Value <<= bUseHighContrast; + + aFilterData[2].Name = "Version"; + const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50; + aFilterData[2].Value <<= nVersion; + + aFilterData[3].Name = "CurrentPage"; + aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY ); + + //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% + aFilterData[4].Name = "ScaleXNumerator"; + aFilterData[4].Value <<= m_nScaleXNumerator; + aFilterData[5].Name = "ScaleXDenominator"; + aFilterData[5].Value <<= m_nScaleXDenominator; + aFilterData[6].Name = "ScaleYNumerator"; + aFilterData[6].Value <<= m_nScaleYNumerator; + aFilterData[7].Name = "ScaleYDenominator"; + aFilterData[7].Value <<= m_nScaleYDenominator; + + + aProps[2].Name = "FilterData"; + aProps[2].Value <<= aFilterData; + + xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) ); + 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 ); + utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream ); + + uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper ); + uno::Reference< io::XInputStream > xInStream( pStreamWrapper ); + uno::Reference< io::XSeekable > xSeekable( pStreamWrapper ); + + if( xOutStream.is() ) + { + this->getMetaFile( xOutStream, bHighContrastMetaFile ); + + if( xInStream.is() && xSeekable.is() ) + { + xSeekable->seek(0); + sal_Int32 nBytesToRead = xInStream->available(); + uno::Sequence< sal_Int8 > aSeq( nBytesToRead ); + xInStream->readBytes( aSeq, nBytesToRead); + aRet <<= aSeq; + xInStream->closeInput(); + } + } + + return aRet; +} +uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors() +{ + uno::Sequence< datatransfer::DataFlavor > aRet(2); + + aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType, + "GDIMetaFile", + cppu::UnoType>::get() ); + aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast, + "GDIMetaFile", + cppu::UnoType>::get() ); + + return aRet; +} +sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) +{ + return ( aFlavor.MimeType == lcl_aGDIMetaFileMIMEType || + aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast ); +} + +// ____ XUnoTunnel ___ +::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier ) +{ + if( isUnoTunnelId(aIdentifier) ) + { + ExplicitValueProvider* pProvider = this; + return reinterpret_cast(pProvider); + } + return 0; +} + +// 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 uno::Reference< XDiagram >& 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 DiagramHelper::isPieOrDonutChart( xDiagram ); +} + +void lcl_setDefaultWritingMode( const std::shared_ptr< DrawModelWrapper >& pDrawModelWrapper, ChartModel& rModel) +{ + //get writing mode from parent document: + if( !SvtLanguageOptions().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 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(nWritingMode), EE_PARA_WRITINGDIR) ); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +sal_Int16 lcl_getDefaultWritingModeFromPool( const std::shared_ptr& pDrawModelWrapper ) +{ + sal_Int16 nWritingMode = text::WritingMode2::LR_TB; + if(!pDrawModelWrapper) + return nWritingMode; + + const SfxPoolItem& rItem = pDrawModelWrapper->GetItemPool().GetDefaultItem(EE_PARA_WRITINGDIR); + nWritingMode + = static_cast(static_cast(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); + + uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() ); + if( !xDiagram.is()) + return aUsedOuterRect; + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + if(!nDimensionCount) + { + //@todo handle mixed dimension + nDimensionCount = 2; + } + + basegfx::B2IRectangle aAvailableOuterRect = BaseGFXHelper::makeRectangle(rParam.maRemainingSpace); + + const std::vector< std::unique_ptr >& rVCooSysList( rParam.mpSeriesPlotterContainer->getCooSysList() ); + SeriesPlottersType& rSeriesPlotterList = rParam.mpSeriesPlotterContainer->getSeriesPlotterList(); + + //create VAxis, so they can give necessary information for automatic scaling + uno::Reference const xChartDoc(&mrChartModel); + uno::Reference const xNumberFormatsSupplier( + mrChartModel.getNumberFormatsSupplier()); + size_t nC = 0; + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); + if(nDimensionCount==3) + { + uno::Reference xSceneProperties( xDiagram, uno::UNO_QUERY ); + CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) ); + CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) ); + CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) ); + pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos ); + } + + pVCooSys->createVAxisList(xChartDoc, rPageSize, rParam.maRemainingSpace, rParam.mbUseFixedInnerSize); + } + + // - 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(); + + uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis; + uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis; + VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount); + {//create diagram + aVDiagram.init(rParam.mxDiagramWithAxesShapes, m_xShapeFactory); + 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.reduceToMimimumSize(); + } + + uno::Reference< drawing::XShapes > xTextTargetShapes = + ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)->createGroup2D(rParam.mxDiagramWithAxesShapes); + + // - create axis and grids for all coordinate systems + + //init all coordinate systems + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); + pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis); + + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + + pVCooSys->initVAxisInList(); + } + + //calculate resulting size respecting axis label layout and fontscaling + + uno::Reference< drawing::XShape > xBoundingShape(rParam.mxDiagramWithAxesShapes, uno::UNO_QUERY); + ::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() ) )); + } + 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( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); + + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + + pVCooSys->createAxesShapes(); + pVCooSys->createGridShapes(); + } + + // - create data series for all charttypes + m_bPointsWereSkipped = false; + for( const std::unique_ptr& aPlotter : rSeriesPlotterList ) + { + VSeriesPlotter* pSeriesPlotter = aPlotter.get(); + uno::Reference< drawing::XShapes > 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,m_xShapeFactory,OUString() ); + pSeriesPlotter->setPageReferenceSize( rPageSize ); + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter ); + if(nDimensionCount==2) + pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() ); + //better performance for big data + { + //calculate resolution for coordinate system + Sequence 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); + 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& 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( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aNewInnerRect ) )); + } + + // - create data series for all charttypes + for( std::unique_ptr& aPlotter : rSeriesPlotterList ) + { + VCoordinateSystem* pVCooSys = lcl_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& 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& 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 = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() ); + } + } + else + { + if (rParam.mbUseFixedInnerSize) + m_aResultingDiagramRectangleExcludingAxes = rParam.maRemainingSpace; + else + { + ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle(); + m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() ); + } + } + + 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; + uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY_THROW ); + xDiaProps->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( + uno::Reference< XAxis > xAxis + , ExplicitScaleData& rExplicitScale + , ExplicitIncrementData& rExplicitIncrement ) +{ + SolarMutexGuard aSolarGuard; + + impl_updateView(); + + if(!xAxis.is()) + return false; + + uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstDiagram() ) ); + const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys); + if(!pVCooSys) + return false; + + sal_Int32 nDimensionIndex=-1; + sal_Int32 nAxisIndex=-1; + if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) ) + { + rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex); + rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex); + if( rExplicitScale.ShiftedCategoryPosition ) + { + //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; + } + return false; +} + +SdrPage* ChartView::getSdrPage() +{ + auto pSvxDrawPage = comphelper::getUnoTunnelImplementation(m_xDrawPage); + if(pSvxDrawPage) + return pSvxDrawPage->GetSdrPage(); + + return nullptr; +} + +uno::Reference< drawing::XShape > ChartView::getShapeForCID( const OUString& rObjectCID ) +{ + SolarMutexGuard aSolarGuard; + SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() ); + if( pObj ) + return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY); + return nullptr; +} + +awt::Rectangle ChartView::getDiagramRectangleExcludingAxes() +{ + impl_updateView(); + return m_aResultingDiagramRectangleExcludingAxes; +} + +awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool bSnapRect ) +{ + impl_updateView(); + + awt::Rectangle aRet; + uno::Reference< drawing::XShape > 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; + SvxShape* pRoot = comphelper::getUnoTunnelImplementation( xShape ); + if( pRoot ) + { + SdrObject* pRootSdrObject = pRoot->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.set( pShape->getUnoShape(), uno::UNO_QUERY); + } + } + } + } + + 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 + SvxShape* pShape = comphelper::getUnoTunnelImplementation( xShape ); + if( pShape ) + { + SdrObject* pSdrObject = pShape->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 +{ +sal_Int32 lcl_getDiagramTitleSpace() +{ + return 200; //=0,2 cm spacing +} +bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram ) +{ + bool bSwapXAndY = false; + + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + if( aCooSysList.hasElements() ) + { + uno::Reference xProp(aCooSysList[0], uno::UNO_QUERY ); + if( xProp.is()) try + { + xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + return bSwapXAndY; +} + +} + +sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( + const Reference< chart2::XAxis >& xAxis + , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem + , const Reference& 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 + , const Reference< uno::XInterface >& xChartView + , const awt::Rectangle& rPositionAndSize, bool bSubtract ) +{ + awt::Rectangle aRet(rPositionAndSize); + + //add axis title sizes to the diagram size + uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel ) ); + uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel ) ); + uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, rModel ) ); + uno::Reference< chart2::XTitle > 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 = comphelper::getUnoTunnelImplementation(xChartView); + if( pExplicitValueProvider ) + { + //detect whether x axis points into x direction or not + if( lcl_getPropertySwapXAndYAxis( rModel.getFirstDiagram() ) ) + { + 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+=lcl_getDiagramTitleSpace(); + } + if( xTitle_Width.is() ) + { + OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, rModel ) ); + nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width; + if(nTitleSpaceWidth) + nTitleSpaceWidth+=lcl_getDiagramTitleSpace(); + } + if( xSecondTitle_Height.is() ) + { + OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, rModel ) ); + nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height; + if( nSecondTitleSpaceHeight ) + nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace(); + } + if( xSecondTitle_Width.is() ) + { + OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, rModel ) ); + nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width; + if( nSecondTitleSpaceWidth ) + nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace(); + } + 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 { + +double lcl_getPageLayoutDistancePercentage() +{ + return 0.02; +} + +bool getAvailablePosAndSizeForDiagram( + CreateShapeParam2D& rParam, const awt::Size & rPageSize, const uno::Reference< beans::XPropertySet >& xProp) +{ + rParam.mbUseFixedInnerSize = false; + + //@todo: we need a size dependent on the axis labels + sal_Int32 nYDistance = static_cast(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); + sal_Int32 nXDistance = static_cast(rPageSize.Width*lcl_getPageLayoutDistancePercentage()); + 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(aRelativeSize.Secondary*rPageSize.Height); + rParam.maRemainingSpace.Width = static_cast(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(fX),static_cast(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 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(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); + sal_Int32 nXDistance = static_cast(rPageSize.Width*lcl_getPageLayoutDistancePercentage()); + switch( eAlignment ) + { + case ALIGN_TOP: + aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2 + , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance ); + break; + case ALIGN_BOTTOM: + aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2 + , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance ); + break; + case ALIGN_LEFT: + aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance + , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); + break; + case ALIGN_RIGHT: + aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance + , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); + break; + case ALIGN_Z: + aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance + , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 ); + break; + default: + 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 lcl_createTitle( TitleHelper::eTitleType eType + , const uno::Reference< drawing::XShapes>& xPageShapes + , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + , ChartModel& rModel + , awt::Rectangle& rRemainingSpace + , const awt::Size & rPageSize + , TitleAlignment eAlignment + , bool& rbAutoPosition ) +{ + std::shared_ptr apVTitle; + + // #i109336# Improve auto positioning in chart + double fPercentage = lcl_getPageLayoutDistancePercentage(); + 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 + } + + uno::Reference< XTitle > xTitle( TitleHelper::getTitle( eType, rModel ) ); + OUString aCompleteString = TitleHelper::getCompleteString(xTitle); + if (aCompleteString.isEmpty()) + return apVTitle; + + //create title + awt::Size aTextMaxWidth(rPageSize.Width, rPageSize.Height); + if (eType == TitleHelper::MAIN_TITLE || eType == TitleHelper::SUB_TITLE) + { + aTextMaxWidth.Width = static_cast(rPageSize.Width * 0.8); + aTextMaxWidth.Height = static_cast(rPageSize.Height * 0.5); + } + apVTitle = std::make_shared(xTitle); + OUString aCID = ObjectIdentifier::createClassifiedIdentifierForObject(xTitle, rModel); + apVTitle->init(xPageShapes, xShapeFactory, aCID); + apVTitle->createShapes(awt::Point(0, 0), rPageSize, aTextMaxWidth); + awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize(); + awt::Size aTitleSize = apVTitle->getFinalSize(); + + //position + rbAutoPosition = true; + awt::Point aNewPosition(0,0); + chart2::RelativePosition aRelativePosition; + uno::Reference xProp(xTitle, uno::UNO_QUERY); + if (xProp.is() && (xProp->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(fX),static_cast(fY)) + , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi ); + } + else //auto position + { + switch( eAlignment ) + { + case ALIGN_TOP: + aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2 + , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance ); + break; + case ALIGN_BOTTOM: + aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2 + , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance ); + break; + case ALIGN_LEFT: + aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance + , rRemainingSpace.Y + rRemainingSpace.Height/2 ); + break; + case ALIGN_RIGHT: + aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance + , rRemainingSpace.Y + rRemainingSpace.Height/2 ); + break; + default: + break; + + } + } + apVTitle->changePosition( aNewPosition ); + + //remaining space + switch( eAlignment ) + { + case ALIGN_TOP: + // Push the remaining space down from top. + rRemainingSpace.Y += ( aTitleSize.Height + nYDistance ); + rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance ); + break; + case ALIGN_BOTTOM: + // Push the remaining space up from bottom. + rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance ); + break; + case ALIGN_LEFT: + // Push the remaining space to the right from left edge. + rRemainingSpace.X += ( aTitleSize.Width + nXDistance ); + rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance ); + break; + case ALIGN_RIGHT: + // Push the remaining space to the left from right edge. + rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance ); + break; + default: + break; + } + + return apVTitle; +} + +bool lcl_createLegend( const uno::Reference< XLegend > & xLegend + , const uno::Reference< drawing::XShapes>& xPageShapes + , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + , const uno::Reference< uno::XComponentContext > & xContext + , awt::Rectangle & rRemainingSpace + , const awt::Size & rPageSize + , ChartModel& rModel + , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList + , sal_Int16 nDefaultWritingMode ) +{ + if (!VLegend::isVisible(xLegend)) + return false; + + awt::Size rDefaultLegendSize; + VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList, + xPageShapes, xShapeFactory, 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 uno::Reference& xPageShapes, + const uno::Reference& xShapeFactory, + ChartModel& rModel, + awt::Rectangle& rRemainingSpace) +{ + uno::Reference xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY); + if (!xPivotTableDataProvider.is()) + return; + + uno::Reference xModelPage(rModel.getPageBackground()); + + awt::Size aSize(4000, 700); // size of the button + + long x = 0; + + if (xPivotTableDataProvider->getPageFields().hasElements()) + { + x = 0; + + const css::uno::Sequence aPivotFieldEntries = xPivotTableDataProvider->getPageFields(); + for (css::chart2::data::PivotTableFieldEntry const & rPageFieldEntry : aPivotFieldEntries) + { + std::unique_ptr pButton(new VButton); + pButton->init(xPageShapes, xShapeFactory); + awt::Point aNewPosition(rRemainingSpace.X + x + 100, rRemainingSpace.Y + 100); + sal_Int32 nDimensionIndex = rPageFieldEntry.DimensionIndex; + OUString aFieldOutputDescription = xPivotTableDataProvider->getFieldOutputDescription(nDimensionIndex); + pButton->setLabel(rPageFieldEntry.Name + " | " + aFieldOutputDescription); + pButton->setCID("FieldButton.Page." + OUString::number(nDimensionIndex)); + pButton->setPosition(aNewPosition); + pButton->setSize(aSize); + if (rPageFieldEntry.HasHiddenMembers) + pButton->setArrowColor(Color(0x0000FF)); + + pButton->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 aPivotFieldEntries = xPivotTableDataProvider->getRowFields(); + for (css::chart2::data::PivotTableFieldEntry const & rRowFieldEntry : aPivotFieldEntries) + { + + std::unique_ptr pButton(new VButton); + pButton->init(xPageShapes, xShapeFactory); + awt::Point aNewPosition(rRemainingSpace.X + x + 100, + rRemainingSpace.Y + rRemainingSpace.Height - aSize.Height - 100); + pButton->setLabel(rRowFieldEntry.Name); + pButton->setCID("FieldButton.Row." + OUString::number(rRowFieldEntry.DimensionIndex)); + pButton->setPosition(aNewPosition); + pButton->setSize(aSize); + if ( rRowFieldEntry.Name == "Data" ) + { + pButton->setBGColor( Color(0x00F6F6F6) ); + pButton->showArrow( false ); + } + else if (rRowFieldEntry.HasHiddenMembers) + pButton->setArrowColor(Color(0x0000FF)); + pButton->createShapes(xModelPage); + x += aSize.Width + 100; + } + rRemainingSpace.Height -= (aSize.Height + 100 + 100); +} + +void formatPage( + ChartModel& rChartModel + , const awt::Size& rPageSize + , const uno::Reference< drawing::XShapes >& xTarget + , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + ) +{ + try + { + uno::Reference< beans::XPropertySet > xModelPage( rChartModel.getPageBackground()); + if( ! xModelPage.is()) + return; + + if( !xShapeFactory.is() ) + return; + + //format page + tPropertyNameValueMap aNameValueMap; + PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage ); + + OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ); + aNameValueMap.emplace( "Name", uno::Any( aCID ) ); //CID OUString + + tNameSequence aNames; + tAnySequence aValues; + PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap ); + + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + pShapeFactory->createRectangle( + xTarget, rPageSize, awt::Point(0, 0), aNames, aValues); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent ) +{ + if(!xParent.is()) + return; + Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY ); + if( !xParentGroup.is() ) + { + Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY ); + if( !xPage.is() ) + return; + } + + //iterate from back! + for( sal_Int32 nN = xParent->getCount(); nN--; ) + { + uno::Any aAny = xParent->getByIndex( nN ); + Reference< drawing::XShapes> xShapes; + if( aAny >>= xShapes ) + lcl_removeEmptyGroupShapes( xShapes ); + if( xShapes.is() && xShapes->getCount()==0 ) + { + //remove empty group shape + Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY ); + Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY ); + if( xGroup.is() ) + xParent->remove( xShape ); + } + } +} + +} + +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", "" ); + } +} + +static const char* envChartDummyFactory = getenv("CHART_DUMMY_FACTORY"); + +void ChartView::createShapes() +{ + SolarMutexGuard aSolarGuard; + + osl::MutexGuard 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 ); + + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + if(!mxRootShape.is()) + mxRootShape = pShapeFactory->getOrCreateChartRootShape( m_xDrawPage ); + + SdrPage* pPage = ChartView::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 */ ) +{ +} + +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(); + } + + //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 + { + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer + .getContainer( cppu::UnoType::get()); + if( pIC ) + { + util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XModeChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->modeChanged( aEvent ); + } + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// ____ XModeChangeBroadcaster ____ + +void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) +{ + m_aListenerContainer.addInterface( + cppu::UnoType::get(), xListener ); +} +void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) +{ + m_aListenerContainer.removeInterface( + cppu::UnoType::get(), 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.Widthmodified( 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(); + beans::PropertyValue* pDataValues = aZoomFactors.getArray(); + 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( 6 ); + + aServiceNames[0] = "com.sun.star.drawing.DashTable"; + aServiceNames[1] = "com.sun.star.drawing.GradientTable"; + aServiceNames[2] = "com.sun.star.drawing.HatchTable"; + aServiceNames[3] = "com.sun.star.drawing.BitmapTable"; + aServiceNames[4] = "com.sun.star.drawing.TransparencyGradientTable"; + aServiceNames[5] = "com.sun.star.drawing.MarkerTable"; + + return aServiceNames; +} + +OUString ChartView::dump() +{ +#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(); + uno::Reference< drawing::XShapes > xShapes( m_xDrawPage, uno::UNO_QUERY_THROW ); + sal_Int32 n = xShapes->getCount(); + OUStringBuffer aBuffer; + for(sal_Int32 i = 0; i < n; ++i) + { + uno::Reference< drawing::XShapes > xShape(xShapes->getByIndex(i), uno::UNO_QUERY); + if(xShape.is()) + { + OUString aString = XShapeDumper::dump(mxRootShape); + aBuffer.append(aString); + } + else + { + uno::Reference< drawing::XShape > xSingleShape(xShapes->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::setViewDirty() +{ + osl::MutexGuard aGuard(maTimeMutex); + m_bViewDirty = true; +} + +IMPL_LINK_NOARG(ChartView, UpdateTimeBased, Timer *, void) +{ + setViewDirty(); + update(); +} + +void ChartView::createShapes2D( const awt::Size& rPageSize ) +{ + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + + // 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, m_xShapeFactory ); + + 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 + uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() ); + uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY); + bool bHasRelativeSize = false; + if( xProp.is() && xProp->getPropertyValue("RelativeSize").hasValue() ) + bHasRelativeSize = true; + + OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible + uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( + pShapeFactory->createGroup2D(mxRootShape,aDiagramCID) ); + + aParam.mxMarkHandles = pShapeFactory->createInvisibleRectangle( + xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0)); + ShapeFactory::setShapeName(aParam.mxMarkHandles, "MarkHandles"); + + aParam.mxPlotAreaWithAxes = pShapeFactory->createInvisibleRectangle( + xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0, 0)); + ShapeFactory::setShapeName(aParam.mxPlotAreaWithAxes, "PlotAreaIncludingAxes"); + + aParam.mxDiagramWithAxesShapes = pShapeFactory->createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes); + + bool bAutoPositionDummy = true; + + // create buttons + lcl_createButtons(mxRootShape, m_xShapeFactory, mrChartModel, aParam.maRemainingSpace); + + lcl_createTitle( + TitleHelper::MAIN_TITLE, mxRootShape, m_xShapeFactory, mrChartModel, + aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy); + if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)) + return; + + lcl_createTitle( + TitleHelper::SUB_TITLE, mxRootShape, m_xShapeFactory, mrChartModel, + aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy ); + if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)) + return; + + aParam.mpSeriesPlotterContainer = std::make_shared(m_aVCooSysList); + aParam.mpSeriesPlotterContainer->initializeCooSysAndSeriesPlotter( mrChartModel ); + if(maTimeBased.bTimeBased && maTimeBased.nFrame != 0) + { + SeriesPlottersType& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList(); + size_t n = rSeriesPlotter.size(); + for(size_t i = 0; i < n; ++i) + { + std::vector 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, m_xShapeFactory, m_xCC, + 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 = DiagramHelper::getVertical(xDiagram, bDummy, bDummy); + + if (getAvailablePosAndSizeForDiagram(aParam, rPageSize, xProp)) + { + 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(), ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize); + if (aParam.mbAutoPosTitleY) + changePositionOfAxisTitle(aParam.mpVTitleY.get(), ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize); + if (aParam.mbAutoPosTitleZ) + changePositionOfAxisTitle(aParam.mpVTitleZ.get(), ALIGN_Z, aDiagramPlusAxesRect, rPageSize); + if (aParam.mbAutoPosSecondTitleX) + changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, rPageSize); + if (aParam.mbAutoPosSecondTitleY) + changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize); + } + + //cleanup: remove all empty group shapes to avoid grey border lines: + lcl_removeEmptyGroupShapes( mxRootShape ); + + if(maTimeBased.bTimeBased && maTimeBased.nFrame % 60 == 0) + { + // create copy of the data for next frame + SeriesPlottersType& 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 aAllNewDataSeries = rSeriesPlotter[i]->getAllSeries(); + std::vector& 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 ) +{ + uno::Reference xDiagram = mrChartModel.getFirstDiagram(); + + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram ); + + if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) ) + rParam.mpVTitleX = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, mxRootShape, m_xShapeFactory, mrChartModel + , rParam.maRemainingSpace, rPageSize, 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, m_xShapeFactory, mrChartModel + , rParam.maRemainingSpace, rPageSize, 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, m_xShapeFactory, mrChartModel + , rParam.maRemainingSpace, rPageSize, ALIGN_RIGHT, rParam.mbAutoPosTitleZ ); + if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) + return false; + + bool bDummy = false; + bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy ); + + if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension ) ) + rParam.mpVTitleSecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel + , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_RIGHT : 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, m_xShapeFactory, mrChartModel + , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_TOP : 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 const &) +{ + ::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 000000000..463b74975 --- /dev/null +++ b/chart2/source/view/main/Clipping.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 +#include +#include + +#include + +#include +#include + +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; +} + +}//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; nOldPolyIndex0 ) + 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); + } +} + +} //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 000000000..7f446139a --- /dev/null +++ b/chart2/source/view/main/DataPointSymbolSupplier.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +uno::Reference< drawing::XShapes > DataPointSymbolSupplier::create2DSymbolList( + const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory + , const uno::Reference< drawing::XShapes >& xTarget + , const drawing::Direction3D& rSize ) +{ + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + uno::Reference< drawing::XShapes > xGroupShapes = + pShapeFactory->createGroup2D( xTarget ); + + drawing::Position3D aPos(0,0,0); + for(sal_Int32 nS=0;nScreateSymbol2D( xGroupShapes, aPos, rSize, nS, 0, 0 ); + } + return xGroupShapes; +} + +} //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 000000000..6403e0eea --- /dev/null +++ b/chart2/source/view/main/DrawModelWrapper.cxx @@ -0,0 +1,329 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "ChartItemPool.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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_pChartItemPool(nullptr) +{ + m_pChartItemPool = ChartItemPool::CreateChartItemPool(); + + SetScaleUnit(MapUnit::Map100thMM); + SetScaleFraction(Fraction(1, 1)); + SetDefaultFontHeight(423); // 12pt + + SfxItemPool* pMasterPool = &GetItemPool(); + pMasterPool->SetDefaultMetric(MapUnit::Map100thMM); + pMasterPool->SetPoolDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, true) ); + pMasterPool->SetPoolDefaultItem(makeSvx3DPercentDiagonalItem (5)); + + SfxItemPool* pPool = pMasterPool; + // append chart pool to end of pool chain + for (;;) + { + SfxItemPool* pSecondary = pPool->GetSecondaryPool(); + if (!pSecondary) + break; + + pPool = pSecondary; + } + pPool->SetSecondaryPool(m_pChartItemPool); + pMasterPool->FreezeIdRanges(); + + //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::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() +{ + //remove m_pChartItemPool from pool chain + if(m_pChartItemPool) + { + SfxItemPool* pPool = &GetItemPool(); + for (;;) + { + SfxItemPool* pSecondary = pPool->GetSecondaryPool(); + if(pSecondary == m_pChartItemPool) + { + pPool->SetSecondaryPool (nullptr); + break; + } + pPool = pSecondary; + } + SfxItemPool::Free(m_pChartItemPool); + } + m_pRefDevice.disposeAndClear(); +} + +uno::Reference< uno::XInterface > DrawModelWrapper::createUnoModel() +{ + uno::Reference< lang::XComponent > xComponent = new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer + return uno::Reference< uno::XInterface >::query( xComponent ); +} + +uno::Reference< frame::XModel > DrawModelWrapper::getUnoModel() +{ + uno::Reference< uno::XInterface > xI = SdrModel::getUnoModel(); + return uno::Reference::query( xI ); +} + +SdrModel& DrawModelWrapper::getSdrModel() +{ + return *this; +} + +uno::Reference< lang::XMultiServiceFactory > DrawModelWrapper::getShapeFactory() +{ + uno::Reference< lang::XMultiServiceFactory > xShapeFactory( getUnoModel(), uno::UNO_QUERY ); + return xShapeFactory; +} + +uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getMainDrawPage() +{ + if (m_xMainDrawPage.is()) + return m_xMainDrawPage; + + // Create draw page. + uno::Reference xDrawPagesSuplier(getUnoModel(), uno::UNO_QUERY); + if (!xDrawPagesSuplier.is()) + return m_xMainDrawPage; + + uno::Reference xDrawPages = xDrawPagesSuplier->getDrawPages(); + if (xDrawPages->getCount() > 1) + { + // Take the first page in case of multiple pages. + uno::Any aPage = xDrawPages->getByIndex(0); + aPage >>= m_xMainDrawPage; + } + + if (!m_xMainDrawPage.is()) + { + m_xMainDrawPage = xDrawPages->insertNewByIndex(0); + } + + //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; +} +uno::Reference< drawing::XDrawPage > const & 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 ) ; + aPage >>= m_xHiddenDrawPage; + } + + if(!m_xHiddenDrawPage.is()) + { + if( xDrawPages->getCount()==0 ) + m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 ); + m_xHiddenDrawPage = xDrawPages->insertNewByIndex( 1 ); + } + } + } + return m_xHiddenDrawPage; +} +void DrawModelWrapper::clearMainDrawPage() +{ + //uno::Reference xChartRoot( m_xMainDrawPage, uno::UNO_QUERY ); + uno::Reference 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 ); + } + } +} + +uno::Reference< drawing::XShapes > DrawModelWrapper::getChartRootShape( + const uno::Reference< drawing::XDrawPage>& 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; + const size_t nCount = pSearchList->GetObjCount(); + for( size_t nN=0; nNGetObj(nN); + if(!pObj) + continue; + if( ObjectIdentifier::areIdenticalObjects( rObjectCID, pObj->GetName() ) ) + return pObj; + pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() ); + if(pObj) + return pObj; + } + return nullptr; +} + +bool DrawModelWrapper::removeShape( const uno::Reference< drawing::XShape >& xShape ) +{ + uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY ); + if( xChild.is() ) + { + uno::Reference xShapes( xChild->getParent(), uno::UNO_QUERY ); + if( xShapes.is() ) + { + xShapes->remove(xShape); + return true; + } + } + return false; +} + +} //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 000000000..811bf7ad1 --- /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 +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +LabelPositionHelper::LabelPositionHelper( + sal_Int32 nDimensionCount + , const uno::Reference< drawing::XShapes >& xLogicTarget + , ShapeFactory* pShapeFactory ) + : m_nDimensionCount(nDimensionCount) + , m_xLogicTarget(xLogicTarget) + , m_pShapeFactory(pShapeFactory) +{ +} + +LabelPositionHelper::~LabelPositionHelper() +{ +} + +awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const +{ + return PlottingPositionHelper::transformSceneToScreenPosition( + rScenePosition3D, m_xLogicTarget, m_pShapeFactory, 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,"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,"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, "CharHeight" ); + lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); + pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, "CharHeightAsian" ); + lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); + pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, "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*rtl::math::sin( fAnglePi )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = -aSize.Width *rtl::math::sin( beta ) + -aSize.Height *rtl::math::cos( beta )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; + else + rfYCorrection = -aSize.Width *rtl::math::cos( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = fAnglePi - F_PI; + rfXCorrection = -aSize.Width *rtl::math::cos( beta ) + -aSize.Height*rtl::math::sin( beta )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; + else + rfYCorrection = aSize.Width *rtl::math::sin( beta ); + } + else + { + double beta = 2*F_PI - fAnglePi; + rfXCorrection = -aSize.Height*rtl::math::sin( beta )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = aSize.Width*rtl::math::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*rtl::math::sin( fAnglePi )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = F_PI - fAnglePi; + rfXCorrection = aSize.Width *rtl::math::cos( beta ) + + aSize.Height*rtl::math::sin( beta )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; + else + rfYCorrection = aSize.Width *rtl::math::sin( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = aSize.Width *rtl::math::sin( beta ) + +aSize.Height*rtl::math::cos( beta )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; + else + rfYCorrection = -aSize.Width *rtl::math::cos( beta ); + } + else + { + rfXCorrection = aSize.Height*rtl::math::sin( 2*F_PI - fAnglePi )/2.0; + if( bRotateAroundCenter ) + rfYCorrection = -aSize.Width*rtl::math::sin( 2*F_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*rtl::math::sin( fAnglePi )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection += aSize.Width*rtl::math::cos( fAnglePi )/2.0; + rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi - F_PI2; + rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection -= aSize.Width*rtl::math::sin( beta )/2.0; + rfYCorrection = -aSize.Width*rtl::math::cos( beta )/2.0 + - aSize.Height*rtl::math::sin( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = fAnglePi - F_PI; + rfXCorrection = -aSize.Height *rtl::math::sin( beta )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection += aSize.Width *rtl::math::cos( beta )/2.0; + rfYCorrection = -aSize.Width *rtl::math::sin( beta )/2.0 + -aSize.Height *rtl::math::cos( beta ); + } + else + { + rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection -= aSize.Width*rtl::math::cos( fAnglePi )/2.0; + rfYCorrection = aSize.Width*rtl::math::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*rtl::math::sin( fAnglePi )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection -= aSize.Width *rtl::math::cos( fAnglePi )/2.0; + rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = -aSize.Height*rtl::math::cos( beta )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection += aSize.Width *rtl::math::sin( beta )/2.0; + rfYCorrection = aSize.Width *rtl::math::cos( beta )/2.0 + +aSize.Height*rtl::math::sin( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection -= aSize.Width *rtl::math::sin( beta )/2.0; + rfYCorrection = aSize.Height*rtl::math::sin( beta ) + +aSize.Width*rtl::math::cos( beta )/2.0; + } + else + { + double beta = 2*F_PI - fAnglePi; + rfXCorrection = aSize.Height*rtl::math::sin( beta )/2.0; + if( !bRotateAroundCenter ) + rfXCorrection += aSize.Width*rtl::math::cos( beta )/2.0; + rfYCorrection = aSize.Width*rtl::math::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*rtl::math::sin( fAnglePi ); + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = -aSize.Width*rtl::math::sin( beta ); + rfYCorrection = -aSize.Height*rtl::math::sin( beta ) + -aSize.Width*rtl::math::cos( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = -aSize.Height*rtl::math::cos( beta ) + -aSize.Width*rtl::math::sin( beta ); + rfYCorrection = -aSize.Height*rtl::math::sin( beta ); + } + else + { + rfXCorrection = aSize.Height*rtl::math::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*rtl::math::sin( fAnglePi ); + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = -aSize.Width*rtl::math::sin( beta ) + -aSize.Height*rtl::math::cos( beta ); + rfYCorrection = aSize.Height*rtl::math::sin( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = -aSize.Width*rtl::math::sin( beta ); + rfYCorrection = aSize.Width*rtl::math::cos( beta ) + +aSize.Height*rtl::math::sin( beta ); + } + else + { + rfYCorrection = -aSize.Width*rtl::math::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*rtl::math::sin( fAnglePi ); + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = aSize.Width*rtl::math::sin( beta ) + +aSize.Height*rtl::math::cos( beta ); + rfYCorrection = -aSize.Height*rtl::math::sin( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = aSize.Width*rtl::math::sin( beta ); + rfYCorrection = -aSize.Width*rtl::math::cos( beta ) + -aSize.Height*rtl::math::sin( beta ); + } + else + { + rfYCorrection = aSize.Width*rtl::math::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*rtl::math::sin( fAnglePi ); + } + else if( fAnglePositiveDegree<= 180.0 ) + { + double beta = fAnglePi-F_PI2; + rfXCorrection = aSize.Width*rtl::math::sin( beta ); + rfYCorrection = aSize.Height*rtl::math::sin( beta ) + +aSize.Width*rtl::math::cos( beta ); + } + else if( fAnglePositiveDegree<= 270.0 ) + { + double beta = 3*F_PI2 - fAnglePi; + rfXCorrection = aSize.Height*rtl::math::cos( beta ) + +aSize.Width*rtl::math::sin( beta ); + rfYCorrection = aSize.Height*rtl::math::sin( beta ); + } + else + { + rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi ); + } +} + +}//end anonymous namespace + +void LabelPositionHelper::correctPositionForRotation( const uno::Reference< drawing::XShape >& 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(aOldPos.X + fXCorrection ) + , static_cast(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 000000000..c27ffa316 --- /dev/null +++ b/chart2/source/view/main/Linear3DTransformation.cxx @@ -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 . + */ + +#include + +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() +{} + +// ____ XTransformation ____ +Sequence< double > SAL_CALL Linear3DTransformation::transform( + const Sequence< double >& rSourceValues ) +{ + double fX = rSourceValues[0]; + double fY = rSourceValues[1]; + double fZ = rSourceValues[2]; + if(m_bSwapXAndY) + std::swap(fX,fY); + Sequence< double > aNewVec(3); + double fZwi; + + fZwi = m_Matrix.Line1.Column1 * fX + + m_Matrix.Line1.Column2 * fY + + m_Matrix.Line1.Column3 * fZ + + m_Matrix.Line1.Column4; + aNewVec[0] = fZwi; + + fZwi = m_Matrix.Line2.Column1 * fX + + m_Matrix.Line2.Column2 * fY + + m_Matrix.Line2.Column3 * fZ + + m_Matrix.Line2.Column4; + aNewVec[1] = fZwi; + + fZwi = m_Matrix.Line3.Column1 * fX + + m_Matrix.Line3.Column2 * fY + + m_Matrix.Line3.Column3 * fZ + + m_Matrix.Line3.Column4; + aNewVec[2] = 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[0] /= fZwi; + aNewVec[1] /= fZwi; + aNewVec[2] /= fZwi; + } + return aNewVec; +} + +sal_Int32 SAL_CALL Linear3DTransformation::getSourceDimension() +{ + return 3; +} + +sal_Int32 SAL_CALL Linear3DTransformation::getTargetDimension() +{ + return 3; +} + +} // 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 000000000..6479668c6 --- /dev/null +++ b/chart2/source/view/main/PlotterBase.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 +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +PlotterBase::PlotterBase( sal_Int32 nDimensionCount ) + : m_pShapeFactory(nullptr) + , m_aCID() + , m_nDimension(nDimensionCount) + , m_pPosHelper(nullptr) +{ +} + +void PlotterBase::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget + , const uno::Reference< drawing::XShapes >& xFinalTarget + , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory + , const OUString& rCID ) +{ + OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters"); + //is only allowed to be called once + m_xLogicTarget = xLogicTarget; + m_xFinalTarget = xFinalTarget; + m_xShapeFactory = xShapeFactory; + m_pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + m_aCID = rCID; +} + +PlotterBase::~PlotterBase() +{ +} + +void PlotterBase::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +{ + if (!m_pPosHelper) + return; + + OSL_PRECOND(m_nDimension<=static_cast(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence"); + m_pPosHelper->setScales( 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 ); +} + +uno::Reference< drawing::XShapes > PlotterBase::createGroupShape( + const uno::Reference< drawing::XShapes >& xTarget + , const OUString& rName ) +{ + if(!m_xShapeFactory.is()) + return nullptr; + + if(m_nDimension==2) + { + //create and add to target + return m_pShapeFactory->createGroup2D( xTarget, rName ); + } + else + { + //create and added to target + return m_pShapeFactory->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 000000000..d26e9331b --- /dev/null +++ b/chart2/source/view/main/PlottingPositionHelper.cxx @@ -0,0 +1,692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +PlottingPositionHelper::PlottingPositionHelper() + : m_aScales() + , m_aMatrixScreenToScene() + , 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::clone() const +{ + return std::make_unique(*this); +} + +std::unique_ptr 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( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +{ + m_aScales = rScales; + m_bSwapXAndY = bSwapXAndYAxis; + m_xTransformationLogicToScene = nullptr; +} + +uno::Reference< XTransformation > 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.is()) + { + ::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 = new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ),m_bSwapXAndY); + } + return m_xTransformationLogicToScene; +} + +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); + + uno::Reference< XTransformation > xTransformation = + getTransformationScaledLogicToScene(); + uno::Sequence< double > aSeq = + xTransformation->transform( Position3DToSequence(aPos) ); + return SequenceToPosition3D(aSeq); +} + +awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D + , const uno::Reference< drawing::XShapes >& xSceneTarget + , ShapeFactory* pShapeFactory + , sal_Int32 nDimensionCount ) +{ + //@todo would like to have a cheaper method to do this transformation + awt::Point aScreenPoint( static_cast(rScenePosition3D.PositionX), static_cast(rScenePosition3D.PositionY) ); + + //transformation from scene to screen (only necessary for 3D): + if(nDimensionCount==3) + { + //create 3D anchor shape + tPropertyNameMap aDummyPropertyNameMap; + uno::Reference< drawing::XShape > xShape3DAnchor = pShapeFactory->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; + for( sal_Int32 nS = rPolygon.SequenceX.getLength(); nS--;) + { + drawing::DoubleSequence& xValues = rPolygon.SequenceX[nS]; + drawing::DoubleSequence& yValues = rPolygon.SequenceY[nS]; + drawing::DoubleSequence& zValues = rPolygon.SequenceZ[nS]; + for( sal_Int32 nP = xValues.getLength(); nP--; ) + { + double& fX = xValues[nP]; + double& fY = yValues[nP]; + double& fZ = zValues[nP]; + 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_aUnitCartesianToScene() +{ + 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 PolarPlottingPositionHelper::clone() const +{ + return std::make_unique(*this); +} + +void PolarPlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix) +{ + PlottingPositionHelper::setTransformationSceneToScreen( rMatrix); + m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene ); +} +void PolarPlottingPositionHelper::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +{ + PlottingPositionHelper::setScales( 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; +} + +uno::Reference< XTransformation > PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const +{ + if( !m_xTransformationLogicToScene.is() ) + m_xTransformationLogicToScene = new VPolarTransformation(*this); + return m_xTransformationLogicToScene; +} + +double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const +{ + const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0]; + if( rAngleScale.Orientation != AxisOrientation_MATHEMATICAL ) + { + double fHelp = fEndLogicValueOnAngleAxis; + fEndLogicValueOnAngleAxis = fStartLogicValueOnAngleAxis; + fStartLogicValueOnAngleAxis = fHelp; + } + + 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*rtl::math::cos(fAnglePi); + double fY=fUnitRadius*rtl::math::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( 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 000000000..a3e9a7cd9 --- /dev/null +++ b/chart2/source/view/main/PolarLabelPositionHelper.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 +#include +#include +#include + +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +PolarLabelPositionHelper::PolarLabelPositionHelper( + PolarPlottingPositionHelper* pPosHelper + , sal_Int32 nDimensionCount + , const uno::Reference< drawing::XShapes >& xLogicTarget + , ShapeFactory* pShapeFactory ) + : LabelPositionHelper( nDimensionCount, xLogicTarget, pShapeFactory ) + , 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 + if( fDX != 0.0 ) + { + fAngleDegree = basegfx::rad2deg(atan(fDY/fDX)); + if(fDX<0.0) + fAngleDegree+=180.0; + } + else + { + if(fDY>0.0) + fAngleDegree = 90.0; + else + fAngleDegree = 270.0; + } + } + //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==0.0) + rAlignment = LABEL_ALIGN_CENTER; + else if(fAngleDegree<=22.5) + rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT; + else if(fAngleDegree<67.5) + rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM; + else if(fAngleDegree<112.5) + rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM; + else if(fAngleDegree<=157.5) + rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM; + else if(fAngleDegree<=202.5) + rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT; + else if(fAngleDegree<247.5) + rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP; + else if(fAngleDegree<292.5) + rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP; + else if(fAngleDegree<337.5) + rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP; + else + rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT; + } + 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 000000000..b33ab3ee3 --- /dev/null +++ b/chart2/source/view/main/PropertyMapper.cxx @@ -0,0 +1,511 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +namespace +{ + +void lcl_overwriteOrAppendValues( + tPropertyNameValueMap &rMap, const tPropertyNameValueMap& rOverwriteMap ) +{ + for (auto const& elem : rOverwriteMap) + rMap[ elem.first ] = elem.second; +} + +} // anonymous namespace + +void PropertyMapper::setMappedProperties( + const uno::Reference< beans::XPropertySet >& xTarget + , const uno::Reference< beans::XPropertySet >& xSource + , const tPropertyNameMap& rMap + , tPropertyNameValueMap const * pOverwriteMap ) +{ + if( !xTarget.is() || !xSource.is() ) + return; + + tNameSequence aNames; + tAnySequence aValues; + getMultiPropertyLists(aNames, aValues, xSource, rMap ); + if(pOverwriteMap && (aNames.getLength() == aValues.getLength())) + { + tPropertyNameValueMap aNewMap; + for( sal_Int32 nI=0; nI& xSourceProp + ) +{ + uno::Reference< beans::XMultiPropertySet > xMultiPropSet(xSourceProp, uno::UNO_QUERY); + if((false) && xMultiPropSet.is()) + { + uno::Sequence< OUString > aPropSourceNames(rNameMap.size()); + uno::Sequence< OUString > aPropTargetNames(rNameMap.size()); + sal_Int32 i = 0; + for (auto const& elem : rNameMap) + { + aPropTargetNames[i] = elem.first; + aPropSourceNames[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) + { + OUString aTarget = elem.first; + OUString aSource = elem.second; + try + { + uno::Any aAny( xSourceProp->getPropertyValue(aSource) ); + if( aAny.hasValue() ) + rValueMap.emplace( aTarget, aAny ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } +} + +void PropertyMapper::getMultiPropertyLists( + tNameSequence& rNames + , tAnySequence& rValues + , const uno::Reference< beans::XPropertySet >& xSourceProp + , const tPropertyNameMap& rNameMap + ) +{ + tPropertyNameValueMap aValueMap; + getValueMap( aValueMap, rNameMap, xSourceProp ); + getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap ); +} + +void PropertyMapper::getMultiPropertyListsFromValueMap( + tNameSequence& rNames + , tAnySequence& rValues + , const tPropertyNameValueMap& rValueMap + ) +{ + sal_Int32 nPropertyCount = rValueMap.size(); + rNames.realloc(nPropertyCount); + rValues.realloc(nPropertyCount); + + //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) + rNames[nN] = elem.first; + rValues[nN] = rAny; + ++nN; + } + } + //reduce to real property count + rNames.realloc(nN); + rValues.realloc(nN); +} + +uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , const OUString& rPropName ) +{ + sal_Int32 nCount = rPropNames.getLength(); + for( sal_Int32 nN = 0; nN < nCount; nN++ ) + { + if(rPropNames[nN] == rPropName) + return &rPropValues[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 + , const css::uno::Reference< + css::beans::XPropertySet >& xTarget ) +{ + bool bSuccess = false; + try + { + uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY ); + if( xShapeMultiProp.is() ) + { + xShapeMultiProp->setPropertyValues( rNames, rValues ); + bSuccess = true; + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance + } + + if(bSuccess) + return; + + try + { + sal_Int32 nCount = std::max( rNames.getLength(), rValues.getLength() ); + OUString aPropName; + uno::Any aValue; + for( sal_Int32 nN = 0; nN < nCount; nN++ ) + { + aPropName = rNames[nN]; + aValue = rValues[nN]; + + try + { + xTarget->setPropertyValue( aPropName, aValue ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } +} + +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 + 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/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx new file mode 100644 index 000000000..6ccaf9fb6 --- /dev/null +++ b/chart2/source/view/main/ShapeFactory.cxx @@ -0,0 +1,2764 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +namespace +{ + +void lcl_addProperty(uno::Sequence & rPropertyNames, uno::Sequence & rPropertyValues, + OUString const & rName, uno::Any const & rAny) +{ + rPropertyNames.realloc(rPropertyNames.getLength() + 1); + rPropertyNames[rPropertyNames.getLength() - 1] = rName; + + rPropertyValues.realloc(rPropertyValues.getLength() + 1); + rPropertyValues[rPropertyValues.getLength() - 1] = rAny; +} + +} // end anonymous namespace + +uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape( + const uno::Reference< drawing::XDrawPage>& xDrawPage ) +{ + uno::Reference 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. + uno::Reference xShape( + m_xShapeFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY); + uno::Reference xShapes2(xDrawPage, uno::UNO_QUERY_THROW); + xShapes2->addBottom(xShape); + + setShapeName(xShape, "com.sun.star.chart2.shapes"); + xShape->setSize(awt::Size(0,0)); + + xRet.set(xShape, uno::UNO_QUERY); + return xRet; +} + +void ShapeFactory::setPageSize(const uno::Reference&, 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::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::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::get()); +} + +// methods for 3D shape creation + +uno::Reference + ShapeFactory::createCube( + const uno::Reference& 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", "" ); + } + } + uno::Reference xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded ); + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if( xSourceProp.is()) + PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap ); + return xShape; +} + +uno::Reference + ShapeFactory::impl_createCube( + const uno::Reference& xTarget + , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize + , sal_Int32 nRotateZAngleHundredthDegree + , bool bRounded ) +{ + if( !xTarget.is() ) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference xMultiPropertySet(xShape, uno::UNO_QUERY); + OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); + if (xMultiPropertySet.is()) + { + 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, -nRotateZAngleHundredthDegree / 18000.00 * F_PI); + aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, + rPosition.PositionZ - (fDepth / 2.0)); + + uno::Sequence aPropertyNames { + UNO_NAME_3D_EXTRUDE_DEPTH, + UNO_NAME_3D_PERCENT_DIAGONAL, + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_TRANSFORM_MATRIX, + }; + + uno::Sequence aPropertyValues { + uno::Any(sal_Int32(fDepth)), // Depth + uno::Any(nPercentDiagonal), // PercentDiagonal + createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded), + uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)) + }; + + xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference + ShapeFactory::createCylinder( + const uno::Reference& xTarget + , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize + , sal_Int32 nRotateZAngleHundredthDegree ) +{ + return impl_createConeOrCylinder( + xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true ); +} + +uno::Reference + ShapeFactory::createPyramid( + const uno::Reference& 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; + + Reference< drawing::XShapes > 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 Reference< drawing::XShape >( xGroup, uno::UNO_QUERY ); +} + +uno::Reference + ShapeFactory::createCone( + const uno::Reference& xTarget + , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize + , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree ) +{ + return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree, false ); +} + +uno::Reference + ShapeFactory::impl_createConeOrCylinder( + const uno::Reference& xTarget + , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize + , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree + , bool bCylinder ) +{ + if( !xTarget.is() ) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DLatheObject" ), uno::UNO_QUERY ); + xTarget->add(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 + uno::Reference xMultiPropertySet(xShape, uno::UNO_QUERY); + OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); + if (xMultiPropertySet.is()) + { + 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,-nRotateZAngleHundredthDegree/18000.00*F_PI); + //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 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 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 + }; + + xMultiPropertySet->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(); + + rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1); + rReturn.Flags[0].realloc(nOldCount+nAddCount+1); + + for(sal_Int32 nN=0;nN( fWidthAngleRadian/fAngleSubdivisionRadian ); + if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount ) + nSegmentCount++; + + double fFirstSegmentAngle = fAngleSubdivisionRadian; + double fLastSegmentAngle = fAngleSubdivisionRadian; + if(nSegmentCount==1) + { + fFirstSegmentAngle = fWidthAngleRadian; + fLastSegmentAngle = 0.0; + } + else + { + double fFirstAngleOnSubDevision = (static_cast(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian; + if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) ) + fFirstSegmentAngle = fFirstAngleOnSubDevision-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 + + aReturn.Coordinates = drawing::PointSequenceSequence(1); + aReturn.Flags = drawing::FlagSequenceSequence(1); + + drawing::PointSequence aPoints(nPointCount); + drawing::FlagSequence aFlags(nPointCount); + + //!! 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( P0.getX()); + aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY()); + aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; + + aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX()); + aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY()); + aFlags[nPoint++] = drawing::PolygonFlags_CONTROL; + + aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX()); + aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY()); + aFlags [nPoint++] = drawing::PolygonFlags_CONTROL; + + if(nSegment==(nSegmentCount-1)) + { + aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX()); + aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY()); + aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; + } + } + + aReturn.Coordinates[0] = aPoints; + aReturn.Flags[0] = 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; + + aReturn.Coordinates = drawing::PointSequenceSequence(1); + aReturn.Flags = drawing::FlagSequenceSequence(1); + + drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords( + fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); + aReturn.Coordinates[0] = aOuterArc.Coordinates[0]; + aReturn.Flags[0] = aOuterArc.Flags[0]; + + drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords( + fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); + appendAndCloseBezierCoords( aReturn, aInnerArc, true ); + + return aReturn; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createPieSegment2D( + const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.ClosedBezierShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); //need to add the shape before setting of properties + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); + aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); + + const double fAngleSubdivisionRadian = F_PI/10.0; + + drawing::PolyPolygonBezierCoords aCoords + = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, + basegfx::deg2rad(fUnitCircleStartAngleDegree), + basegfx::deg2rad(fUnitCircleWidthAngleDegree), + aTransformationFromUnitCircle, fAngleSubdivisionRadian); + + xProp->setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createPieSegment( + const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); + xTarget->add(xShape); //need to add the shape before setting of properties + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); + aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); + + const double fAngleSubdivisionRadian = F_PI/32.0; + + drawing::PolyPolygonBezierCoords aCoords + = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, + basegfx::deg2rad(fUnitCircleStartAngleDegree), + basegfx::deg2rad(fUnitCircleWidthAngleDegree), + aTransformationFromUnitCircle, fAngleSubdivisionRadian); + + //depth + xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH + , uno::Any(static_cast(fDepth)) ); + + //PercentDiagonal + xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL + , uno::Any( sal_Int16(0) ) ); + + //Polygon + drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) ); + ShapeFactory::closePolygon( aPoly ); + xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D + , uno::Any( aPoly ) ); + + //DoubleSided + xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED + , uno::Any( true ) ); + + //Reduced lines + xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY + , uno::Any( true ) ); + + //TextureProjectionMode + xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y + , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); + + //TextureProjectionMode + xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X + , uno::Any( drawing::TextureProjectionMode_PARALLEL ) ); + xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y + , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference xMultiPropertySet(xShape, uno::UNO_QUERY); + OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); + if (xMultiPropertySet.is()) + { + try + { + uno::Sequence aPropertyNames{ + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_TEXTUREPOLYGON3D, + UNO_NAME_3D_NORMALSPOLYGON3D, + UNO_NAME_3D_LINEONLY, + UNO_NAME_3D_DOUBLE_SIDED + }; + + uno::Sequence 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)); + + xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); + + uno::Reference xPropertySet(xShape, uno::UNO_QUERY); + if (xSourceProp.is() && xPropertySet.is()) + { + PropertyMapper::setMappedProperties(xPropertySet, xSourceProp, rPropertyNameMap); + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::PolyPolygonShape3D& rPolyPolygon + , double fDepth ) +{ + if( !xTarget.is() ) + return nullptr; + + if( !rPolyPolygon.SequenceX.hasElements()) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference xMultiPropertySet(xShape, uno::UNO_QUERY); + OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); + if (xMultiPropertySet.is()) + { + try + { + uno::Sequence aPropertyNames{ + UNO_NAME_3D_EXTRUDE_DEPTH, + UNO_NAME_3D_PERCENT_DIAGONAL, + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_DOUBLE_SIDED, + }; + + uno::Sequence aPropertyValues { + uno::Any(sal_Int32(fDepth)), // depth + uno::Any(sal_Int16(0)), // PercentDiagonal + uno::Any(rPolyPolygon), // 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.SequenceZ.hasElements()&& rPolyPolygon.SequenceZ[0].hasElements()) + { + basegfx::B3DHomMatrix aM; + aM.translate(0, 0, rPolyPolygon.SequenceZ[0][0]); + drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM); + lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM)); + } + xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::PolyPolygonShape3D& rPolyPolygon ) +{ + if( !xTarget.is() ) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + //UNO_NAME_POLYGON "Polygon" drawing::PointSequence* + drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) ); + + //Polygon + xProp->setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( aPoints ) ); + + //ZOrder + //an area should always be behind other shapes + xProp->setPropertyValue( UNO_NAME_MISC_OBJ_ZORDER + , uno::Any( sal_Int32(0) ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +static drawing::PolyPolygonShape3D 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(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::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; + + switch(eSymbolType) + { + case Symbol_Square: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + case Symbol_UpArrow: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + break; + } + case Symbol_DownArrow: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + case Symbol_RightArrow: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + case Symbol_LeftArrow: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY; + break; + } + case Symbol_Bowtie: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + case Symbol_Sandglass: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + break; + } + case Symbol_Diamond: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY; + break; + } + case Symbol_HorizontalBar: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-0.2*fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-0.2*fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+0.2*fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+0.2*fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-0.2*fHeightH; + break; + } + case Symbol_VerticalBar: + { + *pInnerSequenceX++ = fX-0.2*fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX+0.2*fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX+0.2*fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX-0.2*fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX-0.2*fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + break; + } + case Symbol_Circle: + { + double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0); + // one point in the middle of each edge to get full size bounding rectangle + *pInnerSequenceX++ = fX + fWidthH; + *pInnerSequenceY++ = fY; + // 0 to PI/2 + for (sal_Int32 i = 1; i <= nQuarterCount; ++i) + { + *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega ); + *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega ); + } + // PI/2 to PI + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY - fHeightH; + for (sal_Int32 i = 1; i <= nQuarterCount; ++i) + { + *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega); + *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega); + } + // PI to 3/2*PI + *pInnerSequenceX++ = fX - fWidthH; + *pInnerSequenceY++ = fY; + for (sal_Int32 i = 1; i <= nQuarterCount; ++i) + { + *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega); + *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega); + } + // 3/2*PI to 2*PI + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY + fHeightH; + for (sal_Int32 i = 1; i <= nQuarterCount; ++i) + { + *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega); + *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega); + } + // close polygon + *pInnerSequenceX++ = fX + fWidthH; + *pInnerSequenceY++ = fY; + break; + } + case Symbol_Star: + { + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX+0.2*fWidthH; + *pInnerSequenceY++ = fY-0.2*fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX+0.2*fWidthH; + *pInnerSequenceY++ = fY+0.2*fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX-0.2*fWidthH; + *pInnerSequenceY++ = fY+0.2*fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX-0.2*fWidthH; + *pInnerSequenceY++ = fY-0.2*fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = 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; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY - fScaleY * fSmall; + + *pInnerSequenceX++ = fX - fScaleX * fLarge; + *pInnerSequenceY++ = fY - fHeightH; + + *pInnerSequenceX++ = fX - fWidthH; + *pInnerSequenceY++ = fY - fScaleY * fLarge; + + *pInnerSequenceX++ = fX - fScaleX * fSmall; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX - fWidthH; + *pInnerSequenceY++ = fY + fScaleY * fLarge; + + *pInnerSequenceX++ = fX - fScaleX * fLarge; + *pInnerSequenceY++ = fY + fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = fY + fScaleY * fSmall; + + *pInnerSequenceX++ = fX + fScaleX * fLarge; + *pInnerSequenceY++ = fY + fHeightH; + + *pInnerSequenceX++ = fX + fWidthH; + *pInnerSequenceY++ = fY + fScaleY * fLarge; + + *pInnerSequenceX++ = fX + fScaleX * fSmall; + *pInnerSequenceY++ = fY; + + *pInnerSequenceX++ = fX + fWidthH; + *pInnerSequenceY++ = fY - fScaleY * fLarge; + + *pInnerSequenceX++ = fX + fScaleX * fLarge; + *pInnerSequenceY++ = fY - fHeightH; + + *pInnerSequenceX++ = fX; + *pInnerSequenceY++ = 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; + + *pInnerSequenceX++ = fX-fdX; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fdX; + *pInnerSequenceY++ = fY-fdY; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fdY; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fdY; + + *pInnerSequenceX++ = fX-fdX; + *pInnerSequenceY++ = fY+fdY; + + *pInnerSequenceX++ = fX-fdX; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fdX; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fdX; + *pInnerSequenceY++ = fY+fdY; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fdY; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fdY; + + *pInnerSequenceX++ = fX+fdX; + *pInnerSequenceY++ = fY-fdY; + + *pInnerSequenceX++ = fX+fdY; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fdX; + *pInnerSequenceY++ = 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 + *pInnerSequenceX++ = fX-fScaleX * fHalf; + *pInnerSequenceY++ = fY-fHeightH; + //2 + *pInnerSequenceX++ = fX-fScaleX * fHalf; + *pInnerSequenceY++ = fY-fScaleY * fTwoY; + //3 + *pInnerSequenceX++ = fX-fScaleX * fThreeX; + *pInnerSequenceY++ = fY-fScaleY * fThreeY; + //4 + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fScaleY * fFourY; + //5 + *pInnerSequenceX++ = fX-fScaleX * fFiveX; + *pInnerSequenceY++ = fY; + //6 as 4 + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fScaleY * fFourY; + //7 as 3 + *pInnerSequenceX++ = fX-fScaleX * fThreeX; + *pInnerSequenceY++ = fY+fScaleY * fThreeY; + //8 as 2 + *pInnerSequenceX++ = fX-fScaleX * fHalf; + *pInnerSequenceY++ = fY+fScaleY * fTwoY; + //9 as 1 + *pInnerSequenceX++ = fX-fScaleX * fHalf; + *pInnerSequenceY++ = fY+fHeightH; + //10 as 1 + *pInnerSequenceX++ = fX+fScaleX * fHalf; + *pInnerSequenceY++ = fY+fHeightH; + //11 as 2 + *pInnerSequenceX++ = fX+fScaleX * fHalf; + *pInnerSequenceY++ = fY+fScaleY * fTwoY; + //12 as 3 + *pInnerSequenceX++ = fX+fScaleX * fThreeX; + *pInnerSequenceY++ = fY+fScaleY * fThreeY; + //13 as 4 + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fScaleY * fFourY; + //14 as 5 + *pInnerSequenceX++ = fX+fScaleX * fFiveX; + *pInnerSequenceY++ = fY; + //15 as 4 + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fScaleY * fFourY; + //16 as 3 + *pInnerSequenceX++ = fX+fScaleX * fThreeX; + *pInnerSequenceY++ = fY-fScaleY * fThreeY; + //17 as 2 + *pInnerSequenceX++ = fX+fScaleX * fHalf; + *pInnerSequenceY++ = fY-fScaleY * fTwoY; + // 18 as 1 + *pInnerSequenceX++ = fX+fScaleX * fHalf; + *pInnerSequenceY++ = fY-fHeightH; + // 19 = 1, closing + *pInnerSequenceX++ = fX-fScaleX * fHalf; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + default: //case Symbol_Square: + { + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY+fHeightH; + + *pInnerSequenceX++ = fX+fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + + *pInnerSequenceX++ = fX-fWidthH; + *pInnerSequenceY++ = fY-fHeightH; + break; + } + } + + return aPP; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createSymbol2D( + const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + drawing::PointSequenceSequence aPoints( PolyToPointSequence( + createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) )); + + //Polygon + xProp->setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( aPoints ) ); + + //LineColor + xProp->setPropertyValue( UNO_NAME_LINECOLOR + , uno::Any( nBorderColor ) ); + + //FillColor + xProp->setPropertyValue( UNO_NAME_FILLCOLOR + , uno::Any( nFillColor ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createGraphic2D( + const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY ); + xTarget->add(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", "" ); + } + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + xProp->setPropertyValue( "Graphic", uno::Any( xGraphic )); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShapes > + ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget + , const OUString& aName ) +{ + if( !xTarget.is() ) + return nullptr; + try + { + //create and add to target + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.GroupShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set name + if(!aName.isEmpty()) + setShapeName( xShape , aName ); + + {//workaround + //need this null size as otherwise empty group shapes where painted with a gray border + xShape->setSize(awt::Size(0,0)); + } + + //return + uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); + return xShapes; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return nullptr; +} + +uno::Reference< drawing::XShapes > + ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget + , const OUString& aName ) +{ + if( !xTarget.is() ) + return nullptr; + try + { + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DSceneObject" ), uno::UNO_QUERY ); + + xTarget->add(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 + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + ::basegfx::B3DHomMatrix aM; + xProp->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 + uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); + return xShapes; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return nullptr; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::Position3D& rPosition + , const drawing::Direction3D& rSize ) +{ + if( !xTarget.is() ) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY ); + xTarget->add(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 + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + xProp->setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createCircle( const uno::Reference< drawing::XShapes >& xTarget + , const awt::Size& rSize + , const awt::Point& rPosition ) +{ + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + xShape->setSize( rSize ); + xShape->setPosition( rPosition ); + + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::PolyPolygonShape3D& rPoints + , const VLineProperties& rLineProperties ) +{ + if( !xTarget.is() ) + return nullptr; + + if(!rPoints.SequenceX.hasElements()) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference xMultiPropertySet(xShape, uno::UNO_QUERY); + OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); + if (xMultiPropertySet.is()) + { + try + { + uno::Sequence aPropertyNames { + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_LINEONLY + }; + + uno::Sequence aPropertyValues { + uno::Any(rPoints), // 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); + } + xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::PointSequenceSequence& rPoints + , const VLineProperties* pLineProperties ) +{ + if( !xTarget.is() ) + return nullptr; + + if(!rPoints.hasElements()) + return nullptr; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.PolyLineShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + //Polygon + xProp->setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( rPoints ) ); + + if(pLineProperties) + { + //Transparency + if(pLineProperties->Transparence.hasValue()) + xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE + , pLineProperties->Transparence ); + + //LineStyle + if(pLineProperties->LineStyle.hasValue()) + xProp->setPropertyValue( UNO_NAME_LINESTYLE + , pLineProperties->LineStyle ); + + //LineWidth + if(pLineProperties->Width.hasValue()) + xProp->setPropertyValue( UNO_NAME_LINEWIDTH + , pLineProperties->Width ); + + //LineColor + if(pLineProperties->Color.hasValue()) + xProp->setPropertyValue( UNO_NAME_LINECOLOR + , pLineProperties->Color ); + + //LineDashName + if(pLineProperties->DashName.hasValue()) + xProp->setPropertyValue( "LineDashName" + , pLineProperties->DashName ); + + //LineCap + if(pLineProperties->LineCap.hasValue()) + xProp->setPropertyValue( UNO_NAME_LINECAP + , pLineProperties->LineCap ); + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createLine ( const uno::Reference< drawing::XShapes >& xTarget, + const awt::Size& rSize, const awt::Point& rPosition ) +{ + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.LineShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + xShape->setSize( rSize ); + xShape->setPosition( rPosition ); + + return xShape; +} + +uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle( + const uno::Reference< drawing::XShapes >& xTarget + , const awt::Size& rSize ) +{ + try + { + if(!xTarget.is()) + return nullptr; + + uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( + "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); + if( xShape.is()) + { + xTarget->add( xShape ); + ShapeFactory::makeShapeInvisible( xShape ); + xShape->setSize( rSize ); + } + return xShape; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return nullptr; +} + +uno::Reference< drawing::XShape > ShapeFactory::createRectangle( + const uno::Reference< drawing::XShapes >& xTarget, + const awt::Size& rSize, + const awt::Point& rPosition, + const tNameSequence& rPropNames, + const tAnySequence& rPropValues, + StackPosition ePos ) +{ + uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( + "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); + if( xShape.is()) + { + if (ePos == StackPosition::Bottom) + { + uno::Reference xTarget2(xTarget, uno::UNO_QUERY); + if (xTarget2.is()) + xTarget2->addBottom(xShape); + } + else + xTarget->add(xShape); + + xShape->setPosition( rPosition ); + xShape->setSize( rSize ); + uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY_THROW ); + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xPropSet ); + } + + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createRectangle( + const uno::Reference< + drawing::XShapes >& xTarget ) +{ + uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( + "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); + xTarget->add( xShape ); + + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set text + uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY ); + if( xTextRange.is() ) + xTextRange->setString( rText ); + + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if( xProp.is() ) + { + //set properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try + { + if (rATransformation.hasValue()) + xProp->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; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget + , const uno::Sequence< OUString >& rTextParagraphs + , const uno::Sequence< tNameSequence >& rParaPropNames + , const uno::Sequence< tAnySequence >& rParaPropValues + , const tNameSequence& rPropNames + , const tAnySequence& rPropValues + , const uno::Any& rATransformation ) +{ + if( !xTarget.is() ) + return nullptr; + + if( !rTextParagraphs.hasElements() ) + return nullptr; + + sal_Int32 nNumberOfParagraphs = rTextParagraphs.getLength(); + + if( rParaPropNames.getLength() != nNumberOfParagraphs ) + return nullptr; + + if( rParaPropValues.getLength() != nNumberOfParagraphs ) + return nullptr; + + bool bNotEmpty = false; + for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) + { + if( !rTextParagraphs[nN].isEmpty() ) + { + bNotEmpty = true; + break; + } + } + if( !bNotEmpty ) + return nullptr; + + //create shape and add to page + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set paragraph properties + bNotEmpty = false; + Reference< text::XText > xText( xShape, uno::UNO_QUERY ); + if( xText.is() ) + { + // 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 = xText->createTextCursor(); + Reference< text::XTextCursor > xSelectionCursor = xText->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( !rTextParagraphs[nN].isEmpty() ) + { + xInsertCursor->gotoEnd(false); + if( bNotEmpty ) + { + xText->insertString( xInsertCursor, "\n", false ); + } + xSelectionCursor->gotoEnd(false); + xText->insertString( xInsertCursor, rTextParagraphs[nN], false ); + bNotEmpty = true; + xSelectionCursor->gotoEnd(true); // select current paragraph + PropertyMapper::setMultiProperties( rParaPropNames[nN], rParaPropValues[nN], xSelectionProp ); + } + } + } + } + } + + if( !bNotEmpty ) + return nullptr; + + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if( xProp.is() ) + { + //set whole text shape properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + + if (rATransformation.hasValue()) + { + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try + { + xProp->setPropertyValue( "Transformation", rATransformation ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget + , 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + xTarget->add(xShape); + + //set paragraph properties + bNotEmpty = false; + Reference< text::XText > xText( xShape, uno::UNO_QUERY ); + if( xText.is() ) + { + // 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 = xText->createTextCursor(); + Reference< text::XTextCursor > xSelectionCursor = xText->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 ); + xText->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; + + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + if( xProp.is() ) + { + //set whole text shape properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + + if( rATransformation.hasValue() ) + { + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try + { + xProp->setPropertyValue( "Transformation", rATransformation ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + return xShape; +} + +uno::Reference< drawing::XShape > + ShapeFactory::createText( const uno::Reference< drawing::XShapes >& 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 + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( + "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + try + { + xTarget->add(xShape); + + //set text and text properties + uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY ); + uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() ); + uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); + if( !xText.is() || !xTextCursor.is() || !xShapeProp.is() || !xTextProperties.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, xShapeProp ); + } + + 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); + xText->insertString( xTextCursor, aLabel, false ); + xTextCursor->gotoEnd(true); + uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY ); + + PropertyMapper::setMappedProperties( xTargetProps, xSourceProps + , PropertyMapper::getPropertyNameMapForCharacterProperties() ); + + // adapt font size according to page size + awt::Size aOldRefSize; + if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize ) + { + RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize ); + } + } + } + else + { + for( const uno::Reference< chart2::XFormattedString >& rxFS : std::as_const(xFormattedString) ) + { + xTextCursor->gotoEnd(false); + xText->insertString( xTextCursor, rxFS->getString(), false ); + xTextCursor->gotoEnd(true); + } + awt::Size aOldRefSize; + bool bHasRefPageSize = + ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize ); + + if( xFormattedString.hasElements() ) + { + uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY ); + PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() ); + + // adapt font size according to page size + if( bHasRefPageSize ) + { + RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize ); + } + } + } + + // #i109336# Improve auto positioning in chart + float fFontHeight = 0.0; + if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( "CharHeight" ) >>= fFontHeight ) ) + { + fFontHeight *= ( 2540.0f / 72.0f ); // pt -> 1/100 mm + 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 ) ); + xShapeProp->setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) ); + xShapeProp->setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) ); + xShapeProp->setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) ); + xShapeProp->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 ); + xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); + + xShapeProp->setPropertyValue( "ParaAdjust", uno::Any( style::ParagraphAdjust_CENTER ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return xShape; +} + +ShapeFactory* ShapeFactory::getOrCreateShapeFactory(const uno::Reference< lang::XMultiServiceFactory>& xFactory) +{ + static ShapeFactory* pShapeFactory = new ShapeFactory(xFactory); + return pShapeFactory; +} + +uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape( + const uno::Reference< drawing::XDrawPage>& xDrawPage ) +{ + uno::Reference< drawing::XShapes > 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.set( xShape, uno::UNO_QUERY ); + break; + } + } + } + } + return xRet; +} + +void ShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape ) +{ + uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet"); + if( xShapeProp.is()) + { + try + { + xShapeProp->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE )); + xShapeProp->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 uno::Reference< drawing::XShape >& xShape + , const OUString& rName ) +{ + if(!xShape.is()) + return; + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + OSL_ENSURE(xProp.is(), "shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + xProp->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( drawing::PolyPolygonShape3D& rPoly) +{ + // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true + for( auto const & i : std::as_const(rPoly.SequenceX) ) + if( i.getLength() > 1 ) + return true; + return false; +} + +bool ShapeFactory::isPolygonEmptyOrSinglePoint( 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)); +} + +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 ); +} + +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(fFactor*rSourceSizeWithCorrectAspectRatio.Width); + aNewSize.Height=static_cast(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(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0); + aNewPosition.Y += static_cast(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0); + return aNewPosition; +} + +::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape( + const uno::Reference< drawing::XShape >& xShape ) +{ + ::basegfx::B2IRectangle aRet; + + if( xShape.is() ) + { + awt::Point aPos = xShape->getPosition(); + awt::Size aSize = xShape->getSize(); + aRet = BaseGFXHelper::makeRectangle(aPos,aSize); + } + return aRet; + +} + +awt::Size ShapeFactory::getSizeAfterRotation( + const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) +{ + awt::Size aRet(0,0); + if(xShape.is()) + { + const awt::Size aSize( xShape->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( + aSize.Width*rtl::math::sin( fAnglePi ) + + aSize.Height*rtl::math::cos( fAnglePi )); + aRet.Width = static_cast( + aSize.Width*rtl::math::cos( fAnglePi ) + + aSize.Height*rtl::math::sin( fAnglePi )); + } + } + return aRet; +} + +void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& 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 ); + } + } +} + +} //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 000000000..74c8ad046 --- /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 +#include +#include +#include +#include + +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::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::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::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 000000000..088df5850 --- /dev/null +++ b/chart2/source/view/main/VButton.cxx @@ -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/. + */ + +#include "VButton.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace chart +{ + +using namespace css; + +VButton::VButton() + : m_bShowArrow(true) + , m_nArrowColor(0x00000000) + , m_nBGColor(0x00E6E6E6) +{ +} + +void VButton::init(const uno::Reference& xTargetPage, + const uno::Reference& xFactory) +{ + m_xTarget = xTargetPage; + m_xShapeFactory = xFactory; +} + +uno::Reference VButton::createTriangle(awt::Size aSize) +{ + uno::Reference xShape; + xShape.set(m_xShapeFactory->createInstance("com.sun.star.drawing.PolyPolygonShape"), uno::UNO_QUERY); + + if (!xShape.is()) + return xShape; + + uno::Reference xProperies(xShape, uno::UNO_QUERY); + + 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; + + xProperies->setPropertyValue("Name", uno::makeAny(m_sCID)); + xProperies->setPropertyValue(UNO_NAME_POLYPOLYGON, uno::Any(PolyToPointSequence(aPolyPolygon))); + xProperies->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_NONE)); + xProperies->setPropertyValue("FillColor", uno::makeAny(m_nArrowColor)); + + return xShape; +} + +void VButton::createShapes(const uno::Reference& xTextProp) +{ + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + + std::unique_ptr pPropNames(new tNameSequence); + std::unique_ptr pPropValues(new tAnySequence); + + PropertyMapper::getTextLabelMultiPropertyLists(xTextProp, *pPropNames, *pPropValues); + + m_xShape.set(pShapeFactory->createGroup2D(m_xTarget, m_sCID), uno::UNO_QUERY); + m_xShape->setPosition(m_aPosition); + m_xShape->setSize(m_aSize); + + uno::Reference xContainer(m_xShape, uno::UNO_QUERY); + if (!xContainer.is()) + return; + + 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(*pPropNames, *pPropValues, aTextValueMap); + + uno::Reference xEntry = pShapeFactory->createText( + xContainer, m_sLabel, *pPropNames, *pPropValues, uno::Any()); + + if (xEntry.is()) + { + xEntry->setPosition(m_aPosition); + xEntry->setSize(m_aSize); + } + + if (!m_bShowArrow) + return; + + awt::Size aPolySize {280, 180}; + + uno::Reference xPoly = createTriangle(aPolySize); + if (xPoly.is()) + { + 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 000000000..cb4203326 --- /dev/null +++ b/chart2/source/view/main/VButton.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/. + */ + +#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VBUTTON_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VBUTTON_HXX + +#include +#include +#include +#include + +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: + css::uno::Reference m_xShapeFactory; + css::uno::Reference m_xTarget; + css::uno::Reference 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; + + css::uno::Reference + createTriangle(css::awt::Size aSize); + +public: + VButton(); + + void init(const css::uno::Reference& xTargetPage, + const css::uno::Reference& xFactory); + + void createShapes(const css::uno::Reference& 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 +#endif + +/* 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 000000000..91388d1c2 --- /dev/null +++ b/chart2/source/view/main/VDataSeries.cxx @@ -0,0 +1,1150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace chart { + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; + +void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel ) +{ + Model = xModel; + Doubles = DataSequenceToDoubleSequence( xModel ); +} + +bool VDataSequence::is() const +{ + return Model.is(); +} +void VDataSequence::clear() +{ + Model = nullptr; + Doubles.realloc(0); +} + +double VDataSequence::getValue( sal_Int32 index ) const +{ + if( 0<=index && indexgetNumberFormatKeyByIndex( index ); + } + + return nNumberFormatKey; +} + +sal_Int32 VDataSequence::getLength() const +{ + return Doubles.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]& xDataSequence ) +{ + //#i71686#, #i101968#, #i102428# + sal_Int32 nCount = rData.Doubles.getLength(); + for( sal_Int32 i = 0; i < nCount; ++i ) + { + if( !std::isnan( rData.Doubles[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 uno::Reference< XDataSeries >& 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(1.0) + , m_fYMeanValue(1.0) + + , m_aAttributedDataPointIndexList() + + , 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) +{ + ::rtl::math::setNan( & m_fXMeanValue ); + ::rtl::math::setNan( & m_fYMeanValue ); + + uno::Reference xDataSource( xDataSeries, uno::UNO_QUERY ); + + uno::Sequence< uno::Reference< + chart2::data::XLabeledDataSequence > > aDataSequences = + xDataSource->getDataSequences(); + + for(sal_Int32 nN = aDataSequences.getLength();nN--;) + { + if(!aDataSequences[nN].is()) + continue; + uno::Reference xDataSequence( aDataSequences[nN]->getValues()); + uno::Reference 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(); + } + + uno::Reference xProp(xDataSeries, uno::UNO_QUERY ); + if( !xProp.is()) + return; + + try + { + //get AttributedDataPoints + xProp->getPropertyValue("AttributedDataPoints") >>= m_aAttributedDataPointIndexList; + + xProp->getPropertyValue("StackingDirection") >>= m_eStackingDirection; + + xProp->getPropertyValue("AttachedAxisIndex") >>= m_nAxisIndex; + 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.Doubles.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 + double fNan; + ::rtl::math::setNan( & fNan ); + sal_Int32 nPointIndex = 0; + for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ ) + { + std::vector< double > aSinglePoint; + aSinglePoint.push_back( (nPointIndex < m_aValues_X.Doubles.getLength()) ? m_aValues_X.Doubles[nPointIndex] : fNan ); + aSinglePoint.push_back( (nPointIndex < m_aValues_Y.Doubles.getLength()) ? m_aValues_Y.Doubles[nPointIndex] : fNan ); + aTmp.push_back( aSinglePoint ); + } + + //do sort + std::stable_sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() ); + + //fill the sorted points back to the members + m_aValues_X.Doubles.realloc( m_nPointCount ); + m_aValues_Y.Doubles.realloc( m_nPointCount ); + + for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ ) + { + m_aValues_X.Doubles[nPointIndex]=aTmp[nPointIndex][0]; + m_aValues_Y.Doubles[nPointIndex]=aTmp[nPointIndex][1]; + } +} + +void VDataSeries::releaseShapes() +{ + m_xGroupShape.set(nullptr); + m_xLabelsGroupShape.set(nullptr); + m_xErrorXBarsGroupShape.set(nullptr); + m_xErrorYBarsGroupShape.set(nullptr); + m_xFrontSubGroupShape.set(nullptr); + m_xBackSubGroupShape.set(nullptr); + + m_aPolyPolygonShape3D.SequenceX.realloc(0); + m_aPolyPolygonShape3D.SequenceY.realloc(0); + m_aPolyPolygonShape3D.SequenceZ.realloc(0); + m_nPolygonIndex = 0; +} + +const uno::Reference& 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, OUString(), 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 = 0.0; + if(m_aValues_X.is()) + { + if( 0<=index && indexm_aValues_X.getLength()) + { + double nOldVal = mpOldSeries->m_aValues_X.Doubles[index]; + fRet = nOldVal + (fRet - nOldVal) * mnPercent; + } + } + else + ::rtl::math::setNan( &fRet ); + } + 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 + else + ::rtl::math::setNan( &fRet ); + } + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; +} + +double VDataSeries::getYValue( sal_Int32 index ) const +{ + double fRet = 0.0; + if(m_aValues_Y.is()) + { + if( 0<=index && indexm_aValues_Y.getLength()) + { + double nOldVal = mpOldSeries->m_aValues_Y.Doubles[index]; + fRet = nOldVal + (fRet - nOldVal) * mnPercent; + } + } + else + ::rtl::math::setNan( &fRet ); + } + 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 + else + ::rtl::math::setNan( &fRet ); + } + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; +} + +void VDataSeries::getMinMaxXValue(double& fMin, double& fMax) const +{ + rtl::math::setNan( &fMax ); + rtl::math::setNan( &fMin ); + + 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") : OUString(CHART_UNONAME_NUMFMT); + bool bHasNumberFormat = false; + bool bLinkToSource = true; + uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( nPointIndex )); + sal_Int32 nNumberFormat = -1; + if( xPointProp.is() && (xPointProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource)) + { + 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") : OUString(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( const OUString& rRole ) +{ + if (rRole == "values-y") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y; + else if (rRole == "values-size") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size; + else if (rRole == "values-min") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min; + else if (rRole == "values-max") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max; + else if (rRole == "values-first") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First; + else if (rRole == "values-last") + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last; + else if (rRole == "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 uno::Reference< chart2::XChartType >& xChartType, bool bSwapXAndY ) const +{ + sal_Int32 nLabelPlacement=0; + try + { + uno::Reference< beans::XPropertySet > xPointProps( getPropertiesOfPoint( nPointIndex ) ); + if( xPointProps.is() ) + xPointProps->getPropertyValue("LabelPlacement") >>= nLabelPlacement; + + 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(aCustomLabelPosition.Primary * m_aReferenceSize.Width) + aTextShapePos.X; + aPos.Y = static_cast(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; + RelativePosition aCustomLabelPosition; + try + { + if( isAttributedDataPoint(nPointIndex) ) + { + uno::Reference< beans::XPropertySet > xPointProps(m_xDataSeries->getDataPointByIndex(nPointIndex)); + 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=0.0; + ::rtl::math::setInf(&fMin, false); + + 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) ) + ::rtl::math::setNan(&fMin); + + return fMin; +} + +double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const +{ + double fMax=0.0; + ::rtl::math::setInf(&fMax, true); + + 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 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.Doubles.realloc( m_nPointCount ); + for(sal_Int32 nN=m_aValues_X.getLength();nN--;) + m_aValues_X.Doubles[nN] = nN+1; + } + return m_aValues_X.Doubles; +} + +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.Doubles.realloc( m_nPointCount ); + for(sal_Int32 nN=m_aValues_Y.getLength();nN--;) + m_aValues_Y.Doubles[nN] = nN+1; + } + return m_aValues_Y.Doubles; +} + +double VDataSeries::getXMeanValue() const +{ + if( std::isnan( m_fXMeanValue ) ) + { + uno::Reference< XRegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( "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 ) ) + { + uno::Reference< XRegressionCurveCalculator > xCalculator( + RegressionCurveHelper::createRegressionCurveCalculatorByServiceName("com.sun.star.chart2.MeanValueRegressionCurve")); + uno::Sequence< double > aXValuesDummy; + xCalculator->recalculateRegression( aXValuesDummy, getAllY() ); + m_fYMeanValue = xCalculator->getCurveValue( 1.0 ); + } + return m_fYMeanValue; +} + +static std::unique_ptr getSymbolPropertiesFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) +{ + std::unique_ptr< Symbol > apSymbolProps( new Symbol() ); + try + { + if( xProp->getPropertyValue("Symbol") >>= *apSymbolProps ) + { + //use main color to fill symbols + xProp->getPropertyValue("Color") >>= apSymbolProps->FillColor; + // border of symbols always same as fill color + apSymbolProps->BorderColor = apSymbolProps->FillColor; + } + else + apSymbolProps.reset(); + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return apSymbolProps; +} + +Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const +{ + Symbol* pRet=nullptr; + if( isAttributedDataPoint( index ) ) + { + adaptPointCache( index ); + if (!m_apSymbolProperties_AttributedPoint) + m_apSymbolProperties_AttributedPoint + = getSymbolPropertiesFromPropertySet(getPropertiesOfPoint(index)); + pRet = m_apSymbolProperties_AttributedPoint.get(); + //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_apSymbolProperties_Series) + m_apSymbolProperties_Series + = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries()); + if( m_apSymbolProperties_Series && m_apSymbolProperties_Series->Style != SymbolStyle_NONE ) + { + if (!m_apSymbolProperties_InvisibleSymbolForSelection) + { + m_apSymbolProperties_InvisibleSymbolForSelection.reset(new Symbol); + m_apSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD; + m_apSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square + m_apSymbolProperties_InvisibleSymbolForSelection->Size = com::sun::star::awt::Size(0, 0);//tdf#126033 + m_apSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible + m_apSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible + } + pRet = m_apSymbolProperties_InvisibleSymbolForSelection.get(); + } + } + } + else + { + if (!m_apSymbolProperties_Series) + m_apSymbolProperties_Series + = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries()); + pRet = m_apSymbolProperties_Series.get(); + } + + 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; + Reference< beans::XPropertySet > xSeriesProp( getPropertiesOfSeries() ); + if( xSeriesProp.is() ) + xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint; + return bVaryColorsByPoint; +} + +uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfPoint( sal_Int32 index ) const +{ + if( isAttributedDataPoint( index ) ) + return m_xDataSeries->getDataPointByIndex(index); + return getPropertiesOfSeries(); +} + +uno::Reference VDataSeries::getPropertiesOfSeries() const +{ + return uno::Reference(m_xDataSeries, css::uno::UNO_QUERY); +} + +static std::unique_ptr getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) +{ + std::unique_ptr< DataPointLabel > apLabel( new DataPointLabel() ); + 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_apLabel_AttributedPoint.reset(); + m_apLabelPropNames_AttributedPoint.reset(); + m_apLabelPropValues_AttributedPoint.reset(); + m_apSymbolProperties_AttributedPoint.reset(); + m_nCurrentAttributedPoint = nNewPointIndex; + } +} + +DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const +{ + DataPointLabel* pRet = nullptr; + if( isAttributedDataPoint( index ) ) + { + adaptPointCache( index ); + if (!m_apLabel_AttributedPoint) + m_apLabel_AttributedPoint + = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index)); + pRet = m_apLabel_AttributedPoint.get(); + } + else + { + if (!m_apLabel_Series) + m_apLabel_Series + = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index)); + pRet = m_apLabel_Series.get(); + } + 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 ) ) + 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_apLabelPropValues_Series) + { + // Cache these properties for the whole series. + m_apLabelPropNames_Series.reset(new tNameSequence); + m_apLabelPropValues_Series.reset(new tAnySequence); + xTextProp.set( getPropertiesOfPoint( index )); + PropertyMapper::getTextLabelMultiPropertyLists( + xTextProp, *m_apLabelPropNames_Series, *m_apLabelPropValues_Series); + bDoDynamicFontResize = true; + } + pPropNames = m_apLabelPropNames_Series.get(); + pPropValues = m_apLabelPropValues_Series.get(); + } + + 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()) + { + double fNan; + ::rtl::math::setNan( &fNan ); + return fNan; + } + + 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(static_cast(fValue)); + Color aOldColor(static_cast(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 t = aOldColor.GetTransparency() + (aColor.GetTransparency() - aOldColor.GetTransparency()) * mnPercent; + Color aRet(t, 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 000000000..d16495e42 --- /dev/null +++ b/chart2/source/view/main/VLegend.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 "VLegend.hxx" +#include "VButton.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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; + + awt::Size aPropRefSize; + float fFontHeight( 0.0 ); + if( xProp.is() && ( xProp->getPropertyValue( "CharHeight") >>= fFontHeight )) + { + fResult = fFontHeight; + try + { + if( (xProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) && + (aPropRefSize.Height > 0)) + { + fResult = ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + // pt -> 1/100th mm + return (fResult * (2540.0 / 72.0)); +} + +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 & rEntries, + const Reference< lang::XMultiServiceFactory > & xShapeFactory, + const Reference< drawing::XShapes > & xTarget, + std::vector< Reference< drawing::XShape > > & rOutTextShapes, + const tPropertyValues & rTextProperties ) +{ + awt::Size aResult; + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + + for (ViewLegendEntry const & rEntry : rEntries) + { + try + { + OUString aLabelString; + Sequence< Reference< XFormattedString2 > > aLabelSeq = rEntry.aLabel; + for( sal_Int32 i = 0; i < aLabelSeq.getLength(); ++i ) + { + // todo: support more than one text range + if( i == 1 ) + break; + + aLabelString += aLabelSeq[i]->getString(); + // workaround for Issue #i67540# + if( aLabelString.isEmpty()) + aLabelString = " "; + } + + Reference< drawing::XShape > xEntry = + pShapeFactory->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< Reference< drawing::XShape > >& 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< Reference< drawing::XShape > >& 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 & rEntries, + css::chart::ChartLegendExpansion eExpansion, + bool bSymbolsLeftSide, + double fViewFontSize, + const awt::Size& rMaxSymbolExtent, + tPropertyValues & rTextProperties, + const Reference< drawing::XShapes > & xTarget, + const Reference< lang::XMultiServiceFactory > & xShapeFactory, + 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, "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< Reference< drawing::XShape > > aTextShapes; + awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xShapeFactory, 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(aTextShapes.size()); nN++ ) + { + Reference< drawing::XShape > 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; + } + } + if( nCurrentColumn < nCurrentColumnCount ) + 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(aTextShapes.size()) ) + { + DrawModelWrapper::removeShape( aTextShapes[nEntry] ); + aTextShapes.pop_back(); + } + if( nEntry < nNumberOfEntries && ( nEntry != 0 || nNumberOfColumns != 1 ) ) + { + DrawModelWrapper::removeShape( rEntries[ nEntry ].aSymbol ); + rEntries.pop_back(); + nNumberOfEntries--; + } + } + if (nRow == 0 && nNumberOfColumns == 1) + { + try + { + OUString aLabelString = rEntries[0].aLabel[0]->getString(); + const OUString sDots = "..."; + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + for (sal_Int32 nNewLen = aLabelString.getLength() - sDots.getLength(); nNewLen > 0; nNewLen--) + { + OUString aNewLabel = aLabelString.copy(0, nNewLen) + sDots; + Reference xEntry = pShapeFactory->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].aLabel[0]->setString(aNewLabel); + aRowHeights[0] = nSumHeight; + aColumnWidths[0] = nWidth; + break; + } + } + DrawModelWrapper::removeShape(xEntry); + } + if (aTextShapes.size() == 0) + { + DrawModelWrapper::removeShape(rEntries[0].aSymbol); + 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(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 + Reference< drawing::XShape > 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 + Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol ); + 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 xSymbol( rEntries[ nEntry ].aSymbol ); + aPos = xSymbol->getPosition(); + aPos.X += nLegendWidth; + xSymbol->setPosition( aPos ); + Reference< drawing::XShape > 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(rOutAvailableSpace.Y)/static_cast(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( SvtLanguageOptions().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> lcl_createButtons( + uno::Reference const & xLegendContainer, + uno::Reference const & xShapeFactory, + ChartModel& rModel, bool bPlaceButtonsVertically, long & nUsedHeight) +{ + std::vector> aButtons; + + uno::Reference 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 aPivotFieldEntries = xPivotTableDataProvider->getColumnFields(); + for (chart2::data::PivotTableFieldEntry const & sColumnFieldEntry : aPivotFieldEntries) + { + auto pButton = std::make_shared(); + aButtons.push_back(pButton); + pButton->init(xLegendContainer, xShapeFactory); + 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( + const Reference< XLegend > & xLegend, + const Reference< uno::XComponentContext > & xContext, + const std::vector< LegendEntryProvider* >& rLegendEntryProviderList, + const Reference< drawing::XShapes >& xTargetPage, + const Reference< lang::XMultiServiceFactory >& xFactory, + ChartModel& rModel ) + : m_xTarget(xTargetPage) + , m_xShapeFactory(xFactory) + , m_xLegend(xLegend) + , mrModel(rModel) + , m_xContext(xContext) + , m_aLegendEntryProviderList(rLegendEntryProviderList) + , m_nDefaultWritingMode(text::WritingMode2::LR_TB) +{ +} + +void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode ) +{ + m_nDefaultWritingMode = nDefaultWritingMode; +} + +bool VLegend::isVisible( const Reference< XLegend > & xLegend ) +{ + if( ! xLegend.is()) + return false; + + bool bShow = false; + try + { + Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY_THROW ); + xLegendProp->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_xShapeFactory.is() && + m_xTarget.is())) + return; + + try + { + //create shape and add to page + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( mrModel ) ); + m_xShape.set( pShapeFactory->createGroup2D( m_xTarget, + ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle )), + uno::UNO_QUERY); + + // create and insert sub-shapes + Reference< drawing::XShapes > xLegendContainer( m_xShape, uno::UNO_QUERY ); + if( xLegendContainer.is()) + { + // for quickly setting properties + tPropertyValues aLineFillProperties; + tPropertyValues aTextProperties; + + Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY ); + css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH; + awt::Size aLegendSize( rAvailableSpace ); + + bool bCustom = false; + LegendPosition eLegendPosition = LegendPosition_LINE_END; + if (xLegendProp.is()) + { + // get Expansion property + xLegendProp->getPropertyValue("Expansion") >>= eExpansion; + if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM ) + { + RelativeSize aRelativeSize; + if (xLegendProp->getPropertyValue("RelativeSize") >>= aRelativeSize) + { + aLegendSize.Width = static_cast(::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width )); + aLegendSize.Height = static_cast(::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height )); + bCustom = true; + } + else + { + eExpansion = css::chart::ChartLegendExpansion_HIGH; + } + } + xLegendProp->getPropertyValue("AnchorPosition") >>= eLegendPosition; + lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, rPageSize ); + } + + // create entries + double fViewFontSize = lcl_CalcViewFontSize( xLegendProp, 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 aViewEntries; + for(LegendEntryProvider* pLegendEntryProvider : m_aLegendEntryProviderList) + { + if (pLegendEntryProvider) + { + std::vector aNewEntries = pLegendEntryProvider->createLegendEntries( + aMaxSymbolExtent, eLegendPosition, xLegendProp, + xLegendContainer, m_xShapeFactory, m_xContext, mrModel); + if (aNewEntries.size() == 0) + return; + aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() ); + } + } + + bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp, m_nDefaultWritingMode ); + + uno::Reference xPivotTableDataProvider( mrModel.getDataProvider(), uno::UNO_QUERY ); + bool bIsPivotChart = xPivotTableDataProvider.is(); + + if ( !aViewEntries.empty() || bIsPivotChart ) + { + // create buttons + long nUsedButtonHeight = 0; + bool bPlaceButtonsVertically = (eLegendPosition != LegendPosition_PAGE_START && + eLegendPosition != LegendPosition_PAGE_END && + eExpansion != css::chart::ChartLegendExpansion_WIDE); + + std::vector> aButtons = lcl_createButtons(xLegendContainer, m_xShapeFactory, 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, + m_xShapeFactory, aLegendSize, nUsedButtonHeight, rPageSize, bIsPivotChart, rDefaultLegendSize); + + uno::Reference xModelPage(mrModel.getPageBackground()); + + for (std::shared_ptr 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); + } + } + + Reference< drawing::XShape > xBorder = + pShapeFactory->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(); + Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY_THROW ); + chart2::RelativePosition aRelativePosition; + + bool bDefaultLegendSize = rDefaultLegendSize.Width != 0 || rDefaultLegendSize.Height != 0; + bool bAutoPosition = + ! (xLegendProp->getPropertyValue( "RelativePosition") >>= aRelativePosition); + + LegendPosition ePos = LegendPosition_LINE_END; + xLegendProp->getPropertyValue( "AnchorPosition") >>= ePos; + + bool bOverlay = false; + xLegendProp->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 000000000..297a99129 --- /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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VLEGEND_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VLEGEND_HXX + +#include + +#include + +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 LegendEntryProvider; + +class VLegend +{ +public: + VLegend( const css::uno::Reference< css::chart2::XLegend > & xLegend, + const css::uno::Reference< css::uno::XComponentContext > & xContext, + const std::vector< LegendEntryProvider* >& rLegendEntryProviderList, + const css::uno::Reference< css::drawing::XShapes >& xTargetPage, + const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, + 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 css::uno::Reference< css::chart2::XLegend > & xLegend ); + +private: + css::uno::Reference< css::drawing::XShapes > m_xTarget; + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + css::uno::Reference< css::chart2::XLegend > m_xLegend; + css::uno::Reference< css::drawing::XShape > 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 +#endif + +/* 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 000000000..1ccc0de34 --- /dev/null +++ b/chart2/source/view/main/VLegendSymbolFactory.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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,"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 Reference< drawing::XShape > & xShape, + ::chart::VLegendSymbolFactory::PropertyType ePropertyType, + const awt::Size& aMaxSymbolExtent) +{ + ::chart::tNameSequence aPropNames; + ::chart::tAnySequence aPropValues; + getPropNamesAndValues( xProp, aPropNames, aPropValues, + ePropertyType, aMaxSymbolExtent ); + + Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); + ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp ); +} + +} // anonymous namespace + +namespace chart +{ + +Reference< drawing::XShape > VLegendSymbolFactory::createSymbol( + const awt::Size& rEntryKeyAspectRatio, + const Reference< drawing::XShapes >& rSymbolContainer, + LegendSymbolStyle eStyle, + const Reference< lang::XMultiServiceFactory > & xShapeFactory, + const Reference< beans::XPropertySet > & xLegendEntryProperties, + PropertyType ePropertyType, const uno::Any& rExplicitSymbol ) +{ + Reference< drawing::XShape > xResult; + + if( ! (rSymbolContainer.is() && xShapeFactory.is())) + return xResult; + + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); + xResult.set( pShapeFactory->createGroup2D( rSymbolContainer ), uno::UNO_QUERY ); + + Reference< drawing::XShapes > xResultGroup( xResult, uno::UNO_QUERY ); + if( ! xResultGroup.is()) + return xResult; + + // add an invisible square box to maintain aspect ratio + pShapeFactory->createInvisibleRectangle( xResultGroup, rEntryKeyAspectRatio ); + + // create symbol + try + { + if( eStyle == LegendSymbolStyle::Line ) + { + Reference< drawing::XShape > xLine = + pShapeFactory->createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ), + awt::Point( 0, rEntryKeyAspectRatio.Height/2 )); + if( xLine.is()) + { + lcl_setPropertiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio ); + } + + Reference< drawing::XShape > xSymbol; + 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 ); + ShapeFactory* pFactory = ShapeFactory::getOrCreateShapeFactory( xShapeFactory ); + 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; + + xSymbol.set( pFactory->createSymbol2D( + xResultGroup, + aPos, + aSymbolSize, + aSymbol.StandardSymbol, + aSymbol.BorderColor, + aSymbol.FillColor )); + } + else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC ) + { + xSymbol.set( pFactory->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 ); + Reference< drawing::XShape > xShape = + pShapeFactory->createCircle( xResultGroup, awt::Size( nSize, nSize ), + awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 )); + if( xShape.is() ) + { + 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 + + pShapeFactory->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 000000000..e86c5f7b8 --- /dev/null +++ b/chart2/source/view/main/VLineProperties.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 +#include +#include +#include +#include + +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 000000000..6d3ba587f --- /dev/null +++ b/chart2/source/view/main/VPolarTransformation.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 +#include + +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() +{ +} + +// ____ XTransformation ____ +Sequence< double > SAL_CALL VPolarTransformation::transform( + const Sequence< double >& rSourceValues ) +{ + 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 B3DPointToSequence(aRet); +} + +sal_Int32 SAL_CALL VPolarTransformation::getSourceDimension() +{ + return 3; +} + +sal_Int32 SAL_CALL VPolarTransformation::getTargetDimension() +{ + return 3; +} + +} // 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 000000000..53e214f76 --- /dev/null +++ b/chart2/source/view/main/VTitle.cxx @@ -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 . + */ + +#include "VTitle.hxx" +#include +#include +#include +#include +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +VTitle::VTitle( const uno::Reference< XTitle > & xTitle ) + : m_xTitle(xTitle) + , m_aCID() + , m_fRotationAngleDegree(0.0) + , m_nXPos(0) + , m_nYPos(0) +{ +} + +VTitle::~VTitle() +{ +} + +void VTitle::init( + const uno::Reference< drawing::XShapes >& xTargetPage + , const uno::Reference< lang::XMultiServiceFactory >& xFactory + , const OUString& rCID ) +{ + m_xTarget = xTargetPage; + m_xShapeFactory = xFactory; + 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; + uno::Reference< beans::XPropertySet > xShapeProp( m_xShape, uno::UNO_QUERY ); + if(!xShapeProp.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( -m_fRotationAngleDegree*F_PI/180.0 );//#i78696#->#i80521# + aM.translate( m_nXPos, m_nYPos); + xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } +} + +void VTitle::createShapes( + const awt::Point& rPos + , const awt::Size& rReferenceSize + , const awt::Size& rTextMaxWidth ) +{ + 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 (m_fRotationAngleDegree <= 15.0 || m_fRotationAngleDegree >= 345.0 + || (m_fRotationAngleDegree >= 165.0 && m_fRotationAngleDegree <= 195.0)) + nTextMaxWidth = rTextMaxWidth.Width; + else + nTextMaxWidth = rTextMaxWidth.Height; + + ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + m_xShape =pShapeFactory->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 000000000..261458025 --- /dev/null +++ b/chart2/source/view/main/VTitle.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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VTITLE_HXX +#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VTITLE_HXX + +#include +#include +#include +#include + +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; } + +namespace chart +{ + +class VTitle final +{ +public: + explicit VTitle( const css::uno::Reference< css::chart2::XTitle > & xTitle ); + ~VTitle(); + + void init( const css::uno::Reference< css::drawing::XShapes >& xTargetPage + , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + , const OUString& rCID ); + + void createShapes( const css::awt::Point& rPos + , const css::awt::Size& rReferenceSize + , const css::awt::Size& nTextMaxWidth ); + + double getRotationAnglePi() const; + css::awt::Size getUnrotatedSize() const; + css::awt::Size getFinalSize() const; + void changePosition( const css::awt::Point& rPos ); + +private: + css::uno::Reference< css::drawing::XShapes > m_xTarget; + css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + css::uno::Reference< css::chart2::XTitle > m_xTitle; + css::uno::Reference< css::drawing::XShape > m_xShape; + OUString m_aCID; + + double m_fRotationAngleDegree; + sal_Int32 m_nXPos; + sal_Int32 m_nYPos; +}; + +} //namespace chart +#endif + +/* 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 000000000..3965f4b8f --- /dev/null +++ b/chart2/uiconfig/accelerator/en-US/default.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/menubar/menubar.xml b/chart2/uiconfig/menubar/menubar.xml new file mode 100644 index 000000000..354ebbc19 --- /dev/null +++ b/chart2/uiconfig/menubar/menubar.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/popupmenu/draw.xml b/chart2/uiconfig/popupmenu/draw.xml new file mode 100644 index 000000000..f7f762ea8 --- /dev/null +++ b/chart2/uiconfig/popupmenu/draw.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/popupmenu/drawtext.xml b/chart2/uiconfig/popupmenu/drawtext.xml new file mode 100644 index 000000000..e13990ca0 --- /dev/null +++ b/chart2/uiconfig/popupmenu/drawtext.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/statusbar/statusbar.xml b/chart2/uiconfig/statusbar/statusbar.xml new file mode 100644 index 000000000..4f718b8d1 --- /dev/null +++ b/chart2/uiconfig/statusbar/statusbar.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/chart2/uiconfig/toolbar/arrowshapes.xml b/chart2/uiconfig/toolbar/arrowshapes.xml new file mode 100644 index 000000000..3f74148c7 --- /dev/null +++ b/chart2/uiconfig/toolbar/arrowshapes.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/basicshapes.xml b/chart2/uiconfig/toolbar/basicshapes.xml new file mode 100644 index 000000000..148245f66 --- /dev/null +++ b/chart2/uiconfig/toolbar/basicshapes.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/calloutshapes.xml b/chart2/uiconfig/toolbar/calloutshapes.xml new file mode 100644 index 000000000..04176302c --- /dev/null +++ b/chart2/uiconfig/toolbar/calloutshapes.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/drawbar.xml b/chart2/uiconfig/toolbar/drawbar.xml new file mode 100644 index 000000000..e6f48002a --- /dev/null +++ b/chart2/uiconfig/toolbar/drawbar.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/flowchartshapes.xml b/chart2/uiconfig/toolbar/flowchartshapes.xml new file mode 100644 index 000000000..019a90862 --- /dev/null +++ b/chart2/uiconfig/toolbar/flowchartshapes.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/standardbar.xml b/chart2/uiconfig/toolbar/standardbar.xml new file mode 100644 index 000000000..a4f3c21d3 --- /dev/null +++ b/chart2/uiconfig/toolbar/standardbar.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/starshapes.xml b/chart2/uiconfig/toolbar/starshapes.xml new file mode 100644 index 000000000..cbc07fc70 --- /dev/null +++ b/chart2/uiconfig/toolbar/starshapes.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/symbolshapes.xml b/chart2/uiconfig/toolbar/symbolshapes.xml new file mode 100644 index 000000000..9ba9f22e0 --- /dev/null +++ b/chart2/uiconfig/toolbar/symbolshapes.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/toolbar/toolbar.xml b/chart2/uiconfig/toolbar/toolbar.xml new file mode 100644 index 000000000..809174ba2 --- /dev/null +++ b/chart2/uiconfig/toolbar/toolbar.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/3dviewdialog.ui b/chart2/uiconfig/ui/3dviewdialog.ui new file mode 100644 index 000000000..1b6e51f67 --- /dev/null +++ b/chart2/uiconfig/ui/3dviewdialog.ui @@ -0,0 +1,101 @@ + + + + + + False + 6 + 3D View + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/attributedialog.ui b/chart2/uiconfig/ui/attributedialog.ui new file mode 100644 index 000000000..943d43a94 --- /dev/null +++ b/chart2/uiconfig/ui/attributedialog.ui @@ -0,0 +1,115 @@ + + + + + + False + 6 + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-revert-to-saved + True + True + True + True + + + False + True + 0 + + + + + gtk-ok + True + True + True + True + True + True + + + False + True + 1 + + + + + gtk-cancel + True + True + True + True + + + False + True + 2 + + + + + gtk-help + True + True + True + True + + + False + True + 3 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + False + True + 1 + + + + + + reset + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/chardialog.ui b/chart2/uiconfig/ui/chardialog.ui new file mode 100644 index 000000000..440afa42d --- /dev/null +++ b/chart2/uiconfig/ui/chardialog.ui @@ -0,0 +1,250 @@ + + + + + + False + 6 + Character + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-revert-to-saved + True + True + True + True + + + False + True + 0 + + + + + gtk-ok + True + True + True + True + True + True + + + False + True + 1 + + + + + gtk-cancel + True + True + True + True + + + False + True + 2 + + + + + gtk-help + True + True + True + True + + + False + True + 3 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + Font + + + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + Font Effects + + + 1 + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + True + False + Position + + + 2 + False + + + + + False + True + 1 + + + + + + reset + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/chartdatadialog.ui b/chart2/uiconfig/ui/chartdatadialog.ui new file mode 100644 index 000000000..c8337d30c --- /dev/null +++ b/chart2/uiconfig/ui/chartdatadialog.ui @@ -0,0 +1,319 @@ + + + + + + False + 6 + Data Table + True + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-close + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + True + True + 12 + + + True + False + + + True + False + Insert Row + True + chart2/res/dataeditor_icon01.png + + + False + True + + + + + True + False + Insert Series + True + chart2/res/dataeditor_icon02.png + + + False + True + + + + + True + False + Insert Text Column + True + chart2/res/dataeditor_icon07.png + + + False + True + + + + + True + False + Delete Row + True + chart2/res/dataeditor_icon03.png + + + False + True + + + + + True + False + Delete Series + True + chart2/res/dataeditor_icon04.png + + + False + True + + + + + True + False + + + False + True + + + + + True + False + Move Series Left + True + chart2/res/dataeditor_icon08.png + + + False + True + + + + + True + False + Move Series Right + True + chart2/res/dataeditor_icon05.png + + + False + True + + + + + True + False + Move Row Up + True + chart2/res/dataeditor_icon09.png + + + False + True + + + + + True + False + Move Row Down + True + chart2/res/dataeditor_icon06.png + + + False + True + + + + + 0 + 0 + + + + + True + False + True + True + vertical + 6 + + + True + True + external + never + + + True + False + + + True + False + True + + + + + + + + + + + + + + + + False + True + 0 + + + + + True + True + external + never + + + True + False + + + True + False + True + + + + + + + + + + + + + + + + False + True + 1 + + + + + True + False + True + True + vertical + + + + + + False + True + 2 + + + + + 0 + 1 + + + + + False + True + 1 + + + + + + close + help + + + diff --git a/chart2/uiconfig/ui/charttypedialog.ui b/chart2/uiconfig/ui/charttypedialog.ui new file mode 100644 index 000000000..def049f9b --- /dev/null +++ b/chart2/uiconfig/ui/charttypedialog.ui @@ -0,0 +1,89 @@ + + + + + + False + 6 + Chart Type + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/columnfragment.ui b/chart2/uiconfig/ui/columnfragment.ui new file mode 100644 index 000000000..c5cf43f1b --- /dev/null +++ b/chart2/uiconfig/ui/columnfragment.ui @@ -0,0 +1,34 @@ + + + + + + True + False + + + True + False + gtk-missing-image + + + False + True + 0 + + + + + 5 + True + True + 1 + + + False + True + 1 + + + + diff --git a/chart2/uiconfig/ui/combobox.ui b/chart2/uiconfig/ui/combobox.ui new file mode 100644 index 000000000..b72cf753c --- /dev/null +++ b/chart2/uiconfig/ui/combobox.ui @@ -0,0 +1,38 @@ + + + + + + True + False + vertical + + + True + False + 6 + True + True + 6 + + + True + False + True + True + + + False + True + 0 + + + + + False + True + 0 + + + + diff --git a/chart2/uiconfig/ui/datarangedialog.ui b/chart2/uiconfig/ui/datarangedialog.ui new file mode 100644 index 000000000..0812509c6 --- /dev/null +++ b/chart2/uiconfig/ui/datarangedialog.ui @@ -0,0 +1,192 @@ + + + + + + False + 6 + Data Ranges + False + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + Data Range + + + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + Data Series + + + 1 + False + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/dlg_DataLabel.ui b/chart2/uiconfig/ui/dlg_DataLabel.ui new file mode 100644 index 000000000..e38ef6b67 --- /dev/null +++ b/chart2/uiconfig/ui/dlg_DataLabel.ui @@ -0,0 +1,515 @@ + + + + + + 359 + 1 + 10 + + + False + 6 + Data Labels for all Data Series + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + 6 + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + True + + + Show value as _number + True + True + False + True + 0 + True + + + 0 + 0 + + + + + Show value as _percentage + True + True + False + True + 0 + True + + + 0 + 1 + + + + + Show _category + True + True + False + True + 0 + True + + + 0 + 2 + + + + + Show _legend key + True + True + False + True + 0 + True + + + 0 + 3 + + + + + Auto text _wrap + True + True + False + True + 0 + True + + + 0 + 4 + + + + + Number _format... + True + True + True + center + True + + + 1 + 0 + + + + + Percentage f_ormat... + True + True + True + center + True + + + 1 + 1 + + + + + False + True + ABCD + + + + + + 1 + 3 + + + + + True + False + 12 + + + True + False + _Separator + True + LB_TEXT_SEPARATOR + 0 + + + False + True + 0 + + + + + True + False + center + + Space + Comma + Semicolon + New line + Period + + + + False + True + 1 + + + + + 0 + 5 + 2 + + + + + True + False + 12 + + + True + False + Place_ment + True + LB_LABEL_PLACEMENT + 0 + + + False + True + 0 + + + + + True + False + center + + Best fit + Center + Above + Top left + Left + Bottom left + Below + Bottom right + Right + Top right + Inside + Outside + Near origin + + + + False + True + 1 + + + + + 0 + 6 + 2 + + + + + False + Number Format for Percentage Value + + + 1 + 2 + + + + + + + + + + + + True + False + Text Attributes + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + + + False + True + 0 + + + + + True + True + center + True + adjustmentDEGREE + True + + + False + True + 1 + + + + + True + False + _Degrees + True + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Te_xt direction + True + LB_LABEL_TEXTDIR + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + Rotate Text + 0 + + + + + + + + False + True + 1 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/dlg_InsertErrorBars.ui b/chart2/uiconfig/ui/dlg_InsertErrorBars.ui new file mode 100644 index 000000000..fcfe86e01 --- /dev/null +++ b/chart2/uiconfig/ui/dlg_InsertErrorBars.ui @@ -0,0 +1,633 @@ + + + + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + True + False + chart2/res/selectrange.png + + + True + False + chart2/res/selectrange.png + + + False + 6 + Legend + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + 6 + vertical + 6 + + + True + False + 12 + True + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + _None + True + True + False + True + 0 + True + + + False + True + 0 + + + + + _Constant Value + True + True + False + True + 0 + True + RB_NONE + + + False + True + 1 + + + + + _Percentage + True + True + False + True + 0 + True + RB_NONE + + + False + True + 2 + + + + + True + False + 6 + + + True + True + False + True + 0 + True + RB_NONE + + + False + True + 0 + + + + + True + False + + Standard Error + Standard Deviation + Variance + Error Margin + + + + False + True + 1 + + + + + False + True + 3 + + + + + Cell _Range + True + True + False + True + 0 + True + RB_NONE + + + False + True + 4 + + + + + + + + + True + False + Error Category + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + Positive _and Negative + True + True + False + True + 0 + True + + + 1 + 0 + + + + + Pos_itive + True + True + False + True + 0 + True + RB_BOTH + + + 1 + 1 + + + + + Ne_gative + True + True + False + True + 0 + True + RB_BOTH + + + 1 + 2 + + + + + True + False + gtk-missing-image + + + 0 + 0 + + + + + True + False + gtk-missing-image + + + 0 + 1 + + + + + True + False + gtk-missing-image + + + 0 + 2 + + + + + + + + + True + False + Error Indicator + 0 + + + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + P_ositive (+) + True + MF_POSITIVE + + + False + True + 0 + + + + + True + True + adjustmentPOS + 2 + + + False + True + 1 + + + + + True + True + True + True + + + False + True + 2 + + + + + True + True + True + Select data range + imageRANGE_SELECT_POSITIVE + + + False + True + 3 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + _Negative (-) + True + MF_NEGATIVE + + + False + True + 0 + + + + + True + True + adjustmentNEG + 2 + + + False + True + 1 + + + + + True + True + True + True + + + False + True + 2 + + + + + True + True + True + Select data range + imageRANGE_SELECT_NEG + + + False + True + 3 + + + + + False + True + 1 + + + + + Same value for both + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + Parameters + 0 + + + + + + + + False + True + 1 + + + + + False + Select Range for Positive Error Bars + + + False + True + 2 + + + + + False + Select Range for Negative Error Bars + + + False + True + 3 + + + + + False + From Data Table + + + False + True + 4 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/dlg_InsertLegend.ui b/chart2/uiconfig/ui/dlg_InsertLegend.ui new file mode 100644 index 000000000..cf386794e --- /dev/null +++ b/chart2/uiconfig/ui/dlg_InsertLegend.ui @@ -0,0 +1,234 @@ + + + + + + False + 6 + Legend + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + 6 + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + 6 + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + _Display legend + True + True + False + True + 0 + True + + + False + True + 0 + + + + + True + False + 12 + 6 + + + _Left + True + True + False + True + 0 + True + True + + + 0 + 0 + + + + + _Right + True + True + False + True + 0 + True + left + + + 0 + 1 + + + + + _Top + True + True + False + True + 0 + True + left + + + 0 + 2 + + + + + _Bottom + True + True + False + True + 0 + True + left + + + 0 + 3 + + + + + False + True + 1 + + + + + + + + + True + False + Position + 0 + + + + + + + + False + True + 0 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/imagefragment.ui b/chart2/uiconfig/ui/imagefragment.ui new file mode 100644 index 000000000..a8e89f2b8 --- /dev/null +++ b/chart2/uiconfig/ui/imagefragment.ui @@ -0,0 +1,22 @@ + + + + + + True + False + vertical + + + True + False + gtk-missing-image + + + True + True + 0 + + + + diff --git a/chart2/uiconfig/ui/insertaxisdlg.ui b/chart2/uiconfig/ui/insertaxisdlg.ui new file mode 100644 index 000000000..c445cc825 --- /dev/null +++ b/chart2/uiconfig/ui/insertaxisdlg.ui @@ -0,0 +1,283 @@ + + + + + + False + 6 + Axes + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + 6 + True + top + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + True + True + 12 + True + + + True + False + True + 0 + none + + + True + False + 6 + 12 + + + True + False + True + vertical + 6 + + + _X axis + True + True + False + True + 0 + True + + + False + True + 0 + + + + + _Y axis + True + True + False + True + 0 + True + + + False + True + 1 + + + + + _Z axis + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + True + Axes + + + + + + + + False + True + 0 + + + + + True + False + True + 0 + none + + + True + False + 6 + 12 + + + True + False + True + vertical + 6 + + + X _axis + True + True + False + True + 0 + True + + + False + True + 0 + + + + + Y ax_is + True + True + False + True + 0 + True + + + False + True + 1 + + + + + Z axi_s + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + True + Secondary Axes + + + + + + + + False + True + 1 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/insertgriddlg.ui b/chart2/uiconfig/ui/insertgriddlg.ui new file mode 100644 index 000000000..ae3863a59 --- /dev/null +++ b/chart2/uiconfig/ui/insertgriddlg.ui @@ -0,0 +1,283 @@ + + + + + + False + 6 + Grids + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + 6 + True + top + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + True + True + 12 + True + + + True + False + True + 0 + none + + + True + False + 6 + 12 + + + True + False + True + vertical + 6 + + + _X axis + True + True + False + True + 0 + True + + + False + True + 0 + + + + + _Y axis + True + True + False + True + 0 + True + + + False + True + 1 + + + + + _Z axis + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + True + Major Grids + + + + + + + + False + True + 0 + + + + + True + False + True + 0 + none + + + True + False + 6 + 12 + + + True + False + True + vertical + 6 + + + X _axis + True + True + False + True + 0 + True + + + False + True + 0 + + + + + Y ax_is + True + True + False + True + 0 + True + + + False + True + 1 + + + + + Z axi_s + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + True + Minor Grids + + + + + + + + False + True + 1 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/inserttitledlg.ui b/chart2/uiconfig/ui/inserttitledlg.ui new file mode 100644 index 000000000..3457aeb02 --- /dev/null +++ b/chart2/uiconfig/ui/inserttitledlg.ui @@ -0,0 +1,372 @@ + + + + + + False + 6 + Titles + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + vertical + 12 + + + True + False + 6 + 12 + + + True + False + _Title + True + maintitle + 0 + + + 0 + 0 + + + + + True + False + _Subtitle + True + subtitle + 0 + + + 0 + 1 + + + + + True + True + True + True + + + 1 + 0 + + + + + True + True + True + True + + + 1 + 1 + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + True + False + _X axis + True + primaryXaxis + 0 + + + 0 + 0 + + + + + True + False + _Y axis + True + primaryYaxis + 0 + + + 0 + 1 + + + + + True + False + _Z axis + True + primaryZaxis + 0 + + + 0 + 2 + + + + + True + True + True + True + + + 1 + 0 + + + + + True + True + True + True + + + 1 + 1 + + + + + True + True + True + True + + + 1 + 2 + + + + + + + + + True + False + Axes + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + True + False + X _axis + True + secondaryXaxis + 0 + + + 0 + 0 + + + + + True + False + Y ax_is + True + secondaryYaxis + 0 + + + 0 + 1 + + + + + True + True + True + True + + + 1 + 0 + + + + + True + True + True + True + + + 1 + 1 + + + + + + + + + True + False + Secondary Axes + + + + + + + + False + True + 2 + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/paradialog.ui b/chart2/uiconfig/ui/paradialog.ui new file mode 100644 index 000000000..0b90192a4 --- /dev/null +++ b/chart2/uiconfig/ui/paradialog.ui @@ -0,0 +1,298 @@ + + + + + + False + 6 + Paragraph + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-revert-to-saved + True + True + True + True + + + False + True + 0 + + + + + gtk-ok + True + True + True + True + True + True + + + False + True + 1 + + + + + gtk-cancel + True + True + True + True + + + False + True + 2 + + + + + gtk-help + True + True + True + True + + + False + True + 3 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + Indents & Spacing + + + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + Alignment + 0.4699999988079071 + + + 1 + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + True + False + Asian Typography + + + 2 + False + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + True + False + Tabs + + + 3 + False + + + + + False + True + 1 + + + + + + reset + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/sidebaraxis.ui b/chart2/uiconfig/ui/sidebaraxis.ui new file mode 100644 index 000000000..bd113fd84 --- /dev/null +++ b/chart2/uiconfig/ui/sidebaraxis.ui @@ -0,0 +1,129 @@ + + + + + + 359 + 5 + + + True + False + 6 + 6 + + + True + False + 6 + 6 + + + Show labels + True + True + False + True + 0 + True + + + 0 + 0 + + + + + Reverse direction + True + True + False + True + 0 + True + + + 0 + 3 + + + + + True + False + 12 + 6 + 5 + + + True + False + end + _Label position: + True + comboboxtext_label_position + + + 0 + 0 + + + + + True + False + + Near Axis + Near Axis (other side) + Outside start + Outside end + + + + 1 + 0 + + + + + True + False + end + center + _Text orientation: + True + spinbutton1 + + + 0 + 1 + + + + + True + True + adjustmentSpinDegrees + + + 1 + 1 + + + + + 0 + 1 + + + + + + + + 0 + 0 + + + + diff --git a/chart2/uiconfig/ui/sidebarelements.ui b/chart2/uiconfig/ui/sidebarelements.ui new file mode 100644 index 000000000..22b1ff60c --- /dev/null +++ b/chart2/uiconfig/ui/sidebarelements.ui @@ -0,0 +1,557 @@ + + + + + + True + False + + + True + False + 6 + vertical + 6 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 6 + + + Subtitle + True + True + False + True + 0 + True + + + 1 + 0 + + + + + Title + True + True + False + True + 0 + True + + + 0 + 0 + + + + + + + + + True + False + Titles + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + + + True + True + False + Show Legend + 5 + True + 0 + True + + + 0 + 0 + + + + + True + False + 6 + + + True + False + end + _Placement: + True + end + + + False + True + 0 + + + + + 100 + True + False + + Right + Top + Bottom + Left + + + + False + True + 3 + + + + + 1 + 0 + + + + + False + True + 0 + + + + + Show the legend without overlapping the chart + True + False + False + True + 0 + True + + + False + True + 1 + + + + + + + + + True + False + Legend + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 6 + + + X axis + True + True + False + True + 0 + True + + + 0 + 0 + + + + + X axis title + True + True + False + True + 0 + True + + + 1 + 0 + + + + + Y axis + True + True + False + True + 0 + True + + + 0 + 1 + + + + + Y axis title + True + True + False + True + 0 + True + + + 1 + 1 + + + + + Z axis + True + True + False + True + 0 + True + + + 0 + 2 + + + + + Z axis title + True + True + False + True + 0 + True + + + 1 + 2 + + + + + 2nd X axis + True + False + True + 0 + True + + + 0 + 3 + + + + + 2nd X axis title + True + False + True + 0 + True + + + 1 + 3 + + + + + 2nd Y axis + True + False + True + 0 + True + + + 0 + 4 + + + + + 2nd Y axis title + True + False + True + 0 + True + + + 1 + 4 + + + + + + + + + True + False + Axes + + + + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 6 + + + Horizontal major + True + True + False + True + 0 + True + + + 0 + 0 + + + + + Vertical major + True + True + False + True + 0 + True + + + 0 + 1 + + + + + Horizontal minor + True + True + False + True + 0 + True + + + 1 + 0 + + + + + Vertical minor + True + True + False + True + 0 + True + + + 1 + 1 + + + + + + + + + True + False + Gridlines + + + + + + + + False + True + 3 + + + + + False + + + False + True + Title + + + 0 + 0 + + + + + False + True + Subtitle + + + 1 + 0 + + + + + False + True + 4 + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/sidebarerrorbar.ui b/chart2/uiconfig/ui/sidebarerrorbar.ui new file mode 100644 index 000000000..032fcce70 --- /dev/null +++ b/chart2/uiconfig/ui/sidebarerrorbar.ui @@ -0,0 +1,237 @@ + + + + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + True + False + chart2/res/errorup_30.png + + + True + False + chart2/res/errorbothverti_30.png + + + True + False + chart2/res/errordown_30.png + + + True + False + + + True + False + 6 + vertical + 6 + top + + + True + False + vertical + 6 + + + True + False + 6 + 6 + + + True + False + start + Category: + True + comboboxtext_type + + + 0 + 0 + + + + + True + False + + Constant + Percentage + Cell Range or Data Table + Standard deviation + Standard error + Variance + Error margin + + + + 1 + 0 + + + + + True + False + start + Positive (+): + + + 0 + 1 + + + + + True + False + start + Negative (-): + + + 0 + 2 + + + + + True + True + start + 0.00 + adjustmentPOS + 2 + + + 1 + 1 + + + + + True + True + start + 0.00 + alpha + adjustmentNEG + 2 + + + 1 + 2 + + + + + True + False + 6 + + + True + True + False + Positive and Negative + image2 + True + 0 + True + True + + + False + True + 0 + + + + + True + True + False + Positive + image1 + True + 0 + True + radiobutton_positive_negative + + + False + True + 1 + + + + + True + True + False + Negative + image3 + True + 0 + True + radiobutton_positive_negative + + + False + True + 2 + + + + + 1 + 3 + + + + + True + False + start + Indicator + + + 0 + 3 + + + + + False + True + 0 + + + + + False + True + 0 + + + + + 0 + 0 + + + + diff --git a/chart2/uiconfig/ui/sidebarseries.ui b/chart2/uiconfig/ui/sidebarseries.ui new file mode 100644 index 000000000..568569464 --- /dev/null +++ b/chart2/uiconfig/ui/sidebarseries.ui @@ -0,0 +1,313 @@ + + + + + + True + False + + + True + False + 6 + vertical + 6 + + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + vertical + 6 + + + Show data labels + True + True + False + True + 0 + True + + + False + True + 0 + + + + + True + False + 12 + 6 + + + True + False + P_lacement: + True + comboboxtext_label + + + False + True + 0 + + + + + True + False + + Above + Below + Center + Outside + Inside + Near origin + + + + False + True + 1 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + Show trendline + True + True + False + True + 0 + True + + + False + True + 1 + + + + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + + + Y error bars + True + True + False + True + 0 + True + + + False + True + 0 + + + + + X error bars + True + True + False + True + 0 + True + + + False + True + 1 + + + + + + + + + True + False + Error Bars + + + + + + + + False + True + 3 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + Primary Y axis + True + True + False + True + 0 + True + True + + + False + True + 0 + + + + + Secondary Y axis + True + True + False + True + 0 + True + True + radiobutton_primary_axis + + + False + True + 1 + + + + + + + + + True + False + Align Series to Axis + + + + + + + + False + True + 4 + + + + + False + Data series '%1' + + + False + True + 5 + + + + + + + + + True + False + label + + + + + + + + False + True + 1 + + + + + 0 + 0 + + + + diff --git a/chart2/uiconfig/ui/sidebartype.ui b/chart2/uiconfig/ui/sidebartype.ui new file mode 100644 index 000000000..d6d9dbaa0 --- /dev/null +++ b/chart2/uiconfig/ui/sidebartype.ui @@ -0,0 +1,418 @@ + + + + + + 1 + 100 + 1 + 10 + + + + + + + + + + + + + + + + + + + + + True + False + 6 + + + True + False + True + 3 + 6 + + + True + True + True + never + never + in + + + True + False + + + True + False + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK + True + + + + + + + 0 + 1 + + + + + True + False + 3 + + + True + False + True + 6 + + + _3D Look + True + False + True + 0 + True + + + + + + 0 + 0 + + + + + False + True + + Simple + Realistic + + + + + + + 1 + 0 + + + + + 0 + 0 + + + + + True + False + Sh_ape + True + shape + 0.02 + 0 + + + 0 + 1 + + + + + True + True + True + in + + + True + True + True + liststore1 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + + + 0 + 2 + + + + + 0 + 2 + + + + + True + False + 3 + + + _Stack series + True + False + True + 0 + True + + + 0 + 0 + + + + + True + False + 12 + + + True + False + 3 + + + On top + True + False + True + 0 + True + True + + + 0 + 0 + + + + + Percent + True + False + True + 0 + True + ontop + + + 0 + 1 + + + + + Deep + True + False + True + 0 + True + ontop + + + 0 + 2 + + + + + + + 0 + 1 + + + + + True + False + True + 6 + + + False + _Line type + True + linetype + 0 + + + 0 + 0 + + + + + False + True + + Straight + Smooth + Stepped + + + + 1 + 0 + + + + + Properties... + True + True + True + + + 2 + 0 + + + + + 0 + 2 + + + + + _Sort by X values + True + False + True + 0 + True + + + 0 + 3 + + + + + True + False + True + 6 + + + False + True + _Number of lines + True + nolines + end + 0 + + + 0 + 0 + + + + + True + True + True + True + adjustment1 + + + 1 + 0 + + + + + 0 + 4 + + + + + 0 + 3 + + + + + True + False + 3 + 6 + + + True + False + center + True + liststore2 + 0 + 1 + + + + 0 + + + + + + 2 + + + + + 0 + 0 + 2 + + + + + 0 + 0 + + + + + 0 + 0 + + + + diff --git a/chart2/uiconfig/ui/smoothlinesdlg.ui b/chart2/uiconfig/ui/smoothlinesdlg.ui new file mode 100644 index 000000000..63714a454 --- /dev/null +++ b/chart2/uiconfig/ui/smoothlinesdlg.ui @@ -0,0 +1,231 @@ + + + + + + 1 + 15 + 3 + 1 + 10 + + + 1 + 100 + 20 + 1 + 10 + + + False + 6 + Smooth Lines + True + -1 + -1 + dialog + + + + + + False + vertical + 12 + + + False + True + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + 6 + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + vertical + + + True + False + 12 + + + True + False + Line _Type: + True + 0 + + + False + True + 0 + + + + + True + False + 0 + + Cubic spline + B-spline + + + + False + True + 1 + + + + + False + True + 1 + + + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + True + False + start + _Resolution: + True + ResolutionSpinbutton + + + 0 + 0 + + + + + True + False + start + _Degree of polynomials: + True + PolynomialsSpinButton + + + 0 + 1 + + + + + True + True + start + True + ResolutionAdjustment + + + 1 + 0 + + + + + True + True + start + True + PolynomialsAdjustment + + + 1 + 1 + + + + + + + False + True + 2 + + + + + False + True + 0 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/steppedlinesdlg.ui b/chart2/uiconfig/ui/steppedlinesdlg.ui new file mode 100644 index 000000000..56592471e --- /dev/null +++ b/chart2/uiconfig/ui/steppedlinesdlg.ui @@ -0,0 +1,236 @@ + + + + + + + False + 6 + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + True + False + chart2/res/step_center_x_30.png + + + 0 + 1 + + + + + True + False + chart2/res/step_end_30.png + + + 2 + 0 + + + + + True + False + chart2/res/step_center_y_30.png + + + 2 + 1 + + + + + _Start with horizontal line + True + True + False + True + 0 + True + True + + + 1 + 0 + + + + + Step at the _horizontal mean + True + True + False + True + 0 + True + True + step_start_rb + + + 1 + 1 + + + + + _End with horizontal line + True + True + False + True + 0 + True + True + step_start_rb + + + 3 + 0 + + + + + Step to the _vertical mean + True + True + False + True + 0 + True + True + step_start_rb + + + 3 + 1 + + + + + True + False + chart2/res/step_start_30.png + + + 0 + 0 + + + + + + + + + True + False + Type of Stepping + + + + + + + + False + True + 1 + + + + + + ok + cancel + help + + + diff --git a/chart2/uiconfig/ui/titlerotationtabpage.ui b/chart2/uiconfig/ui/titlerotationtabpage.ui new file mode 100644 index 000000000..04fa4dfce --- /dev/null +++ b/chart2/uiconfig/ui/titlerotationtabpage.ui @@ -0,0 +1,168 @@ + + + + + + 359 + 5 + + + True + False + True + 6 + 0 + none + + + True + False + 6 + 12 + + + True + False + True + 6 + 12 + + + True + False + 6 + 12 + + + True + True + 40 + adjustmentSpinDegrees + True + + + 0 + 2 + + + + + True + False + 40 + _Degrees + True + + + 1 + 2 + + + + + + + + + + + + + + + + + 1 + 0 + + + + + True + False + 6 + 12 + + + Ve_rtically stacked + True + True + False + True + 0.019999999552965164 + True + True + + + 0 + 0 + + + + + False + ABCD + + + 0 + 1 + + + + + 2 + 0 + + + + + True + False + Te_xt direction: + True + + + 0 + 1 + + + + + True + False + + + 1 + 1 + 2 + + + + + True + False + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + center + center + + + 0 + 0 + + + + + + + + + True + False + Text Orientation + + + + + + + diff --git a/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui b/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui new file mode 100644 index 000000000..6cf5681f3 --- /dev/null +++ b/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui @@ -0,0 +1,127 @@ + + + + + + True + False + 6 + vertical + 6 + + + True + False + 12 + + + True + False + Sche_me + True + LB_SCHEME + 0 + + + False + True + 0 + + + + + True + False + + Simple + Realistic + Custom + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + 6 + + + True + False + + + False + True + 0 + + + + + _Shading + True + True + False + True + 0 + True + + + False + True + 1 + + + + + _Object borders + True + True + False + True + 0 + True + + + False + True + 2 + + + + + _Rounded edges + True + True + False + True + 0 + True + + + False + True + 3 + + + + + False + True + 1 + + + + diff --git a/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui b/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui new file mode 100644 index 000000000..6717e5897 --- /dev/null +++ b/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui @@ -0,0 +1,168 @@ + + + + + + 100 + 1 + 10 + + + -180 + 180 + 1 + 10 + + + -180 + 180 + 1 + 10 + + + -180 + 180 + 1 + 10 + + + True + False + 6 + 6 + 12 + + + _Right-angled axes + True + True + False + True + 0 + True + + + 0 + 0 + 2 + + + + + True + False + _X rotation + True + MTR_FLD_X_ROTATION + 0 + + + 0 + 1 + + + + + True + False + _Y rotation + True + MTR_FLD_Y_ROTATION + 0 + + + 0 + 2 + + + + + True + False + _Z rotation + True + MTR_FLD_Z_ROTATION + 0 + + + 0 + 3 + + + + + _Perspective + True + True + False + True + 0 + True + + + + + + 0 + 4 + + + + + True + True + True + adjustmentPERSPECTIVE + + + + + + Perspective + + + + + 1 + 4 + + + + + True + True + True + alpha + adjustmentROTATION3 + + + 1 + 3 + + + + + True + True + True + adjustmentROTATION2 + + + 1 + 2 + + + + + True + True + True + adjustmentROTATION1 + + + 1 + 1 + + + + diff --git a/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui b/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui new file mode 100644 index 000000000..fd1a7c6c4 --- /dev/null +++ b/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui @@ -0,0 +1,434 @@ + + + + + + True + False + svx/res/colordlg.png + + + True + False + svx/res/colordlg.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + svx/res/lighton.png + + + True + False + 6 + 12 + + + True + False + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 6 + 12 + + + True + True + True + Light source 1 + IMG_LIGHT_1 + True + + + 0 + 0 + + + + + True + True + True + Light source 2 + IMG_LIGHT_2 + True + + + 1 + 0 + + + + + True + True + True + Light source 3 + IMG_LIGHT_3 + True + + + 2 + 0 + + + + + True + True + True + Light source 4 + IMG_LIGHT_4 + True + + + 3 + 0 + + + + + True + True + True + Light source 5 + IMG_LIGHT_5 + True + + + 0 + 1 + + + + + True + True + True + Light source 6 + IMG_LIGHT_6 + True + + + 1 + 1 + + + + + True + True + True + Light source 7 + IMG_LIGHT_7 + True + + + 2 + 1 + + + + + True + True + True + Light source 8 + IMG_LIGHT_8 + True + + + 3 + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + True + False + 0 + True + + + + + + + False + True + 0 + + + + + True + True + True + Select a color using the color dialog + IMG_LIGHTSOURCE_COLOR + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + _Light source + True + BTN_LIGHT_1 + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 12 + + + True + True + False + 0 + True + + + + + + + False + True + 0 + + + + + True + True + True + Select a color using the color dialog + IMG_AMBIENT_COLOR + + + False + True + 1 + + + + + + + + + True + False + _Ambient light + True + LB_AMBIENTLIGHT + 0 + + + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + True + never + never + in + + + True + False + + + True + False + + + True + True + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + Light Preview + True + True + + + 0 + 0 + + + + + True + True + True + + + 1 + 1 + + + + + True + True + 1 + False + + + 0 + 1 + + + + + True + True + vertical + 1 + False + + + 1 + 0 + + + + + + + + + True + True + 1 + + + + diff --git a/chart2/uiconfig/ui/tp_AxisPositions.ui b/chart2/uiconfig/ui/tp_AxisPositions.ui new file mode 100644 index 000000000..98aa603cb --- /dev/null +++ b/chart2/uiconfig/ui/tp_AxisPositions.ui @@ -0,0 +1,660 @@ + + + + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + True + False + 6 + vertical + 6 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + _Cross other axis at + True + LB_CROSSES_OTHER_AXIS_AT + 0 + + + False + True + 0 + + + + + True + False + + Start + End + Value + Category + + + + False + True + 1 + + + + + True + True + True + adjustment1 + + + False + True + 2 + + + + + True + False + True + + + True + True + + + + + False + True + 3 + + + + + False + True + 0 + + + + + Axis _between categories + True + False + True + 0 + True + + + False + True + 1 + + + + + + + + + True + False + Axis Line + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + + + _On tick marks + True + True + False + True + 0 + True + + + 0 + 0 + + + + + _Between tick marks + True + True + False + True + 0 + True + RB_ON + + + 0 + 1 + + + + + + + + + True + False + Position Axis + 0 + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + _Place labels + True + LB_PLACE_LABELS + 0 + + + False + True + 0 + + + + + True + False + + Near axis + Near axis (other side) + Outside start + Outside end + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + False + _Distance + True + EDT_AXIS_LABEL_DISTANCE + 0 + + + False + True + 0 + + + + + True + True + adjustment2 + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + Labels + 0 + + + + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 6 + 12 + + + True + False + Major: + 0 + + + + + + + 0 + 0 + + + + + True + False + Minor: + 0 + + + + + + + 0 + 1 + + + + + _Inner + True + True + False + True + 0 + True + + + + + + 1 + 0 + + + + + _Outer + True + True + False + True + 0 + True + + + + + + 2 + 0 + + + + + I_nner + True + True + False + True + 0 + True + + + + + + 1 + 1 + + + + + O_uter + True + True + False + True + 0 + True + + + + + + 2 + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Place _marks + True + LB_PLACE_TICKS + 0 + + + False + True + 0 + + + + + True + False + + At labels + At axis + At axis and labels + + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + Interval Marks + 0 + + + + + + + + False + True + 3 + + + + + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 12 + 6 + + + Show major _grid + True + True + False + half + True + 0 + True + + + 0 + 0 + + + + + _Show minor grid + True + True + False + True + 0 + True + + + 0 + 1 + + + + + Mo_re... + True + True + True + True + + + 1 + 0 + + + + + Mor_e... + True + True + True + True + 0.49000000953674316 + + + 1 + 1 + + + + + + + + + True + False + Grids + 0 + + + + + + + + False + True + 4 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_ChartType.ui b/chart2/uiconfig/ui/tp_ChartType.ui new file mode 100644 index 000000000..7955f0247 --- /dev/null +++ b/chart2/uiconfig/ui/tp_ChartType.ui @@ -0,0 +1,467 @@ + + + + + + 1 + 100 + 1 + 1 + 10 + + + + + + + + + + + + + + + + + + + + + True + False + True + True + 6 + 12 + + + True + False + True + True + vertical + 6 + + + False + Choose a Chart Type + 0 + + + + + + False + True + 0 + + + + + True + False + True + True + 12 + + + True + False + True + 6 + + + True + True + True + never + never + in + + + True + True + + + True + True + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK + True + + + + + + + 0 + 0 + + + + + True + False + 6 + + + True + False + 12 + + + _3D Look + True + False + True + 0 + True + + + + + + 0 + 0 + + + + + False + + Simple + Realistic + + + + + + + 1 + 0 + + + + + 0 + 0 + + + + + True + False + Sh_ape + True + shape + 0.02 + 0 + + + 0 + 1 + + + + + True + False + True + in + + + True + True + True + liststore1 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + + + 0 + 2 + + + + + 0 + 1 + + + + + True + False + 6 + + + _Stack series + True + False + True + 0 + True + + + 0 + 0 + + + + + True + False + 12 + + + True + False + 6 + + + On top + True + False + True + 0 + True + True + + + 0 + 0 + + + + + Percent + True + False + True + 0 + True + ontop + + + 0 + 1 + + + + + Deep + True + False + True + 0 + True + ontop + + + 0 + 2 + + + + + + + 0 + 1 + + + + + True + False + 12 + + + False + _Line type + True + linetype + 0 + + + 0 + 0 + + + + + False + + Straight + Smooth + Stepped + + + + 1 + 0 + + + + + Properties... + True + True + True + + + 2 + 0 + + + + + 0 + 2 + + + + + _Sort by X values + True + False + True + 0.029999999329447746 + True + + + 0 + 3 + + + + + True + False + 12 + + + False + True + _Number of lines + True + nolines + end + 0 + + + 0 + 0 + + + + + True + True + True + adjustment1 + + + 1 + 0 + + + + + 0 + 4 + + + + + 0 + 2 + + + + + 1 + 0 + + + + + True + False + True + never + in + + + True + True + True + liststore2 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + 0 + 0 + + + + + False + True + 1 + + + + + False + True + 0 + + + + diff --git a/chart2/uiconfig/ui/tp_DataLabel.ui b/chart2/uiconfig/ui/tp_DataLabel.ui new file mode 100644 index 000000000..8e0ed64aa --- /dev/null +++ b/chart2/uiconfig/ui/tp_DataLabel.ui @@ -0,0 +1,430 @@ + + + + + + 359 + 1 + 10 + + + True + False + 6 + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + True + + + Show value as _number + True + True + False + True + 0 + True + + + 0 + 0 + + + + + Show value as _percentage + True + True + False + True + 0 + True + + + 0 + 1 + + + + + Show _category + True + True + False + True + 0 + True + + + 0 + 2 + + + + + Show _legend key + True + True + False + True + 0 + True + + + 0 + 3 + + + + + Auto text _wrap + True + True + False + True + 0 + True + + + 0 + 4 + + + + + Number _format... + True + True + True + center + True + + + 1 + 0 + + + + + Percentage f_ormat... + True + True + True + center + True + + + 1 + 1 + + + + + False + True + ABCD + + + + + + 1 + 3 + + + + + True + False + 12 + + + True + False + _Separator + True + LB_TEXT_SEPARATOR + 0 + + + False + True + 0 + + + + + True + False + center + + Space + Comma + Semicolon + New line + Period + + + + False + True + 1 + + + + + 0 + 5 + 2 + + + + + True + False + 12 + + + True + False + Place_ment + True + LB_LABEL_PLACEMENT + 0 + + + False + True + 0 + + + + + True + False + center + + Best fit + Center + Above + Top left + Left + Bottom left + Below + Bottom right + Right + Top right + Inside + Outside + Near origin + + + + False + True + 1 + + + + + 0 + 6 + 2 + + + + + False + Number Format for Percentage Value + + + 1 + 2 + + + + + + + + + + + + True + False + Text Attributes + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + + + False + True + 0 + + + + + True + True + center + True + adjustmentDEGREE + True + + + False + True + 1 + + + + + True + False + _Degrees + True + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Te_xt direction + True + LB_LABEL_TEXTDIR + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + Rotate Text + 0 + + + + + + + + False + True + 1 + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_DataPointOption.ui b/chart2/uiconfig/ui/tp_DataPointOption.ui new file mode 100644 index 000000000..01e93dac9 --- /dev/null +++ b/chart2/uiconfig/ui/tp_DataPointOption.ui @@ -0,0 +1,76 @@ + + + + + + 600 + 1 + 10 + + + -100 + 100 + 1 + 10 + + + True + False + 6 + vertical + 6 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + + + Hide legend entry + True + True + False + start + True + + + False + True + 0 + + + + + + + + + True + False + Legend Entry + + + + + + + + False + True + 3 + + + + diff --git a/chart2/uiconfig/ui/tp_DataSource.ui b/chart2/uiconfig/ui/tp_DataSource.ui new file mode 100644 index 000000000..7d41f8a11 --- /dev/null +++ b/chart2/uiconfig/ui/tp_DataSource.ui @@ -0,0 +1,438 @@ + + + + + + True + False + gtk-go-up + + + True + False + gtk-go-down + + + True + False + Select data range + chart2/res/selectrange.png + + + True + False + Select data range + chart2/res/selectrange.png + + + + + + + + + + + True + False + True + True + 6 + 6 + + + True + False + True + True + 12 + + + True + False + True + vertical + 6 + + + True + False + Data _series: + True + LB_SERIES + 0 + + + 0 + 0 + + + + + True + False + True + True + in + + + True + True + True + True + liststore1 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + + + 0 + 1 + + + + + True + False + True + 6 + 12 + + + _Add + True + True + True + True + True + + + 0 + 0 + + + + + True + True + True + image1 + True + + + Up + + + + + 1 + 0 + + + + + _Remove + True + True + True + True + True + + + 0 + 1 + + + + + True + True + True + image2 + True + + + Down + + + + + 1 + 1 + + + + + 0 + 2 + + + + + 0 + 0 + + + + + True + False + True + True + + + True + False + start + True + True + vertical + 6 + + + True + False + _Data ranges: + True + LB_ROLE + 0 + + + 0 + 0 + + + + + True + True + True + True + in + + + True + True + True + True + liststore2 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + 0 + 1 + + + + + True + False + Ran_ge for %VALUETYPE + True + EDT_RANGE + 0 + + + 0 + 2 + + + + + True + False + True + 6 + + + True + True + True + True + + + 0 + 0 + + + + + True + True + True + imageIMB_RANGE_MAIN + + + 1 + 0 + + + + + 0 + 3 + + + + + True + False + vertical + + + True + False + _Categories + True + EDT_CATEGORIES + 0 + + + 0 + 0 + + + + + True + False + Data _labels + True + 0 + + + 0 + 1 + + + + + 0 + 4 + + + + + True + False + True + 6 + + + True + True + True + True + + + 0 + 0 + + + + + True + True + True + imageIMB_RANGE_CAT + + + 1 + 0 + + + + + 0 + 5 + + + + + 0 + 0 + + + + + 1 + 0 + + + + + 0 + 0 + + + + + True + False + Customize Data Ranges for Individual Data Series + 0 + + + + + + 0 + 1 + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_ErrorBars.ui b/chart2/uiconfig/ui/tp_ErrorBars.ui new file mode 100644 index 000000000..1736c2a0f --- /dev/null +++ b/chart2/uiconfig/ui/tp_ErrorBars.ui @@ -0,0 +1,553 @@ + + + + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + True + False + chart2/res/selectrange.png + + + True + False + chart2/res/selectrange.png + + + True + False + 6 + vertical + 6 + + + True + False + 12 + True + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + _None + True + True + False + start + center + True + True + True + + + False + True + 0 + + + + + _Constant Value + True + True + False + start + center + True + True + RB_NONE + + + False + True + 1 + + + + + _Percentage + True + True + False + start + center + True + True + RB_NONE + + + False + True + 2 + + + + + True + False + 6 + + + True + True + False + start + center + True + True + RB_NONE + + + False + True + 0 + + + + + True + False + + Standard Error + Standard Deviation + Variance + Error Margin + + + + False + True + 1 + + + + + False + True + 3 + + + + + Cell _Range + True + True + False + start + center + True + True + RB_NONE + + + False + True + 4 + + + + + + + + + True + False + Error Category + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + start + 6 + 12 + + + Positive _and Negative + True + True + False + start + center + True + True + True + + + 1 + 0 + + + + + Pos_itive + True + True + False + start + center + True + True + RB_BOTH + + + 1 + 1 + + + + + Ne_gative + True + True + False + start + center + True + True + RB_BOTH + + + 1 + 2 + + + + + True + False + gtk-missing-image + + + 0 + 0 + + + + + True + False + gtk-missing-image + + + 0 + 1 + + + + + True + False + gtk-missing-image + + + 0 + 2 + + + + + + + + + True + False + Error Indicator + 0 + + + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 12 + + + True + False + P_ositive (+) + True + MF_POSITIVE + + + False + True + 0 + + + + + True + True + adjustmentPOS + 2 + + + False + True + 1 + + + + + True + True + True + True + + + False + True + 2 + + + + + True + True + True + Select data range + imageRANGE_SELECT_POSITIVE + + + False + True + 3 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + _Negative (-) + True + MF_NEGATIVE + + + False + True + 0 + + + + + True + True + adjustmentNEG + 2 + + + False + True + 1 + + + + + True + True + True + + + False + True + 2 + + + + + True + True + True + Select data range + imageRANGE_SELECT_NEG + + + False + True + 3 + + + + + False + True + 1 + + + + + Same value for both + True + True + False + True + 0 + True + + + False + True + 2 + + + + + + + + + True + False + Parameters + 0 + + + + + + + + False + True + 1 + + + + + False + Select Range for Positive Error Bars + + + False + True + 2 + + + + + False + Select Range for Negative Error Bars + + + False + True + 3 + + + + + False + From Data Table + + + False + True + 4 + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_LegendPosition.ui b/chart2/uiconfig/ui/tp_LegendPosition.ui new file mode 100644 index 000000000..993c04096 --- /dev/null +++ b/chart2/uiconfig/ui/tp_LegendPosition.ui @@ -0,0 +1,233 @@ + + + + + + True + False + 6 + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + + + _Left + True + True + False + True + 0 + True + + + 0 + 0 + + + + + _Right + True + True + False + True + 0 + True + left + + + 0 + 1 + + + + + _Top + True + True + False + True + 0 + True + left + + + 0 + 2 + + + + + _Bottom + True + True + False + True + 0 + True + left + + + 0 + 3 + + + + + + + + + True + False + Position + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 12 + + + True + False + Te_xt direction + True + 0 + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + + + + + True + False + Text Orientation + 0 + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 12 + + + Show the legend without overlapping the chart + True + False + False + True + 0 + True + + + False + True + 0 + + + + + + + + + True + False + Overlay + 0 + + + + + + + + False + True + 2 + + + + diff --git a/chart2/uiconfig/ui/tp_PolarOptions.ui b/chart2/uiconfig/ui/tp_PolarOptions.ui new file mode 100644 index 000000000..ceea40c58 --- /dev/null +++ b/chart2/uiconfig/ui/tp_PolarOptions.ui @@ -0,0 +1,185 @@ + + + + + + 359 + 1 + 10 + + + True + False + 6 + vertical + 6 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + _Clockwise direction + True + True + False + True + 0 + True + + + + + + + True + False + Orientation + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 12 + + + True + False + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + center + center + + + False + True + 0 + + + + + True + False + center + adjustmentDEGREE + True + + + False + True + 1 + + + + + True + False + _Degrees + True + NF_STARTING_ANGLE + 0 + + + False + True + 2 + + + + + + + + + True + False + Starting Angle + 0 + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + Include _values from hidden cells + True + True + False + True + 0 + True + + + + + + + True + False + Plot Options + 0 + + + + + + + + False + True + 2 + + + + diff --git a/chart2/uiconfig/ui/tp_RangeChooser.ui b/chart2/uiconfig/ui/tp_RangeChooser.ui new file mode 100644 index 000000000..9a74a3d17 --- /dev/null +++ b/chart2/uiconfig/ui/tp_RangeChooser.ui @@ -0,0 +1,258 @@ + + + + + + True + False + Select data range + chart2/res/selectrange.png + + + True + False + True + 6 + + + True + False + True + 6 + + + True + False + Choose a Data Range + 0 + + + + + + 0 + 0 + + + + + True + False + True + 6 + + + True + False + _Data range: + True + ED_RANGE + 0 + + + 0 + 0 + + + + + True + True + True + True + + + 1 + 0 + + + + + True + True + True + Select data range + imageIB_RANGE + + + 2 + 0 + + + + + 0 + 1 + + + + + Data series in _rows + True + True + False + True + 0 + True + True + + + 0 + 2 + + + + + Data series in _columns + True + True + False + True + 0 + True + RB_DATAROWS + + + 0 + 3 + + + + + _First row as label + True + True + False + True + 0 + True + + + 0 + 4 + + + + + F_irst column as label + True + True + False + True + 0 + True + + + 0 + 5 + + + + + True + False + + + 0 + 6 + + + + + Time based charting + True + True + False + True + 0 + True + + + 0 + 7 + + + + + True + False + 12 + + + True + True + True + 5 + 0 + number + + + 1 + 0 + + + + + True + True + True + 5 + 0 + + + 3 + 0 + + + + + True + False + 4 + Start Table Index + True + ED_TIME_BASED_START + + + 0 + 0 + + + + + True + False + 8 + End Table Index + True + ED_TIME_BASED_END + + + 2 + 0 + + + + + 0 + 8 + + + + + False + Data Range + + + 0 + 9 + + + + + 0 + 0 + + + + diff --git a/chart2/uiconfig/ui/tp_Scale.ui b/chart2/uiconfig/ui/tp_Scale.ui new file mode 100644 index 000000000..2bdcf6741 --- /dev/null +++ b/chart2/uiconfig/ui/tp_Scale.ui @@ -0,0 +1,603 @@ + + + + + + 1 + 10 + + + 1 + 10 + + + 1 + 10 + + + 1 + 10 + + + 1 + 100 + 1 + 10 + + + 1 + 100 + 1 + 10 + + + True + False + 6 + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + vertical + 6 + + + _Reverse direction + True + True + False + True + 0 + True + + + False + True + 0 + + + + + _Logarithmic scale + True + True + False + True + 0 + True + + + False + True + 1 + + + + + True + False + 12 + + + True + False + T_ype + True + LB_AXIS_TYPE + 0 + + + False + True + 0 + + + + + True + False + + Automatic + Text + Date + + + + False + True + 1 + + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + 6 + 12 + + + True + False + _Minimum + True + EDT_MIN + 0 + + + 0 + 0 + + + + + True + False + Ma_ximum + True + EDT_MAX + 0 + + + 0 + 1 + + + + + _Automatic + True + True + False + True + 0 + True + + + 2 + 0 + + + + + A_utomatic + True + True + False + True + 0 + True + + + 2 + 1 + + + + + True + True + True + 10 + adjustment1 + + + 1 + 0 + + + + + True + True + True + 10 + adjustment2 + + + 1 + 1 + + + + + False + True + 1 + + + + + True + False + 12 + + + True + False + R_esolution + True + LB_TIME_RESOLUTION + 0 + + + False + True + 0 + + + + + True + False + + Days + Months + Years + + + + False + True + 1 + + + + + Automat_ic + True + True + False + True + 0 + True + + + False + True + 2 + + + + + False + True + 2 + + + + + True + False + 12 + + + True + False + Ma_jor interval + True + 0 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + 12 + + + True + True + True + 10 + adjustmentINTERVAL + + + False + True + 0 + + + + + True + False + + Days + Months + Years + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + True + True + 10 + adjustment4 + + + False + True + 1 + + + + + False + True + 1 + + + + + Au_tomatic + True + True + False + True + 0 + True + + + False + True + 3 + + + + + False + True + 3 + + + + + True + False + 12 + + + True + False + vertical + + + True + False + Minor inter_val + True + 0 + + + True + True + 0 + + + + + True + False + Minor inter_val count + True + 0 + + + True + True + 1 + + + + + False + True + 0 + + + + + True + True + True + 10 + adjustmentINTERVAL1 + + + False + True + 1 + + + + + True + False + + Days + Months + Years + + + + False + True + 2 + + + + + Aut_omatic + True + True + False + True + 0 + True + + + False + True + 3 + + + + + False + True + 4 + + + + + True + False + 12 + + + True + False + Re_ference value + True + 0 + + + False + True + 0 + + + + + True + True + True + 10 + adjustment3 + + + False + True + 1 + + + + + Automat_ic + True + True + False + True + 0 + True + + + False + True + 2 + + + + + False + True + 5 + + + + + + + + + True + False + Scale + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_SeriesToAxis.ui b/chart2/uiconfig/ui/tp_SeriesToAxis.ui new file mode 100644 index 000000000..6ccb912da --- /dev/null +++ b/chart2/uiconfig/ui/tp_SeriesToAxis.ui @@ -0,0 +1,420 @@ + + + + + + 600 + 1 + 10 + + + -100 + 100 + 1 + 10 + + + True + False + 6 + vertical + 6 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + Primary Y axis + True + True + False + True + 0 + True + True + + + False + True + 0 + + + + + Secondary Y axis + True + True + False + True + 0 + True + True + RBT_OPT_AXIS_1 + + + False + True + 1 + + + + + + + + + True + False + Align Data Series to + 0 + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 6 + 12 + + + True + False + _Spacing + True + MT_GAP + + + 0 + 0 + + + + + True + False + _Overlap + True + MT_OVERLAP + + + 0 + 1 + + + + + True + False + adjustmentGAP + + + 1 + 0 + + + + + True + False + adjustmentOVERLAP + + + 1 + 1 + + + + + False + True + 0 + + + + + Show _bars side by side + True + True + False + start + True + True + + + False + True + 1 + + + + + Connection lines + True + True + False + start + True + True + + + False + True + 2 + + + + + + + + + True + False + Settings + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + 6 + + + True + False + 6 + 12 + + + True + False + Plot missing values + 0 + + + 0 + 0 + + + + + _Leave gap + True + True + False + True + 0 + True + True + + + 1 + 0 + + + + + _Assume zero + True + True + False + True + 0 + True + True + RB_DONT_PAINT + + + 1 + 1 + + + + + _Continue line + True + True + False + True + 0 + True + True + RB_DONT_PAINT + + + 1 + 2 + + + + + + + + + + + False + True + 0 + + + + + Include _values from hidden cells + True + True + False + start + True + True + + + False + True + 1 + + + + + + + + + True + False + Plot Options + 0 + + + + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + vertical + + + Hide legend entry + True + True + False + start + True + + + False + True + 0 + + + + + + + + + True + False + Legend Entry + + + + + + + + False + True + 3 + + + + diff --git a/chart2/uiconfig/ui/tp_Trendline.ui b/chart2/uiconfig/ui/tp_Trendline.ui new file mode 100644 index 000000000..2120b2d4c --- /dev/null +++ b/chart2/uiconfig/ui/tp_Trendline.ui @@ -0,0 +1,575 @@ + + + + + + 2 + 10 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + 2 + 100 + 1 + 10 + + + True + False + True + True + 6 + vertical + 12 + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + start + 6 + 6 + True + + + _Linear + True + True + False + True + 0 + True + True + + + 1 + 0 + + + + + L_ogarithmic + True + True + False + True + 0 + True + True + linear + + + 1 + 1 + + + + + _Exponential + True + True + False + True + 0 + True + True + linear + + + 1 + 2 + + + + + Po_wer + True + True + False + True + 0 + True + True + linear + + + 1 + 3 + + + + + _Polynomial + True + True + False + True + 0 + True + True + linear + + + 3 + 0 + + + + + _Moving Average + True + True + False + True + 0 + True + True + linear + + + 3 + 2 + + + + + True + False + 12 + + + True + False + Degree + True + degree + + + 0 + 0 + + + + + True + True + True + adjustmentDegree + + + 1 + 0 + + + + + 3 + 1 + + + + + True + False + 12 + + + True + False + Period + True + period + + + 0 + 0 + + + + + True + True + True + adjustmentPeriod + + + 1 + 0 + + + + + 3 + 3 + + + + + True + False + gtk-missing-image + + + 0 + 0 + + + + + True + False + gtk-missing-image + + + 0 + 1 + + + + + True + False + gtk-missing-image + + + 0 + 2 + + + + + True + False + gtk-missing-image + + + 0 + 3 + + + + + True + False + gtk-missing-image + + + 2 + 0 + + + + + True + False + gtk-missing-image + + + 2 + 2 + + + + + + + + + + + + + + + True + False + Regression Type + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + True + + + True + False + Extrapolate Forward + True + extrapolateForward + 0 + + + 0 + 1 + + + + + True + False + Extrapolate Backward + True + extrapolateBackward + 0 + + + 0 + 2 + + + + + True + True + True + False + adjustmentForwardBackward + 2 + + + 1 + 1 + + + + + True + True + True + adjustmentForwardBackward1 + 2 + + + 1 + 2 + + + + + Force _Intercept + True + True + False + True + 0 + True + + + + + + 0 + 3 + + + + + Show E_quation + True + True + False + True + 0 + True + + + 0 + 4 + 2 + + + + + Show _Coefficient of Determination (R²) + True + True + False + True + 0 + True + + + 0 + 5 + 2 + + + + + True + False + Trendline _Name + True + entry_name + 0 + + + 0 + 0 + + + + + True + True + True + + + 1 + 0 + + + + + True + True + True + 0 + False + number + adjustmentForwardBackward2 + 2 + + + + + + 1 + 3 + + + + + True + False + _X Variable Name + True + entry_Xname + 0 + + + 0 + 6 + + + + + True + True + True + + + 1 + 6 + + + + + True + False + _Y Variable Name + True + entry_Yname + 0 + + + 0 + 7 + + + + + True + True + True + + + 1 + 7 + + + + + + + + + True + False + Options + + + + + + + + False + True + 1 + + + + + + + + + + diff --git a/chart2/uiconfig/ui/tp_axisLabel.ui b/chart2/uiconfig/ui/tp_axisLabel.ui new file mode 100644 index 000000000..328f81a5a --- /dev/null +++ b/chart2/uiconfig/ui/tp_axisLabel.ui @@ -0,0 +1,397 @@ + + + + + + 359 + 5 + + + True + False + True + True + 6 + vertical + 12 + + + Sho_w labels + True + True + False + True + 0 + True + True + + + False + True + 0 + + + + + True + False + 18 + True + + + True + False + 0 + none + + + True + False + True + True + 6 + 12 + + + True + False + vertical + 6 + + + _Tile + True + True + False + True + 0 + True + True + + + False + True + 0 + + + + + St_agger odd + True + True + False + True + 0 + True + tile + + + False + True + 1 + + + + + Stagger _even + True + True + False + True + 0 + True + tile + + + False + True + 2 + + + + + A_utomatic + True + True + False + True + 0 + True + tile + + + False + True + 3 + + + + + + + + + True + False + Order + + + + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + True + True + 6 + 12 + + + True + False + vertical + 6 + + + O_verlap + True + True + False + True + 0 + True + + + False + True + 0 + + + + + _Break + True + True + False + True + 0 + True + + + False + True + 1 + + + + + + + + + True + False + Text Flow + + + + + + + + False + True + 1 + + + + + False + True + 1 + + + + + True + False + True + 6 + 0 + none + + + True + False + 6 + 12 + + + True + False + True + 6 + 12 + + + True + False + 6 + 12 + + + True + True + 40 + True + adjustmentSpinDegrees + True + + + 0 + 2 + + + + + True + False + 40 + _Degrees + True + + + 1 + 2 + + + + + + + + + + + + + + + + + 1 + 0 + + + + + True + False + 6 + 12 + + + Ve_rtically stacked + True + True + False + True + 0.019999999552965164 + True + True + + + 0 + 0 + + + + + False + ABCD + + + 0 + 1 + + + + + 2 + 0 + + + + + True + False + Te_xt direction: + True + + + 0 + 1 + + + + + True + False + + + 1 + 1 + 2 + + + + + True + False + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + center + center + + + 0 + 0 + + + + + + + + + True + False + Text Orientation + + + + + + + + False + True + 2 + + + + diff --git a/chart2/uiconfig/ui/wizelementspage.ui b/chart2/uiconfig/ui/wizelementspage.ui new file mode 100644 index 000000000..574907036 --- /dev/null +++ b/chart2/uiconfig/ui/wizelementspage.ui @@ -0,0 +1,441 @@ + + + + + + True + False + True + 6 + vertical + 12 + + + True + False + True + 0 + none + + + True + False + True + 6 + 12 + + + True + False + True + 18 + + + True + False + True + 6 + 12 + + + True + False + _X axis + True + primaryXaxis + 0 + + + 0 + 2 + + + + + True + False + _Y axis + True + primaryYaxis + 0 + + + 0 + 3 + + + + + True + False + _Z axis + True + primaryZaxis + 0 + + + 0 + 4 + + + + + True + True + True + True + + + 1 + 2 + + + + + True + True + True + True + + + 1 + 3 + + + + + True + True + True + True + + + 1 + 4 + + + + + True + False + _Title + True + maintitle + 0 + + + 0 + 0 + + + + + True + False + _Subtitle + True + subtitle + 0 + + + 0 + 1 + + + + + True + True + True + True + + + 1 + 0 + + + + + True + True + True + True + + + 1 + 1 + + + + + False + True + X _axis + True + secondaryXaxis + 0 + + + 0 + 5 + + + + + False + True + Y ax_is + True + secondaryYaxis + 0 + + + 0 + 6 + + + + + True + True + True + True + + + 1 + 5 + + + + + True + True + True + True + + + 1 + 6 + + + + + 0 + 0 + + + + + True + False + 6 + + + _Display legend + True + True + False + True + 0 + True + + + 0 + 0 + + + + + True + False + 12 + + + True + False + 6 + + + _Left + True + True + False + True + 0 + True + True + + + 0 + 0 + + + + + _Right + True + True + False + True + 0 + True + left + + + 0 + 1 + + + + + _Top + True + True + False + True + 0 + True + left + + + 0 + 2 + + + + + _Bottom + True + True + False + True + 0 + True + left + + + 0 + 3 + + + + + + + 0 + 1 + + + + + 1 + 0 + + + + + + + + + True + False + Choose Titles, Legend, and Grid Settings + + + + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 6 + 12 + + + True + False + 6 + 12 + + + X axis + True + True + False + True + 0 + True + + + 0 + 0 + + + + + Y ax_is + True + True + False + True + 0 + True + + + 1 + 0 + + + + + Z axi_s + True + True + False + True + 0 + True + + + 2 + 0 + + + + + + + + + True + False + Display Grids + + + + + + + + False + True + 2 + + + + diff --git a/chart2/workbench/addin/exports.dxp b/chart2/workbench/addin/exports.dxp new file mode 100644 index 000000000..51703a046 --- /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 000000000..a7f8c5f0a --- /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 000000000..665a205ab --- /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 +#include +#include + +#include +#include +#include +#include +#include + +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( 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& ) + { + OSL_FAIL( "### InvalidRegistryException!" ); + } + } + 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( 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(aPos.Y + nLength * (1.0 - fPercentage)); // y scale goes from top to bottom + } + else + { + aOutPosition.X = static_cast(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(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 000000000..b13949b6a --- /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 000000000..5e32e479c --- /dev/null +++ b/chart2/workbench/addin/sampleaddin.hxx @@ -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 . + */ + +#ifndef INCLUDED_CHART2_WORKBENCH_ADDIN_SAMPLEADDIN_HXX +#define INCLUDED_CHART2_WORKBENCH_ADDIN_SAMPLEADDIN_HXX + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +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 ); +}; + +#endif // INCLUDED_CHART2_WORKBENCH_ADDIN_SAMPLEADDIN_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3