Initial implementation of rendering for funnel charts

Framework for funnel chart rendering. For now this just renders them as
horizontal bar charts: that is, not properly centred as a funnel. UI
functionality is untested and probably broken.

Signed-off-by: Kurt Nordback <kurt.nordback@collabora.com>
Change-Id: I3a0e923b801c840138c90dcf3609253a467d23d1
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/7905
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 172e4233b70f1d73ca942876f3f47458843ffa36)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209739
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Kurt Nordback
2026-08-25 08:52:54 +02:00
committed by Xisco Fauli
parent 8749466df2
commit 160014f44b
14 changed files with 297 additions and 45 deletions
+1
View File
@@ -254,6 +254,7 @@ $(eval $(call gb_Library_add_exception_objects,chart2,\
chart2/source/view/charttypes/BubbleChart \
chart2/source/view/charttypes/CandleStickChart \
chart2/source/view/charttypes/CategoryPositionHelper \
chart2/source/view/charttypes/FunnelChart \
chart2/source/view/charttypes/NetChart \
chart2/source/view/charttypes/PieChart \
chart2/source/view/charttypes/UnsupportedChart \
+13
View File
@@ -497,6 +497,19 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testStockChartShiftedCategoryPosition)
CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
}
CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testFunnelChartShiftedCategoryPosition)
{
loadFromFile(u"xlsx/color_funnel.xlsx");
uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0);
CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
CPPUNIT_ASSERT(xAxis.is());
chart2::ScaleData aScaleData = xAxis->getScaleData();
CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
}
CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf133376)
{
// FIXME: the DPI check should be removed when either (1) the test is fixed to work with
Binary file not shown.
+5 -7
View File
@@ -444,14 +444,12 @@ bool ChartType::isSupportingOverlapAndGapWidthProperties(sal_Int32 nDimensionCou
return false;
OUString aChartTypeName = getChartType();
if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN))
return true;
if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR))
return true;
if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM))
if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ||
aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ||
aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) ||
aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) {
return true;
}
return false;
}
@@ -585,6 +585,7 @@ void ChartTypeTemplate::adaptScales(
m_aServiceName.indexOf("Column") != -1 ||
(m_aServiceName.indexOf("Bar") != -1 &&
!m_aServiceName.indexOf("BarOfPie")) ||
m_aServiceName.indexOf("Funnel") != -1 ||
m_aServiceName.endsWith("Close");
}
bool bSupportsDates = xChartType.is() ? xChartType->isSupportingDateAxis(nDimensionX) : true;
@@ -9,8 +9,15 @@
#include "FunnelChartType.hxx"
#include <servicenames_charttypes.hxx>
#include <Axis.hxx>
#include <AxisHelper.hxx>
#include <AxisIndexDefines.hxx>
#include <CartesianCoordinateSystem.hxx>
#include <PropertyHelper.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <cppuhelper/supportsservice.hxx>
namespace com::sun::star::uno
@@ -110,6 +117,46 @@ void FunnelChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const
rAny = (*aFound).second;
}
rtl::Reference<::chart::BaseCoordinateSystem>
FunnelChartType::createCoordinateSystem2(sal_Int32 DimensionCount)
{
rtl::Reference<CartesianCoordinateSystem> xResult
= new CartesianCoordinateSystem(DimensionCount);
for (sal_Int32 i = 0; i < DimensionCount; i++)
{
rtl::Reference<Axis> xAxis = xResult->getAxisByDimension2(i, MAIN_AXIS_INDEX);
if (!xAxis.is())
continue;
chart2::ScaleData aScaleData = xAxis->getScaleData();
if (i == 0) // X-axis
{
// Set up X-axis specifically for histogram bins
aScaleData.AxisType = chart2::AxisType::CATEGORY;
aScaleData.AutoDateAxis = false;
aScaleData.ShiftedCategoryPosition = true;
aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
// Clear any existing scaling/categories
AxisHelper::removeExplicitScaling(aScaleData);
aScaleData.Categories.clear();
}
else if (i == 1) // Y-axis
{
aScaleData.AxisType = chart2::AxisType::REALNUMBER;
aScaleData.ShiftedCategoryPosition = false;
aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
aScaleData.Scaling = AxisHelper::createLinearScaling();
}
xAxis->setScaleData(aScaleData);
}
return xResult;
}
::cppu::IPropertyArrayHelper& SAL_CALL FunnelChartType::getInfoHelper()
{
return StaticFunnelChartTypeInfoHelper();
@@ -8,7 +8,9 @@
*/
#pragma once
#include <ChartModel.hxx>
#include <ChartType.hxx>
#include <Diagram.hxx>
namespace chart
{
@@ -27,6 +29,9 @@ public:
private:
explicit FunnelChartType(const FunnelChartType& rOther);
virtual rtl::Reference<::chart::BaseCoordinateSystem>
createCoordinateSystem2(sal_Int32 DimensionCount) override;
// ____ XChartType ____
virtual OUString SAL_CALL getChartType() override;
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedPropertyRoles() override;
+4 -7
View File
@@ -913,16 +913,13 @@ void BarChart::doXSlot(
}
else //m_nDimension!=3
{
drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
std::vector<std::vector<css::drawing::Position3D>> aPoly
{
{ // inner vector
drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ),
drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ),
aRightUpperPoint,
aLeftUpperPoint,
drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ)
drawing::Position3D( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ),
drawing::Position3D( fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ),
drawing::Position3D( fLogicX+fLogicBarWidth/2.0, fUpperYValue, fLogicZ),
drawing::Position3D( fLogicX-fLogicBarWidth/2.0, fUpperYValue, fLogicZ )
}
};
pPosHelper->transformScaledLogicToScene( aPoly );
@@ -0,0 +1,139 @@
/* -*- 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/.
*/
#include "FunnelChart.hxx"
#include <ChartType.hxx>
#include <ChartModel.hxx>
#include <AxisIndexDefines.hxx>
#include <Clipping.hxx>
#include <CommonConverters.hxx>
#include <DateHelper.hxx>
#include <ObjectIdentifier.hxx>
#include <LabelPositionHelper.hxx>
#include <ShapeFactory.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/scopeguard.hxx>
#include <rtl/math.hxx>
#include <svx/scene3d.hxx>
#include <com/sun/star/chart/DataLabelPlacement.hpp>
#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
namespace chart
{
using namespace ::com::sun::star;
FunnelChart::FunnelChart(const rtl::Reference<ChartType>& xChartTypeModel,
sal_Int32 nDimensionCount)
: BarChart(xChartTypeModel, nDimensionCount)
{
// We only support 2 dimensional funnel charts
assert(nDimensionCount == 2 && "FunnelChart only supports 2D charts");
// Runtime check for all builds
if (nDimensionCount != 2)
{
// Log a warning or throw an exception if appropriate
SAL_WARN("chart2", "FunnelChart created with invalid dimension count. Forcing 2D.");
}
PlotterBase::m_pPosHelper = &m_aMainPosHelper;
VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper;
try
{
if (m_xChartTypeModel.is())
m_xChartTypeModel->getPropertyValue(u"GapwidthSequence"_ustr) >>= m_aGapwidthSequence;
}
catch (const uno::Exception&)
{
TOOLS_WARN_EXCEPTION("chart2", "");
}
}
FunnelChart::~FunnelChart() {}
#if 0
PlottingPositionHelper& FunnelChart::getPlottingPositionHelper(sal_Int32 nAxisIndex) const
{
PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper(nAxisIndex);
BarPositionHelper* pFunnelPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper);
if (pFunnelPosHelper && nAxisIndex >= 0)
{
if (nAxisIndex < m_aGapwidthSequence.getLength())
pFunnelPosHelper->setOuterDistance(m_aGapwidthSequence[nAxisIndex] / 100.0);
}
return rPosHelper;
}
css::awt::Point FunnelChart::getLabelScreenPositionAndAlignment(
LabelAlignment& rAlignment, sal_Int32 nLabelPlacement, double fScaledX,
double fScaledLowerYValue, double fScaledUpperYValue, double fBaseValue,
BarPositionHelper const* pPosHelper) const
{
double fY = fScaledUpperYValue;
bool bReverse = !pPosHelper->isMathematicalOrientationY();
bool bNormalOutside = (!bReverse == (fBaseValue < fScaledUpperYValue));
switch (nLabelPlacement)
{
case css::chart::DataLabelPlacement::TOP:
fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
rAlignment = LABEL_ALIGN_TOP;
break;
case css::chart::DataLabelPlacement::BOTTOM:
fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
rAlignment = LABEL_ALIGN_BOTTOM;
break;
case css::chart::DataLabelPlacement::OUTSIDE:
fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
break;
case css::chart::DataLabelPlacement::INSIDE:
fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
break;
case css::chart::DataLabelPlacement::CENTER:
fY -= (fScaledUpperYValue - fScaledLowerYValue) / 2.0;
rAlignment = LABEL_ALIGN_CENTER;
break;
default:
OSL_FAIL("this label alignment is not implemented yet");
break;
}
css::drawing::Position3D aScenePosition3D(
pPosHelper->transformScaledLogicToScene(fScaledX, fY, 0.0, true));
return LabelPositionHelper(2, m_xLogicTarget).transformSceneToScreenPosition(aScenePosition3D);
}
#endif
void FunnelChart::createShapes()
{
if (m_aZSlots.empty()) //No data series Available
return;
OSL_ENSURE(m_xLogicTarget.is() && m_xFinalTarget.is(),
"FunnelChart is not properly initialized"); // Ensuring chart is properly initialized
if (!(m_xLogicTarget.is() && m_xFinalTarget.is()))
return;
if (!m_pMainPosHelper)
m_pMainPosHelper = new BarPositionHelper();
BarChart::createShapes();
}
} // namespace chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
@@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "BarChart.hxx"
#include "BarPositionHelper.hxx"
#include <memory>
namespace chart
{
class FunnelChart : public BarChart
{
public:
FunnelChart() = delete;
FunnelChart(const rtl::Reference<ChartType>& xChartTypeModel, sal_Int32 nDimensionCount);
virtual ~FunnelChart() override;
virtual void createShapes() override;
private:
#if 0
virtual PlottingPositionHelper& getPlottingPositionHelper(sal_Int32 nAxisIndex) const override;
css::awt::Point getLabelScreenPositionAndAlignment(LabelAlignment& rAlignment,
sal_Int32 nLabelPlacement, double fScaledX,
double fScaledLowerYValue,
double fScaledUpperYValue, double fBaseValue,
BarPositionHelper const* pPosHelper) const;
#endif
private:
BarPositionHelper m_aMainPosHelper;
css::uno::Sequence<sal_Int32> m_aGapwidthSequence;
};
} // namespace chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
@@ -59,6 +59,7 @@
#include "CandleStickChart.hxx"
#include "BubbleChart.hxx"
#include "NetChart.hxx"
#include "FunnelChart.hxx"
#include "UnsupportedChart.hxx"
#include <unonames.hxx>
#include <SpecialCharacters.hxx>
@@ -2901,8 +2902,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter(
pRet = new NetChart(xChartTypeModel,nDimensionCount,false,std::make_unique<PolarPlottingPositionHelper>());
else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
pRet = new CandleStickChart(xChartTypeModel,nDimensionCount);
else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_AREA) )
pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) )
pRet = new FunnelChart(xChartTypeModel,nDimensionCount);
else
pRet = new UnsupportedChart(xChartTypeModel);
return pRet;
@@ -106,6 +106,9 @@ struct TypeGroupInfo
bool mbSwappedAxesSet; /// True = X axis and Y axis are swapped.
bool mbSupportsStacking; /// True = data points can be stacked on each other.
bool mbPictureOptions; /// True = bitmaps support options from c:pictureOptions.
bool mbShiftedCatPos; /// True = default category axis position is shifted
/// This can get overridden in AxisConverter::convertFromModel()
bool mb3dShiftedCatPos; /// True = default category axis position is shifted for 3d charts
};
const TypeGroupInfo& GetTypeGroupInfo( TypeId eType );
+5 -5
View File
@@ -333,14 +333,14 @@ void AxisConverter::convertFromModel(const Reference<XCoordinateSystem>& rxCoord
}
/* set default ShiftedCategoryPosition values for some charttype,
because the XML can contain wrong CrossBetween value, if came from MSO */
if( rTypeGroups.front()->is3dChart() && (rTypeInfo.meTypeId == TYPEID_BAR || rTypeInfo.meTypeId == TYPEID_HORBAR || rTypeInfo.meTypeId == TYPEID_STOCK) )
aScaleData.ShiftedCategoryPosition = true;
else if( rTypeInfo.meTypeId == TYPEID_RADARLINE || rTypeInfo.meTypeId == TYPEID_RADARAREA )
if( rTypeGroups.front()->is3dChart()) {
aScaleData.ShiftedCategoryPosition = rTypeInfo.mb3dShiftedCatPos;
} else if( rTypeInfo.meTypeId == TYPEID_RADARLINE || rTypeInfo.meTypeId == TYPEID_RADARAREA )
aScaleData.ShiftedCategoryPosition = false;
else if( pCrossingAxis->mnCrossBetween != -1 ) /*because of backwards compatibility*/
aScaleData.ShiftedCategoryPosition = pCrossingAxis->mnCrossBetween == XML_between;
else if( rTypeInfo.meTypeCategory == TYPECATEGORY_BAR || rTypeInfo.meTypeId == TYPEID_LINE || rTypeInfo.meTypeId == TYPEID_STOCK )
aScaleData.ShiftedCategoryPosition = true;
else
aScaleData.ShiftedCategoryPosition = rTypeInfo.mbShiftedCatPos;
}
else
{
@@ -91,33 +91,33 @@ namespace csscd = css::chart::DataLabelPlacement;
const TypeGroupInfo spTypeInfos[] =
{
// type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack picopt
{ TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true },
{ TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true },
{ TYPEID_HISTO, TYPECATEGORY_HISTO, SERVICE_CHART2_HISTO, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true },
{ TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false },
{ TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, false },
{ TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false },
{ TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, false, false, true, false, false, false },
{ TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::OUTSIDE, true, true, false, true, false, false, false },
{ TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false },
{ TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, false, true, false, false, false },
{ TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false },
{ TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, false, false, false, false },
{ TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, false, false, false, false },
{ TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, false, false },
{ TYPEID_FUNNEL, TYPECATEGORY_FUNNEL, SERVICE_CHART2_FUNNEL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_BOXWHISKER,TYPECATEGORY_BOXWHISKER, SERVICE_CHART2_BOXWHISKER, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_CLUSTEREDCOLUMN,TYPECATEGORY_CLUSTEREDCOLUMN, SERVICE_CHART2_CLUSTEREDCOLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_PARETOLINE,TYPECATEGORY_PARETOLINE, SERVICE_CHART2_PARETOLINE, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_REGIONMAP, TYPECATEGORY_REGIONMAP, SERVICE_CHART2_REGIONMAP, VARPOINTMODE_NONE, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_SUNBURST, TYPECATEGORY_SUNBURST, SERVICE_CHART2_SUNBURST, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_TREEMAP, TYPECATEGORY_TREEMAP, SERVICE_CHART2_TREEMAP, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false },
{ TYPEID_WATERFALL, TYPECATEGORY_WATERFALL, SERVICE_CHART2_WATERFALL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false }
// type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack picopt shftcat 3dshftcat
{ TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, true },
{ TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true, true, true },
{ TYPEID_HISTO, TYPECATEGORY_HISTO, SERVICE_CHART2_HISTO, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, false, false},
{ TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false, true, false},
{ TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, false, false, false},
{ TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false, true, true },
{ TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, false, false, true, false, false, false, false, false},
{ TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::OUTSIDE, true, true, false, true, false, false, false, false, false},
{ TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false, false},
{ TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, false, true, false, false, false, false, false},
{ TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false, false},
{ TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, false, false, false, false, false, false},
{ TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, false, false, false, false, false, false},
{ TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, false, false, false, false},
{ TYPEID_FUNNEL, TYPECATEGORY_FUNNEL, SERVICE_CHART2_FUNNEL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, false, false, true, false},
{ TYPEID_BOXWHISKER,TYPECATEGORY_BOXWHISKER, SERVICE_CHART2_BOXWHISKER, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_CLUSTEREDCOLUMN,TYPECATEGORY_CLUSTEREDCOLUMN, SERVICE_CHART2_CLUSTEREDCOLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_PARETOLINE,TYPECATEGORY_PARETOLINE, SERVICE_CHART2_PARETOLINE, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_REGIONMAP, TYPECATEGORY_REGIONMAP, SERVICE_CHART2_REGIONMAP, VARPOINTMODE_NONE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_SUNBURST, TYPECATEGORY_SUNBURST, SERVICE_CHART2_SUNBURST, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_TREEMAP, TYPECATEGORY_TREEMAP, SERVICE_CHART2_TREEMAP, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false},
{ TYPEID_WATERFALL, TYPECATEGORY_WATERFALL, SERVICE_CHART2_WATERFALL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}
};
const TypeGroupInfo saUnknownTypeInfo =
{ TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true };
{ TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, false, false};
const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId )
{