//===============================================================
// vCanvasPaneDC - a basic canvas for drawing
//
// Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
//
// This file is part of the V C++ GUI Framework, and is covered
// under the terms of the GNU Library General Public License,
// Version 2. This library has NO WARRANTY. See the source file
// vapp.cxx for more complete information about license terms.
//===============================================================

#include <v/vos2.h>		// for OS/2 stuff
extern "C"
{
  #include <math.h>
}
#include <v/vcpdc.h>
#include <v/vapp.h>		// need access to the app
#include <v/vcanvas.h>		// our own canvas widget

//================>>> vCanvasPaneDC::vCanvasPaneDC <<<========================
  vCanvasPaneDC::vCanvasPaneDC(vCanvasPane* parentPane) : vWinDC()
  {
    SysDebug(Constructor,"vCanvasPaneDC::vCanvasPaneDC() constructor\n")
    _parentPane = parentPane;
    _drawWidget = _parentPane->DrawingWindow();	// client window handle

    // this is the contructor for the presentation space.  The first
    // thing to do is to create and associate the PS, then set the
    // defaults as needed.
    GetHDC();

    // set the PS to RGB mode
    GpiCreateLogColorTable(_hdc, 0L, LCOLF_RGB, 0L, 0L, NULL);

    // set model space transform to put origin at upper left corner
    // since OS/2 puts the origin in the bottom left by default
    // V to OS/2 Coord Transform Equations:
    //
    // (os/2)  y = -(1 - height + y)  (V)
    //
    // for inclusive/inclusive (ie. Gpi*)
    //         y = -(yBottom - yTop + y)
    //  where  height = yTop - yBottom + 1
    //
    // for inclusive/exclusive (ie. Win*)
    //         y = -(1 + yBottom - yTop + y)
    //  where    height = yTop - yBottom
/*
    MATRIXLF TransformMatrix;
    POINTL translate, origin;
    FIXED scale[2];
    translate.x = 0;
    translate.y = 1 -_parentPane->GetHeight();
    GpiTranslate(_hdc, &TransformMatrix, TRANSFORM_REPLACE, &translate);
    origin.x = 0; origin.y = 0;
    scale[0] = MAKEFIXED( 1,0);   // x scale
    scale[1] = MAKEFIXED(-1,0);   // y scale
    GpiScale(_hdc, &TransformMatrix, TRANSFORM_ADD, scale, &origin);
    GpiSetModelTransformMatrix(_hdc, 9, &TransformMatrix, TRANSFORM_REPLACE);
*/
    // display is never scaled so set scaling to unity
    SetOS2Map(_parentPane->GetHeight(), MAKEFIXED(1,0));
  }

//================>>> vCanvasPaneDC::~vCanvasPaneDC <<<========================
  vCanvasPaneDC::~vCanvasPaneDC()
  {
    SysDebug(Destructor,"vCanvasPaneDC::~vCanvasPaneDC() destructor\n")
    // disassociate PS from window, then  destroy PS
    ReleaseHDC();
  }

//================>>> vCanvasPaneDC::GetHDC <<<========================
  void vCanvasPaneDC::GetHDC(void)
  {
    _devCtxt = WinQueryWindowDC(_drawWidget);  // the client window handle
    if (_devCtxt == NULLHANDLE)
      _devCtxt = WinOpenWindowDC(_drawWidget);
    if (_hdc == 0)
    {
      // Create a normal presentation space and associate with window
      _pageSize.cx = 0L;   // using PELS so default pagesize is okay
      _pageSize.cy = 0L;
      _hdc = GpiCreatePS(theApp->AppHab(), _devCtxt, &_pageSize,
        PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC );
      SysDebug1(Build,"vCanvasPaneDC::GetHDC() _hdc=%u\n", _hdc);
    }
  }

//================>>> vCanvasPaneDC::ReleaseHDC <<<========================
  void vCanvasPaneDC::ReleaseHDC(void)
  {
    SysDebug(Build,"vCanvasPaneDC::ReleaseHDC() entry point\n");
    if (_hdc != 0)
    {
      GpiAssociate(_hdc, NULLHANDLE);
      GpiDestroyPS(_hdc);
      _hdc = 0;
    }
  }

//=====================>>> vCanvasPaneDC::Clear <<<==========================
  void vCanvasPaneDC::Clear(void)
  {
    RECTL rc;
    BeginPaint();
    // CAUTION: returned coords are inclusive/exclusive
    WinQueryWindowRect(_drawWidget, &rc);
    WinFillRect (_hdc, &rc, _canvasBG);

    // update the transformation in case the size of the
    // canvas has been changed.

    // V to OS/2 Coord Transform Equations:
    // (os/2)  y = -(1 - height + y)  (V)
    //
    // for inclusive/inclusive (ie. Gpi)
    //         y = -(yBottom - yTop + y)
    //  where  height = yTop - yBottom + 1
    //
    // for inclusive/exclusive (ie. Win)
    //         y = -(1 + yBottom - yTop + y)
    //  where    height = yTop - yBottom

/*
    MATRIXLF TransformMatrix;
    POINTL translate, origin;
    FIXED scale[2];
    translate.x = 0;
    translate.y = 1 + rc.yBottom - rc.yTop;
    GpiTranslate(_hdc, &TransformMatrix, TRANSFORM_REPLACE, &translate);
    origin.x = 0; origin.y = 0;
    scale[0] = MAKEFIXED( 1,0);   // x scale
    scale[1] = MAKEFIXED(-1,0);   // y scale
    GpiScale(_hdc, &TransformMatrix, TRANSFORM_ADD, scale, &origin);
    GpiSetModelTransformMatrix(_hdc, 9, &TransformMatrix, TRANSFORM_REPLACE);
*/
    // display is never scaled so set scaling to unity
    SetOS2Map(rc.yTop - rc.yBottom, MAKEFIXED(1,0));

    EndPaint();
  }

//==================>>> vCanvasPaneDC::ClearRect <<<==========================
// note: coords are in V space
  void vCanvasPaneDC::ClearRect(int x, int y, int width, int height)
  {
    SysDebug2(WindowEvents,"vCanvasPaneDC::ClearRect() w=%d h=%d \n", width, height)

    if (height == 0 || width == 0)
	return;

    BeginPaint();
    // update the transformation in case the size of the
    // canvas has been changed. This ensures that all GPI
    // calls in V coords will map to the right place in OS/2
    RECTL rc;
    // CAUTION: returned rc coords are inclusive/exclusive
    WinQueryWindowRect(_drawWidget, &rc);

    // V to OS/2 Coord Transform Equations:
    // (os/2)  y = -(1 - height + y)  (V)
    //
    // for inclusive/inclusive (ie. Gpi)
    //         y = -(yBottom - yTop + y)
    //  where  height = yTop - yBottom + 1
    //
    // for inclusive/exclusive (ie. Win)
    //         y = -(1 + yBottom - yTop + y)
    //  where    height = yTop - yBottom
/*
    MATRIXLF TransformMatrix;
    POINTL translate, origin;
    FIXED scale[2];
    translate.x = 0;
    translate.y = 1 + rc.yBottom - rc.yTop;
    GpiTranslate(_hdc, &TransformMatrix, TRANSFORM_REPLACE, &translate);
    origin.x = 0; origin.y = 0;
    scale[0] = MAKEFIXED( 1,0);   // x scale
    scale[1] = MAKEFIXED(-1,0);   // y scale
    GpiScale(_hdc, &TransformMatrix, TRANSFORM_ADD, scale, &origin);
    GpiSetModelTransformMatrix(_hdc, 9, &TransformMatrix, TRANSFORM_REPLACE);
*/
    // display is never scaled so set scaling to unity
    SetOS2Map(rc.yTop - rc.yBottom, MAKEFIXED(1,0));

    // Clear a rectangular area starting at x, y of width and height
    // the function inputs are assumed in V coords space
    int h = rc.yTop - rc.yBottom;  // h>0
    y = h - 1 - y;   // transform y to OS/2 coords

    // calc coords as inclusive/exclusive
    rc.yTop = y + 1;           // exclusive coord
    rc.yBottom = y - height;   // inclusive coord
    rc.xLeft = x;              // inclusive coord
    rc.xRight = x + width;     // exclusive coord

    // coords are inclusive/exclusive
    WinFillRect (_hdc, &rc, _canvasBG);
    EndPaint();
  }

//================>>> vCanvasPaneDC::SetBackground <<<==========================
  void vCanvasPaneDC::SetBackground(VCONST vColor& color)
  {
    BeginPaint();
    _canvasBG = color.pixel();		// retrieve X pixel value
    GpiSetBackColor (_hdc, _canvasBG);
    Clear();
    _parentPane->Redraw(0,0,0,0);
    EndPaint();
  }

//======================>>> vCanvasPaneDC::SetFont <<<===========================
  void vCanvasPaneDC::SetFont(VCONST vFont& vf)
  {
    // Change the font associated with this window.
    _font = vf;
    // First, make sure the font is loaded
    _parentPane->FontChanged(_font); // We have changed the font,
					// so we may need to do some things
  }
