// @(#) 1.3 com/src/samples/scrgraph/iodgpext.cpp, odgrafscript, od96nt, odnt9712d 1/22/97 15:34:22 [3/21/97 17:42:50]
//#====START_GENERATED_PROLOG======================================
//#
//#
//#   COMPONENT_NAME: odgrafscript
//#
//#   CLASSES: none
//#
//#   ORIGINS: 27
//#
//#
//#   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//#   All Rights Reserved
//#   Licensed Materials - Property of IBM
//#   US Government Users Restricted Rights - Use, duplication or
//#   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//#
//#   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//#   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//#   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//#   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//#   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//#   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//#   OR PERFORMANCE OF THIS SOFTWARE.
//#
//#====END_GENERATED_PROLOG========================================


// This file implements the ScriptExtension code for a scriptable part which
// inherits from 'GraphPart'.

/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitxtm.dll: Development
 */

#ifndef SOM_Module_iodgpext_Source
#define SOM_Module_iodgpext_Source
#endif
#define ODS_Graph_Class_Source

#include "iodscrgp.xh"
#include "scrcomp.xh"          // to get return value codes
#define VARIABLE_MACROS
#include "iodgpext.xih"

#include "iodgfigr.xh"          // interface for common graph figure
#include "iodgpoin.xh"          // interface for point
#include "iodgline.xh"          // interface for line
#include "iodgrect.xh"          // interface for rectangle
#include "iodgtext.xh"          // interface for text
#include "iodgraph.hpp"         // for figure type codes
#include "oddsemgr.xh"          // for ODDSEventManager
#include "somtc.h"              // for TypeCodeNew declarations
#include "somtcnst.h"           // for TypeCode Constants

#include "Frame.xh"             // for ODFrame interface
#include "Shape.xh"             // for ODShape interface
#include <FrFaItr.xh>           // for FrameFacetIterator
#include "Facet.xh"             // for Facet interface
#include <Trnsform.xh>          // for ODTransform
#include "TempObj.h"            // for TempODTransform
#include "ODMath.h"             // for ODIntToFixed

// By setting the name field in this routine, we establish a default name for
// the object.  It will be overridded by any name read in from persistent storage
// but that would represent an earlier use and thus would be the preferred name.
// Note that we want to establish this default BEFORE calling a parent class so
// that the parent will not replace our default.


// -------------------------------------------------------------------------
// InitScriptExtension - Override Base Class, add logic to set a name for
//      the instance.
// -------------------------------------------------------------------------

SOM_Scope void  SOMLINK SGPExt_InitScriptExtension(
                                   ODS_Graph *somSelf,

                                   Environment *ev,
                                   ODPart *owner)
{

    string somName ;
    #define theName "Graph"

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_InitScriptExtension");

    // Set the preferred name for this object.
    // Set this BEFORE calling parent to ensure that the derived class's
    // preferred name is used.

    if (somSelf->getExtName(ev) == NULL)
    {
      somSelf->setExtName(ev, theName) ;
    }

    ODS_Graph_parent_ODS_BaseContainer_InitScriptExtension(somSelf,
                                                           ev,
                                                           owner);


    _FontHeight = 10 ;
    _FontAngle = 0 ;
    _FontName = (string) SOMMalloc(strlen("Courier")+1) ;
    strcpy(_FontName, "Courier") ;
    _refreshShape = NULL ;

    // There is an error in the logic of the Script Extension which results
    // in this code being called twice when initializing from a storage
    // unit.  That, in turn, was causing the following event management
    // logic to throw an exception (two managers for the same event).
    // The combination of deleting the old event manager and catching
    // (but ignoring) the exception is over kill but prevents the resultant
    // errors.

    if (_fEventManagerMouseDown)
    {
      somSelf->DeleteEventMgr(ev,&_fODGuidMouseDown) ;
      delete _fEventManagerMouseDown ;
      _fEventManagerMouseDown = NULL ;
    }

    ODGUID odguid = { 0xa7dc3cb0,0x3f00, 0x11d0,
                     { 0x80, 0x16, 0x08, 0x00, 0x5a, 0x88, 0x88, 0x7e}};

    _fODGuidMouseDown = odguid ;

    try
    {
      _fEventManagerMouseDown =  new ODDSEventMgr(ev, _fODGuidMouseDown);
      somSelf->AddEventMgr(ev, _fEventManagerMouseDown);
    }
    catch (...)
    { }

    return ;
}



// -------------------------------------------------------------------------
// Register - override base class version to be a noop
// -------------------------------------------------------------------------


// When Register is called it is possible that this class/instance has already
// been registered.  This will occur when the instance is contained within
// some 'container object' which is scripted.  In that case we do not want
// to register this instance again.  When Register is called with a null prefix
// then this instance is the top level object to be scripted and we want to
// register the class and instance at that time.


SOM_Scope ODScriptExtension_ODScrRegRet  SOMLINK SGPExt_Register(ODS_Graph *somSelf,
                                                                  Environment *ev,
                                                                 ODScriptExtension* RegScope,
                                                                 string Prefix)
{
    ODScrRegRet RetVal = ODScrRegOK ;
    ODObject* basepart ;
    char*     className ;
    char*     nameAssigned ;

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_Register");

    if (( Prefix == NULL)  || ( *Prefix == '\0'))
    {
      className = somSelf->somGetClassName() ;
      RetVal = RegScope->DoRegisterClass(ev, className) ;
      if (RetVal != ODScrRegOK)
      { return RetVal ; }

      RetVal = RegScope->DoRegisterObject(ev,
                        (ODScriptExtension *) somSelf,    // the object to be scriptable
                        className,                // the class name of that object
                        somSelf->getExtName(ev),  //the default name to be used
                        Prefix,                   // prefix that applies in the scope
                                                  //  where registration begins
                        &nameAssigned,            // receives name actually assigned
                        somSelf,                  // the scope/extension of the object
                        kODTrue);                 // digits to be appended to make the
                                                  //  name unique if needed.

      if (RetVal == ODScrRegOK)            // if registration was successful
      {
        somSelf->setExtName(ev, nameAssigned) ;   // save the name that was used
        SOMFree(nameAssigned) ;                   // then release copy we got back
      }

      if (RetVal == ODScrRegOK)
      {
        // Now call parent Register to register any parts needed by base classes
        RetVal = ODS_Graph_parent_ODS_BaseContainer_Register(somSelf,
                                                             ev,
                                                             RegScope,
                                                             Prefix) ;
      }
    }
    return (RetVal) ;

}


// The following helper functions are used by the interface code to
// access the OpenDoc components associated with the Graph Part.


// -------------------------------------------------------------------------
// FirstFrame
//
//     Global helper function: return the first facet associated with a frame
// -------------------------------------------------------------------------
 static ODFrame*    FirstFrame( ODS_Graph *somSelf,
                        Environment*    ev)
{
    ALinkedList         *frameList ;
    ALink               *frameListItem ;
    ScriptableGraphPart *base ;
    ODFrame             *frame;

    base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
    frameList = base->GetDisplayFrames(ev) ;
    frameListItem = frameList->First(ev) ;
    frame = (ODFrame *) frameListItem->Content(ev);

    return frame;
}   // FirstFrame()



// -------------------------------------------------------------------------
// FirstFacet
//
//     Global helper function: return the first facet associated with a frame
// -------------------------------------------------------------------------
 static ODFacet*    FirstFacet( Environment*    ev,
                        ODFrame*        frame)
{
    ODFacet*    facet;
    try
    {
        ODFrameFacetIterator *ffitr  = frame->CreateFacetIterator(ev);
        facet = (ODFacet *)ffitr->First(ev);
        ODDeleteObject(ffitr);
    }   // try

    catch(...)
    {
    }

    return facet;
}   // FirstFacet()



// -------------------------------------------------------------------------
//  GetPoint
//
//     Global helper function: update a point object with the OpenDoc form
//              of the indicated point.
// -------------------------------------------------------------------------
 static void    GetPoint(   Environment*    ev,
                    ODPoint*        point)
{
   // point contains coordinates in 'normal' form
   // convert to OD form

   point->x = ODIntToFixed(point->x) ;
   point->y = ODIntToFixed(point->y) ;

}   // GetPoint()



// -------------------------------------------------------------------------
// FindInstance
//
//     Global helper function: locate imbedded object given id, note ID is
//              actually the object reference but this code will verify
//              that the object is still in the embedded objects list and
//              is one of the graphic part types.
// -------------------------------------------------------------------------
 static ODBoolean FindInstance( ODS_Graph *somSelf,
                        Environment*    ev,
                        long id,
                        ContentObject **InstanceFound )
{

    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentGrafPartFigr    *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type

    base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
    eList = base->GetEmbeddedObjects(ev);       // get the list of embedded objects
    for(eIter = eList->First(ev);               // for each object in the embedded list
        (figr = (ContentGrafPartFigr *) eIter->Content(ev)) != kODNULL ;
        eIter = eIter->Next(ev) )
    {
        coType = figr->_get_objType(ev);         // store the specific type

        if ( ( coType >  COBJ_GRAFPART_FIGR ) && // if it is GP-intrinsic content
             ( coType <= COBJ_GRAFPART_LAST ) )
        {
          if (figr == (ContentGrafPartFigr *) id)
          {
            *InstanceFound = (ContentObject *) figr ;
            return kODTrue ;
          }
        }
    }
    return kODFalse ;
}   // FindInstance()


// -------------------------------------------------------------------------
//  FluffRect
//
//     Global helper function: expand a rectangle by one pixel in each direction
// -------------------------------------------------------------------------
 static ODRect* FluffRect(  ODRect*  rect)
{

    ODFixed one   = ODIntToFixed(1);

#ifdef _PLATFORM_OS2_                   // OS2 origin is LLC
    rect->top    += one;
    rect->bottom -= one;
#else                                   // everyone else's origin is ULC
    rect->top    -= one;
    rect->bottom += one;
#endif  // _PLATFORM_OS2_
    rect->left   -= one;
    rect->right  += one;

    return rect;
}   // FluffRect()





// -------------------------------------------------------------------------
// AddLine - exposed function to create a new line object for the
//              graph part.
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_AddLine(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x1, long y1, long x2, long y2,
                                      long RGBValue)
{
  ContentGrafPartLine *lineObj ;
  ODFrame             *frame ;
  ODPoint pt ;

  /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
  ODS_GraphMethodDebug("ODS_Graph","SGPExt_AddLine");

  frame = FirstFrame(somSelf, ev) ;

  lineObj = new ContentGrafPartLine();
  lineObj->_set_fColor(ev, RGBValue) ;

  pt.x = x1 ; pt.y = y1 ;
  GetPoint(ev, &pt) ;
  lineObj->Initialize(ev, frame, &pt) ;

  pt.x = x2 ; pt.y = y2 ;
  GetPoint(ev, &pt) ;
  lineObj->Update(ev, &pt);

  lineObj->AdjustBoundingRect(ev) ;
  somSelf->AccumulateChanges(ev, lineObj) ;

  return (long) lineObj ;
}


// -------------------------------------------------------------------------
// AddRectangle - exposed function to create a new rectangle object
//              on the graph part.
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_AddRectangle(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x1, long y1, long x2, long y2,
                                      long RGBValue)
{
  ContentGrafPartRect *rectObj ;
  ODFrame             *frame ;
  ODPoint              pt ;

  /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
  ODS_GraphMethodDebug("ODS_Graph","SGPExt_AddRectangle");

  frame = FirstFrame(somSelf, ev) ;

  rectObj = new ContentGrafPartRect();
  rectObj->_set_fColor(ev, RGBValue) ;

  pt.x = x1 ; pt.y = y1 ;
  GetPoint(ev, &pt) ;
  rectObj->Initialize(ev, frame, &pt) ;

  pt.x = x2 ; pt.y = y2 ;
  GetPoint(ev, &pt) ;
  rectObj->Update(ev, &pt);

  rectObj->AdjustBoundingRect(ev) ;
  somSelf->AccumulateChanges(ev, rectObj) ;

  return (long) rectObj ;
}


// -------------------------------------------------------------------------
// AddPoint - exposed scripting function to create a point on the graph
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_AddPoint(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x, long y,
                                      long RGBValue)
{
  ContentGrafPartPoin *pointObj ;
  ODFrame             *frame ;
  ODPoint              pt ;

  /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
  ODS_GraphMethodDebug("ODS_Graph","SGPExt_AddPoint");

  frame = FirstFrame(somSelf, ev) ;

  pointObj = new ContentGrafPartPoin();
  pointObj->_set_fColor(ev, RGBValue) ;

  pt.x = x ; pt.y = y ;
  GetPoint(ev, &pt) ;
  pointObj->Initialize(ev, frame, &pt) ;

  pointObj->Update(ev, &pt);

  pointObj->AdjustBoundingRect(ev) ;
  somSelf->AccumulateChanges(ev, pointObj) ;

  return (long) pointObj ;
}

// -------------------------------------------------------------------------
// AddText - exposed function to create a new text object on the graph part
//              with font attributes as set by prior SetupFont call (or
//              defaults).
//           returns handle of new object.
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_AddText(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x1, long y1, long x2, long y2,
                                      string text)
{
  ContentGrafPartText *textObj ;
  ODFrame             *frame ;
  ODPoint              pt ;

  ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
  ODS_GraphMethodDebug("ODS_Graph","SGPExt_AddText");

  frame = FirstFrame(somSelf, ev) ;

  textObj = new ContentGrafPartText();
  textObj->_set_fColor     (ev, _FontColor) ;
  textObj->_set_fFontName  (ev, _FontName) ;
  textObj->_set_fFontHeight(ev, _FontHeight) ;
  textObj->_set_fFontAngle (ev, _FontAngle) ;
  textObj->_set_fText      (ev, text) ;
  textObj->_set_fFontFlags (ev, _FontFlags) ;

  pt.x = x1 ; pt.y = y1 ;
  GetPoint(ev, &pt) ;
  textObj->Initialize(ev, frame, &pt) ;


  pt.x = x2 ; pt.y = y2 ;
  GetPoint(ev, &pt) ;
  textObj->Update(ev, &pt);

  textObj->AdjustBoundingRect(ev) ;
  somSelf->AccumulateChanges(ev, textObj) ;

  return (long) textObj ;
}

// -------------------------------------------------------------------------
// Shift - exposed scripting function to move the referenced object by
//              the offset specified.
//         returns false if no matching object could be found.
// -------------------------------------------------------------------------

SOM_Scope boolean SOMLINK SGPExt_Shift(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long index,
                                      long deltaX, long deltaY)
{
    ContentObject  *theInstance ;
    ODPoint         pt          ;

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_Shift");

    if (FindInstance(somSelf, ev, index, &theInstance) )
    {
      pt.x = ODIntToFixed(deltaX) ;
      pt.y = ODIntToFixed(deltaY) ;
      theInstance->MoveBy(ev, &pt) ;
      return kODTrue ;
    }
    return kODFalse ;
}


// -------------------------------------------------------------------------
// Adjust - Scripting interface to adjust both defining points for one of
//              the included objects.  The second value specified will be
//              ignored for a point
//          returns false if the index does not match a valid object
// -------------------------------------------------------------------------

SOM_Scope boolean SOMLINK SGPExt_Adjust(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long index,
                                      long x1, long y1,
                                      long x2, long y2)
{
   ContentObject  *theInstance ;
   ODPoint         pt ;
   ODULong         coType ;

   /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
   ODS_GraphMethodDebug("ODS_Graph","SGPExt_Adjust");
   if (FindInstance(somSelf, ev, index, &theInstance))
   {
      somSelf->AccumulateChanges(ev, theInstance) ;
      pt.x = x1 ; pt.y = y1 ;
      GetPoint(ev, &pt) ;
      ((ContentGrafPartFigr *)theInstance)->_set_fPt1(ev, &pt) ;

      coType = theInstance->_get_objType(ev);   // store the specific type

      pt.x = x2 ; pt.y = y2 ;
      GetPoint(ev, &pt) ;
      switch (coType)
        {
        case COBJ_GRAFPART_POIN :
          {
            ((ContentGrafPartPoin *)theInstance)->AdjustBoundingRect(ev) ;
            break ;
          }
        case COBJ_GRAFPART_LINE :
          {
            ((ContentGrafPartLine *)theInstance)->_set_fPt2(ev, &pt) ;
            ((ContentGrafPartLine *)theInstance)->AdjustBoundingRect(ev) ;
            break ;
          }
        case COBJ_GRAFPART_TEXT :
        case COBJ_GRAFPART_RECT :
          {
            ((ContentGrafPartRect *)theInstance)->_set_fPt2(ev, &pt) ;
            ((ContentGrafPartRect *)theInstance)->AdjustBoundingRect(ev) ;
            break ;
          }
//      case COBJ_GRAFPART_ELLI
//      case COBJ_GRAFPART_CIRC
//      case COBJ_GRAFPART_PLIN
//      case COBJ_GRAFPART_PGON
//      case COBJ_GRAFPART_FREE
//      case COBJ_GRAFPART_IMAG
        default :
          {
            break ;
          }
        }
      somSelf->AccumulateChanges(ev, theInstance) ;
//    ((ContentGrafPartFigr *)theInstance)->AdjustBoundingRect(ev) ;
      return kODTrue ;
   }

   return kODFalse ;
}


// -------------------------------------------------------------------------
// Remove - scripting interface to delete the specified object from the
//              graph container.
//          returns false if no graph part matched the index specified.
// -------------------------------------------------------------------------

SOM_Scope boolean SOMLINK SGPExt_Remove(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long index)
{
    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentObject          *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_Remove");

    if (FindInstance(somSelf, ev, index, &figr))
    {
      somSelf->AccumulateChanges(ev, figr) ;
      ((ContentGrafPartFigr *)figr)->Uninitialize(ev) ;
      delete figr ;
      return kODTrue ;
    }
    return kODFalse ;
}


// -------------------------------------------------------------------------
// CountOver - Scripting interface that returns a count of the number of
//              graphic parts that are 'over' the specified point, i.e. within
//              the tollerance of that point.
//             returns count of such objects.
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_CountOver(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x, long y)
{

    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentGrafPartFigr    *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type
    long                    theCount=0; // the return value
    ODPoint                 pt ;

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_CountOver");

    pt.x = x ; pt.y = y ;
    GetPoint(ev, &pt) ;

    base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
    eList = base->GetEmbeddedObjects(ev);       // get the list of embedded objects
    for(eIter = eList->First(ev);               // for each object in the embedded list
        (figr = (ContentGrafPartFigr *) eIter->Content(ev)) != kODNULL ;
        eIter = eIter->Next(ev) )
    {
        coType = figr->_get_objType(ev);        // store the specific type

        if ( ( coType >  COBJ_GRAFPART_FIGR ) && // if it is GP-intrinsic content
             ( coType <= COBJ_GRAFPART_LAST ) )
        {
          if (figr->ContainsPoint(ev, &pt))
          {
            theCount += 1 ;
          }
        }
    }
    return theCount ;

}

// -------------------------------------------------------------------------
// FirstOver - returns theindex of the first located point that is 'over' the
//              specified coordinates.
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_FirstOver(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long x, long y)
{

    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentGrafPartFigr    *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type
    ODPoint                 pt ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_FirstOver");

    pt.x = x ; pt.y = y ;
    GetPoint(ev, &pt) ;

    base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
    eList = base->GetEmbeddedObjects(ev);       // get the list of embedded objects
    for(eIter = eList->First(ev);               // for each object in the embedded list
        (figr = (ContentGrafPartFigr *) eIter->Content(ev)) != kODNULL ;
        eIter = eIter->Next(ev) )
    {
        coType = figr->_get_objType(ev);        // store the specific type

        if ( ( coType >  COBJ_GRAFPART_FIGR ) && // if it is GP-intrinsic content
             ( coType <= COBJ_GRAFPART_LAST ) )
        {
          if (figr->ContainsPoint(ev, &pt))
          {
            return (long)figr ;
          }
        }
    }
    return kODNULL ;
}

// -------------------------------------------------------------------------
// IsOver - returns boolean result of testing if given coordinates are 'over'
//              the specified part.
// -------------------------------------------------------------------------

SOM_Scope boolean SOMLINK SGPExt_IsOver(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long handle,
                                      long x, long y)
{

    ContentObject          *figr;       // declare a buffer for a intrinsic object
    ODPoint                 pt ;
    boolean                 RetVal = kODFalse ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_IsOver");

    if (FindInstance(somSelf, ev, handle, &figr))
    {
      pt.x = x ; pt.y = y ;
      GetPoint(ev, &pt) ;
      if ( ((ContentGrafPartFigr *)figr)->ContainsPoint(ev, &pt) )
      {
        RetVal = kODTrue ;
      }
    }
    return RetVal ;
}

// -------------------------------------------------------------------------
// Refresh - forces a refresh of the Graphic Part, refresh the shape
//              that has been accumulated and clear that shape.  If no
//              accumulated shape, refresh the graph part (the big hammer)
// -------------------------------------------------------------------------

SOM_Scope void SOMLINK SGPExt_Refresh(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long          index)
{
    ContentObject       *theInstance ;
    ScriptableGraphPart *Base ;
    ODFrame             *frame ;
    ODFacet             *facet ;
    ODShape             *shape ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_Refresh");

    if (FindInstance(somSelf, ev, index, &theInstance) )
    {
      somSelf->AccumulateChanges(ev, theInstance) ;
    }

    if (_refreshShape != NULL)
    {
      frame = FirstFrame(somSelf, ev) ;
      facet = FirstFacet(ev, frame) ;
      facet->Update(ev, _refreshShape, kODNULL) ;
      _refreshShape->Release(ev) ;
      delete _refreshShape ;
      _refreshShape = NULL ;
    }
    else
    {
      Base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
      Base->HandleRefresh(ev) ;
    }
}


// -------------------------------------------------------------------------
// AccumulateChanges - builds up a refresh shape with explicit refresh requests
//              and AdjustRequests.
// -------------------------------------------------------------------------

SOM_Scope void SOMLINK SGPExt_AccumulateChanges(ODS_Graph * somSelf,
                                      Environment * ev,
                                      ContentObject *theInstance)


{

    ODShape             *shape ;
    ODFrame             *frame ;
    ODFacet             *facet ;
    ODRect               rect  ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_AccumulateChanges");

    frame = FirstFrame(somSelf, ev) ;
    facet = FirstFacet(ev, frame) ;
    shape = frame->CreateShape(ev);
    rect = theInstance->_get_boundingRect(ev) ;
    FluffRect (&rect) ;
    shape->SetRectangle(ev, &rect) ;

    if (_refreshShape == NULL)
    {
      _refreshShape = shape ;
    }
    else
    {
      _refreshShape->Union(ev, shape) ;
      shape->Release(ev) ;
    }
}

// -------------------------------------------------------------------------
// SetBackground - scripting interface to set the color for one of the
//                      graphic parts, defaults to the graph part itself
// -------------------------------------------------------------------------


SOM_Scope void SOMLINK SGPExt_SetColor(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long handle,
                                      long RGBvalue)
{
    ContentObject        *figr;       // declare a buffer for a intrinsic object
    ScriptableGraphPart  *base ;

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_SetColor");

    if (FindInstance( somSelf, ev, handle, &figr))
    {
      ((ContentGrafPartFigr *)figr)->_set_fColor(ev, RGBvalue) ;
    }
    else
    {
      base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
      base->SetBackgroundColor(ev, RGBvalue) ;
    }

}

// -------------------------------------------------------------------------
// SetupFont - scripting interface to collect the set of attributes that
//                      control a font.
// -------------------------------------------------------------------------


SOM_Scope void SOMLINK SGPExt_SetupFont(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long fontHeight,
                                      long fontAngle,
                                      long RGBValue,
                                      long fontFlags,
                                      string fontName)
{
    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_SetupFont");

    _FontHeight = fontHeight ;
    _FontAngle  = fontAngle  ;
    _FontColor  = RGBValue ;
    _FontFlags  = fontFlags ;
    if (_FontName != NULL) SOMFree(_FontName) ;
    _FontName = (string) SOMMalloc(strlen(fontName) + 1) ;
    strcpy(_FontName, fontName) ;

}

// -------------------------------------------------------------------------
// GetBounds - scripting interface to get current bounds for specified
//              part. if part is not found, return bound for the
//              whole graph part
//             returns true if part found, else false
// -------------------------------------------------------------------------


SOM_Scope boolean SOMLINK SGPExt_GetBounds(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long index,
                                      long *x1, long *y1,
                                      long *x2, long *y2)
{
    ContentObject  *theInstance ;
    ODFrame        *frame ;
    ODFacet        *facet ;
    ODBoolean       RetVal ;
    ODRect          rect ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_GetBounds");


    if (FindInstance(somSelf, ev, index, &theInstance) )
    {
      RetVal = kODTrue ;
      rect = theInstance->_get_boundingRect(ev) ;
    }
    else
    {
      RetVal = kODFalse ;
      frame = FirstFrame(somSelf, ev) ;
      facet = FirstFacet(ev, frame) ;
      TempODShape shape = frame->AcquireFrameShape(ev, facet->GetCanvas(ev));
      shape->GetBoundingBox(ev, &rect);
    }
    *x1 = FixedToInt(rect.left  ) ;
    *y1 = FixedToInt(rect.top   ) ;
    *x2 = FixedToInt(rect.right ) ;
    *y2 = FixedToInt(rect.bottom) ;

    return RetVal ;
}


// -------------------------------------------------------------------------
// GetAllParts - Scripting interface that returns a sequence of part handles
//              for all the graphic items in the parent part.
// -------------------------------------------------------------------------

//SOM_Scope sequence(long) SOMLINK SGPExt_GetAllParts(ODS_Graph * somSelf,
//                                      Environment * ev,
//                                      boolean *sequenceOK)
SOM_Scope boolean SOMLINK SGPExt_GetAllParts(ODS_Graph * somSelf,
                                      Environment * ev,
                                      sequence(long) *theParts)
{

    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentGrafPartFigr    *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type

    /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_GetAllParts");

    base = (ScriptableGraphPart *) somSelf->GetBase(ev) ;
    eList = base->GetEmbeddedObjects(ev);       // get the list of embedded objects

    if (theParts == NULL) { return kODFalse ; } // null sequence ptr, return error

    theParts->_length = 0 ;

    for(eIter = eList->First(ev);               // for each object in the embedded list
        (figr = (ContentGrafPartFigr *) eIter->Content(ev)) != kODNULL ;
        eIter = eIter->Next(ev) )
    {
        coType = figr->_get_objType(ev);        // store the specific type

        if ( ( coType >  COBJ_GRAFPART_FIGR ) && // if it is GP-intrinsic content
             ( coType <= COBJ_GRAFPART_LAST ) )
        {
          if (theParts->_length >= theParts->_maximum)
          {
            if (theParts->_buffer == NULL)
            {
              theParts->_buffer = (long *) SOMMalloc(sizeof(long)*10) ;
            }
            else
            {
              theParts->_buffer = (long *) SOMRealloc(theParts->_buffer, sizeof(long)*(theParts->_maximum + 10)) ;
            }
            if (theParts->_buffer == NULL)
            {
              return kODFalse ;
            }
            theParts->_maximum += 10 ;
          }
          theParts->_buffer[theParts->_length] = (long)figr ;
          theParts->_length += 1 ;
        }
    }
    return kODTrue ;

}


// -------------------------------------------------------------------------
// GetTypeCode - returns code reflecting the type of the item referenced
//                      0 = unknown - no such part
//                      1 = Point
//                      2 = Line
//                      3 = Rectangle
//                      4 = Text
// -------------------------------------------------------------------------

SOM_Scope long SOMLINK SGPExt_GetTypeCode(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long handle)
{

    ODFrame        *frame ;
    ODFacet        *facet ;
    ScriptableGraphPart    *base ;
    ALinkedList            *eList ;     // get the list of embedded objects
    ALink                  *eIter;      // define an iterator on the embedded list
    ContentObject          *figr;       // declare a buffer for a intrinsic object
    ODULong                 coType;     // declare a buffer for a intrinsic type
    ODPoint                 pt ;
    long                    RetVal = 0 ;// Return value

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_GetTypeCode");


    if (FindInstance(somSelf, ev, handle, &figr))
    {
       switch ( figr->_get_objType(ev))
       {
         case COBJ_GRAFPART_POIN :
           { RetVal = 1 ; break ; }

         case COBJ_GRAFPART_LINE :
           { RetVal = 2 ; break ; }

         case COBJ_GRAFPART_RECT :
           { RetVal = 3 ; break ; }

         case COBJ_GRAFPART_TEXT :
           { RetVal = 4 ; break ; }

         default:
           { break ; }
       }
    }
    return RetVal ;
}



// -------------------------------------------------------------------------
// GetPointList - Updates the argument sequence with the set of points that
//                      define the specified object.  Return value is a Boolean
//                      that reflects success in building the list
// -------------------------------------------------------------------------

SOM_Scope boolean SOMLINK SGPExt_GetPointList(ODS_Graph * somSelf,
                                      Environment * ev,
                                      long handle,
                                      sequence(long) * AllPts)
{
  ContentObject          *figr;
  ODPoint                 pt1, pt2 ;
  boolean                 seqOK = kODFalse ;

  /* ODS_GraphData *somThis = ODS_GraphGetData(somSelf); */
  ODS_GraphMethodDebug("ODS_Graph","SGPExt_GetPointList");

  if (AllPts == NULL)
  { return (seqOK) ; }

  AllPts->_length  = 0 ;                 // init length of return

  if (FindInstance (somSelf, ev, handle, &figr) )
  {
    pt1 = ((ContentGrafPartFigr *)figr)->_get_fPt1(ev); // get first point

    switch (figr->_get_objType(ev))     // Just which type was it
    {
      case COBJ_GRAFPART_POIN :
         AllPts->_length = 2 ;
         break ;

      case COBJ_GRAFPART_LINE  :
         AllPts->_length = 4 ;
         pt2 = ((ContentGrafPartLine *)figr)->_get_fPt2(ev) ;
         break ;
      case COBJ_GRAFPART_RECT  :
         AllPts->_length = 4 ;
         pt2 = ((ContentGrafPartRect *)figr)->_get_fPt2(ev) ;
         break ;
      case COBJ_GRAFPART_TEXT  :
         AllPts->_length = 4 ;
         pt2 = ((ContentGrafPartText *)figr)->_get_fPt2(ev) ;
         break ;
      default :
         break ;
    }

    if (AllPts->_length > 0)            // if we recognized the type
    {                                   //  allocate buffer
      if (AllPts->_maximum < AllPts->_length)
      {                                 // need to expand buffer
        if (AllPts->_buffer != NULL)
        {                               // expand existing buffer
          AllPts->_buffer = (long *) SOMRealloc(AllPts->_buffer, sizeof(long) * AllPts->_length) ;
        } else {                        // create new buffer
          AllPts->_buffer =(long *) SOMMalloc(sizeof(long) * AllPts->_length) ;
        }
        if (AllPts->_buffer != NULL)
          AllPts->_maximum = AllPts->_length ;
      }
    }

                                        // this logic will need rework
                                        //  when we support 'poly' figures

    if (AllPts->_buffer != NULL)         // if type is ok and buffer is ok
    {
      AllPts->_buffer[0] = FixedToInt(pt1.x) ;   // all have the first point
      AllPts->_buffer[1] = FixedToInt(pt1.y) ;
      if (AllPts->_length == 4)                  // if second point defined
      {
        AllPts->_buffer[2] = FixedToInt(pt2.x) ;
        AllPts->_buffer[3] = FixedToInt(pt2.y) ;
      }
      seqOK = kODTrue ;
    }                                   // end buffer and type ok.
  }                                     // end found part
  return seqOK ;
}


//=======================================================================
// Method to invoke any event sinks attached to the MouseDown event
//=======================================================================


SOM_Scope long  SOMLINK SGPExt_TriggerMouseDown(ODS_Graph *somSelf,
                                                  Environment *ev,
                                                  long x,
                                                  long y)
{
    ODPoint  Pt ;
    ODFrame        *frame ;
    ODFacet        *facet ;

    ODS_GraphData *somThis = ODS_GraphGetData(somSelf);
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_TriggerMouseDown");


    _IDL_SEQUENCE_any  inParms;
    ODDSRESULT         result;
    long               sinkCount ;
    long               sinkNumber ;
    any                data[3];
    ODDSSinkEnum       *sinkEnum;
    long               handled = 0 ;

    // The coordinates received here are not relative to the
    // graph part so we need to go thru the following to transform
    // them appropriately

    Pt.x = ODIntToFixed(x) ;
    Pt.y = ODIntToFixed(y) ;
    frame = FirstFrame(somSelf, ev) ;
    facet = FirstFacet(ev, frame) ;
    TempODTransform xform = facet->AcquireWindowContentTransform(ev, kODNULL) ;
    xform->InvertPoint(ev, &Pt) ;
    x = FixedToInt (Pt.x) ;
    y = FixedToInt (Pt.y) ;

    data[0]._type = TC_long ;
    data[0]._value = (void *) &x;
    data[1]._type = TC_long ;
    data[1]._value = (void *) &y;
    data[2]._type = TypeCodeNew(tk_pointer, TC_long);
    data[2]._value = (void *) &handled ;

    inParms._length  = 3;
    inParms._maximum = 3;
    inParms._buffer = data;

    if (_fEventManagerMouseDown)
    {
      _fEventManagerMouseDown->PrepareEventFiring(ev, &sinkCount, &sinkEnum);
      for (sinkNumber = 0 ; sinkNumber < sinkCount ; sinkNumber++ )
      {
        _fEventManagerMouseDown->FireEvent(ev, sinkEnum, "MouseDown",&inParms,&result);
      }
      _fEventManagerMouseDown->StopEventFiring(ev, sinkEnum);
    }

    tcFree(data[2]._type, ev) ;           // release TypeCode we created.

    return ( handled != 0 ? kODTrue : kODFalse) ;
}


//=======================================================================
// Override somDestruct to properly dispose of connection data
//=======================================================================
SOM_Scope void SOMLINK SGPExt_somDestruct(ODS_Graph *somSelf,
                                          octet doFree, somDestructCtrl* ctrl)
{
    ODS_GraphData *somThis; /* set in BeginDestructor */
    somDestructCtrl globalCtrl;
    somBooleanVector myMask;
    ODS_GraphMethodDebug("ODS_Graph","SGPExt_somDestruct");
    ODS_Graph_BeginDestructor;

    /*
     * local ODS_Graph deinitialization code
     */

    if (_fEventManagerMouseDown)
    {
      Environment *ev = SOM_CreateLocalEnvironment();
      somSelf->DeleteEventMgr(ev,&_fODGuidMouseDown) ;
      delete _fEventManagerMouseDown ;
      _fEventManagerMouseDown = NULL ;
      SOM_DestroyLocalEnvironment(ev);
    }

    ODS_Graph_EndDestructor;
}
