/***************************************************************************** * * Copyright (c) 1999, KL GROUP INC. All Rights Reserved. * http://www.klgroup.com * * This file is provided for demonstration and educational uses only. * Permission to use, copy, modify and distribute this file for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of KL Group not be used in advertising * or publicity pertaining to this material without the specific, * prior written permission of an authorized representative of * KL Group. * * KL GROUP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. KL GROUP SHALL NOT BE LIABLE FOR ANY * DAMAGES SUFFERED BY USERS AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ // ParetoView.cpp : implementation of the CParetoView class // #include //For OleCurrencyType #include #include #include #include "stdafx.h" #include "Pareto.h" #include "ParetoDoc.h" #include "ParetoView.h" #include "Axis.h" #include "AxisCollection.h" #include "Bar.h" #include "Border.h" #include "ChartArea.h" #include "Chart2DData.h" #include "ChartGroup.h" #include "ChartGroupCollection.h" #include "ChartLabel.h" #include "ChartLabelCollection.h" #include "ChartStyle.h" #include "ChartStyleCollection.h" #include "DataIndex.h" #include "DerivedDouble.h" #include "FillStyle.h" #include "Font.h" #include "GridLines.h" #include "Interior.h" #include "Label.h" #include "LabelCollection.h" #include "Legend.h" #include "PlotArea.h" #include "Title.h" #include "2dconst.h" #include "oc_color.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CParetoView IMPLEMENT_DYNCREATE(CParetoView, CView) BEGIN_MESSAGE_MAP(CParetoView, CView) //{{AFX_MSG_MAP(CParetoView) ON_WM_CREATE() ON_COMMAND(IDM_REGEN, OnRegenerate) ON_WM_SIZE() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CParetoView construction/destruction CParetoView::CParetoView() { // TODO: add construction code here } CParetoView::~CParetoView() { } BOOL CParetoView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CParetoView drawing void CParetoView::OnDraw(CDC* pDC) { CParetoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } ///////////////////////////////////////////////////////////////////////////// // CParetoView printing BOOL CParetoView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CParetoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CParetoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CParetoView diagnostics #ifdef _DEBUG void CParetoView::AssertValid() const { CView::AssertValid(); } void CParetoView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CParetoDoc* CParetoView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CParetoDoc))); return (CParetoDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CParetoView message handlers ///////////////////////////////////////////////////////////////////////////// // This is where it all begins ///////////////////////////////////////////////////////////////////////////// int CParetoView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; if (!m_chart.Create(NULL, WS_VISIBLE, CRect(0, 0, 800, 500), this, 1)) { return -1; } //Setup how the Chart looks SetupTheChart(); //Fill the Chart with Data GenerateTheChartData(); return 0; } ///////////////////////////////////////////////////////////////////////////// // Setup The Chart ///////////////////////////////////////////////////////////////////////////// void CParetoView::SetupTheChart() { TotalPoints = 10; CAxis AxisX(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("x"))); CAxis AxisY(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y"))); CAxis AxisY2(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y2"))); CChart2DData Data1(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetData()); CChart2DData Data2(m_chart.GetChartGroups().GetItem(COleVariant(short(2))).GetData()); COleCurrency hFontSize; // don't allow the user to change any of the following m_chart.SetAllowUserChanges(FALSE); //Batch all the updates to the Chart m_chart.SetIsBatched(true); //Set the Chart Types m_chart.GetChartGroups().GetItem(COleVariant(short(1))).SetChartType(oc2dTypeBar); m_chart.GetChartGroups().GetItem(COleVariant(short(2))).SetChartType(oc2dTypePlot); m_chart.GetChartGroups().GetItem(COleVariant(short(1))).SetDrawingOrder(2); //Set the colors and border styles m_chart.GetInterior().SetBackgroundColor(ocColorGray76); m_chart.GetChartArea().GetInterior().SetBackgroundColor(ocColorGray81); //Setup the Borders m_chart.GetBorder().SetType(oc2dBorder3DIn); m_chart.GetBorder().SetWidth(4); m_chart.GetChartArea().GetBorder().SetType(oc2dBorder3DIn); m_chart.GetChartArea().GetBorder().SetWidth(4); //Setup the Legend m_chart.GetLegend().GetFont().SetName("Arial"); //Set the Legend Font point size hFontSize.SetCurrency(10, 0); m_chart.GetLegend().GetFont().SetSize(hFontSize); m_chart.GetLegend().GetBorder().SetType(oc2dBorderFrameIn); m_chart.GetLegend().GetBorder().SetWidth(4); // Set the legend title m_chart.GetLegend().GetText().SetText("Data Set"); //Setup the Header m_chart.GetHeader().GetText().SetText("Pareto Chart"); //Set the Header Font point size hFontSize.SetCurrency(14, 0); m_chart.GetHeader().GetFont().SetSize(hFontSize); m_chart.GetHeader().GetFont().SetUnderline(TRUE); m_chart.GetHeader().GetBorder().SetType(oc2dBorderShadow); m_chart.GetHeader().GetBorder().SetWidth(3); //Setup the Footer m_chart.GetFooter().GetText().SetText("Use to Generate Different Data"); //Set the Header Font point size hFontSize.SetCurrency(12, 0); m_chart.GetFooter().GetFont().SetSize(hFontSize); m_chart.GetFooter().GetBorder().SetType(oc2dBorderShadow); m_chart.GetFooter().GetBorder().SetWidth(3); //Batch the Data Objects for efficiency Data1.SetIsBatched(TRUE); Data2.SetIsBatched(TRUE); //Set the Data Layout Data1.SetLayout(oc2dDataArray); Data2.SetLayout(oc2dDataArray); //Setup Data Group 1 Data1.SetNumSeries(TotalPoints); Data1.SetNumPoints(1, 0); Data1.SetNumPoints(1, TotalPoints); //Setup Data Group 2 Data2.SetNumSeries(1); Data2.SetNumPoints(1, TotalPoints); //Go back to normal updates on the Data Objects Data1.SetIsBatched(FALSE); Data2.SetIsBatched(FALSE); //Set some misc. properties m_chart.GetChartArea().GetBar().SetClusterWidth(75); m_chart.GetChartArea().GetBar().SetClusterOverlap(100); m_chart.GetChartArea().GetPlotArea().SetIsBoxed(true); AxisX.GetMajorGrid().GetSpacing().SetValue(1); // Don't want X annotations ... we have no ValueLabels so this effectively hides X annotations. AxisX.SetAnnotationMethod(oc2dAnnotateValueLabels); //Setup the Colors for the Data CChartStyleCollection cStyles(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetStyles()); cStyles.GetItem(COleVariant(short(1))).GetFill().GetInterior().SetForegroundColor(ocColorRed); cStyles.GetItem(COleVariant(short(2))).GetFill().GetInterior().SetForegroundColor(ocColorGreen); cStyles.GetItem(COleVariant(short(3))).GetFill().GetInterior().SetForegroundColor(ocColorBlue); cStyles.GetItem(COleVariant(short(4))).GetFill().GetInterior().SetForegroundColor(ocColorBlanchedAlmond); cStyles.GetItem(COleVariant(short(5))).GetFill().GetInterior().SetForegroundColor(ocColorPurple); cStyles.GetItem(COleVariant(short(6))).GetFill().GetInterior().SetForegroundColor(ocColorYellow); cStyles.GetItem(COleVariant(short(7))).GetFill().GetInterior().SetForegroundColor(ocColorMagenta); cStyles.GetItem(COleVariant(short(8))).GetFill().GetInterior().SetForegroundColor(ocColorNavyBlue); cStyles.GetItem(COleVariant(short(9))).GetFill().GetInterior().SetForegroundColor(ocColorWhite); cStyles.GetItem(COleVariant(short(10))).GetFill().GetInterior().SetForegroundColor(ocColorSeaGreen); //Do some last minute Axis configuration AxisY.GetMin().SetValue(0); AxisY2.GetMin().SetValue(0); //If there are any ChartLabels already defined, remove them if (m_chart.GetChartLabels().GetCount() > 0) { m_chart.GetChartLabels().RemoveAll(); } //Change the Axis font temporarily so that all the ChartLabels that are about // to be added have the font we want AxisX.GetFont().SetName("Arial"); hFontSize.SetCurrency(8, 0); AxisX.GetFont().SetSize(hFontSize); AxisX.GetFont().SetBold(true); for (int i = 1; i <= TotalPoints; i++) { CChartLabel cLbl(m_chart.GetChartLabels().Add()); cLbl.SetIsBatched(true); cLbl.GetText().SetText(""); cLbl.GetBorder().SetType(oc2dBorderNone); cLbl.SetAttachMethod(oc2dAttachDataIndex); cLbl.GetAttachDataIndex().SetSeries(1); cLbl.GetAttachDataIndex().SetPoint(i); cLbl.GetAttachDataIndex().SetChartGroup(2); cLbl.SetIsBatched(false); } //Change the Axis font temporarily so that all the ChartLabels that are about // to be added have the font we want AxisX.GetFont().SetName("Arial"); hFontSize.SetCurrency(12, 0); AxisX.GetFont().SetSize(hFontSize); AxisX.GetFont().SetBold(false); //Go back to normal Chart updates m_chart.SetIsBatched(false); } ///////////////////////////////////////////////////////////////////////////// // Generate the Chart Data ///////////////////////////////////////////////////////////////////////////// void CParetoView::GenerateTheChartData() { double Percentage; char szBuffer[80]; //Pre-Define some variables for easier reference later CChart2DData Data1(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetData()); CChart2DData Data2(m_chart.GetChartGroups().GetItem(COleVariant(short(2))).GetData()); CAxis AxisY(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y"))); CAxis AxisY2(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y2"))); CLabelCollection sLbl(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetSeriesLabels()); //Initialize the Random Number Generator using the Timer srand( (unsigned)time( NULL ) ); //Batch all the updates to the Chart m_chart.SetIsBatched(true); //Batch all the updates to the Data Objects Data1.SetIsBatched(true); Data2.SetIsBatched(true); //Setup the Colors for the Data CChartStyleCollection cStyles(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetStyles()); cStyles.GetItem(COleVariant(short(1))).GetFill().GetInterior().SetForegroundColor(ocColorRed); cStyles.GetItem(COleVariant(short(2))).GetFill().GetInterior().SetForegroundColor(ocColorGreen); cStyles.GetItem(COleVariant(short(3))).GetFill().GetInterior().SetForegroundColor(ocColorBlue); cStyles.GetItem(COleVariant(short(4))).GetFill().GetInterior().SetForegroundColor(ocColorBlanchedAlmond); cStyles.GetItem(COleVariant(short(5))).GetFill().GetInterior().SetForegroundColor(ocColorPurple); cStyles.GetItem(COleVariant(short(6))).GetFill().GetInterior().SetForegroundColor(ocColorYellow); cStyles.GetItem(COleVariant(short(7))).GetFill().GetInterior().SetForegroundColor(ocColorMagenta); cStyles.GetItem(COleVariant(short(8))).GetFill().GetInterior().SetForegroundColor(ocColorNavyBlue); cStyles.GetItem(COleVariant(short(9))).GetFill().GetInterior().SetForegroundColor(ocColorWhite); cStyles.GetItem(COleVariant(short(10))).GetFill().GetInterior().SetForegroundColor(ocColorSeaGreen); //Add random data and labels to Data Group 1 sLbl.RemoveAll(); for (int i = 1; i <= 10; i++) { Data1.SetY(i, i, ((rand() / 1000) * 25) + 1); itoa(i, szBuffer, 10); sLbl.Add(szBuffer, COleVariant(short(i))); } SortTheData(); TotalValue = 0; //Figure out the TotalValue of the points generated above for (i = 1; i <= TotalPoints; i++) { TotalValue = TotalValue + Data1.GetY(i, i); } //Create the points for Data Group 2 using the Data generated // for Data Group 1 for (i = 1; i <= TotalPoints; i++) { if (i == 1) { Data2.SetY(1, i, Data1.GetY(1, i)); } else { Data2.SetY(1, i, Data1.GetY(i, i) + Data2.GetY(1, i - 1)); } } //Calculate the first percentage Percentage = (Data1.GetY(1, 1) / TotalValue) * 100; //Add the labels to Data Group 2 for (i = 1; i <= TotalPoints; i++) { if (i > 1) { Percentage = Percentage + (Data1.GetY(i, i) / TotalValue) * 100; } sprintf(szBuffer, "%3.0f%%", Percentage); m_chart.GetChartLabels().GetItem(COleVariant(short(i))).GetText().SetText(szBuffer); } //Go back to normal updates on the Data Objects Data1.SetIsBatched(false); Data2.SetIsBatched(false); //Make both the Y and Y2 Axis read the same AxisY.GetMax().SetValue(AxisY2.GetMax().GetValue()); //Batch all the updates to the Chart m_chart.SetIsBatched(false); } ///////////////////////////////////////////////////////////////////////////// // Generate the Chart Data ///////////////////////////////////////////////////////////////////////////// void CParetoView::SortTheData() { double HoldValue; int MaxX; bool Done; CString HoldLabel; unsigned long HoldColor; unsigned long SwapColor; //Pre-Define some variables for easier reference later CChart2DData Data1(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetData()); CChart2DData Data2(m_chart.GetChartGroups().GetItem(COleVariant(short(2))).GetData()); CAxis AxisY(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y"))); CAxis AxisY2(m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y2"))); CLabelCollection sLbl(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetSeriesLabels()); CChartStyleCollection cStyles(m_chart.GetChartGroups().GetItem(COleVariant(short(1))).GetStyles()); Done = false; MaxX = TotalPoints - 1; Data1.SetIsBatched(true); //Sort the Bar Chart so it goes from highest to lowest using an // Optimized Bubble Sort do { Done = true; for (int i = 1; i <= MaxX; i++) { if (Data1.GetY(i, i) < Data1.GetY(i + 1, i + 1)) { HoldValue = Data1.GetY(i, i); Data1.SetY(i, i, Data1.GetY(i + 1, i + 1)); Data1.SetY(i + 1, i + 1, HoldValue); HoldLabel = sLbl.GetItem(COleVariant(short(i))).GetText(); sLbl.GetItem(COleVariant(short(i))).SetText(sLbl.GetItem(COleVariant(short(i + 1))).GetText()); sLbl.GetItem(COleVariant(short(i + 1))).SetText(HoldLabel); HoldColor = cStyles.GetItem(COleVariant(short(i))).GetFill().GetInterior().GetForegroundColor(); SwapColor = cStyles.GetItem(COleVariant(short(i+1))).GetFill().GetInterior().GetForegroundColor(); cStyles.GetItem(COleVariant(short(i))).GetFill().GetInterior().SetForegroundColor(SwapColor); cStyles.GetItem(COleVariant(short(i+1))).GetFill().GetInterior().SetForegroundColor(HoldColor); Done = false; } } MaxX = MaxX - 1; } while (!Done); Data1.SetIsBatched(false); } ///////////////////////////////////////////////////////////////////////////// // Re-Generate the Chart Data at the User's request ///////////////////////////////////////////////////////////////////////////// void CParetoView::OnRegenerate() { GenerateTheChartData(); } ///////////////////////////////////////////////////////////////////////////// // Size the Chart to fit the Window ///////////////////////////////////////////////////////////////////////////// void CParetoView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // size the chart to fit the window if ((cx > 0) && (cy > 0)) { m_chart.MoveWindow(0, 0, cx, cy); } }