
//////////////////////////////////
// START of File: C1_CMODL.HPP
//////////////////////////////////

#ifndef C1_CMODL_HPP
#define C1_CMODL_HPP

//-------------------------------------------------------------------
// COPYRIGHT NOTICE:  This code is protected by Copyright!
//
// Copyright (c) 1994 through 1997 by DPC Technology Corporation.
// All rights reserved by DPC Technology Corporation.
//
// See files "cf_copyr.txt" and "cf_licen.txt" for details of
// copyright and license specifications, and contact information.
//-------------------------------------------------------------------

// Master Header File Listing:
// Usage:   #include    <cf_api/c1_cmodl.hpp>
            // This "Chart-Model" object hold user-data and group-attributes,
            // (in "Data-Groups") for one or more "Chart-Engine" object(s)
            // -- which generate and render the chart's geometrical objects).
            // Note that a Chart-Model exists as part of a "Chart-View" which
            // is usually owned by some sort of "Chart-Control" object
            // in a Model/View/Controller configuration/relationship.


//--------------------------------------------------------------------
// Specify the Chart Framework classes or defs/headers this file needs.
//--------------------------------------------------------------------
#include    <cf_api/cf_defs.h>
            // contains Chart Framework typedef(s)

#include    <cf_api/cf_const.h>
            // defines chart engine default values

class       cf_DyArr;   // We'll use dynamic arrays of (void) ptrs...
#include    <cf_api/c0_dyarr.hpp>   // ...to cf-data-group objects
                                    // ...and cf-chart-engine objects
class       cf_String;
#include    <cf_api/c0_dystr.hpp>

class       bf_Color;
#include    <cf_api/b0_color.hpp>

class       bf_Display;
#include    <cf_api/b0_dspla.hpp>
            // also has enums bf_PenStyle and bf_BrushHatch...

class       bf_2DBitmap;
#include    <cf_api/b0_dsbmp.hpp>

class       cf_DataGroup;
#include    <cf_api/c1_dgrou.hpp>

class       cf_ChartEngine;
#include    <cf_api/c1_engin.hpp>

class       cf_ChartView;
#include    <cf_api/c4_cview.hpp>

// Define values used throughout this module:
#define     C1_CMODL_NUM_PALETTE_COLORS         16
#define     C1_CMODL_NUM_PEN_STYLES              3
#define     C1_CMODL_NUM_BRUSH_HATCHES           3

//------------------------------------------------------------
// Declare a ChartFolio "User-Chart Data-Model" (base) Class:
//------------------------------------------------------------
class CF_EXPORT   cf_ChartModel

{

public:

    cf_ChartModel(  cf_ChartView    *p_bf_cviewOwner,
                    cf_IndexMode    enumIndexMode  = CF_INDEX_NAT_N );

    ~cf_ChartModel();

    cf_DataGroup*   accessGroupsList();
    cf_DataGroup*   accessDomainItems();
    cf_DataGroup*   accessRangeValues();
                    // Allow users to access the implicit "domain",
                    // "range", and "group-list" data-groups this
                    // model constructs from user data.


    cf_DataGroup*   activateGroupAxis( cf_ChartAxis  enumChartAxisSelector );
    cf_DataGroup*   activateGroupAxisLabel( cf_ChartAxis enumChartAxisSelector );
    cf_DataGroup*   activateGroupLegend(  int   iUserLegendNumber );
    cf_DataGroup*   activateGroupTitle( cf_ChartTitle  enumChartTitleSelector );
    cf_DataGroup*   activateGroupUserData( int  iUserGroupIndex );
                    // Engines interact with (e.g. pull data) from pointers
                    // to "active" group in either: (1) a "dynamic array"
                    // of data groups, or (2) a collection of data-groups
                    // that this Chart-Model keeps for their reference...


    cf_ChartEngine* activeEngine();
    BOOL            activeEngine(   cf_ChartEngine  *p_cf_engToUseOurData );

    cf_ChartView*   activeView();
                    // Returns the current pointer to the "parent" chart-view.


    cf_XYZ*     addDataYVal( double      dUserYVal,
                             const char* a_cDomainItemLabel = NULL,
                             const char* a_cRangeValueLabel = NULL );
                //===================================================
                // Add a (y) data item to the current "activated"
                // (z) group.  Domain (x) index values automatically
                // generated according to the chart-model's current
                // domain-indexing method ID. Group (z) index
                // generated from current "activateGroupUserData()" call.
                // Optional labels from const char* strings show up
                // on respective domain and range axes. Note that
                // THIS IS THE RECOMMENDED DATA STORAGE METHOD for
                // about 90 to 95 percent of all Chart Types!
                //===================================================

    cf_XYZ*     addDataXYVal( double      dUserXVal,
                              double      dUserYVal,
                              const char* a_cDomainItemLabel = NULL,
                              const char* a_cRangeValueLabel = NULL );
                //===================================================
                // Add a (x,y) data item to the current "activated"
                // (z) group. Domain (x) index value is SPECIFIED by
                // the user.  Domain index method AUTOMATICALLY reset
                // to CF_ID_YVALS_AT_USR_XS; e.g. x = 2.3, 10.2 .. X.
                // Z-index generated from current "activateGroupUserData()"
                // call.  Optional labels from const char* strings
                // show up on respective domain and range axes.
                // Note that this data storage method is ONLY
                // RECOMMENDED for X/Y "Scatter Plots" or EXPLICIT
                // "Time-Series Plots"!
                //===================================================


    cf_XYZ*     addDataXYZVal( double      dUserXVal,
                               double      dUserYVal,
                               double      dUserZVal,
                               const char* a_cDomainItemLabel = NULL,
                               const char* a_cRangeValueLabel = NULL );
                //===================================================
                // Add a (x,y,z) data item to the current "activated"
                // group. Domain (x) index value is SPECIFIED by the
                // user.  Domain Index method AUTOMATICALLY reset
                // to CF_ID_YVALS_AT_USR_XS; e.g. x = 2.3, 10.2 .. X.
                // Note that y AND z values are specified by the user,
                // so there is NOT implicit z-group indexing. The
                // optional labels from const char* string show up
                // on respective domain and range axes.  Note that
                // this data storage method is ONLY RECOMMENDED
                // for X/Y/Z "Scatter Plots"!
                //===================================================



    cf_XYZ* addLabelDomainItem( double      dDomainItemIndex,
                                const char  *p_strDomainItemLabel );
    cf_XYZ* addLabelDomainItem( double      dDomainItemIndex,
                                double      dValueForLabel );
            // Add an index (char string OR user-specified
            // value) label to the "domain axis item" group:

    cf_XYZ* addLabelGroupsList( double      dGroupListIndex,
                                const char  *p_strGroupListLabel );
    cf_XYZ* addLabelGroupsList( double      dGroupListIndex,
                                double      dValueForLabel );
            // Add an index (char string OR user-specified
            // value) label to the "data-groups list" group:

    cf_XYZ* addLabelRangeValue( double      dRangeValueIndex,
                                const char  *p_strRangeValueLabel );
    cf_XYZ* addLabelRangeValue( double      dRangeValueIndex,
                                double      dValueForLabel );
            // Add an user-specified (char string OR user-specified)
            // value) label to the "range values" group:

    int     dataGroupActive();
            // Returns the current active index value

    int     dataGroupCount();
            // Returns the number of allocated data-groups

    int     dataGroupsStartAt();
    int     dataGroupsEndAt();
            // Yields the min and max index values for
            // the current set of activated data-groups

    cf_DataGroup*   dataGroupsReset();
                    // Performs a "delete" op on each activated
                    // data-group, then re-inits a default active
                    // data-group number one, and returns a pointer
                    // to this default data-group.


    cf_IndexMode    dataIndexMethod();
    BOOL            dataIndexMethod(    cf_IndexMode    enumNewIndexMode,
                                        BOOL            bForceEngineUpdate );
                    //=======================================================
                    // Get/set Index Method IDs as follows:
                    //  CF_INDEX_NAT_NS; e.g: n = 1, 2, 3, .. N.
                    //  CF_INDEX_INT_IS; e.g: i = 0, 1, 2, .. I.
                    //  CF_INDEX_USR_XS; e.g. x = 2.3, 10.2 .. X.
                    //=======================================================


    double      dataRangeInclMaxBuffer();
    void        dataRangeInclMaxBuffer( double dAddOntoCurrentRange );
                // Get/set extra "margin" onto the user-data-range.
                // Subject to range's "use-max-ceiling" state (below).
                // C-tor inits this buffer value to zero.

    double      dataRangeInclMaxCandidate();
    void        dataRangeInclMaxCandidate( double dPossibleMaxVal );
                // Get/set a "candidate" max value for user-data-range.
                // Subject to range's "max-buffer" state (above).
                // Subject to range's "use-max-ceiling" state (below).

    BOOL        dataRangeInclMaxCandidateInUse();
    void        dataRangeInclMaxCandidateInUse( BOOL bNewState );
                // Turn consideration of any candidate max value for
                // the user data-range ON/OFF.  C-tor inits to FALSE.
                // Calls to dataRangeInclMaxCandidate( double );
                // (immediately above) reset this state to TRUE!

    BOOL        dataRangeInclMaxCeiling();
    void        dataRangeInclMaxCeiling( BOOL bNewState );
                // If set TRUE, uses math.h ceil() to round user data
                // ranges UP to an integer value.  C-tor inits to FALSE.

    double      dataRangeInclMinBuffer();
    void        dataRangeInclMinBuffer( double dAddOntoCurrentRange );
                // Get/set extra "margin" onto the user-data-range.
                // Subject to range's "use-min-floor" state (below).
                // C-tor inits this buffer value to zero.

    double      dataRangeInclMinCandidate();
    void        dataRangeInclMinCandidate( double dPossibleMinVal );
                // Get/set a "candidate" min value for user-data-range.
                // Subject to range's "min-buffer" state (above).
                // Subject to range's "use-min-floor" state (below).

    BOOL        dataRangeInclMinCandidateInUse();
    void        dataRangeInclMinCandidateInUse( BOOL bNewState );
                // Turn consideration of any candidate min value for
                // the user data-range ON/OFF.  C-tor inits to FALSE.
                // Calls to dataRangeInclMinCandidate( double );
                // (immediately above) reset this state to TRUE!

    BOOL        dataRangeInclMinFloor();
    void        dataRangeInclMinFloor( BOOL bNewState );
                // If set TRUE, uses math.h floor() to round user data
                // ranges DOWN to an integer value.  C-tor inits to FALSE.


    BOOL        dataRangeInclOrigAlways();
    void        dataRangeInclOrigAlways( BOOL bNewState );
                // Get/set data-range-origin-in(/ex)clusion treatment.
                // C-tor inits this FORCED origin inclusion to FALSE;

    double      dataRangeInclOrigFromDelta();
    void        dataRangeInclOrigFromDelta( double dNumDataDeltasAway );
                // Get/set data-range-origin-in(/ex)clusion treatment.
                // C-tor inits this data-dependent limit to 3 data deltas.

    double      dataXItemsMax();
    double      dataXItemsMin();
    double      dataXItemsExtent();
                // Query methods for special use.  See note below...

    double      dataYValuesMax();
    double      dataYValuesMin();
    double      dataYValuesExtent();
                // Query methods for special use.  See note below...

    double      dataYValSumsMax();
    double      dataYValSumsMin();
    double      dataYValSumsExtent();
                // Query methods for special use.  See note below...

    double      dataZGroupsMax();
    double      dataZGroupsMin();
    double      dataZGroupsExtent();
                // Query the active data groups for min/max/range
                // values.  For use in engine axis/tick ops, etc...
                // ...or for "advanced" or customized-engine usage.


    cf_DataGroup*   labelAxis(  const char      *p_strNewLabel,
                                cf_ChartAxis    enumChartAxisSelector,
                                double          dPercentFromXCenterCoord,
                                double          dPercentFromYCenterCoord,
                                double          dPercentFromZCenterCoord );

    cf_DataGroup*   labelAxisData( cf_ChartAxis   enumChartAxisSelector );
    //BOOL            labelAxisIs( cf_ChartAxis   enumChartAxisSelector );
                    // Run the BOOL validator *BEFORE* the pointer-accessor!

    void            labelAxesReset();


    cf_DataGroup*   labelLegendData( int iAtIndex );

    cf_DataGroup*   labelLegendNew( const char  *p_strLegendLabel,
                                    double      dPercentFromXCenterCoord,
                                    double      dPercentFromYCenterCoord,
                                    double      dPercentFromZCenterCoord );

    int             labelLegendCount();
    void            labelLegendsReset();

    cf_DataGroup*   labelTitle( const char      *p_strNewLabel,
                                cf_ChartTitle   enumChartTitleSelector,
                                double          dPercentFromXCenterCoord,
                                double          dPercentFromYCenterCoord,
                                double          dPercentFromZCenterCoord );

    cf_DataGroup*   labelTitleData( cf_ChartTitle   enumChartTitleSelector );
    //BOOL            labelTitleIs( cf_ChartTitle enumChartTitleSelector );
                    // Run the BOOL validator *BEFORE* the pointer-accessor!

    void            labelTitlesReset();


    bf_Color    paletteColor(   int iModIntoAvailColors );
    void        paletteColor(   int     iModIntoAvailColors,
                                bf_Color   bf_clrNew );
                                // get/set from the palette of available
                                // colors that are applied to newly-
                                // created data groups...

    void        paletteColors(  bf_Color   bf_clr01,
                                bf_Color   bf_clr02,
                                bf_Color   bf_clr03,
                                bf_Color   bf_clr04,
                                bf_Color   bf_clr05,
                                bf_Color   bf_clr06,
                                bf_Color   bf_clr07,
                                bf_Color   bf_clr08,
                                bf_Color   bf_clr09,
                                bf_Color   bf_clr10,
                                bf_Color   bf_clr11,
                                bf_Color   bf_clr12,
                                bf_Color   bf_clr13,
                                bf_Color   bf_clr14,
                                bf_Color   bf_clr15,
                                bf_Color   bf_clr16 );
                                // Allow users to (re)init a palette of colors
                                // to apply to newly created data-groups.


    bf_BrushHatch   paletteBrushHatch(  int     iModIntoAvailHatches );
    void            paletteBrushHatch(  int         iModIntoAvailHatches,
                                        bf_BrushHatch  bf_bhatNewHatch );
                    // get/set from the palette of available brush hatches

    void            paletteBrushHatches(// C-tor inits #1 to "CF_BHAT_NONE"
                                        bf_BrushHatch  bf_bhat01,
                                        // C-tor inits #2 to "CF_BHAT_VERT"
                                        bf_BrushHatch  bf_bhat02,
                                        // C-tor inits #3 to "CF_BHAT_HORZ"
                                        bf_BrushHatch  bf_bhat03 );
                    // (re)init a palette of available brush hatches.


    BOOL            paletteMarkers2D3D( int     i2For2D_3For3D );
                    // Boolean query method return TRUE if flag is on,
                    // FALSE otherwise.  Pass int value of 2 to report
                    // on 2D-markers and 3 to report on 3D-markers.
                    // Any other int value return boolean FALSE.

    void            paletteMarkers2D3D( BOOL    bDisp2DMarkers,
                                        BOOL    bDisp3DMarkers,
                                        BOOL    bResetCurrentGroups );
                    // Get/set 2D/3D point marking on/off -- only
                    // affects objects/engines that perform separate
                    // 2D/3D marking, (e.g. 2D/3D Line Charts).



    bf_PenStyle     palettePenStyle(    int     iModIntoAvailStyles );
    void            palettePenStyle(    int         iModIntoAvailStyles,
                                        bf_PenStyle    bf_pstyNewStyle );
                    // get/set from the palette of available pen styles

    void            palettePenStyles(   // C-tor inits #1 to "CF_PS_SOLID"
                                        bf_PenStyle  bf_psty01,
                                        // C-tor inits #2 to "CF_PS_DASH"
                                        bf_PenStyle  bf_psty02,
                                        // Cot-r inits #3 to "CF_PS_DOT"
                                        bf_PenStyle  bf_psty03 );
                    // (re)init a palette of available pen styles.

    int             palettePenWidth();
    void            palettePenWidth( int iNewWidth );
                    // Same Concept: Get/set a default pen/line-width
                    // for any new data-group created by the chart-model.

    BOOL    updateNeededIs();
            // Simple query method allows a chart-view to optimize-away any
            // unneccessary update-methods calls (e.g. in chart-view::draw()).

    void    updateViewingEngines(   BOOL bForceDataUpdate = FALSE,
                                    BOOL bForceAutoConfig = FALSE,
                                    BOOL bForceGeomXform = FALSE,
                                    BOOL bForceProjXform = FALSE,
                                    BOOL bForceDispMetrics = FALSE );
            // Re-generate and/or re-configure the chart-engine's
            // chart-objects -- depending upon the data-state of the
            // chart-model.  IF the data-state of the chart-model
            // has changed, chart-engine object re-generation and
            // chart-engine re-configuration and re-transformation
            // will naturally occur.  But data-resets can also be
            // forced, and engine object re-configs and re-transforms
            // can also be suppressed (for performance purposes,
            // etc.) depending upon the update needs of the caller.

protected:

    //=======================================================
    // These protected methods are called by the standard
    // chart-model's addData*() interface method according
    // to the current state of the data indexing mode set
    // by either the c-tor or the user's calls to the
    // chart-model's dataIndexMethod(...) method(s).
    //
    // The methods are defined as protected so that users
    // will adhere to the (hopefully clear and simple)
    // dataIndexMethod(...) ... addData*(...) methodlogy,
    // but are NOT defined as private, so that if the user
    // wants to derive their OWN custom chart-model object,
    // these methods can thence be re-used!...
    //=======================================================
    cf_XYZ* addDataYValIndexNatN( double    dUserYVal,
                                const char* a_cDomainItemLabel = NULL,
                                const char* a_cRangeValueLabel = NULL );
            //--------------------------------------------------
            // Add a data item to the current "activated" group:
            // Adds user's Y-val with an X-Index equal to
            // Natural Number Sequence 'N' (1, 2, 3, .. 'n').
            // Z-index generated from current "activateGroupUserData()"
            // call.  Optional labels from const char* strings
            // show up on respective domain and range axes.
            //--------------------------------------------------

    cf_XYZ* addDataYValIndexIntI( double    dUserYVal,
                                const char* a_cDomainItemLabel = NULL,
                                const char* a_cRangeValueLabel = NULL );
            //--------------------------------------------------
            // Add a data item to the current "activated" group:
            // Adds user's Y-val with an X-Index equal to
            // Integer Number Sequence "I" (0, 1, 2, .. 'i')
            // Z-index generated from current "activateGroupUserData()"
            // call.  Optional labels from const char* strings
            // show up on respective domain and range axes.
            //--------------------------------------------------

    //============================================================
    // Declare critical protected vars, which are non-accessible
    // to the public, but potentially accessible for any user
    // derivations of customized chart-model objects:
    //============================================================
    cf_ChartView    *p_bf_cviewParentView_;
                    //--------------------------------------------
                    // Pointer to a "display event manager" that
                    // keeps a display which provides:
                    //
                    // (1)  a display context for the kernel
                    //      to perform 3D-to-2D projection
                    //      transformation calculations, and
                    //
                    // (2)  the actual chart display rendering
                    //      context...
                    //--------------------------------------------

    cf_ChartEngine  *p_cf_engChartEngine_;
                    //--------------------------------------------
                    // Pointer to the engine which controls the
                    // "geometry model" of this "chart data model"...
                    //--------------------------------------------


    cf_IndexMode    cf_enumCurrentIndexMode_;
                    // Indexing method set by dataIndexMethod() member.
                    // C-tor default value is: CF_INDEX_NAT_NS.

private:

    int         i,j,k; // Std. ICVs (Iteration Control Variables).

    bf_Color    a_bf_clrChartPalette_[ C1_CMODL_NUM_PALETTE_COLORS ];
                // Declare a "Color Palette" for users to select
                // colors for the objects (particularly dynamically
                // created data groups) that this cf_ChartModel object
                // will create and control...

    bf_BrushHatch
                a_bf_bhatChartPalette_[ C1_CMODL_NUM_BRUSH_HATCHES ];
                // Same Concept:  A "Palette" of brush hatches for the
                // dynamically created data groups to use...

    bf_PenStyle
                a_bf_pstyChartPalette_[ C1_CMODL_NUM_PEN_STYLES ];
                // Same Concept:  A "Palette" of pen styles for the
                // dynamically created data groups to use...

    int         iDefaultPenWidth_;       // C-tor inits = 1;
                // Same Concept: A default line-width for any new data-group

    BOOL        bDraw2DPointMarkers_;    // C-tor inits = FALSE.
    BOOL        bDraw3DPointMarkers_;    // C-tor inits = FALSE.
                // Same Concept:  A "Palette" of BOOL flags that
                // indicate 2D/3D markers for objects created from
                // the data model...

    BOOL        bDataRangeInclOrigAlways_;       // C-tor inits = FALSE;
    double      dNumDataDeltasForOrigInclus_;    // C-tor inits = 3.0;
                // Attribute vars for Data/Range/Origin Inclusion Treatment:

    double      dBufferRangeMinLimitBy_;     // C-tor inits = 0.0;
    BOOL        bRangeMinLimitUsesFloor_;    // C-tor inits = FALSE
                // Range-calculation modifier-vars.

    double      dBufferRangeMaxLimitBy_;     // C-tor inits = 0.0;
    BOOL        bRangeMaxLimitUsesCeil_;     // C-tor inits = FALSE
                // Range-calculation modifier-vars.

    double      dCandidateRangeMaxLimit_;     // C-tor inits = 0.0;
    BOOL        bRangeMaxLimitUsesCand_;      // C-tor inits = FALSE
                // Range-calculation modifier-vars.

    double      dCandidateRangeMinLimit_;     // C-tor inits = 0.0;
    BOOL        bRangeMinLimitUsesCand_;      // C-tor inits = FALSE
                // Range-calculation modifier-vars.

    int         iNumAllocatedGroups_;
    int         iMaxGroupIndex_;
    int         iMinGroupIndex_;
    int         iActiveGroupIndex_;
    BOOL        bUpdatedChartData_;
                // Run-time state vars.

    cf_DyArr    da_p_cf_dgDataGroups_;
    //===============================================================
    // This cf_ChartModel will coordinate the creation, destruction,
    // and manipulation of a set of cf_DataGroup objects...
    //
    // C-tor inits iNumAllocatedGroups = 0,  and addData*Val(...)
    // methods perform an ++ op before any cf_DataGroup is added.
    // This implies: indexing by natural numbers, 1..n.
    //
    // C-tor inits iMinGroupIndex = iMaxGroupIndex = 1, and creates
    // a default "active" group at index 1.
    // iMax val != iNum val indicates "empty" (non-assigned) index vals.
    //
    // Dynamic Array "grow-by" val is #define'd in this *.cpp
    // file as C1_CMODL_DGROU_GROWBY.
    //
    // C-tor inits bUpdatedChartData = FALSE; After this,
    // any addData*Val(...) methods reset this flag = TRUE.
    // The updateChartEngine() method (when complete) resets
    // this flag = FALSE, which implies that the chart engine
    // has been updated from the last chart/user data update,
    // and is now awaiting any further chart/user date updates
    // (i.e. for bUpdatedChartData to be assigned = TRUE, and
    // updateChartEngine() to be called...).
    //===============================================================

    cf_DataGroup    *p_cf_dgGroupsList_;
    cf_DataGroup    *p_cf_dgDomainItems_;
    cf_DataGroup    *p_cf_dgRangeValues_;
    //===============================================================
    // These data groups are responsible for keeping track of
    // impliticly generated or explicitly set (by the user)
    // index values that can be used by axis grid/tick-series
    // objects, etc.
    //===============================================================


    cf_DataGroup    *p_cf_dgLabelTitleMain_;
    cf_DataGroup    *p_cf_dgLabelTitleSub_;

    cf_DataGroup    *p_cf_dgLabelAxisXBottom_;
    cf_DataGroup    *p_cf_dgLabelAxisXBack_;
    cf_DataGroup    *p_cf_dgLabelAxisYLeft_;
    cf_DataGroup    *p_cf_dgLabelAxisYBack_;
    cf_DataGroup    *p_cf_dgLabelAxisZBottom_;
    cf_DataGroup    *p_cf_dgLabelAxisZBack_;
    cf_DataGroup    *p_cf_dgLabelAxisPolarFloor_;

    cf_DataGroup    *p_cf_dgAxisXBottom_;
    cf_DataGroup    *p_cf_dgAxisXBack_;
    cf_DataGroup    *p_cf_dgAxisYLeft_;
    cf_DataGroup    *p_cf_dgAxisYBack_;
    cf_DataGroup    *p_cf_dgAxisZBottom_;
    cf_DataGroup    *p_cf_dgAxisZBack_;
    cf_DataGroup    *p_cf_dgAxisPolarFloor_;

    cf_DyArr    da_p_cf_dgLegendMarkers_;
    int         iNumAllocatedLegendMarkers_;

};  // End of cf_ChartModel declaration.

#endif

//////////////////////////////////////
// END of File: C1_CMODL.HPP
//////////////////////////////////////

