/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifdef _MSC_VER
#pragma optimize("",off)
#pragma hdrstop
#endif

#include <bf_svx/svdorect.hxx>

#include <bf_svx/svdopath.hxx>

#include <bf_svx/xlnclit.hxx>

#ifndef _ZFORLIST_HXX //autogen
#ifndef _ZFORLIST_DECLARE_TABLE
#define _ZFORLIST_DECLARE_TABLE
#endif
#endif

#include <list>

#include <bf_svx/eeitem.hxx>

#include "schattr.hxx"
#include "memchrt.hxx"

#ifndef _SVX_CHRTITEM_HXX //autogen
#define ITEMID_CHARTDATADESCR   SCHATTR_DATADESCR_DESCR
#define ITEMID_CHARTTEXTORDER   SCHATTR_TEXT_ORDER
#define ITEMID_CHARTTEXTORIENT  SCHATTR_TEXT_ORIENT
#endif

#define ITEMID_FONTHEIGHT  EE_CHAR_FONTHEIGHT
#define ITEMID_FONTWIDTH   EE_CHAR_FONTWIDTH
#include <bf_svx/fhgtitem.hxx>
#include <bf_svx/fwdtitem.hxx>

// header for class SdrOutliner
// header for GetDraftFillColor()
#include <bf_svx/svdetc.hxx>

#include "globfunc.hxx"

#include "ChXChartDocument.hxx"

#include <float.h>
#include "glob.hrc"

#include "chaxis.hxx"
#include "chdescr.hxx"
#include "calculat.hxx"
namespace binfilter {

/*************************************************************************
|*
|* Koordinatenachsen und Rueckwand mit Unterteilung und Beschriftung
|* erzeugen; Liefert die Einfuege-Position fuer die Chart-Datenobjekte.
|*
\************************************************************************/
/*N*/ void ChartModel::Create2DXYTitles(Rectangle& rRect,BOOL bSwitchColRow)
/*N*/ {
/*N*/   SdrPage* pPage=GetPage(0);
/*N*/
/*N*/   SdrTextObj         *pXAxisTitleObj = NULL;
/*N*/   SdrTextObj         *pYAxisTitleObj = NULL;
/*N*/
/*N*/   if (bShowXAxisTitle)
/*N*/   {
/*N*/       pXAxisTitleObj = CreateTitle (pXAxisTitleAttr, CHOBJID_DIAGRAM_TITLE_X_AXIS,
/*N*/                                     bSwitchColRow,aXAxisTitle, FALSE, &eAdjustXAxesTitle);
/*N*/
/*N*/       if (GetAdjustMarginsForXAxisTitle())
/*N*/       {
/*N*/           if (bSwitchColRow)
/*N*/               rRect.Left() += GetOutputSize(*pXAxisTitleObj).Width() + 200;
/*N*/           else
/*N*/               rRect.Bottom() -= GetOutputSize(*pXAxisTitleObj).Height() + 200;
/*N*/       }
/*N*/   }
/*N*/   if (bShowYAxisTitle)
/*N*/   {
/*N*/       pYAxisTitleObj = CreateTitle (pYAxisTitleAttr, CHOBJID_DIAGRAM_TITLE_Y_AXIS,
/*N*/           bSwitchColRow,aYAxisTitle, TRUE, &eAdjustYAxesTitle);
/*N*/       if (GetAdjustMarginsForYAxisTitle())
/*N*/       {
/*N*/           if (bSwitchColRow)
/*N*/               rRect.Bottom() -= GetOutputSize(*pYAxisTitleObj).Height() + 200;
/*N*/           else
/*N*/               rRect.Left() += GetOutputSize(*pYAxisTitleObj).Width() + 200;
/*N*/       }
/*N*/   }
/*N*/   if (pXAxisTitleObj)
/*N*/       pPage->NbcInsertObject(pXAxisTitleObj);
/*N*/   if (pYAxisTitleObj)
/*N*/       pPage->NbcInsertObject(pYAxisTitleObj);
/*N*/ }


/*N*/ BOOL ChartModel::CanAxis(long nAxisId) const
/*N*/ {
/*N*/   switch(nAxisId)
/*N*/   {
/*N*/      case CHART_AXIS_PRIMARY_X:
/*?*/          return ( ! ( IsPieChart() || IsDonutChart() || IsNetChart() ));
/*N*/      case CHART_AXIS_PRIMARY_Y:
/*?*/          return ( ! ( IsPieChart() || IsDonutChart() ));
/*N*/      case CHART_AXIS_SECONDARY_X:
/*N*/      case CHART_AXIS_SECONDARY_Y:
/*N*/          switch(eChartStyle)
/*N*/          {
/*N*/               case CHSTYLE_2D_LINE:
/*N*/               case CHSTYLE_2D_STACKEDLINE:
/*N*/               case CHSTYLE_2D_PERCENTLINE:
/*N*/               case CHSTYLE_2D_COLUMN:
/*N*/               case CHSTYLE_2D_STACKEDCOLUMN:
/*N*/               case CHSTYLE_2D_PERCENTCOLUMN:
/*N*/               case CHSTYLE_2D_BAR:
/*N*/               case CHSTYLE_2D_STACKEDBAR:
/*N*/               case CHSTYLE_2D_PERCENTBAR:
/*N*/               case CHSTYLE_2D_AREA:
/*N*/               case CHSTYLE_2D_STACKEDAREA:
/*N*/               case CHSTYLE_2D_PERCENTAREA:
/*              case CHSTYLE_2D_PIE:
                case CHSTYLE_3D_STRIPE:
                case CHSTYLE_3D_COLUMN:
                case CHSTYLE_3D_FLATCOLUMN:
                 case CHSTYLE_3D_STACKEDFLATCOLUMN:
                case CHSTYLE_3D_PERCENTFLATCOLUMN:
                case CHSTYLE_3D_AREA:
                case CHSTYLE_3D_STACKEDAREA:
                case CHSTYLE_3D_PERCENTAREA:
                case CHSTYLE_3D_SURFACE:
                case CHSTYLE_3D_PIE:
*/              case CHSTYLE_2D_XY:
/*N*/ //                case CHSTYLE_3D_XYZ:
/*N*/               case CHSTYLE_2D_LINESYMBOLS:
/*N*/               case CHSTYLE_2D_STACKEDLINESYM:
/*N*/               case CHSTYLE_2D_PERCENTLINESYM:
/*N*/               case CHSTYLE_2D_XYSYMBOLS:
/*N*/               case CHSTYLE_3D_XYZSYMBOLS:
/*N*/ //                case CHSTYLE_2D_DONUT1:
/*N*/ //                case CHSTYLE_2D_DONUT2:
/*N*/               case CHSTYLE_3D_BAR:
/*N*/               case CHSTYLE_3D_FLATBAR:
/*N*/               case CHSTYLE_3D_STACKEDFLATBAR:
/*N*/               case CHSTYLE_3D_PERCENTFLATBAR:
/*              case CHSTYLE_2D_PIE_SEGOF1:
                case CHSTYLE_2D_PIE_SEGOFALL:
                case CHSTYLE_2D_NET:
                case CHSTYLE_2D_NET_SYMBOLS:
                case CHSTYLE_2D_NET_STACK:
                case CHSTYLE_2D_NET_SYMBOLS_STACK:
                case CHSTYLE_2D_NET_PERCENT:
                case CHSTYLE_2D_NET_SYMBOLS_PERCENT:
*/              case CHSTYLE_2D_CUBIC_SPLINE:
/*N*/               case CHSTYLE_2D_CUBIC_SPLINE_SYMBOL:
/*N*/               case CHSTYLE_2D_LINE_STACKEDCOLUMN:
/*N*/               case CHSTYLE_2D_LINE_COLUMN:
/*N*/               case CHSTYLE_2D_B_SPLINE:
/*N*/               case CHSTYLE_2D_B_SPLINE_SYMBOL:
/*N*/               case CHSTYLE_2D_CUBIC_SPLINE_XY:
/*N*/               case CHSTYLE_2D_CUBIC_SPLINE_SYMBOL_XY:
/*N*/               case CHSTYLE_2D_B_SPLINE_XY:
/*N*/               case CHSTYLE_2D_B_SPLINE_SYMBOL_XY:
/*N*/               case CHSTYLE_2D_XY_LINE:
/*N*/               case CHSTYLE_2D_STOCK_1:
/*N*/               case CHSTYLE_2D_STOCK_2:
/*N*/               case CHSTYLE_2D_STOCK_3:
/*N*/               case CHSTYLE_2D_STOCK_4:
/*N*/               case CHSTYLE_ADDIN:
/*N*/                  return TRUE;
/*N*/              default:
/*N*/                  return FALSE;
/*N*/          }
/*N*/          break;
/*N*/
/*N*/
/*N*/      default:
/*?*/           return FALSE;
/*N*/   }
/*N*/   return FALSE;
/*N*/ }
/*N*/ BOOL ChartModel::HasSecondYAxis() const
/*N*/ {
/*N*/   switch(eChartStyle)
/*N*/   {
/*N*/       case CHSTYLE_2D_STOCK_3:
/*N*/       case CHSTYLE_2D_STOCK_4:
            default: break;
/*N*/           return TRUE;
/*N*/   }
/*N*/   if(!CanAxis(CHART_AXIS_SECONDARY_Y))
/*N*/       return FALSE;
/*N*/
/*N*/   if(pChartBAxis->IsVisible())
/*N*/       return TRUE;
/*N*/
/*N*/
/*N*/   const SfxPoolItem *pPoolItem = NULL;
/*N*/
/*N*/   for(long n=0;n<GetRowCount();n++)
/*N*/       if(GetDataRowAttr(n).GetItemState(SCHATTR_AXIS,TRUE, &pPoolItem) == SFX_ITEM_SET)
/*N*/           if(((const SfxInt32Item*)pPoolItem)->GetValue()==CHART_AXIS_SECONDARY_Y)
/*N*/               return TRUE;
/*N*/
/*N*/   return FALSE;
/*N*/ }
/*N*/ void ChartModel::Create2DBackplane(Rectangle &rRect,SdrObjList &rObjList,BOOL bPartDescr,USHORT eStackMode)
/*N*/ {
/*N*/   BOOL bPercent=IsPercent();
/*N*/   BOOL bSwitchColRow=IsXVertikal();//IsBar()
/*N*/
/*N*/   //Initialisieren:
/*N*/   pChartXAxis->Initialise(rRect,bSwitchColRow,eStackMode,bPercent,FALSE);
/*N*/   pChartYAxis->Initialise(rRect,bSwitchColRow,eStackMode,bPercent,FALSE);
/*N*/   pChartBAxis->Initialise(rRect,bSwitchColRow,eStackMode,bPercent,FALSE);
/*N*/   pChartAAxis->Initialise(rRect,bSwitchColRow,eStackMode,bPercent,FALSE);
/*N*/
/*N*/   //Position setzen (kann man eigentlich auch im ctor des Model machen?)
/*N*/   pChartAAxis->SetPosition(CHAXIS_POS_B); //A,B sind sekund?e Achsen => oben und rechts
/*N*/   pChartBAxis->SetPosition(CHAXIS_POS_B);
/*N*/   pChartXAxis->SetPosition(CHAXIS_POS_A); //prim?e Positionen=links, unten
/*N*/   pChartYAxis->SetPosition(CHAXIS_POS_A);
/*N*/
/*N*/   pChartXAxis->CalcValueSteps();
/*N*/   pChartYAxis->CalcValueSteps();//#63904# 12%
/*N*/   pChartAAxis->CalcValueSteps();
/*N*/   pChartBAxis->CalcValueSteps();//#63904# 11%
/*N*/
/*N*/   pChartBAxis->AttachIfNoOwnData(pChartYAxis); //skalierung transferieren, falls Y keine automatische Skalierung benutzt und B keine Daten besitzt!
/*N*/   pChartYAxis->AttachIfNoOwnData(pChartBAxis); // und umgekehrt
/*N*/
/*N*/   //Falls  einer der beiden Y-Daten keine Reihen zugeordnet sind, soll diese die andere kopieren
/*N*/
/*N*/   long nTitleBottom   = rRect.Bottom();
/*N*/   long nTitleLeft     = rRect.Left();
/*N*/
/*N*/ // ******* RECT_CHANGES **** Ab hier wird am rRect rumgeschraubt ******************
/*N*/
/*N*/   Create2DXYTitles(rRect,bSwitchColRow);  //abziehen der Achsen-Titel-Fl?he
/*N*/
/*N*/   // FG: Ich merke mir vor jeglicher Aenderung des linken oder rechten Randes wo der Seitenrand
/*N*/   //     gewesen ist. Das braucht man um nun zu entscheiden ob der linke Rand wegen eines
/*N*/   //     ?erstehenden Textes nachgeregelt werden soll.
/*N*/   const Rectangle aOldRect(rRect);
/*N*/
/*N*/   //Zusammenfassen ???
/*N*/   pChartYAxis->CalcMaxTextSize();//#63904# 14%, aber Aufruf nur wenn n?ig
/*N*/   pChartYAxis->InitDescr();
/*N*/   pChartYAxis->SubtractDescrSize(rRect);//Gr?e der Beschriftung vom Rechteck abziehen
/*N*/   pChartBAxis->CalcMaxTextSize();//#63904# s.o. 0% wenn nicht benutzt!
/*N*/   pChartBAxis->InitDescr();
/*N*/   pChartBAxis->SubtractDescrSize(rRect);
/*N*/
/*N*/   pChartXAxis->SetArea(rRect); //Die X-Achsenl?ge ist bereits bekannt! wichtig f? nDescrWidth
/*N*/   pChartAAxis->SetArea(rRect); //Die Y-L?gen werden nachfolgend korrigiert
/*N*/
/*N*/   pChartAAxis->SetColTextMode(!IsXYChart(),!bPartDescr);
/*N*/   pChartXAxis->SetColTextMode(!IsXYChart(),!bPartDescr);
/*N*/
/*N*/   //f? die X-Achse gibt es ein paar sonderregel, insbesondere wird
/*N*/   //das Rect auch in der X-Breite ge?dert, wenn die Spaltenunterschriften sehr lang sind
/*N*/   //hinzu kommt noch Umbruch (an Y-Achse nicht vorgesehen), daher mu?hier eine
/*N*/   //Sonderbehandlung erfolgen, auch das InitDescr erfolgt hier nachtr?lich!
/*N*/   pChartXAxis->SubtractDescrSize_X(rRect,aOldRect);
/*N*/
/*N*/   pChartAAxis->SetArea(rRect);
/*N*/
/*N*/   pChartAAxis->SubtractDescrSize_X(rRect,aOldRect); //noch falsch!
/*N*/
/*N*/   pChartXAxis->SetArea(rRect); //jetzt sind x und y l?ge bekannt
/*N*/   pChartYAxis->SetArea(rRect);
/*N*/   pChartAAxis->SetArea(rRect);
/*N*/   pChartBAxis->SetArea(rRect);
/*N*/
/*N*/ // ******* END RECT_CHANGES ********************************************************************
/*N*/
/*N*/   rRect.Justify();
/*N*/
/*N*/   pChartXAxis->SetArea(rRect); //jetzt sind x und y l?ge bekannt
/*N*/   pChartYAxis->SetArea(rRect);
/*N*/   pChartAAxis->SetArea(rRect);
/*N*/   pChartBAxis->SetArea(rRect);
/*N*/
/*N*/   /*long nStepPartWidth=*/pChartXAxis->GetDescrWidth(); //Warum nochmal? sollte noch immer identisch nDescrWidth sein!
/*N*/
/*N*/   Position2DAxisTitles(rRect,bSwitchColRow,nTitleLeft,nTitleBottom);
/*N*/
/*N*/   // Diagrammwand
/*N*/   SdrRectObj* pWallObj = new SdrRectObj( rRect );
/*N*/   pWallObj->SetModel( this );
/*N*/   rObjList.NbcInsertObject( SetObjectAttr( pWallObj, CHOBJID_DIAGRAM_WALL,
/*N*/                                            TRUE, TRUE, pDiagramWallAttr));
/*N*/
/*N*/   //********* Erzeugung der Achsen und Gitter *****************************
/*N*/
/*N*/   SdrObjList* pXGridMainList = NULL;
/*N*/   SdrObjList* pYGridMainList = NULL;
/*N*/   SdrObjList* pXGridHelpList = NULL;
/*N*/   SdrObjList* pYGridHelpList = NULL;
/*N*/
/*N*/
/*N*/   BOOL bXAxis = (pChartXAxis->IsVisible() && pChartYAxis->IsOriginInRange());
/*N*/   BOOL bYAxis = (pChartYAxis->IsVisible() &&
/*N*/       (!IsXYChart() || (IsXYChart() && pChartXAxis->IsOriginInRange())));
/*N*/
/*N*/   if(bShowXGridMain)
/*N*/       pXGridMainList = CreateGroup (rObjList, CHOBJID_DIAGRAM_X_GRID_MAIN_GROUP);
/*N*/   if(bShowYGridMain)
/*N*/       pYGridMainList = CreateGroup (rObjList, CHOBJID_DIAGRAM_Y_GRID_MAIN_GROUP);
/*N*/   if(bShowXGridHelp)
/*?*/       pXGridHelpList = CreateGroup (rObjList, CHOBJID_DIAGRAM_X_GRID_HELP_GROUP);
/*N*/   if(bShowYGridHelp)
/*?*/       pYGridHelpList = CreateGroup (rObjList, CHOBJID_DIAGRAM_Y_GRID_HELP_GROUP);
/*N*/
/*N*/   pChartXAxis->CreateAxis( rObjList, CHOBJID_DIAGRAM_X_AXIS );
/*N*/   pChartYAxis->CreateAxis( rObjList, CHOBJID_DIAGRAM_Y_AXIS );
/*N*/
/*N*/   pChartXAxis->ShowAxis(bXAxis);
/*N*/   pChartYAxis->ShowAxis(bYAxis);
/*N*/
/*N*/   pChartXAxis->SetMainGrid(pYGridMainList,pYGridMainAttr);
/*N*/   pChartXAxis->SetHelpGrid(pYGridHelpList,pYGridHelpAttr);
/*N*/
/*N*/   pChartYAxis->SetHelpGrid(pXGridHelpList,pXGridHelpAttr);
/*N*/   pChartYAxis->SetMainGrid(pXGridMainList,pXGridMainAttr);
/*N*/
/*N*/   pChartAAxis->CreateAxis(rObjList,CHOBJID_DIAGRAM_A_AXIS);
/*N*/   pChartBAxis->CreateAxis(rObjList,CHOBJID_DIAGRAM_B_AXIS);
/*N*/
/*N*/   //sek. Achsen haben nie ein Gitter
/*N*/   pChartAAxis->SetHelpGrid(NULL,NULL);
/*N*/   pChartAAxis->SetMainGrid(NULL,NULL);
/*N*/   pChartBAxis->SetHelpGrid(NULL,NULL);
/*N*/   pChartBAxis->SetMainGrid(NULL,NULL);
/*N*/
/*N*/   pChartXAxis->CreateAxis(pChartYAxis->GetPosOrigin(),pChartXAxis->HasDescription(),bXAxis);
/*N*/
/*N*/   if (IsXYChart())
/*N*/   {
/*N*/       pChartYAxis->CreateAxis(pChartXAxis->GetPosOrigin(),pChartYAxis->HasDescription(),bYAxis);
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       if(bYAxis)
/*N*/           pChartYAxis->CreateAxis();
/*N*/   }
/*N*/
/*N*/   pChartYAxis->DrawGrids();
/*N*/   pChartBAxis->DrawGrids();//eigentlich kein Grid, nur die Ticks!
/*N*/
/*N*/   if(IsXYChart())
/*N*/   {   //Achtung! Die X-Achse unterst?zt Umbruch (nColumnTextWidth)!
/*N*/       pChartXAxis->InitDescr();
/*N*/       pChartAAxis->InitDescr();
/*N*/   }
/*N*/   else //Hier wird der ColText genutzt -> Beschr?kung auf maMaxTextSize!
/*N*/   {
/*N*/       pChartXAxis->InitDescr_X();
/*N*/       pChartAAxis->InitDescr_X();
/*N*/   }
/*N*/   pChartAAxis->DrawGrids();
/*N*/   pChartXAxis->DrawGrids();
/*N*/ }
/*N*/ void ChartModel::Position2DAxisTitles(const Rectangle& rRect,BOOL bSwitchColRow,long nTitleLeft,long nTitleBottom)
/*N*/ {
/*N*/   SdrPage *pPage = GetPage(0);
/*N*/   Size aPageSize = pPage->GetSize();
/*N*/
/*N*/   if(bShowXAxisTitle)
/*N*/   {
/*N*/       SdrObject *pXAxisTitleObj = GetObjWithId(CHOBJID_DIAGRAM_TITLE_X_AXIS,*pPage);
/*N*/
/*N*/       if (pXAxisTitleObj)
/*N*/       {
/*N*/
/*N*/
/*N*/           Point aXAxesTitlePosition (rRect.Left() + (int) (rRect.GetWidth() / 2),nTitleBottom);
/*N*/
/*N*/           if (GetXAxisTitleHasBeenMoved() && GetUseRelativePositions() &&
/*N*/               (aXAxesTitlePosition.X() > 0) && (aXAxesTitlePosition.Y() > 0))
/*N*/           {
/*N*/               // FG: Das ist eine Variable die in BuildChart gesetzt wird, kurz bevor
/*N*/               //     das Objekt zerstoert wird.
/*N*/               double fRelativeXPosition = ((double) aTitleXAxisPosition.X()) / aInitialSize.Width();
/*N*/               double fRelativeYPosition = ((double) aTitleXAxisPosition.Y()) / aInitialSize.Height();
/*N*/               aXAxesTitlePosition.X() = (int) (aPageSize.Width() * fRelativeXPosition + 0.5);
/*N*/               aXAxesTitlePosition.Y() = (int) (aPageSize.Height() * fRelativeYPosition + 0.5);
/*N*/           }
/*N*/           else
/*N*/           {
/*N*/               if (bSwitchColRow)
/*N*/               {
/*N*/                   aXAxesTitlePosition.X() = nTitleLeft;
/*N*/                   aXAxesTitlePosition.Y() = (long)(rRect.Top() + rRect.GetHeight() / 2);
/*N*/               }
/*N*/           }
/*N*/           SetTextPos((SdrTextObj &) *pXAxisTitleObj, aXAxesTitlePosition,pXAxisTitleAttr);
/*N*/       }
/*N*/   }
/*N*/
/*N*/   if(bShowYAxisTitle)
/*N*/   {
/*N*/       SdrObject *pYAxisTitleObj = GetObjWithId(CHOBJID_DIAGRAM_TITLE_Y_AXIS,*pPage);
/*N*/
/*N*/       if (pYAxisTitleObj)
/*N*/       {
/*N*/           Point aYAxesTitlePosition (Max(0L,nTitleLeft),
/*N*/               Max(0L,(long) (rRect.Top() + (int) (rRect.GetHeight() / 2))));
/*N*/
/*N*/           if (GetYAxisTitleHasBeenMoved() && GetUseRelativePositions() &&
/*N*/               (aYAxesTitlePosition.X() >= 0) && (aYAxesTitlePosition.Y() >= 0))
/*N*/           {
/*N*/               // FG: Das ist eine Variable die in BuildChart gesetzt wird, kurz bevor
/*N*/               //     das Objekt zerstoert wird.
/*N*/               double fRelativeXPosition = ((double) aTitleYAxisPosition.X()) / aInitialSize.Width();
/*N*/               double fRelativeYPosition = ((double) aTitleYAxisPosition.Y()) / aInitialSize.Height();
/*N*/               aYAxesTitlePosition.X() = (int) (aPageSize.Width() * fRelativeXPosition + 0.5);
/*N*/               aYAxesTitlePosition.Y() = (int) (aPageSize.Height() * fRelativeYPosition + 0.5);
/*N*/           }
/*N*/           else
/*N*/           {
/*N*/               if (bSwitchColRow)
/*N*/               {
/*N*/                   aYAxesTitlePosition.X() = rRect.Left() + (int) (rRect.GetWidth() / 2);
/*N*/                   aYAxesTitlePosition.Y() = nTitleBottom;
/*N*/               }
/*N*/           }
/*N*/           SetTextPos((SdrTextObj &)*pYAxisTitleObj, aYAxesTitlePosition,pYAxisTitleAttr);
/*N*/       }
/*N*/   }
/*N*/ }
/*************************************************************************
|*
|* create 2d column charts
|*
\************************************************************************/

/*N*/ SdrObjGroup* ChartModel::Create2DColChart(Rectangle aRect)
/*N*/ {
/*N*/
/*N*/   // Background
/*N*/   SchObjGroup* pGroup;
/*N*/   SdrObjList*  pList;
/*N*/   CreateChartGroup (pGroup, pList);
/*N*/   Create2DBackplane(aRect, *pList, TRUE,IsStacked() ? CHSTACK_MINMAX : CHSTACK_NONE);
/*N*/
/*N*/   Rectangle aClipRect( aRect );
/*N*/   aClipRect.Right() += 1;
/*N*/   aClipRect.Top() -= 1;
/*N*/
/*N*/   long nColCnt = GetColCount();
/*N*/   long nRowCnt = GetRowCount();
/*N*/
/*N*/   ULONG nInsert,nInsStat;
/*N*/   ULONG nAxisBPos=CONTAINER_APPEND;
/*N*/   ULONG nAxisYPos=pList->GetObjCount()-1;
/*N*/
/*N*/   //VerbundChart, Symbol der Linie, dynamische Gr?e:
/*N*/   Size aLegendSize (((SvxFontWidthItem &) pLegendAttr->Get (EE_CHAR_FONTWIDTH)).GetWidth (),
/*N*/                     ((SvxFontHeightItem &) pLegendAttr->Get (EE_CHAR_FONTHEIGHT)).GetHeight ());
/*N*/     OutputDevice * pRefDev = GetRefDevice();
/*N*/   if(pRefDev)
/*N*/       aLegendSize = pRefDev->PixelToLogic (pRefDev->LogicToPixel (aLegendSize));
/*N*/   else
/*N*/       OSL_FAIL("ChartModel: no RefDevice");
/*N*/   long nLegendHeight = aLegendSize.Height () * 9 / 10;
/*N*/
/*N*/   SdrObject   *pObj;
/*N*/   ChartAxis* pAxis=pChartYAxis;
/*N*/   short nCol, nRow;
/*N*/   BOOL  bPercent = IsPercent();
/*N*/
/*N*/   long nLines = Min((long)GetNumLinesColChart(),(long)(nRowCnt));;//#50212#
/*N*/   long nLineStart = nRowCnt-nLines; //#50212# Ab hier werden Linien gezeichnet
/*N*/
/*N*/   //BarDescriptoren erzeugen
/*N*/   long nR1=0,nR2=0;
/*N*/   if(IsStacked())//Reihenzahl in diesem Fall egal
/*N*/   {
/*N*/       nR1=nR2=1;
/*N*/   }
/*N*/   else //sonst Datenreihen mit Balken je Achse z?len: (Lines fallen weg)
/*N*/   {
/*N*/       for(nRow=0;nRow<nRowCnt;nRow++)
/*N*/       {
/*N*/           long nAxisUID=((const SfxInt32Item&)GetDataRowAttr(nRow).Get(SCHATTR_AXIS)).GetValue();
/*N*/           if(IsBar()||IsCol(nRow))
/*N*/           {
/*N*/               if(nAxisUID == CHART_AXIS_SECONDARY_Y)
/*N*/                   nR2++;
/*N*/               else
/*N*/                   nR1++;
/*N*/           }
/*N*/       }
/*N*/   }
/*N*/
/*N*/   if(!nR1)    //Verbundcharts, Lines werden oben nicht ber?ksichtigt,
/*N*/       nR1=1;  //aber nRn=0 macht keinen Sinn -> Korrektur
/*N*/   if(!nR2)
/*N*/       nR2=1;
/*N*/   aBarY1.Create(aRect,nColCnt,nR1);
/*N*/   aBarY2.Create(aRect,nColCnt,nR2);
/*N*/   ChartBarDescriptor* pBar=&aBarY1;
/*N*/
/*N*/   SdrObjList      **pRowLists   = new SdrObjList*[nRowCnt];
/*N*/   SdrObjList      **pStatLists  = new SdrObjList*[nRowCnt];
/*N*/
/*N*/   ChartDataDescription aDescr(nColCnt,nRowCnt,pList,this,bShowDataDescr);
/*N*/
/*N*/   Point *pTracePoint=0;
/*N*/   if(m_nDefaultColorSet&CHSPECIAL_TRACELINES)
/*N*/   {
/*?*/       pTracePoint = new Point[nRowCnt];//#50149#
/*N*/   }
/*N*/
/*N*/
/*N*/   XPolygon *pLine = new XPolygon[nLines]; //#50149#
/*N*/   BOOL    bStartPointIsValid(FALSE);  //  Indicates wether the first point of a line
/*N*/                               //  segment is valid.
/*N*/
/*N*/   for (nCol = 0; nCol < nColCnt; nCol++)
/*N*/   {
/*N*/       Point aTextPos;
/*N*/
/*N*/       for (nRow = 0; nRow < nRowCnt; nRow++)
/*N*/       {
/*N*/           const SfxItemSet& rDataRowAttr = GetDataRowAttr(nRow);
/*N*/           SfxItemSet aDataPointAttr(rDataRowAttr);
/*N*/           MergeDataPointAttr(aDataPointAttr,nCol,nRow); //#63904#
/*N*/
/*N*/           //Achse und Bardescriptor w?len, Insertreihenfolge festlegen  ->
/*N*/           long nAxisUID=((const SfxInt32Item&)rDataRowAttr.Get(SCHATTR_AXIS)).GetValue();
/*N*/           pAxis=GetAxisByUID(nAxisUID);
/*N*/           if(nAxisUID==CHART_AXIS_SECONDARY_Y)
/*N*/           {
/*?*/               pBar=&aBarY2;
/*?*/               nInsert=nAxisBPos;
/*N*/           }
/*N*/           else
/*N*/           {
/*N*/               pBar=&aBarY1;
/*N*/               nInsert=nAxisYPos;//Insert-Reihenfolge festlegen
/*N*/           }
/*N*/           BOOL bIsLine=IsLine(nRow);
/*N*/           if(bIsLine)
/*N*/               nInsert=CONTAINER_APPEND;
/*N*/
/*N*/           nInsStat = (nInsert==CONTAINER_APPEND) ? nInsert : nInsert+1;//Statistik immer hinter den Reihenobjekten, sonst wird sie verdeckt
/*N*/           //<- Achse und Bardescriptor w?len, Insertreihenfolge festlegen
/*N*/
/*N*/           if(!nRow)
/*N*/           {
/*N*/               pChartBAxis->InitStacking();
/*N*/               pChartYAxis->InitStacking();
/*N*/           }
/*N*/
/*N*/           if (!nCol)
/*N*/           {
/*N*/               SchObjGroup* pRowGroup = (SchObjGroup*) CreateSimpleGroup (CHOBJID_DIAGRAM_ROWGROUP, TRUE, TRUE);
/*N*/
/*N*/               pRowGroup->InsertUserData(new SchDataRow(nRow));
/*N*/               pList->NbcInsertObject(pRowGroup,nInsert);
/*N*/               pRowLists[nRow] = pRowGroup->GetSubList();
/*N*/
/*N*/               SchObjGroup* pStatGroup = (SchObjGroup*) CreateSimpleGroup (CHOBJID_DIAGRAM_STATISTICS_GROUP, TRUE, TRUE);
/*N*/
/*N*/               pStatGroup->InsertUserData(new SchDataRow(nRow));
/*N*/               pList->NbcInsertObject(pStatGroup,nInsStat);
/*N*/               pStatLists [nRow] = pStatGroup->GetSubList ();
/*N*/           }
/*N*/
/*N*/           double     fData          = GetData(nCol, nRow, bPercent);
/*N*/
/*N*/           BOOL bLogarithm = pAxis->IsLogarithm();
/*N*/           switch (eChartStyle)
/*N*/           {
/*N*/               case CHSTYLE_2D_COLUMN:
/*N*/               case CHSTYLE_2D_LINE_COLUMN:
/*N*/               {
/*N*/                   Point aTopLeft(pBar->BarLeft(),pAxis->GetUpper(fData,TRUE));
/*N*/                   Point aBottomRight(pBar->BarRight(),pAxis->GetLower(fData,TRUE));
/*N*/
/*N*/                   Rectangle aObjRect(aTopLeft, aBottomRight);
/*N*/
/*N*/                   BOOL bShow = (aObjRect.Bottom() >= aObjRect.Top());
/*N*/                   aObjRect.Justify();
/*N*/
/*N*/                   if (bShow && ((!bLogarithm && (fData != DBL_MIN)) ||
/*N*/                                 (bLogarithm && (fData != DBL_MIN) && (fData > 0.0))))
/*N*/                   {
/*N*/                       if(bIsLine) //#50212#
/*N*/                       {
/*N*/                           // Verbund-Chart
/*N*/                           // Letzte "Datenreihe" als Linie ausgeben
/*N*/                           pLine[nRow-nLineStart][1] =
/*N*/                               Point(pBar->Middle(),pAxis->GetPos(fData));
/*N*/
/*N*/                           if (nCol == 0)
/*N*/                           {
/*N*/                               // Beim ersten Datenpunkt: Anfangspunkt = EndPunkt
/*N*/                               pLine[nRow-nLineStart][0] = pLine[nRow-nLineStart][1];//#50212#
/*N*/                               bStartPointIsValid = TRUE;
/*N*/                           }
/*N*/                           // Symbol einfuegen
/*N*/                             Point& rInsert = pLine[ nRow - nLineStart ][ 1 ];
/*N*/
/*N*/                             if( aClipRect.IsInside( rInsert ) )
/*N*/                             {
/*N*/                                 SdrObject* pNewObj = CreateSymbol( rInsert, nRow, nCol,
/*N*/                                                                    (SfxItemSet &)aDataPointAttr,
/*N*/                                                                    nLegendHeight ); //#50212#
/*N*/                                 if(pNewObj)
/*N*/                                 {
/*N*/                                     pNewObj->InsertUserData(new SchObjectId(CHOBJID_DIAGRAM_DATA));
/*N*/                                     pRowLists[nRow]->NbcInsertObject(pNewObj);
/*N*/                                 }
/*N*/                             }
/*N*/
/*N*/                           //  Insert the line segment only if its starting point has a valid
/*N*/                           //  value.
/*N*/                           if (bStartPointIsValid)
/*N*/                           {
/*N*/                               // Insert line.
/*N*/                                 XPolyPolygon aResult;
/*N*/                                 SchCalculationHelper::IntersectPolygonWithRectangle( pLine[ nRow - nLineStart ],
/*N*/                                                                                      aClipRect,
/*N*/                                                                                      aResult );
/*N*/                                 if( aResult.Count())
/*N*/                                 {
/*N*/                                     SdrPathObj* pLclObj = new SdrPathObj( OBJ_PLIN, aResult );
/*N*/                                     pLclObj->InsertUserData( new SchObjectId( CHOBJID_DIAGRAM_ROWSLINE ));
/*N*/                                     pLclObj->InsertUserData( new SchDataRow( nRow ));
/*N*/                                     pRowLists[ nRow ]->NbcInsertObject( pLclObj, 0 );
/*N*/
/*N*/                                     // Set the line's attributes.
/*N*/                                     pLclObj->SetItemSet( rDataRowAttr );
/*N*/                                 }
/*N*/                           }
/*N*/
/*N*/                           // Anfangspunkt des naechsten Datenpunkts =
/*N*/                           // Endpunkt des aktuellen Datenpunkts
/*N*/                           pLine[nRow-nLineStart][0] = pLine[nRow-nLineStart][1];//#50212#
/*N*/                           bStartPointIsValid = TRUE;
/*N*/                       }
/*N*/                       else
/*N*/                       {
/*N*/                           pRowLists[nRow]->NbcInsertObject(CreateRect (aObjRect, nCol, nRow, aDataPointAttr));
/*N*/                       }
/*N*/
/*N*/                   }
/*N*/                   else if (bIsLine)
/*N*/                   {
/*N*/                       //  Remember that the current point may not be inserted.
/*?*/                       bStartPointIsValid = FALSE;
/*N*/                   }
/*N*/
/*N*/                   pBar->NextBar();
/*N*/               }
/*N*/               break;
/*N*/
/*N*/               case CHSTYLE_2D_STACKEDCOLUMN:
/*N*/               case CHSTYLE_2D_PERCENTCOLUMN:
/*N*/               case CHSTYLE_2D_LINE_STACKEDCOLUMN:
/*N*/               {
/*N*/                   Pair aTopBottom(pAxis->Stack(fData,TRUE));
/*N*/                   Point aTopLeft(pBar->BarLeft(),aTopBottom.A());
/*N*/                   Point aBottomRight(pBar->BarRight(),aTopBottom.B());
/*N*/
/*N*/
/*N*/                   Rectangle aObjRect(aTopLeft, aBottomRight);
/*N*/
/*N*/                   BOOL bShow =   (aObjRect.Bottom() >= aObjRect.Top());
/*N*/
/*N*/                   //Stackedline-Chart benutzt dieses ObjectRect nicht => Bug #48970#
/*N*/                   if (bIsLine)
/*?*/                          bShow=TRUE;//#50212#
/*N*/
/*N*/                   if(fData==DBL_MIN)
/*N*/                   {
/*?*/                       bShow=FALSE;
/*N*/                   }
/*N*/                   else
/*N*/                   {
/*N*/                       // bShow includes Top == Bottom and that may be ok, if there is no data in the chart
/*N*/                       // and > might also happen (difference 1 from rounding errors)
/*N*/                       // AND if bShow is TRUE the following part fixes the problem
/*N*/                       // so ASSERT => TRACE
/*N*/                       CHART_TRACE1( "Create2DColChart bShow = %s", bShow? "True" : "False" );
/*N*/                   }
/*N*/                   if(bLogarithm && (fData <= 0.0) )
/*?*/                       bShow=FALSE;
/*N*/
/*N*/                   if (bShow)
/*N*/                   {
/*N*/                       aObjRect.Justify();
/*N*/
/*N*/                       if (bIsLine)//#50212#
/*N*/                       {
/*?*/                           pLine[nRow-nLineStart][1] = Point(pBar->Middle()//MIDPOS//zu umst?dlich: nPos + nPartWidth/2 - nGap
/*?*/                               ,pAxis->GetPos(fData));//#50212#
/*?*/
/*?*/                           if (nCol == 0)
/*?*/                           {
/*?*/                               // Beim ersten Datenpunkt: Anfangspunkt = EndPunkt
/*?*/                               pLine[nRow-nLineStart][0] = pLine[nRow-nLineStart][1];//#50212#
/*?*/                           }
/*?*/                             Point& rInsert = pLine[ nRow - nLineStart ][ 1 ];
/*?*/
/*?*/                             if( aClipRect.IsInside( rInsert ))
/*?*/                             {
/*?*/                                 SdrObject* pNewObj = CreateSymbol( rInsert, nRow, nCol,
/*?*/                                                                    (SfxItemSet &) aDataPointAttr,
/*?*/                                                                    nLegendHeight ); //#50212#
/*?*/                                 if(pNewObj)
/*?*/                                 {
/*?*/                                     pNewObj->InsertUserData(new SchObjectId(CHOBJID_DIAGRAM_DATA));
/*?*/                                     pRowLists[nRow]->NbcInsertObject(pNewObj);
/*?*/                                 }
/*?*/                             }
/*?*/
/*?*/                           // Insert line.
/*?*/                             XPolyPolygon aResult;
/*?*/                             SchCalculationHelper::IntersectPolygonWithRectangle( pLine[ nRow - nLineStart ],
/*?*/                                                                                  aClipRect,
/*?*/                                                                                  aResult );
/*?*/                             if( aResult.Count())
/*?*/                             {
/*?*/                                 SdrPathObj* pLclObj = new SdrPathObj( OBJ_PLIN, aResult );
/*?*/                                 pLclObj->InsertUserData( new SchObjectId( CHOBJID_DIAGRAM_ROWSLINE ));
/*?*/                                 pLclObj->InsertUserData( new SchDataRow( nRow ));
/*?*/                                 pRowLists[ nRow ]->NbcInsertObject( pLclObj, 0 );
/*?*/
/*?*/                                 // Set the line's attributes.
/*?*/                                 pLclObj->SetItemSet( rDataRowAttr );
/*?*/                             }
/*?*/
/*?*/                           // Anfangspunkt des naechsten Datenpunkts =
/*?*/                           // Endpunkt des aktuellen Datenpunkts
/*?*/                           pLine[nRow-nLineStart][0] = pLine[nRow-nLineStart][1];//#50212#
/*N*/                       }
/*N*/                       else
/*N*/                       { //#50116#
/*N*/                           Rectangle aBarRect(aObjRect);
/*N*/                           if(nBarPercentWidth<100 && nBarPercentWidth>0)
/*N*/                           {
/*?*/                               double fWidth=aBarRect.GetWidth();
/*?*/                               fWidth=fWidth*((double)nBarPercentWidth/100.0);
/*?*/                               long nWidth=Round(fWidth);
/*?*/                               long nDiff=(aBarRect.GetWidth()-nWidth);
/*?*/
/*?*/                               Size aSize=aBarRect.GetSize();
/*?*/                               aSize.Width()-=nDiff;
/*?*/                               aBarRect.SetSize(aSize);
/*?*/                               aBarRect.Move(nDiff/2,0);
/*N*/                           }
/*N*/                           pRowLists[nRow]->NbcInsertObject(CreateRect (aBarRect, nCol, nRow, aDataPointAttr));
/*N*/
/*N*/                           BOOL bIsDownward=(BOOL)(fData < 0.0);//FALSE;//#51471#
/*N*/
/*N*/                           if(pTracePoint) //#50149#
/*N*/                           {
/*?*/                               if(nCol != 0)
/*?*/                               {
/*?*/                                   Point aEndPoint=bIsDownward ? aBarRect.BottomLeft() : aBarRect.TopLeft();//#51471#
/*?*/                                   SdrPathObj* pLclObj = new SdrPathObj(pTracePoint[nRow],aEndPoint);
/*?*/                                   pLclObj->InsertUserData(new SchObjectId (0));
/*?*/                                   pList->NbcInsertObject(pLclObj);//immer vorne, egal welche Achse
/*?*/                                   // Linie attributieren
/*?*/
/*?*/                                   pLclObj->SetItemSet(rDataRowAttr);
/*?*/
/*?*/                              }
/*?*/                               pTracePoint[nRow]=bIsDownward ? aBarRect.BottomRight() :aBarRect.TopRight();//#51471#
/*N*/                           }
/*N*/                       }
/*N*/                   }
/*N*/                   break;
/*N*/               }
/*N*/
/*N*/               case CHSTYLE_2D_BAR:
/*N*/               {
/*N*/                   Point aTopLeft( pAxis->GetLower(fData),pBar->BarTop() );
/*N*/                   Point aRightBottom( pAxis->GetUpper(fData),pBar->BarBottom() );
/*N*/                   Rectangle aObjRect(aTopLeft,aRightBottom);
/*N*/
/*N*/                   BOOL bShow = (aObjRect.Right() >= aObjRect.Left());
/*N*/                   aObjRect.Justify();
/*N*/
/*N*/                   if ((bShow) && ((!bLogarithm && (fData != DBL_MIN)) ||
/*N*/                                   (bLogarithm && (fData != DBL_MIN) && (fData > 0.0))))
/*N*/                   {
/*N*/                       pRowLists[nRow]->NbcInsertObject(CreateRect (aObjRect, nCol, nRow, aDataPointAttr));
/*N*/
/*N*/                       if(aDescr.Enabled())
/*N*/                       {
/*N*/                           Point aPos(aObjRect.TopRight());
/*N*/                           aPos.Y()+=aObjRect.GetHeight() / 2;
/*N*/                           aPos.X()+=500;
/*N*/                       }
/*N*/                   }
/*N*/                   pBar->NextBar();
/*N*/               }
/*N*/               break;
/*N*/
/*N*/               case CHSTYLE_2D_STACKEDBAR:
/*N*/               case CHSTYLE_2D_PERCENTBAR:
/*N*/               {
/*N*/                   Pair aLeftRight(pAxis->Stack(fData,TRUE));
/*N*/                   Point aTopLeft(aLeftRight.A(),pBar->BarBottom());
/*N*/                   Point aBottomRight(aLeftRight.B(),pBar->BarTop());
/*N*/
/*N*/                   Rectangle aObjRect(aTopLeft,aBottomRight);
/*N*/
/*N*/
/*N*/                   if ((aObjRect.Right() >= aObjRect.Left()) &&
/*N*/                       ((!bLogarithm && (fData != DBL_MIN)) ||
/*N*/                        (bLogarithm && (fData != DBL_MIN) && (fData > 0.0))))
/*N*/                   {
/*N*/                       aObjRect.Justify();
/*N*/
/*N*/                       pObj = new SdrRectObj( aObjRect );
/*N*/                       pObj->SetModel( this );
/*N*/                       pObj = SetObjectAttr( pObj, CHOBJID_DIAGRAM_DATA, TRUE, TRUE, &aDataPointAttr );
/*N*/                       pObj->InsertUserData(new SchDataPoint(nCol, nRow));
/*N*/                       pRowLists[nRow]->NbcInsertObject(pObj);
/*N*/                   }
/*N*/                   break;
/*N*/               }
                    default: break;
/*N*/           }
/*N*/       } //for nRow
/*N*/       aBarY1.NextCol();
/*N*/       aBarY2.NextCol();
/*N*/   }//for nCol
/*N*/
/*N*/   aDescr.Build(TRUE);
/*N*/   delete[] pTracePoint;//#50149#
/*N*/   delete[] pLine;//#50212#
/*N*/   delete[] pRowLists;
/*N*/   delete[] pStatLists;
/*N*/   return pGroup;
/*N*/ }


/*************************************************************************
|*
|* Fl?chendiagramm erzeugen
|*      case CHSTYLE_2D_LINE:
|*      case CHSTYLE_2D_STACKEDLINE:
|*      case CHSTYLE_2D_PERCENTLINE:
|*      case CHSTYLE_2D_LINESYMBOLS :
|*      case CHSTYLE_2D_STACKEDLINESYM :
|*      case CHSTYLE_2D_PERCENTLINESYM :
|*      case CHSTYLE_2D_CUBIC_SPLINE :
|*      case CHSTYLE_2D_CUBIC_SPLINE_SYMBOL :
|*      case CHSTYLE_2D_B_SPLINE :
|*      case CHSTYLE_2D_B_SPLINE_SYMBOL :
|*
\************************************************************************/
/*N*/ BOOL ChartModel::HasStockLines( SvxChartStyle* pStyle )
/*N*/ {
/*N*/   switch( pStyle? *pStyle: eChartStyle )
/*N*/   {
/*N*/       case CHSTYLE_2D_STOCK_1:
/*N*/       case CHSTYLE_2D_STOCK_2:
/*N*/       case CHSTYLE_2D_STOCK_3:
/*N*/       case CHSTYLE_2D_STOCK_4:
/*N*/       return TRUE;
/*N*/       default:
/*N*/       return FALSE;
/*N*/   }
/*N*/ }
/*N*/ BOOL ChartModel::HasStockRects( SvxChartStyle* pStyle )
/*N*/ {
/*N*/   switch( pStyle? *pStyle: eChartStyle )
/*N*/   {
/*N*/       case CHSTYLE_2D_STOCK_2:
/*N*/       case CHSTYLE_2D_STOCK_4:
/*N*/       return TRUE;
/*N*/       default:
/*N*/       return FALSE;
/*N*/   }
/*N*/ }
/*N*/ BOOL ChartModel::HasStockBars( SvxChartStyle* pStyle )
/*N*/ {
/*N*/   switch( pStyle? *pStyle: eChartStyle )
/*N*/   {
/*N*/       case CHSTYLE_2D_STOCK_3:
/*N*/       case CHSTYLE_2D_STOCK_4:
/*N*/       return TRUE;
/*N*/       default:
/*N*/       return FALSE;
/*N*/   }
/*N*/ }
/*N*/ ChartAxis* ChartModel::GetAxisByUID(long nUId)
/*N*/ {
/*N*/   switch(nUId)
/*N*/   {
/*N*/   case CHART_AXIS_PRIMARY_X:
/*N*/       return pChartXAxis;
/*N*/   case CHART_AXIS_PRIMARY_Y:
/*N*/       return pChartYAxis;
/*N*/   case CHART_AXIS_PRIMARY_Z:
/*N*/       return pChartZAxis;
/*N*/   case CHART_AXIS_SECONDARY_Y:
/*N*/       return pChartBAxis;
/*N*/   case CHART_AXIS_SECONDARY_X:
/*N*/       return pChartAAxis;
/*N*/   }
/*N*/   OSL_TRACE( "ChartAxis not found: id=%ld", nUId );
/*N*/   return pChartYAxis;
/*N*/ }
/*N*/ #define SchDataCol(a) SchDataRow(a)     //erst mal testen..... (wird eh ne geklonte Klasse)

/*N*/ void ChartModel::DrawStockLines( SdrObjList* pList, const Rectangle& rRect )
/*N*/ { //und fuer Stock-Charts
/*N*/
/*N*/   long nStart=HasStockBars() ? 1:0;
/*N*/   if(HasStockLines())
/*N*/   {
/*N*/
/*N*/       long nColCnt = GetColCount();
/*N*/       long nRowCnt = GetRowCount();
/*N*/       long nCol, nRow;
/*N*/
/*N*/       SdrObject   *pObj;
/*N*/       SdrObjList  *pLineList,*pLossList=NULL,*pPlusList=NULL;
/*N*/       SchObjGroup *pLineGroup,*pLossGroup=NULL,*pPlusGroup=NULL;
/*N*/
/*N*/
/*N*/       ChartBarDescriptor* pBar(0);
/*N*/       aBarY2.Create(rRect,nColCnt,1);
/*N*/       aBarY1.Create(rRect,nColCnt,1);
/*N*/
/*N*/       pLineGroup =(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_STOCKLINE_GROUP,TRUE, TRUE);
/*N*/       pList->NbcInsertObject(pLineGroup);
/*N*/       pLineList = pLineGroup->GetSubList();
/*N*/
/*N*/       XPolygon aPolyStock(2);
/*N*/
/*N*/       //StockRects:
/*N*/       long nLow,nHi;
/*N*/
/*N*/       for (nCol = 0; nCol < nColCnt; nCol++)
/*N*/       {
/*N*/           BOOL bOK=FALSE;
/*N*/           nLow=nHi=0;
/*N*/           for (nRow = nStart; nRow < nRowCnt; nRow++)
/*N*/           {
/*N*/               if(GetAxisUID(nRow)==CHART_AXIS_SECONDARY_Y)
/*?*/                   pBar=&aBarY2;
/*N*/               else
/*N*/                   pBar=&aBarY1;
/*N*/
/*N*/               ChartAxis *pAxis=GetAxisByUID(((const SfxInt32Item &)GetDataRowAttr(nRow).Get(SCHATTR_AXIS)).GetValue());
/*N*/               double fData = GetData(nCol,nRow,FALSE);
/*N*/               if(fData != DBL_MIN)
/*N*/               {
/*N*/                   bOK=TRUE;
/*N*/                   long nYPos = pAxis->GetPos(fData);
/*N*/
/*N*/                   aPolyStock[0].X()=aPolyStock[1].X()=(USHORT)pBar->Middle();
/*N*/                   if(nRow==nStart)//geht auch sch?er: bInitialise (ToDo:)
/*N*/                   {
/*N*/                       aPolyStock[0].Y()=aPolyStock[1].Y()=(USHORT) nYPos;
/*N*/                   }
/*N*/                   else
/*N*/                   {
/*N*/                       if((USHORT)nYPos > aPolyStock[0].Y())
/*N*/                           aPolyStock[0].Y()=(USHORT)nYPos;
/*N*/                       if((USHORT)nYPos < aPolyStock[1].Y())
/*N*/                           aPolyStock[1].Y()=(USHORT)nYPos;
/*N*/                   }
/*N*/                   switch(nRow-nStart)//StockRects
/*N*/                   {
/*N*/                       case 0:
/*N*/                           nLow=nYPos;
/*N*/                           break;
/*N*/                       case 3:
/*N*/                           nHi=nYPos;
/*N*/                           break;
/*N*/                   }
/*N*/               }
/*N*/           }
/*N*/           if(bOK)
/*N*/           {
/*N*/               pObj = new SdrPathObj(OBJ_PLIN, aPolyStock);
/*N*/               pObj->InsertUserData(new SchObjectId (CHOBJID_DIAGRAM_STOCKLINE));
/*N*/               pObj->InsertUserData(new SchDataCol((short)nCol));
/*N*/               pLineList->NbcInsertObject(pObj,LIST_APPEND);
/*N*/
/*N*/               pObj->SetItemSet(*pStockLineAttr);
/*N*/
/*N*/               if(HasStockRects()&&nRowCnt>3)
/*N*/               {
/*N*/                   BOOL bLoss=TRUE;
/*N*/                   if(nLow>nHi)
/*N*/                   {
/*N*/                       long nTmp=nLow;
/*N*/                       nLow=nHi;
/*N*/                       nHi=nTmp;
/*N*/                       bLoss=FALSE;
/*N*/                   }
/*N*/
/*N*/                   if(!pLossList&&bLoss)
/*N*/                   {
/*N*/                       pLossGroup =(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_STOCKLOSS_GROUP,TRUE, TRUE);
/*N*/                       pList->NbcInsertObject(pLossGroup);
/*N*/                       pLossList = pLossGroup->GetSubList();
/*N*/                   }
/*N*/                   if(!pPlusList && !bLoss)
/*N*/                   {
/*N*/                       pPlusGroup =(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_STOCKPLUS_GROUP,TRUE, TRUE);
/*N*/                       pList->NbcInsertObject(pPlusGroup);
/*N*/                       pPlusList = pPlusGroup->GetSubList();
/*N*/                   }
/*N*/                   pObj = new SdrRectObj(Rectangle(Point(pBar->BarLeft(),nLow),Size(pBar->BarWidth(),nHi-nLow)));
/*N*/                   pObj->InsertUserData(new SchObjectId (CHOBJID_DIAGRAM_STOCKRECT));
/*N*/                   pObj->InsertUserData(new SchDataCol((short)nCol));
/*N*/                   if(bLoss)
/*N*/                   {
/*N*/                       pLossList->NbcInsertObject(pObj,LIST_APPEND);
/*N*/
/*N*/                       pObj->SetItemSet(*pStockLossAttr);
/*N*/                   }
/*N*/                   else
/*N*/                   {
/*N*/                       pPlusList->NbcInsertObject(pObj,LIST_APPEND);
/*N*/
/*N*/                       pObj->SetItemSet(*pStockPlusAttr);
/*N*/                   }
/*N*/               }
/*N*/           }
/*N*/
/*N*/           aBarY1.NextCol();
/*N*/           aBarY2.NextCol();
/*N*/       }
/*N*/   }
/*N*/ }
/*N*/ void ChartModel::DrawStockBars(SdrObjList* pList,const Rectangle& aRect)
/*N*/ {
/*N*/   const long nRow = 0;
/*N*/
/*N*/   const SfxItemSet& rDataRowAttr = GetDataRowAttr(nRow);
/*N*/
/*N*/   long nColCnt = GetColCount();
/*N*/
/*N*/   ChartBarDescriptor* pBar;
/*N*/   long nAxisUID=GetAxisUID(nRow);
/*N*/   switch(nAxisUID)
/*N*/   {
/*N*/       case CHART_AXIS_SECONDARY_Y:
/*N*/           aBarY2.Create(aRect,nColCnt,1);
/*N*/           pBar=&aBarY2;
/*N*/           break;
/*N*/       default:
/*N*/           aBarY1.Create(aRect,nColCnt,1);
/*N*/           pBar=&aBarY1;
/*N*/           break;
/*N*/   }
/*N*/
/*N*/   if(GetRowCount()&&HasStockBars())
/*N*/   {
/*N*/       ChartAxis *pAxis=GetAxisByUID(((const SfxInt32Item &)rDataRowAttr.Get(SCHATTR_AXIS)).GetValue());
/*N*/       long nCol;
/*N*/
/*N*/       SdrObjList  *pBarList;
/*N*/
/*N*/       SchObjGroup *pBarGroup;
/*N*/
/*N*/       pBarGroup =(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_ROWGROUP,TRUE, TRUE);
/*N*/       pBarGroup->InsertUserData(new SchDataRow(nRow));
/*N*/
/*N*/       pList->NbcInsertObject(pBarGroup);
/*N*/       pBarList = pBarGroup->GetSubList();
/*N*/
/*N*/       for (nCol = 0; nCol < nColCnt; nCol++)
/*N*/       {
/*N*/           SfxItemSet aDataPointAttr(GetFullDataPointAttr(nCol,nRow));
/*N*/
/*N*/
/*N*/           double fData = GetData(nCol,nRow,FALSE);
/*N*/           long nHi = pAxis->GetPos(fData);
/*N*/           long nLow= pAxis->GetPosOrigin();
/*N*/
/*N*/           if(fData != DBL_MIN)
/*N*/           {
/*N*/               Rectangle aObjRect(Point(pBar->BarLeft(),nLow),Size(pBar->BarWidth(),nHi-nLow));
/*N*/               pBarList->NbcInsertObject(CreateRect(aObjRect,nCol,nRow,aDataPointAttr));
/*N*/           }
/*N*/           pBar->NextCol();
/*N*/       }
/*N*/   }
/*N*/ }


/*N*/ SdrObjGroup* ChartModel::Create2DRowLineChart(Rectangle aRect)
/*N*/ {
/*N*/   BOOL bPartDescr=FALSE;
/*N*/   if(HasStockLines())
/*N*/       bPartDescr=TRUE;
/*N*/
/*N*/   SchObjGroup *pGroup;
/*N*/   SdrObjList  *pList;
/*N*/   CreateChartGroup (pGroup, pList);
/*N*/   BOOL bStacked   = IsStacked();
/*N*/   USHORT eStackMode =  bStacked ? CHSTACK_OVERLAP : CHSTACK_NONE;
/*N*/   Create2DBackplane(aRect, *pList, bPartDescr, eStackMode);
/*N*/
/*N*/   Rectangle aClipRect( aRect );
/*N*/   aClipRect.Right() += 1;
/*N*/   aClipRect.Top() -= 1;
/*N*/
/*N*/   SdrObject   *pObj;
/*N*/   long    nColCnt = GetColCount();
/*N*/   long    nRowCnt = GetRowCount();
/*N*/   long    nCol, nRow;
/*N*/
/*N*/   BOOL bPercent   = IsPercent();
/*N*/
/*N*/   //ToDo: XAchse-Logarithmus auf FALSE erzwingen (???)
/*N*/
/*N*/   long nBackColCnt = (bPartDescr) ? nColCnt +1: nColCnt ;
/*N*/
/*N*/   if (nColCnt > 1)
/*N*/   {
/*N*/       nBackColCnt--;
/*N*/   }
/*N*/
/*N*/   long   nPartWidth = aRect.GetWidth() / nBackColCnt;
/*N*/   double fPartWidth = ((double) aRect.GetWidth() / (double) nBackColCnt);
/*N*/
/*N*/   SdrObjList** pRowLists   = new SdrObjList*[nRowCnt];
/*N*/   SdrObjList** pStatLists  = new SdrObjList*[nRowCnt];
/*N*/
/*N*/   ChartDataDescription aDescr(nColCnt,nRowCnt,pList,this,bShowDataDescr);
/*N*/
/*N*/   //Berechnung von nLegendHeigth:
/*N*/   Size aLegendSize (((SvxFontWidthItem &) pLegendAttr->Get(EE_CHAR_FONTWIDTH)).GetWidth(),
/*N*/                     ((SvxFontHeightItem &) pLegendAttr->Get(EE_CHAR_FONTHEIGHT)).GetHeight());
/*N*/
/*N*/   //#54884# Was soll das hier? Create2DRowLineChart
/*N*/     OutputDevice * pRefDev = GetRefDevice();
/*N*/   if(pRefDev)
/*N*/       aLegendSize = pRefDev->PixelToLogic (pRefDev->LogicToPixel (aLegendSize));
/*N*/   else
/*N*/       OSL_FAIL("ChartModel: no RefDevice");
/*N*/
/*N*/   long nLegendHeight = aLegendSize.Height () * 9 / 10;
/*N*/
/*N*/   Polygon   aPolygon( nColCnt + 16 );     // +4 -> +16: let some more points be possible. Is set to exact size later
/*N*/
/*N*/   //Ab hier speziell fuer (Sp)Line-Charts:
/*N*/   XPolygon   *pSpline = new XPolygon(nColCnt * nGranularity);
/*N*/
/*N*/   long nStartX=aRect.Left();
/*N*/   if(bPartDescr)
/*N*/       nStartX+=nPartWidth/2;
/*N*/
/*N*/   if(HasStockBars())
/*N*/       DrawStockBars( pList, aRect );
/*N*/   if(HasStockLines())
/*N*/       DrawStockLines( pList, aRect );
/*N*/
/*N*/   long nStart=HasStockBars() ? 1: 0;
/*N*/
/*N*/   long nAllObjects = pList->GetObjCount () - 1;
/*N*/
/*N*/   for (nRow = nStart; nRow < nRowCnt; nRow++)
/*N*/   {
/*N*/       BOOL bArea=IsArea(nRow);
/*N*/       const SfxItemSet &rDataRowAttr = GetDataRowAttr(nRow);
/*N*/       long nAxisUId = ((const SfxInt32Item &)rDataRowAttr.Get(SCHATTR_AXIS)).GetValue();
/*N*/       ChartAxis *pAxis=GetAxisByUID(nAxisUId);
/*N*/
/*N*/       long             nPos          = nStartX;
/*N*/       double           fPos          = nStartX;
/*N*/       USHORT           nPoints       = 0;
/*N*/
/*N*/       SchObjGroup *pRowGroup =(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_ROWGROUP,TRUE, TRUE);
/*N*/       SchObjGroup *pStatGroup=(SchObjGroup*)CreateSimpleGroup(CHOBJID_DIAGRAM_STATISTICS_GROUP,TRUE,TRUE);
/*N*/
/*N*/       pRowGroup->InsertUserData(new SchDataRow((short)nRow));
/*N*/
/*N*/       if(bArea)
/*N*/           pList->NbcInsertObject(pRowGroup, nAllObjects);
/*N*/       else
/*N*/           pList->NbcInsertObject(pRowGroup);
/*N*/
/*N*/       pRowLists[nRow]   = pRowGroup->GetSubList();
/*N*/
/*N*/       pStatGroup->InsertUserData(new SchDataRow((short)nRow));
/*N*/       pList->NbcInsertObject(pStatGroup);
/*N*/       pStatLists [nRow] = pStatGroup->GetSubList();
/*N*/
/*N*/       for (nCol = 0; nCol < nColCnt; nCol++)
/*N*/       {
/*N*/           SfxItemSet aDataPointAttr(rDataRowAttr);//#63904#
/*N*/           MergeDataPointAttr(aDataPointAttr,nCol,nRow);
/*N*/
/*N*/           double fData = GetData(nCol, nRow, bPercent);
/*N*/
/*N*/           BOOL bLogarithm = pAxis->IsLogarithm();
/*N*/           BOOL bValidData=((fData!=DBL_MIN)&&(!bLogarithm||(bLogarithm&&(fData>0.0))));
/*N*/
/*N*/           if(!bValidData && bStacked)
/*N*/           {
/*N*/               fData      = 0.0;
/*N*/               bValidData = TRUE;
/*N*/           }
/*N*/
/*N*/           // *****************************end Data Valid? ***************************
/*N*/
/*N*/           if (bValidData)
/*N*/           {
/*N*/               if(eStackMode != CHSTACK_NONE)
/*N*/                   fData = pAxis->StackColData(fData,nCol,nColCnt);
/*N*/
/*N*/               long nYPos = pAxis->GetPos(fData);
/*N*/
/*N*/               aPolygon[nPoints].X() = nPos;
/*N*/               aPolygon[nPoints].Y() = nYPos;
/*N*/
/*N*/               nPoints++;
/*N*/
/*N*/               if (HasSymbols(nRow))
/*N*/               {
/*N*/
/*N*/                   Point& rInsert = aPolygon[nPoints - 1];
/*N*/
/*N*/                   if( aClipRect.IsInside( rInsert ) )
/*N*/                   {
/*N*/                       SdrObject *pNewObj = CreateSymbol( rInsert, nRow, nCol,
/*N*/                                                          (SfxItemSet &) aDataPointAttr, nLegendHeight );
/*N*/                       if(pNewObj)
/*N*/                       {
/*N*/                           pNewObj->InsertUserData(new SchObjectId(CHOBJID_DIAGRAM_DATA));
/*N*/                           pRowLists[nRow]->NbcInsertObject(pNewObj);
/*N*/                       }
/*N*/                   }
/*N*/               }
/*N*/
/*N*/               if(aDescr.Enabled())
/*N*/               {
/*N*/                   Point aPos(aPolygon[nPoints-1]);
/*N*/                   if(aPos.X() == aRect.Left())
/*N*/                   {
/*N*/                       aPos.X()+=50;
/*N*/                   }
/*N*/               }
/*N*/               // ************************* end description *******************************
/*N*/           }
/*N*/           else if( bArea )        // invalid data, area
/*N*/           {
/*?*/               if(eStackMode != CHSTACK_NONE)
/*?*/                   fData = pAxis->StackColData(fData,nCol,nColCnt);
/*?*/               long nYPos = pAxis->GetPos(0.0);
/*?*/               //fehlende Werte werden hier als 0 interpretiert - weglassen des BlockInhalts w?e Interpolation!
/*?*/               aPolygon[nPoints].X() = nPos;
/*?*/               aPolygon[nPoints].Y() = nYPos;
/*?*/               nPoints++;
/*N*/           }
/*N*/           else                // invalid data, no area
/*N*/           {
/*?*/               if( nPoints )
/*?*/               {
/*?*/                   if( nPoints > 1 )
/*?*/                   {
/*?*/                       if( IsSplineChart() )
/*?*/                       {
/*?*/                           Polygon aNewPoly( nPoints );
/*?*/                           for( USHORT i = 0; i < nPoints; i++ )
/*?*/                               aNewPoly[ i ] = aPolygon[ i ];
/*?*/
/*?*/                           XPolygon aXPoly( aNewPoly );
/*?*/                           if ((eChartStyle == CHSTYLE_2D_CUBIC_SPLINE) ||
/*?*/                               (eChartStyle == CHSTYLE_2D_CUBIC_SPLINE_SYMBOL))
/*?*/                           {
/*?*/                               CubicSpline( aXPoly, nPoints - 1, nGranularity, *pSpline );
/*?*/                           }
/*?*/                           else
/*?*/                           {
/*?*/                               approxMesh( nGranularity, *pSpline, aXPoly, nPoints - 1, nSplineDepth );
/*?*/                           }
/*?*/
/*?*/                           XPolygon aSplinePoly( *pSpline );
/*?*/                           aSplinePoly.SetSize( (nPoints - 1) * nGranularity );
/*?*/
/*?*/                           // #67488# crop polygon
/*?*/                           XPolyPolygon aResult;
/*?*/                           SchCalculationHelper::IntersectPolygonWithRectangle( aSplinePoly, aClipRect, aResult );
/*?*/                           pObj = new SdrPathObj( OBJ_PLIN, aResult );
/*?*/                       }
/*?*/                       else
/*?*/                       {
/*?*/                           Polygon aNewPoly( nPoints );
/*?*/                           for( USHORT i = 0; i < nPoints; i++ )
/*?*/                               aNewPoly[ i ] = aPolygon[ i ];
/*?*/
/*?*/                           // #67488# crop polygon
/*?*/                           XPolyPolygon aResult;
/*?*/                           XPolygon aXPoly( aNewPoly );
/*?*/
/*?*/                           SchCalculationHelper::IntersectPolygonWithRectangle( aXPoly, aClipRect, aResult );
/*?*/                           pObj = new SdrPathObj( OBJ_PLIN, aResult );
/*?*/                       }
/*?*/
/*?*/                       pObj->InsertUserData( new SchObjectId( CHOBJID_DIAGRAM_ROWSLINE ));
/*?*/                       pObj->InsertUserData( new SchDataRow( (short)nRow ));
/*?*/                       pRowLists[ nRow ]->NbcInsertObject( pObj, 0 ); //#54870# put line to background, so symbol is in front
/*?*/
/*?*/                       pObj->SetItemSet( rDataRowAttr);
/*?*/
/*?*/                   }
/*?*/               }
/*?*/               nPoints = 0;
/*N*/           }
/*N*/
/*N*/           fPos += fPartWidth;
/*N*/           nPos = long(fPos);
/*N*/       } //for nCol
/*N*/
/*N*/       if( nPoints )
/*N*/       {
/*N*/           pObj = NULL;
/*N*/
/*N*/           if( IsSplineChart() )
/*N*/           {
/*N*/               if( nPoints > 1 )
/*N*/               {
/*N*/                   Polygon aNewPoly( nPoints );
/*N*/                   for( USHORT i = 0; i < nPoints; i++ )
/*N*/                       aNewPoly[ i ] = aPolygon[ i ];
/*N*/
/*N*/                   XPolygon aXPoly( aNewPoly );
/*N*/                   if ((eChartStyle == CHSTYLE_2D_CUBIC_SPLINE) ||
/*N*/                       (eChartStyle == CHSTYLE_2D_CUBIC_SPLINE_SYMBOL))
/*N*/                   {
/*N*/                       CubicSpline( aXPoly, nPoints - 1,nGranularity, *pSpline );
/*N*/                   }
/*N*/                   else
/*N*/                   {
/*N*/                       approxMesh( nGranularity, *pSpline, aXPoly, nPoints - 1, nSplineDepth );
/*N*/                   }
/*N*/
/*N*/                   XPolygon aSplinePoly( *pSpline );
/*N*/                   aSplinePoly.SetSize( (nPoints - 1) * nGranularity );
/*N*/
/*N*/                   // #67488# crop polygon
/*N*/                   XPolyPolygon aResult;
/*N*/                   SchCalculationHelper::IntersectPolygonWithRectangle( aSplinePoly, aClipRect, aResult );
/*N*/                   pObj = new SdrPathObj( OBJ_PLIN, aResult );
/*N*/               }
/*N*/           }
/*N*/           else
/*N*/           {
/*N*/               if( bArea )
/*N*/               {
/*N*/                   Polygon aNewPoly( nPoints + 3 );
/*N*/                   for( USHORT i = 0; i < nPoints + 3; i++ )
/*N*/                       aNewPoly[ i ] = aPolygon[ i ];
/*N*/                   XPolygon aBase( 2 );
/*N*/
/*N*/                   pAxis->GridLine( aBase, pAxis->GetPosOrigin() );
/*N*/                   aNewPoly[ nPoints ]     = aBase[ 1 ];
/*N*/                   aNewPoly[ nPoints + 1 ] = aBase[ 0 ];
/*N*/                   aNewPoly[ nPoints + 2 ] = aNewPoly[ 0 ];
/*N*/
/*N*/                   // #67488# crop polygon
/*N*/                   aNewPoly.Clip( aClipRect );
/*N*/                   XPolygon aXPoly( aNewPoly );
/*N*/
/*N*/                   pObj = new SdrPathObj( OBJ_POLY, aXPoly );
/*N*/                   pObj->SetModel( this );
/*N*/                   SetObjectAttr( pObj,CHOBJID_DIAGRAM_ROWS, TRUE, TRUE, (SfxItemSet *)&rDataRowAttr );
/*N*/               }
/*N*/               else if( nPoints > 1 )          // line
/*N*/               {
/*N*/                   // #67488# crop polygon
/*N*/                   Polygon aNewPoly( nPoints );
/*N*/                   for( USHORT i = 0; i < nPoints; i++ )
/*N*/                       aNewPoly[ i ] = aPolygon[ i ];
/*N*/
/*N*/                   XPolyPolygon aResult;
/*N*/                   XPolygon aXPoly( aNewPoly );
/*N*/
/*N*/                   SchCalculationHelper::IntersectPolygonWithRectangle( aXPoly, aClipRect, aResult );
/*N*/                   pObj = new SdrPathObj( OBJ_PLIN, aResult );
/*N*/               }
/*N*/           }
/*N*/
/*N*/           if( pObj )
/*N*/           {
/*N*/               pObj->InsertUserData( new SchObjectId( CHOBJID_DIAGRAM_ROWSLINE ));
/*N*/
/*N*/               pObj->SetItemSet( rDataRowAttr);
/*N*/
/*N*/               pObj->InsertUserData( new SchDataRow( (short)nRow ));
/*N*/
/*N*/               if( ! bArea || (bArea && IsStacked()) )
/*N*/                   pRowLists[ nRow ]->NbcInsertObject( pObj, 0 );
/*N*/               else
/*N*/                   pRowLists[ nRow ]->NbcInsertObject( pObj );
/*N*/           }
/*N*/       } // if( nPoints )
/*N*/   } //for nRow
/*N*/
/*N*/   delete pSpline;
/*N*/
/*N*/   //Ab hier wieder wie in Create2DRow(Area)Chart:
/*N*/
/*N*/   aDescr.Build(TRUE);
/*N*/   delete[] pRowLists;
/*N*/   delete[] pStatLists;
/*N*/   return pGroup;
/*N*/ }

/*N*/ bool ChartModel::UsesSourceFormat( long nAxisUID, SfxItemSet** pItemSetPointer /* = NULL */ )
/*N*/ {
/*N*/     const SfxPoolItem*    pPoolItem     = NULL;
/*N*/           ChartAxis*      pAxis         = NULL;
/*N*/           SfxItemSet*     pItemSet      = NULL;
/*N*/
/*N*/     if( ( pAxis = GetAxisByUID( nAxisUID )) &&
/*N*/         ( pItemSet = pAxis->GetItemSet()))
/*N*/     {
/*N*/         if( pItemSetPointer )
/*N*/             *pItemSetPointer = pItemSet;
/*N*/
/*N*/         // return true if item is not set (default) or it is set to TRUE
/*N*/         return ( ( SFX_ITEM_SET !=
/*N*/                    pItemSet->GetItemState( SID_ATTR_NUMBERFORMAT_SOURCE, FALSE, &pPoolItem )) ||
/*N*/                  ( SAL_STATIC_CAST( const SfxBoolItem*, pPoolItem )->GetValue() == TRUE ));
/*N*/     }
/*N*/
/*N*/     return false;
/*N*/ }

// checks if the numberformat was set in MemChart (by Calc/Writer)
// if this is the case the axis attributes are overwritten and TRUE is returned
/*N*/ BOOL ChartModel::CheckForNewAxisNumFormat()
/*N*/ {
/*N*/     //    Don't set the numberformater for a percent chart.
/*N*/     //  or when formats are not set from the outside
/*N*/     if ( IsPercentChart() ||
/*N*/          UsesOwnNumberFormatter() )
/*N*/       return FALSE;
/*N*/
/*N*/     // if source format is used, update
/*N*/     const SfxPoolItem*    pPoolItem  = NULL;
/*N*/           SfxItemSet*     pItemSet   =  NULL;
/*N*/           SfxItemSet*     pItemSetA  =  NULL;
/*N*/           bool            bRet       =  false;
/*N*/           long            nRow       =  0;
/*N*/           INT32           nFmt       = -1;
/*N*/           USHORT          nSchattr   =  IsPercentChart()
/*N*/               ? SCHATTR_AXIS_NUMFMTPERCENT
/*N*/               : SCHATTR_AXIS_NUMFMT;
/*N*/
/*N*/     // x axis
/*N*/     if( IsXYChart())
/*N*/     {
/*N*/         bool bXUsesSrcFmt = UsesSourceFormat( CHAXIS_AXIS_X, &pItemSet );
/*N*/         bool bAUsesSrcFmt = UsesSourceFormat( CHAXIS_AXIS_A, &pItemSetA );
/*N*/         if( bXUsesSrcFmt || bAUsesSrcFmt )
/*N*/         {
/*N*/             // use source format for x-axis
/*N*/             nFmt = IsDataSwitched()
/*N*/                 ? pChartData->GetTransNumFormatIdCol( nRow )
/*N*/                 : pChartData->GetTransNumFormatIdRow( nRow );
/*N*/         }
/*N*/
/*N*/         if( bXUsesSrcFmt && pItemSet && nFmt != -1 )
/*N*/         {
/*N*/             pItemSet->Put( SfxUInt32Item( nSchattr, nFmt ));
/*N*/             bRet = true;
/*N*/             nXLastNumFmt = nFmt;    // for binary file format only
/*N*/         }
/*N*/         if( bAUsesSrcFmt && pItemSetA && nFmt != -1 )
/*N*/         {
/*N*/             pItemSetA->Put( SfxUInt32Item( nSchattr, nFmt ));
/*N*/             bRet = true;
/*N*/             nXLastNumFmt = nFmt;
/*N*/         }
/*N*/         nRow++;
/*N*/     }
/*N*/
/*N*/   if( HasSecondYAxis() )  // check both y axes
/*N*/     {
/*N*/         // seek first series using second axis
/*N*/         bool    bYAxisFound     = false;
/*N*/         bool    bBAxisFound     = false;
/*N*/         long    nMaxRow         = GetRowCount();
/*N*/
/*N*/         for( ; nRow < nMaxRow; nRow++ )
/*N*/         {
/*N*/             if( ! bBAxisFound &&
/*N*/                 SFX_ITEM_SET ==
/*N*/                 GetDataRowAttr( nRow ).GetItemState( SCHATTR_AXIS, FALSE, &pPoolItem ) &&
/*N*/                 SAL_STATIC_CAST( const SfxInt32Item*, pPoolItem )->GetValue() == CHART_AXIS_SECONDARY_Y )
/*N*/             {
/*N*/                 if( UsesSourceFormat( CHAXIS_AXIS_B, &pItemSet ) &&
/*N*/                     pItemSet )
/*N*/                 {
/*N*/                     // use source format for secondary y-axis
/*N*/                     nFmt = IsDataSwitched()
/*N*/                         ? pChartData->GetTransNumFormatIdCol( nRow )
/*N*/                         : pChartData->GetTransNumFormatIdRow( nRow );
/*N*/
/*N*/                     if( nFmt != -1 )
/*N*/                     {
/*N*/                         pItemSet->Put( SfxUInt32Item( nSchattr, nFmt ));
/*N*/                         bRet = true;
/*N*/                         nBLastNumFmt = nFmt;    // for binary file format only
/*N*/                     }
/*N*/                 }
/*N*/                 bBAxisFound = true;
/*N*/             }
/*N*/             else
/*N*/             {
/*N*/                 if( ! bYAxisFound &&
/*N*/                     UsesSourceFormat( CHAXIS_AXIS_Y, &pItemSet ) &&
/*N*/                     pItemSet )
/*N*/                 {
/*N*/                     // use source format for primary  y-axis
/*N*/                     nFmt = IsDataSwitched()
/*N*/                         ? pChartData->GetTransNumFormatIdCol( nRow )
/*N*/                         : pChartData->GetTransNumFormatIdRow( nRow );
/*N*/
/*N*/                     if( nFmt != -1 )
/*N*/                     {
/*N*/                         pItemSet->Put( SfxUInt32Item( nSchattr, nFmt ));
/*N*/                         bRet = true;
/*N*/                         nYLastNumFmt = nFmt;    // for binary file format only
/*N*/                     }
/*N*/                 }
/*N*/                 bYAxisFound = true;
/*N*/             }
/*N*/
/*N*/             if( bYAxisFound && bBAxisFound )
/*N*/                 break;
/*N*/         }
/*N*/     }
/*N*/     else
/*N*/     {
/*N*/         // get first setting
/*N*/         if( nRow < GetRowCount() &&
/*N*/             UsesSourceFormat( CHAXIS_AXIS_Y, &pItemSet ) &&
/*N*/             pItemSet )
/*N*/         {
/*N*/             nFmt = IsDataSwitched()
/*N*/                 ? pChartData->GetTransNumFormatIdCol( nRow )
/*N*/                 : pChartData->GetTransNumFormatIdRow( nRow );
/*N*/
/*N*/             if( nFmt != -1 )
/*N*/             {
/*N*/                 pItemSet->Put( SfxUInt32Item( nSchattr, nFmt ));
/*N*/                 bRet = true;
/*N*/                 nYLastNumFmt = nFmt;    // for binary file format only
/*N*/             }
/*N*/         }
/*N*/     }
/*N*/
/*N*/     return bRet;
/*N*/ }

/*N*/ BOOL ChartModel::HasDefaultGrayArea( SvxChartStyle* pStyle ) const
/*N*/ {
/*N*/   SvxChartStyle eStyle = pStyle? *pStyle: eChartStyle;
/*N*/
/*N*/   switch( eStyle )
/*N*/   {
/*N*/       case CHSTYLE_2D_NET:
/*N*/       case CHSTYLE_2D_NET_SYMBOLS:
/*N*/       case CHSTYLE_2D_NET_STACK:
/*N*/       case CHSTYLE_2D_NET_SYMBOLS_STACK:
/*N*/       case CHSTYLE_2D_NET_PERCENT:
/*N*/       case CHSTYLE_2D_NET_SYMBOLS_PERCENT:
/*N*/           return TRUE;
/*N*/
/*N*/       default:
/*N*/           return FALSE;
/*N*/   }
/*N*/
/*N*/   return FALSE;
/*N*/ }

/*N*/ BOOL ChartModel::HasDefaultGrayWall( SvxChartStyle* pStyle ) const
/*N*/ {
/*N*/   SvxChartStyle eStyle = pStyle? *pStyle: eChartStyle;
/*N*/
/*N*/   switch( eStyle )
/*N*/   {
/*N*/       case CHSTYLE_2D_LINE:
/*N*/       case CHSTYLE_2D_STACKEDLINE:
/*N*/       case CHSTYLE_2D_PERCENTLINE:
/*N*/       case CHSTYLE_2D_XY:
/*N*/       case CHSTYLE_2D_LINESYMBOLS:
/*N*/       case CHSTYLE_2D_STACKEDLINESYM:
/*N*/       case CHSTYLE_2D_PERCENTLINESYM:
/*N*/       case CHSTYLE_2D_XYSYMBOLS:
/*N*/       case CHSTYLE_2D_CUBIC_SPLINE:
/*N*/       case CHSTYLE_2D_CUBIC_SPLINE_SYMBOL:
/*N*/       case CHSTYLE_2D_B_SPLINE:
/*N*/       case CHSTYLE_2D_B_SPLINE_SYMBOL:
/*N*/       case CHSTYLE_2D_CUBIC_SPLINE_XY:
/*N*/       case CHSTYLE_2D_CUBIC_SPLINE_SYMBOL_XY:
/*N*/       case CHSTYLE_2D_B_SPLINE_XY:
/*N*/       case CHSTYLE_2D_B_SPLINE_SYMBOL_XY:
/*N*/       case CHSTYLE_2D_XY_LINE:
/*N*/           return TRUE;
/*N*/
/*N*/       default:
/*N*/           return FALSE;
/*N*/   }
/*N*/
/*N*/   return FALSE;
/*N*/ }

/*N*/ using namespace ::com::sun::star;

/*N*/ void ChartModel::SetNumberFormatter( SvNumberFormatter* pFormatter )
/*N*/ {
/*N*/   pNumFormatter = pFormatter;
/*N*/
/*N*/   pChartXAxis->SetNumberFormatter( pNumFormatter );
/*N*/   pChartYAxis->SetNumberFormatter( pNumFormatter );
/*N*/   pChartZAxis->SetNumberFormatter( pNumFormatter );
/*N*/   pChartAAxis->SetNumberFormatter( pNumFormatter );
/*N*/   pChartBAxis->SetNumberFormatter( pNumFormatter );
/*N*/
/*N*/     // update UNO Numberformatter Wrapper
/*N*/     SfxObjectShell* pMyDocShell = GetObjectShell();
/*N*/     if( pMyDocShell != NULL )
/*N*/     {
/*N*/         ChXChartDocument* pUnoDoc = ChXChartDocument::getImplementation( pMyDocShell->GetModel());
/*N*/         DBG_ASSERT( pUnoDoc, "Couldn't get XModel implementation" );
/*N*/         if( pUnoDoc != NULL )
/*N*/         {
/*N*/             // invalidate old number formatter
/*N*/             pUnoDoc->ClearNumberFormatter();
/*N*/         }
/*N*/   }
/*N*/ }

/*N*/ void ChartModel::SetNumLinesColChart(const long nSet, BOOL bForceStyleChange)
/*N*/ {
/*N*/     const long nOldNumLines = nNumLinesInColChart;
/*N*/     const long nLastSeries = GetRowCount() - 1;
/*N*/
/*N*/     switch( eChartStyle  )
/*N*/   {
/*N*/       case CHSTYLE_2D_COLUMN:                 // only types supporting mixing with lines
/*N*/           case CHSTYLE_2D_STACKEDCOLUMN:
/*N*/       case CHSTYLE_2D_PERCENTCOLUMN:
/*N*/       case CHSTYLE_2D_LINE_COLUMN:
/*N*/       case CHSTYLE_2D_LINE_STACKEDCOLUMN:
/*N*/           if( bForceStyleChange )
/*N*/           {
/*N*/               if( nSet <= 0 )
/*N*/               {
/*N*/                   nNumLinesInColChart = 0;
/*N*/                   if( eChartStyle == CHSTYLE_2D_LINE_COLUMN )
/*?*/                       eChartStyle = CHSTYLE_2D_COLUMN;
/*N*/                   else if( eChartStyle == CHSTYLE_2D_LINE_STACKEDCOLUMN )
/*?*/                       eChartStyle = CHSTYLE_2D_STACKEDCOLUMN;
/*N*/               }
/*N*/               else
/*N*/               {
/*N*/                   nNumLinesInColChart = nSet;
/*N*/
/*N*/                   if( eChartStyle == CHSTYLE_2D_COLUMN )
/*N*/                       eChartStyle = CHSTYLE_2D_LINE_COLUMN;
/*N*/                   else if( eChartStyle == CHSTYLE_2D_STACKEDCOLUMN )
/*?*/                       eChartStyle = CHSTYLE_2D_LINE_STACKEDCOLUMN;
/*N*/               }
/*N*/           }
/*N*/           else
/*N*/           {
/*N*/               nNumLinesInColChart = nSet > 0 ? nSet : 0;
/*N*/           }
/*N*/             break;
/*N*/
/*N*/         default:
/*N*/             nNumLinesInColChart = nSet > 0 ? nSet : 0;
/*N*/             break;
/*N*/   }
/*N*/
/*N*/     // #101164# map fill-/line colors
/*N*/     if( nNumLinesInColChart > nOldNumLines )
/*N*/     {
/*N*/         for( int i = nOldNumLines ;
/*N*/              i < nNumLinesInColChart && i < nLastSeries ;
/*N*/              ++i )
/*N*/         {
/*N*/             SfxItemSet * pSet = aDataRowAttrList[ nLastSeries - i ];
/*N*/             OSL_ASSERT( pSet );
/*N*/             pSet->Put( XLineColorItem(
/*N*/                            String(),
/*N*/                            static_cast< const XFillColorItem & >(
/*N*/                                pSet->Get( XATTR_FILLCOLOR )).GetValue() ));
/*N*/         }
/*N*/     }
/*N*/     else
/*N*/     {
/*N*/         for( int i = nNumLinesInColChart ;
/*N*/              i < nOldNumLines && i < nLastSeries ;
/*N*/              ++i )
/*N*/         {
/*?*/             SfxItemSet * pSet = aDataRowAttrList[ nLastSeries - i ];
/*?*/             OSL_ASSERT( pSet );
/*?*/             pSet->Put( XFillColorItem(
/*?*/                            String(),
/*?*/                            static_cast< const XLineColorItem & >(
/*?*/                                pSet->Get( XATTR_LINECOLOR )).GetValue() ));
/*?*/             pSet->Put( XLineColorItem( String(), RGBColor( COL_BLACK ) ));
/*N*/         }
/*N*/     }
/*N*/ }

/*N*/ BOOL ChartModel::SetObjectShell( SfxObjectShell* pDocSh )
/*N*/ {
/*N*/   if( ! pDocShell )
/*N*/   {
/*N*/       pDocShell = pDocSh;
/*N*/       return TRUE;
/*N*/   }
/*N*/   return FALSE;
/*N*/ }

/*N*/ using namespace ::com::sun::star;

/*N*/ void ChartModel::SetChartAddIn( uno::Reference< util::XRefreshable >& xChartAddIn )
/*N*/ {
/*N*/   if( xChartAddIn.is())
/*N*/   {
/*N*/       // acquire add-in
/*?*/       mxChartAddIn = xChartAddIn;
/*?*/       ChangeChart( CHSTYLE_ADDIN );
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       // release add-in
/*N*/       mxChartAddIn = NULL;
/*N*/       // if base type was not set, use default
/*N*/       if( eChartStyle == CHSTYLE_ADDIN )
/*?*/           ChangeChart( CHSTYLE_2D_BAR );
/*N*/   }
/*N*/ }


/*N*/ void ChartModel::HandsOff()
/*N*/ {
/*N*/     mxPictureStorage = SotStorageRef();
/*N*/   mpDocStor = NULL;
/*N*/ }


/*N*/ uno::Sequence< uno::Sequence< sal_Int32 > > ChartModel::GetSetDataPointList()
/*N*/ {
/*N*/     const ItemSetList & rAttrList = IsDataSwitched()
/*N*/         ? aSwitchDataPointAttrList
/*N*/         : aDataPointAttrList;
/*N*/     const long nSize = rAttrList.size();
/*N*/     long nRow, nCol;
/*N*/   long nColCnt = GetColCount();
/*N*/     long nRowCnt = GetRowCount();
/*N*/
/*N*/     DBG_ASSERT( nSize == ( nRowCnt * nColCnt ), "Data-Point list has invalid size!" );
/*N*/     (void)nSize;
/*N*/
/*N*/     // the 'outer' sequence contains one sequence for each series
/*N*/     uno::Sequence< uno::Sequence< sal_Int32 > > aResult( nRowCnt );
/*N*/
/*N*/     // here we need again a special treatment for pie charts as a single pie
/*N*/     // uses merged data point and data row attributes the data points are also
/*N*/     // set if data row attributes are set, which is always the case
/*N*/     if( IsPieChart())
/*N*/     {
/*N*/         aResult[ 0 ].realloc( nColCnt );
/*N*/         sal_Int32 * pArray = aResult[ 0 ].getArray();
/*N*/
/*N*/         for( nCol = 0; nCol < nColCnt; ++nCol )
/*N*/             pArray[ nCol ] = nCol;
/*N*/     }
/*N*/     else
/*N*/     {
/*N*/         // use a vector for quick dynamic resizing
/*N*/         ::std::list< sal_Int32 > aList;
/*N*/
/*N*/         for( nRow = 0; nRow < nRowCnt; ++nRow )
/*N*/         {
/*N*/             for( nCol = 0; nCol < nColCnt; ++nCol )
/*N*/             {
/*N*/                 if( rAttrList[ nCol * nRowCnt + nRow ] != NULL )
/*N*/                     aList.push_back( nCol );
/*N*/             }
/*N*/
/*N*/             if( aList.size() > 0 )
/*N*/             {
/*N*/                 // copy list to 'inner' sequence
/*N*/                 aResult[ nRow ].realloc( aList.size());
/*N*/                 sal_Int32 * pArray = aResult[ nRow ].getArray();
/*N*/                 sal_Int32 i = 0;
/*N*/                 ::std::list< sal_Int32 >::iterator aIter;
/*N*/                 for( aIter = aList.begin(); aIter != aList.end(); ++aIter )
/*N*/                 {
/*N*/                     pArray[ i++ ] = (*aIter);
/*N*/                 }
/*N*/                 aList.clear();
/*N*/             }
/*N*/         }
/*N*/     }
/*N*/
/*N*/     return aResult;
/*N*/ }

/*N*/ void ChartModel::PageColorChanged( const SfxItemSet& rItems )
/*N*/ {
/*N*/     Color aColor;
/*N*/
/*N*/     // GetDraftFillColor is defined in bf_svx/svdetc.hxx
/*N*/     if( GetDraftFillColor( rItems, aColor ))
/*N*/     {
/*N*/         SdrOutliner *  pOut = GetOutliner();
/*N*/         if( pOut )
/*N*/             pOut->SetBackgroundColor( aColor );
/*N*/         GetDrawOutliner().SetBackgroundColor( aColor );
/*N*/     }
/*N*/ }

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
