//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odclockpart
//
//   CLASSES: none
//
//   ORIGINS: 82,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========================================
//
/* @(#) 1.25 com/src/samples/clock/iodclock.cpp, odclockpart, od96nt, odnt9712d 2/25/97 16:42:53 [3/21/97 17:36:29] */
/*
 *  This file was generated by the SOM Compiler.
 *  Generated using:
 *     SOM incremental update: 2.41
 */

/*
 *      File:           Clock.CPP
 *
 *   Contains:  Implementation of Clock Part
 *
 *   Copyright: (c) 1996 by IBM Corp., all rights reserved.
 *
 */

/******************************************************************
   Implementation of Clock as subclassed from ShapePart requires
   changes in the following methods:
   1) CommonInit
   2) Draw
   3) Externalize
   4) HandleEvent
  ******************************************************************/

#ifndef SOM_Module_Clock_Source
#define SOM_Module_Clock_Source
#endif

#define Clock_Class_Source
#define VARIABLE_MACROS
#include "iodclock.xih"


#define INCL_ODAPI
#define INCL_ODARBITRATOR
#define INCL_ODCANVAS
#define INCL_ODDRAGANDDROP
#define INCL_ODDRAFT
#define INCL_ODERRORS
#define INCL_ODFACET
#define INCL_ODFOCUSSET
#define INCL_ODFRAME
#define INCL_ODINFO
#define INCL_ODSHAPE
#define INCL_ODSESSION
#define INCL_ODSTORAGEUNIT
#define INCL_ODSTORAGEUNITVIEW
#define INCL_ODTRANSFORM
#define INCL_ODUI
#define INCL_ODUNDO
#define INCL_ODWINDOW
#define INCL_ODWINDOWSTATE


#ifndef _ODEXCEPT_
#include "ODExcept.h"
#endif

#ifndef _FOCUSLIB_
#include <focuslib.h>
#endif

#ifndef _ODMATH_
#include "ODMath.h"
#endif

#ifndef _MATH_
#include "Math.h"
#endif

#ifndef _TIME_
#include "Time.h"
#endif

#ifndef _STORUTIL_
#include <storutil.h>
#endif

#ifndef _TEMPOBJ_
#include "TempObj.h"
#endif

#ifndef _WINUTILS_
#include "winutils.h"
#endif

#ifndef  __string_h
#include <string.h>
#endif

#ifndef _STDTYPIO_
#include "stdtypio.h"
#endif

#ifdef ODDebug
#include <qprintf.h>       // MSGDISP.EXE qprintf's
#endif

#ifndef _ODALL_
#include <odall.h>
#endif

#ifndef _ITEXT_
#include <IText.h>
#endif

#ifndef _StorUtil_
#include <StorUtil.h>
#endif

#ifndef _IBASE_                         //  Make sure ibase.hpp is included
#include <ibase.hpp>                    //  since that is where IC_<environ>
#include <igrafctx.hpp>
#include <igbundle.hpp>
#include <igrect.hpp>
#include <igline.hpp>
#endif

const ODType   kClockKind            = "Clock";
const ODType   kClockKindDisplayName = "Clock Part Kind";
const ODType   kClockPartHandlerName  =  "Clock";
const ODType   kClockPartHandlerDisplayName  =  "Clock Part";
const ODType   kClockIconFileName  =  "iodclock.ico";
const ODType   kClockCategory         =  "OpenDoc:Category:Sample";

char* kClockPartPropertyName  =  "Clock";

/*******************************************************************
 The following methods is defined by ClockPart to invalidate
 the interior regions of its face.
 *******************************************************************/

SOM_Scope void  SOMLINK ClockInvalidateHands(Clock* somSelf,
                                            Environment* ev,
                                            ODFacet* facet,
                                            ODFrame* frame)
{
    ClockData *somThis = ClockGetData(somSelf);
    ClockMethodDebug("Clock","ClockInvalidateHands");
#ifdef ODDebug
   qprintf("Invoked Clock::InvalidateHands\n");
#endif

   try {

           if ((facet != kODNULL) && (frame != kODNULL))
           {
               int width;
               int height;
               ODRgnHandle hrgnToInval;
               ODRect box;
               TempODShape tempShape = frame->AcquireFrameShape(ev, facet->GetCanvas(ev));
               tempShape->GetBoundingBox(ev, &box);

               width  = FixedToInt(box.right) - FixedToInt(box.left);        // shape to be
               height = abs(FixedToInt(box.top) - FixedToInt(box.bottom));   // invalidated

               // create the region to be invalidated
#ifdef _PLATFORM_WIN32_
               hrgnToInval = CreateEllipticRgn(width*.15,height*.15,width*.85,height*.85);
#elif defined(_PLATFORM_OS2_)

               POINTL center;
               ODPlatformCanvas* canvas = facet->GetCanvas(ev)->GetPlatformCanvas(ev, kODPM);
               HPS hps = ((ODOS2WindowCanvas*)canvas)->GetPS(ev);
               int rad = (width < height) ? width : height;       // get radius
               center.x = width/2;
               center.y = height/2;
               GpiBeginPath(hps,1L);                              // Define GPI
               GpiSetCurrentPosition(hps , &center);              // for circle
               GpiFullArc(hps,DRO_OUTLINE,MAKEFIXED((rad*0.4),0));
               GpiEndPath(hps);
               hrgnToInval = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);  // Convert path
#endif
               // Ensure that the region to invalidate is not null before proceeding
               // (CreateEllipticRegion on Win95 returns null region if we're minimized)
               if (hrgnToInval) {
                  // get the shape of the region and call invalidate
                  ODShape *MyShape= frame->CreateShape(ev);
                  MyShape->SetRegion(ev,hrgnToInval);

                  frame->Invalidate(ev,MyShape,kODNULL);          // invalidate clock hands

#ifdef _PLATFORM_OS2_
                  ((ODOS2WindowCanvas *)canvas)->ReleasePS(ev);   // Release the canvas
#endif
                  MyShape->Release(ev);
               } // endif hrgnToInval
           }
   }
   catch(...){}
}

/*******************************************************************
  The following 4 Methods are defined in Clocks parents and overridden
  here.
 *******************************************************************/

SOM_Scope void  SOMLINK ClockCommonInit(Clock *somSelf,
                                           Environment *ev,
                                           ODPart        *partWrapper)
{
    ClockData *somThis = ClockGetData(somSelf);
    ClockMethodDebug("Clock","ClockCommonInit");
#ifdef ODDebug
   qprintf("Invoked Clock::CommonInit\n");
#endif

   try {

    Clock_parent_ShapePart_CommonInit(somSelf,  ev, partWrapper);


    double pi=4.*atan(1.);   // set pi
    double d2r=pi/180. ;     // set degrees to radians

    // Calculate the points on the outside of the clock
    for (int i=0;(i<359);(i=i+6))
      {
       _ClockPtx[i]=sin(d2r*i);
       _ClockPty[i]=-cos(d2r*i);
      }

   }
   catch(...){}
}

SOM_Scope void  SOMLINK ClockDraw(Clock *somSelf,  Environment *ev,
                                       ODFacet* facet, ODShape* invalidShape)
{
    ClockData *somThis = ClockGetData(somSelf);
    ClockMethodDebug("Clock","ClockDraw");
#ifdef ODDebug
   qprintf("Invoked Clock::Draw\n");
#endif

   try {

   // Let ShapePart fill in the background color.
   Clock_parent_ShapePart_Draw(somSelf,  ev, facet, invalidShape);

   ODRect rect;
   POINTL pttmp;
   POINTL MidPt;
   ODBoolean printing = kODFalse;

   // If we are printing, we will always set our pen width to 1
#ifdef _PLATFORM_OS2_
   if (facet->GetCanvas(ev)->HasPlatformPrintJob(ev,kODPM))
#elif defined(_PLATFORM_WIN32_)
   if (facet->GetCanvas(ev)->HasPlatformPrintJob(ev,kODWin32))
#endif
          printing = kODTrue;

   ODFrame* displayFrame = facet->GetFrame(ev);
   TempODShape tempShape = displayFrame->AcquireFrameShape(ev, facet->GetCanvas(ev));
   tempShape->GetBoundingBox(ev, &rect);

#if defined(_PLATFORM_WIN32_)
   HDC hdcDraw;
#elif defined(_PLATFORM_OS2_)
   HPS hdcDraw;
#endif

   // Set up drawing environment
   CFocus f(facet, invalidShape, &hdcDraw);



   IPresSpaceHandle ipsh(hdcDraw);
   IGraphicContext gc(ipsh);
   gc.setPenType(IGraphicBundle::solid);
   gc.setPenWidth(1);
   gc.setPenColor(IColor::black);

   // Draw the Clock Face
   POINTL ptl1 = {FixedToInt(rect.left),  FixedToInt(rect.bottom)};
   POINTL ptl2 = {FixedToInt(rect.right), FixedToInt(rect.top)};

   // Calculate the points of the clock
   float MidxPoint = ((float)(ptl1.x + ptl2.x)/2);
   float MidyPoint = ((float)(ptl1.y + ptl2.y)/2);
   float radius;
   int linesub;

   // Get the smallest radius of the bounding box
   if ((MidxPoint - FixedToInt(rect.left)) <=
        abs(MidyPoint - FixedToInt(rect.top)) )
     radius = (MidxPoint - FixedToInt(rect.left));
   else
     radius = abs(MidyPoint - FixedToInt(rect.top));

   MidPt.x   = MidxPoint;
   MidPt.y   = MidyPoint;

   double pi=4.*atan(1.);   // set pi
   double d2r=pi/180. ;     // set degrees to radians

   POINTL ClockPts[359];

   for  (int i=0;(i<359);(i=i+6))
      {
       ClockPts[i].x=((radius*_ClockPtx[i])+(MidxPoint));
       ClockPts[i].y=((radius*_ClockPty[i])+(MidyPoint));

       // Calculate the 15 minute marks
       if ((i%90) == 0)
         {
            if (printing) {
              gc.setPenWidth(1);
            } else {
              gc.setPenWidth(3);
            } /* endif */
          linesub = ((radius*2)*.08);
         }
       // Calculate the 5 minute marks
       else if ((i%30) == 0)
         {
            if (printing) {
              gc.setPenWidth(1);
            } else {
              gc.setPenWidth(2);
            } /* endif */
          linesub = ((radius*2)*.05);
         }
       // Otherwise, set up the 1 minute mark
       else
         {
          gc.setPenWidth(1);
          linesub = ((radius*2)*.025);
         }

       pttmp.x=(((radius-linesub)*_ClockPtx[i])+(MidxPoint));
       pttmp.y=(((radius-linesub)*_ClockPty[i])+(MidyPoint));

       // Draw the marks on the clock face
       IGLine(IPoint(ClockPts[i]), IPoint(pttmp)).drawOn(gc);

      }  // end of for (i=0;(i<359);(i=i+6))

  time_t tm;
  time (&tm);
  struct tm *ltime = localtime(&tm);    // get the time from the system

  int secpt =  (ltime->tm_sec * 6);
  int minpt =  (ltime->tm_min * 6);
  int hourpt;

// adjust the hour hand every 12 min.  ------------------------------------
  int hradjust = 0;
      if ((minpt>71)&&(minpt<144))
        hradjust = 6;

      else if ((minpt>143)&&(minpt<216))
        hradjust = 12;

      else if ((minpt>215)&&(minpt<288))
        hradjust = 18;

      else if ((minpt>287)&&(minpt<360))
        hradjust = 24;


  if ((ltime->tm_hour) >= 12)
    hourpt = ((((ltime->tm_hour)-12)*30)+hradjust);
  else
    hourpt = ((ltime->tm_hour *30)+hradjust);
//  endof adjust the hour hand every 12 min. ------------------------------

// draw the second hand  --------------------------------------------------
  POINTL tmpsec;
  linesub = (radius*2) * .15;
  tmpsec.x = ((radius-linesub)*_ClockPtx[secpt]) + MidxPoint;
#if defined(_PLATFORM_WIN32_)
  tmpsec.y = MidyPoint + ((radius-linesub)*_ClockPty[secpt]);
#elif defined(_PLATFORM_OS2_)
  tmpsec.y = MidyPoint - ((radius-linesub)*_ClockPty[secpt]);
#endif

  gc.setPenWidth(1);
  IGLine(IPoint(MidPt), IPoint(tmpsec)).drawOn(gc);

// draw the minute hand  --------------------------------------------------
   POINTL tmpmin;
   linesub = ((radius*2)*.20);
   tmpmin.x=(((radius-linesub)*_ClockPtx[minpt])+(MidxPoint));
#if defined(_PLATFORM_WIN32_)
  tmpmin.y = MidyPoint + ((radius-linesub)*_ClockPty[minpt]);
#elif defined(_PLATFORM_OS2_)
  tmpmin.y = MidyPoint - ((radius-linesub)*_ClockPty[minpt]);
#endif

   if (printing) {
     gc.setPenWidth(1);
   } else {
     gc.setPenWidth(2);
   } /* endif */
   IGLine(IPoint(MidPt), IPoint(tmpmin)).drawOn(gc);

// draw the hour hand  --------------------------------------------------
   POINTL tmphour;
   linesub = ((radius*2)*.27);
   tmphour.x=(((radius-linesub)*_ClockPtx[hourpt])+(MidxPoint));
#if defined(_PLATFORM_WIN32_)
  tmphour.y = MidyPoint + ((radius-linesub)*_ClockPty[hourpt]);
#elif defined(_PLATFORM_OS2_)
  tmphour.y = MidyPoint - ((radius-linesub)*_ClockPty[hourpt]);
#endif

   if (printing) {
     gc.setPenWidth(1);
   } else {
     gc.setPenWidth(3);
   } /* endif */
   IGLine(IPoint(MidPt), IPoint(tmphour)).drawOn(gc);


// call the system timer it will send back a timer event in one second
   HWND hwndFacet = facet->GetFacetHWND(ev);
#if defined(_PLATFORM_WIN32_)
   SetTimer(hwndFacet,100,1000,(TIMERPROC)NULL);
#elif defined(_PLATFORM_OS2_)
   WinStartTimer(WinQueryAnchorBlock(hwndFacet), hwndFacet, 0, 1000);
#endif

   }
   catch(...){}
}



SOM_Scope void  SOMLINK ClockExternalize(Clock *somSelf,
                                               Environment *ev)
{
    ClockData *somThis = ClockGetData(somSelf);
    ClockMethodDebug("Clock","ClockExternalize");

#ifdef ODDebug
   qprintf("Invoked Clock::Externalize\n");
#endif

    // call the parent's method
    Clock_parent_ShapePart_Externalize(somSelf, ev);

    try{

      ODStorageUnit* su = somSelf->GetStorageUnit(ev);

      // Add the kind name to this part's storageUnit
      if (ODSUExistsThenFocus (ev, su, kODPropContents, kClockKind))
         su->Remove (ev);

      su->AddProperty(ev, kODPropContents)->AddValue(ev, kClockKind);

      // Add a default kODPropName to this part's storageUnit for the
      // document properties notebook.  The notebook will maintain
      // it's persistence.
      if (ODSUExistsThenFocus (ev, su, kODPropName, kODIntlText)) {
         if (su->GetSize(ev) == 0) {
            // create string to place in kODPropName property
            ODIText* iClockPropName = CreateITextFromCharPtr(kClockPartPropertyName);

            // write the name into the kODPropName property
            ODSetITextProp(ev, su, kODPropName, kODIntlText, iClockPropName);
         }
      }
   } catch (...) {
   } /* end catch */
}




SOM_Scope ODBoolean  SOMLINK ClockHandleEvent(Clock *somSelf,
                                                    Environment *ev,
                                                    ODEventData* event,
                                                    ODFrame* frame,
                                                    ODFacet* facet,
                                                    ODEventInfo* eventInfo)
{
    ClockData *somThis = ClockGetData(somSelf);
    ClockMethodDebug("Clock","ClockHandleEvent");

// call the parents method
    Clock_parent_ShapePart_HandleEvent(somSelf, ev, event, frame, facet, eventInfo);


    ODBoolean handled = kODFalse;

    try {

#if defined(_PLATFORM_WIN32_)
    switch (event->message)
#elif defined(_PLATFORM_OS2_)
    switch (event->msg)
#endif
    {

       case WM_TIMER:
       // Invalidate the clock hands, so that OpenDoc redraws only
       // the Clock hands and not the Clock face.
       {
           somSelf->InvalidateHands(ev, facet, frame);
           handled = kODTrue;
           break;
       } // end WM_TIMER

       default:
            handled = kODFalse;
            break;
    } // end switch

    } catch(...) {}

    return handled;
}

/******************************************************************
  The following 5 messages belong to the Clock Part's Metaclass.
 ******************************************************************/

SOM_Scope ISOString  SOMLINK M_ClockclsGetODPartHandlerName(M_Clock *somSelf,
                                                                  Environment *ev)
{
    /* M_ClockData *somThis = M_ClockGetData(somSelf); */
    M_ClockMethodDebug("M_Clock","M_ClockclsGetODPartHandlerName");

    string handlerName = (string)SOMMalloc(strlen(kClockPartHandlerName)+1);
    strcpy(handlerName,kClockPartHandlerName);

    return (ISOString) handlerName;
}


SOM_Scope string  SOMLINK M_ClockclsGetODPartHandlerDisplayName(M_Clock *somSelf,
                                                                      Environment *ev)
{
    /* M_ClockData *somThis = M_ClockGetData(somSelf); */
    M_ClockMethodDebug("M_Clock","M_ClockclsGetODPartHandlerDisplayName");

    string displayName = (string)SOMMalloc(strlen(kClockPartHandlerDisplayName)+1);
    strcpy(displayName,kClockPartHandlerDisplayName);

    return displayName;

}

SOM_Scope _IDL_SEQUENCE_PartKindInfo  SOMLINK M_ClockclsGetODPartKinds(M_Clock *somSelf,
                                                                             Environment *ev)
{
    /* M_ClockData *somThis = M_ClockGetData(somSelf); */
    M_ClockMethodDebug("M_Clock","M_ClockclsGetODPartKinds");

    _IDL_SEQUENCE_PartKindInfo ClockInfo;
    // Create structure PartKindInfo  and allocate memory for variable
    PartKindInfo * info = (PartKindInfo *)SOMMalloc(sizeof(PartKindInfo));
    info->partKindName = (ISOString) SOMMalloc(strlen(kClockKind) + 1);
    info->partKindDisplayName = (string)SOMMalloc(strlen(kClockKindDisplayName)+1);
    info->filenameFilters =  (string)SOMMalloc(strlen("")+1);
    info->filenameTypes =  (string)SOMMalloc(strlen("")+1);
    info->categories =  (string)SOMMalloc(strlen(kClockCategory) + 1);
    info->categoryDisplayName =  (string)SOMMalloc(strlen("Sample") + 1);
    info->objectID =  (string)SOMMalloc(strlen("") + 1);
    // Copy the information into the structure
    strcpy(info->partKindName , kClockKind);
    strcpy(info->partKindDisplayName, kClockKindDisplayName);
    strcpy(info->filenameFilters, "");
    strcpy(info->filenameTypes, "");
    strcpy(info->categories, kClockCategory);
    strcpy(info->categoryDisplayName, "Sample");
    strcpy(info->objectID, "");


    ClockInfo._maximum = 1;
    ClockInfo._length = 1;
    ClockInfo._buffer = info;

    return ClockInfo;



}

SOM_Scope string  SOMLINK M_ClockclsGetOLE2ClassId(M_Clock *somSelf,
                                                         Environment *ev)
{
    /* M_ClockData *somThis = M_ClockGetData(somSelf); */
    M_ClockMethodDebug("M_Clock","M_ClockclsGetOLE2ClassId");

    // OLE2 Class ID is determined by running the tool UUIDGEN.EXE
    // or GUIDGEN.EXE found in the IBM VAC++ SDK\BIN directory
    // this tool is guaranteed to generate a unique ID based on your
    // network address and the time of day (DCE Standard)


    string classID = "{f135e430-de1a-11cf-9937-08005a88688b}";
    string OLE2ClassId = (string)SOMMalloc(strlen(classID)+1);
    strcpy(OLE2ClassId,classID);

    return classID;
}

SOM_Scope string  SOMLINK M_ClockclsGetWindowsIconFileName(M_Clock *somSelf,
                                                                 Environment *ev)
{
    /* M_ClockData *somThis = M_ClockGetData(somSelf); */
    M_ClockMethodDebug("M_Clock","M_ClockclsGetWindowsIconFileName");

    string fileName = (string) SOMMalloc (strlen(kClockIconFileName)+1);
    strcpy(fileName,kClockIconFileName);
    return fileName;
}




