/*  Project Tec3270

	 SUBSYSTEM:    Tec3270.exe (Tec3270 application)
	 FILE:         alffprev.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:

    ALFFLayoutWindow and ALFFPreviewWindow Classes Implementation,
    the Tec3270 printing preview function specific classes.

    COPYRIGHT:    © 1998-2007
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Tec3270_License (docs/Tec3270_License.txt)
*/


#include "alffnall.h"
//{{ALFFLayoutWindow Implementation}}
//{{ALFFLayoutWindowRSP_TBL_BEGIN}}
DEFINE_RESPONSE_TABLE1(ALFFLayoutWindow, TLayoutWindow)
	 EV_WM_KEYDOWN,
//{{ALFFLayoutWindow_TBL_END}}
END_RESPONSE_TABLE;

//Constructor
ALFFLayoutWindow::ALFFLayoutWindow (TWindow* parent,
												const char far *title,
												TModule* module):
												TLayoutWindow(parent,title,module)
{
 hBar = vBar = false;
 previewWindow = NULL;
}

//Destructor
ALFFLayoutWindow::~ALFFLayoutWindow()
{
}

void
ALFFLayoutWindow::SetPreviewWindow(TWindow* prevW)
{
 if (prevW)
  previewWindow = prevW;
}

void
ALFFLayoutWindow::ShowScrollBar(int bar, bool show)
{
 switch (bar)
  {
	case SB_HORZ:  if (show)
						  hBar = true;
						 else hBar = false;
						 break;
	case SB_VERT:  if (show)
						  vBar = true;
						 else vBar = false;
						 break;
	case SB_BOTH:  if (show)
						 {
						  hBar = true;
						  vBar = true;
						 }
						 else
						 {
						  hBar = false;
						  vBar = false;
						 }
						 break;
	default:        return;
  }
 TLayoutWindow::ShowScrollBar(bar,show);
}

void
ALFFLayoutWindow::EvKeyDown(UINT key,UINT,UINT)
{
 switch (key)
  {
	case   VK_NEXT:  if (previewWindow)
							{
							  ALFFPreviewWindow* prevWin =
								 TYPESAFE_DOWNCAST(previewWindow, ALFFPreviewWindow);
							  prevWin->PPR_Next();
							}
						  break;
	case  VK_PRIOR:  if (previewWindow)
							{
							  ALFFPreviewWindow* prevWin =
								 TYPESAFE_DOWNCAST(previewWindow, ALFFPreviewWindow);
							  prevWin->PPR_Previous();
							}
						  break;
	case  VK_RIGHT:  if (hBar)
							Scroller->ScrollBy(10,0);
						  break;
	case   VK_LEFT:  if (hBar)
							Scroller->ScrollBy(-10,0);
						  break;
	case   VK_DOWN:  if (vBar)
							Scroller->ScrollBy(0,10);
						  break;
	case     VK_UP:  if (vBar)
							Scroller->ScrollBy(0,-10);
						  break;
  }
}


//{{ALFFPreviewWindow Implementation}}
//{{ALFFPreviewWindowRSP_TBL_BEGIN}}
DEFINE_RESPONSE_TABLE1(ALFFPreviewWindow, TDecoratedFrame)
	 EV_COMMAND(CM_ALFF_PPR_ZOOM, PPR_Zoom),
	 EV_COMMAND(CM_ALFF_PPR_PREVIOUS, PPR_Previous),
	 EV_COMMAND(CM_ALFF_PPR_NEXT, PPR_Next),
	 EV_COMMAND(CM_ALFF_PPR_ONEUP, PPR_OneUp),
	 EV_COMMAND(CM_ALFF_PPR_TWOUP, PPR_TwoUp),
	 EV_COMMAND(CM_ALFF_PPR_DONE, PPR_Done),
	 EV_COMMAND(CM_ALFFPRINT, CmPrint),
	 EV_COMMAND_ENABLE(CM_ALFF_PPR_ONEUP, PPR_OneUpEnable),
	 EV_COMMAND_ENABLE(CM_ALFF_PPR_TWOUP, PPR_TwoUpEnable),
	 EV_COMMAND_ENABLE(CM_ALFFPRINT, CmPrintEnable),
	 EV_COMMAND_ENABLE(CM_ALFF_PPR_PREVIOUS, PPR_PreviousEnable),
	 EV_COMMAND_ENABLE(CM_ALFF_PPR_NEXT, PPR_NextEnable),
//{{ALFFPreviewWindowRSP_TBL_END}}
END_RESPONSE_TABLE;

ALFFPreviewWindow::ALFFPreviewWindow
					 (TWindow *parentWindow,
					  ALFFPrinter *printer,
					  TWindow* currWindow,
					  ALFFPrtData* prtDta,
					  const char far* title,
					  ALFFLayoutWindow* client) :
					  TDecoratedFrame(parentWindow, title, client, true)
{
	 CurrWindow = currWindow;
	 prtData  = prtDta;
	 Printer = printer;
	 Client = client;
	 Client->Attr.Style |= DS_3DLOOK | WS_VSCROLL | WS_HSCROLL;
	 Page1 = 0;
	 Page2 = 0;
	 pMsgs = new ALFFMsgs(this);

	 TPrintDialog::TData& data = Printer->GetSetup();
	 try
	  {
		PrnDC = new TPrintDC(data.GetDriverName(),
									data.GetDeviceName(),
									data.GetOutputName(),
									data.GetDevMode());
	  }
	 catch (TGdiBase::TXGdi)
	  {
		/*
		 *  If Invalid Printer - force user to set other up:
		 *  Bring up the Print Setup dialog.
		 */
		printer->Setup(parentWindow);
		return;
	  }

	 /* Match the Preview WIndow to the Printer Paper Size */
	 PrintExtent = new TSize(PrnDC->GetDeviceCaps(HORZRES),
									 PrnDC->GetDeviceCaps(VERTRES));

	 /* Create the Printout Object  */
    Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
	 Printout = new ALFFPrintOut(Printer,
                                theApp->printerBuf,
                                "Print Preview",
										  CurrWindow,
										  prtData,
                                NULL,   //connData not available here
                                        // (this is done out of session level)
                                        // (used to preview printed screens)
										  true);

	 /* Set the workspace background color */
	 SetBkgndColor(::GetSysColor(COLOR_APPWORKSPACE));

	 /* Set the Layout Client Scroller object with correct units and ranges */
	 const int xUnit = 10;
	 const int yUnit = 10;
	 const int xRange = GetSystemMetrics(SM_CXFULLSCREEN)/xUnit;
	 const int yRange = GetSystemMetrics(SM_CYFULLSCREEN)/yUnit;
	 Client->Scroller = new TScroller(Client,xUnit,yUnit,xRange,yRange);

	 /* Create default toolbar New and associate toolbar buttons with commands.*/
	 char rcBuffer[STRINGMSGLEN+1];
	 PreviewSpeedBar = new TControlBar(this);
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_PREVIOUS, CM_ALFF_PPR_PREVIOUS, TButtonGadget::Command, true));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_NEXT, CM_ALFF_PPR_NEXT, TButtonGadget::Command, true));
	 PreviewSpeedBar->Insert(*new TSeparatorGadget(6));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_ONEUP, CM_ALFF_PPR_ONEUP, TButtonGadget::Exclusive, true, TButtonGadget::Down));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_TWOUP, CM_ALFF_PPR_TWOUP, TButtonGadget::Exclusive, true));
	 PreviewSpeedBar->Insert(*new TSeparatorGadget(12));

	 pMsgs->LoadString(IDS_ALFFPRTPREVPAGE,rcBuffer,STRINGMSGLEN);
	 char    buffer[32];
	 wsprintf(buffer, rcBuffer, 1);
	 PreviewSpeedBar->Insert(*new TTextGadget(CM_ALFF_PPR_CURRPAGE, TGadget::Recessed, TTextGadget::Left, 10, buffer));
	 PreviewSpeedBar->Insert(*new TSeparatorGadget(20));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFFPRINT, CM_ALFFPRINT, TButtonGadget::Command, true));
	 PreviewSpeedBar->Insert(*new TSeparatorGadget(20));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_ZOOM, CM_ALFF_PPR_ZOOM, TButtonGadget::Command, true));
	 PreviewSpeedBar->Insert(*new TSeparatorGadget(20));
	 PreviewSpeedBar->Insert(*new TButtonGadget(CM_ALFF_PPR_DONE, CM_ALFF_PPR_DONE, TButtonGadget::Command, true));
	 Insert(*PreviewSpeedBar, TDecoratedFrame::Top);

	 /* Add fly-over help hints. */
	 PreviewSpeedBar->SetHintMode(TGadgetWindow::EnterHints);


	 /* Create and Insert Status Bar to Get Command Hints */
	 TStatusBar *sb = new TStatusBar(this, TGadget::Recessed);
	 Insert(*sb, TDecoratedFrame::Bottom);

	 /* We want a window that cannot be sized, maximized, or minimized.*/
	 Attr.Style = (WS_VISIBLE | WS_POPUP | WS_DLGFRAME | DS_3DLOOK);

	 /* Don't show the border of the preview window. */
	 Attr.X = 0;
	 Attr.Y = -1;
	 Attr.W = Parent->GetClientRect().Width();
	 Attr.H = Parent->GetClientRect().Height() + 1;

	 /* Make Window be Over MDI workspace to prevent any other operation */
	 parentWindow->MapWindowPoints(HWindow, (TPoint *)&(Attr.X), 1);

	 zoom = false;
}


ALFFPreviewWindow::~ALFFPreviewWindow ()
{
    if (Page1)
	   delete Page1;
	 if (Page2)
	   delete Page2;

	 if (PrnDC)
     delete PrnDC;

    delete PreviewSpeedBar;
	 delete PrintExtent;
	 delete Printout;
	 delete pMsgs;
}


void
ALFFPreviewWindow::SetupWindow ()
{
	 TDecoratedFrame::SetupWindow();

    //Assure that printerBuffer is correctly paginated
    Printout->Paginate();

	 Client->SetBkgndColor(TColor(GetSysColor(COLOR_APPWORKSPACE)));

	 Page1 = new TPreviewPage(Client, *Printout, *PrnDC, *PrintExtent, 1);
	 Page1->SetPageNumber(1);
	 //Page1->Attr.Style = (WS_VISIBLE | WS_CHILD | WS_DLGFRAME | DS_3DLOOK);
	 prtData->FromPage = prtData->MinPage;
	 prtData->ToPage   = prtData->MinPage;

	 Page2 = 0;

	 TLayoutMetrics metrics1;
	 metrics1.X.Set(lmLeft, lmRightOf, lmParent, lmLeft, 5); // era 15
	 metrics1.Y.Set(lmTop, lmBelow, lmParent, lmTop, 5);

	 /*
	  * Determine major axis of preview page, have that follow
	  * parent size. Make minor axis a percentage (aspect ratio)
	  * of the page's major axis
	  */
    /*------------------------LIXO - LIXO - LIXO -------------------------------
	 TRect r = Client->GetClientRect();
	 long ratio;

	 if (PrintExtent->cx > PrintExtent->cy)
		ratio = ((long)PrintExtent->cy * 100) / PrintExtent->cx;
	  else
		ratio = ((long)PrintExtent->cx * 100) / PrintExtent->cy;

	 BOOL xMajor = (((r.Width()*ratio) / 100) > r.Height());

	 if (xMajor)
	  {
		metrics1.Height.Set(lmBottom, lmAbove, lmParent, lmBottom, 15);
		metrics1.Width.PercentOf(Page1,
			(int)((long)PrintExtent->cx * 95 / PrintExtent->cy), lmHeight);
	  }
	  else
	  {
		metrics1.Width.Set(lmRight, lmLeftOf, lmParent, lmRight, 15);
		metrics1.Height.PercentOf(Page1,
			(int)((long)PrintExtent->cy * 95 / PrintExtent->cx), lmWidth);
	  }
     ------------------------LIXO - LIXO - LIXO -------------------------------*/

    if (PrintExtent->cx > PrintExtent->cy)
     {
      metrics1.Width.
               Set(lmRight, lmPercentOf, lmParent, lmRight, 95);
      metrics1.Height.
              PercentOf(Page1,(int)((long)PrintExtent->cy * 100 / PrintExtent->cx), lmWidth);
     }
    else
     {
      metrics1.Height.
               Set(lmBottom, lmPercentOf, lmParent, lmBottom, 95);
      metrics1.Width.
              PercentOf(Page1,(int)((long)PrintExtent->cx * 100 / PrintExtent->cy), lmHeight);
     }

	 Page1->Create();

	 Client->SetPreviewWindow(this);
	 Client->ShowScrollBar(SB_BOTH,false);
	 Client->SetChildLayoutMetrics(*Page1, metrics1);
	 Client->Layout();
}

void
ALFFPreviewWindow::PPR_Zoom()
{
 TLayoutMetrics metrics1;
 if (zoom)
  {
	 metrics1.X.Set(lmLeft, lmRightOf, lmParent, lmLeft, 5);
	 metrics1.Y.Set(lmTop, lmBelow, lmParent, lmTop, 5);

	 /*
	  * Determine major axis of preview page, have that follow
	  * parent size. Make minor axis a percentage (aspect ratio)
	  * of the page's major axis
	  */

    /*------------------------LIXO - LIXO - LIXO -------------------------------
	 TRect r = Client->GetClientRect();
	 long ratio;

	 if (PrintExtent->cx > PrintExtent->cy)
		ratio = ((long)PrintExtent->cy * 100) / PrintExtent->cx;
	  else
		ratio = ((long)PrintExtent->cx * 100) / PrintExtent->cy;

	 BOOL xMajor = (((r.Width() * ratio) / 100) > r.Height());

	 if (xMajor)
	  {
		metrics1.Height.Set(lmBottom, lmAbove, lmParent, lmBottom, 15);
		metrics1.Width.PercentOf(Page1,
			(int)((long)PrintExtent->cx * 95 / PrintExtent->cy), lmHeight);
	  }
	  else
	  {
		metrics1.Width.Set(lmRight, lmLeftOf, lmParent, lmRight, 15);
		metrics1.Height.PercentOf(Page1,
			(int)((long)PrintExtent->cy * 95 / PrintExtent->cx), lmWidth);
	  }
     ------------------------LIXO - LIXO - LIXO -------------------------------*/


    if (PrintExtent->cx > PrintExtent->cy)
     {
      metrics1.Width.
               Set(lmRight, lmPercentOf, lmParent, lmRight, 95);
      metrics1.Height.
              PercentOf(Page1,(int)((long)PrintExtent->cy * 100 / PrintExtent->cx), lmWidth);
     }
    else
     {
      metrics1.Height.
               Set(lmBottom, lmPercentOf, lmParent, lmBottom, 95);
      metrics1.Width.
              PercentOf(Page1,(int)((long)PrintExtent->cx * 100 / PrintExtent->cy), lmHeight);
     }
	 Client->ShowScrollBar(SB_BOTH,false);
	 Client->SetChildLayoutMetrics(*Page1, metrics1);
	 Client->Layout();

	 //if (Page2)
		//Page2->Show(SW_NORMAL);

	 zoom = false;
  }
  else
  {
	 Client->ShowScrollBar(SB_BOTH,true);

	 long cWidth = Client->GetClientRect().Width();
	 long p1Width = Page1->GetClientRect().Width();
	 long p1WidthToClient = cWidth*80/p1Width;  // era 116

	 TRect rPage1 = Page1->GetClientRect();
	 rPage1.left = 10;
	 rPage1.top  = 10;
	 rPage1.right = (int)(((long)rPage1.right*p1WidthToClient)/100);
	 rPage1.bottom = (int)(((long)rPage1.bottom*p1WidthToClient)/100);

	 Page1->MoveWindow(rPage1,true);

	 /* Set Scroller Range and Unit Values */

	 TRect rect = Client->GetClientRect();

	 /* Calculate and Set Scroll X-Y Units    */
	 long xRange = 100;
	 long yRange = 100;
	 Client->Scroller->SetRange(xRange, yRange);

	 /* Calculate and Set Scroll X-Y Units    */
	 int xUnit  = ((rPage1.Width()/2)+rPage1.left)/(int)xRange;
	 int yUnit  = (rPage1.Height()+rPage1.top)/(int)yRange;
	 Client->Scroller->SetUnits(xUnit,yUnit);


	 if (Page2)
	 {
		Client->RemoveChildLayoutMetrics(*Page2);
		delete Page2;
		Page2 = 0;
		prtData->ToPage = prtData->FromPage;
		SpeedBarState();
	 }
	 zoom = true;
  }
}


void
ALFFPreviewWindow::SpeedBarState ()
{
	 char rcBuffer[STRINGMSGLEN+1];
	 // Update the page count.
	 TTextGadget *theTGadget =
	  TYPESAFE_DOWNCAST(PreviewSpeedBar->GadgetWithId(CM_ALFF_PPR_CURRPAGE), TTextGadget);
	 TButtonGadget *oneTGadget =
	  TYPESAFE_DOWNCAST(PreviewSpeedBar->GadgetWithId(CM_ALFF_PPR_ONEUP), TButtonGadget);
	 TButtonGadget *twoTGadget =
	  TYPESAFE_DOWNCAST(PreviewSpeedBar->GadgetWithId(CM_ALFF_PPR_TWOUP), TButtonGadget);

	 if (theTGadget)
	  {
		  char    buffer[32];
		  if (Page2 && (prtData->FromPage != prtData->ToPage))
			 {
			  pMsgs->LoadString(IDS_ALFFPRTPREVPAGRANGE,rcBuffer,STRINGMSGLEN);
			  wsprintf(buffer, rcBuffer, prtData->FromPage, prtData->ToPage);
			  oneTGadget->SetButtonState(TButtonGadget::Up);
			 }
		  else
			 {
				pMsgs->LoadString(IDS_ALFFPRTPREVPAGE,rcBuffer,STRINGMSGLEN);
				wsprintf(buffer, rcBuffer, prtData->FromPage);
				twoTGadget->SetButtonState(TButtonGadget::Up);
			 }
		  theTGadget->SetText(buffer);
	  }
}


void
ALFFPreviewWindow::PPR_PreviousEnable (TCommandEnabler &tce)
{
  tce.Enable((prtData->FromPage != 1));
}


void
ALFFPreviewWindow::PPR_NextEnable (TCommandEnabler &tce)
{
  tce.Enable((prtData->ToPage != prtData->MaxPage));
}

void
ALFFPreviewWindow::PPR_Previous ()
{
	 //TPrintDialog::TData &printerData = Printer->GetSetup();
	 if (prtData->FromPage > prtData->MinPage)
	  {
		prtData->FromPage--;
		prtData->ToPage--;

		Page1->SetPageNumber(prtData->FromPage);
		if (Page2)
		  Page2->SetPageNumber(prtData->ToPage);
	  }
	 SpeedBarState();
}


void
ALFFPreviewWindow::PPR_Next ()
{
	 //TPrintDialog::TData &printerData = Printer->GetSetup();
	 if (prtData->ToPage < prtData->MaxPage)
	  {
		prtData->FromPage++;
		prtData->ToPage++;

		Page1->SetPageNumber(prtData->FromPage);
		if (Page2)
		  Page2->SetPageNumber(prtData->ToPage);
	  }
	 SpeedBarState();
}

void
ALFFPreviewWindow::PPR_OneUpEnable (TCommandEnabler &tce)
{
	 // One up is only available when Two is up and we are not in
	 // zoom mode.
	 tce.Enable(!zoom && Page2 );
}

void
ALFFPreviewWindow::PPR_OneUp ()
{
	 if (Page2)
	 {
		  Client->RemoveChildLayoutMetrics(*Page2);
		  delete Page2;
		  Page2 = 0;
		  Client->Layout();
		  prtData->ToPage = prtData->FromPage;
		  SpeedBarState();
	 }
}


void
ALFFPreviewWindow::PPR_TwoUpEnable (TCommandEnabler &tce)
{
	 // Two up is only available for portrait mode.
	 tce.Enable((PrintExtent->cx <= PrintExtent->cy)
					 && !zoom && !Page2
					 && (prtData->MaxPage > prtData->MinPage));
}


void
ALFFPreviewWindow::PPR_TwoUp ()
{
	 if (Page2 == 0)
		{
		  Page2 = new TPreviewPage(Client, *Printout, *PrnDC, *PrintExtent, PageNumber + 1);
		  //Page2->Attr.Style = (WS_VISIBLE|WS_CHILD|WS_DLGFRAME |DS_3DLOOK);
		  Page2->Create();

		  TLayoutMetrics metrics2;
		  metrics2.X.Set(lmRight, lmPercentOf, lmParent, lmRight, 95);
		  metrics2.Y.SameAs(Page1, lmTop);

		  // Assume portrait
		  //
		  metrics2.Width.SameAs(Page1, lmWidth);
		  metrics2.Height.SameAs(Page1, lmBottom);

		  Client->SetChildLayoutMetrics(*Page2, metrics2);
		  Client->Layout();

		  //TPrintDialog::TData &printerData = Printer->GetSetup();

		  // Page 2 is the next page.  If the next page is outside of our
		  // range then set the first page back one and the 2nd page is
		  // the current page.  If the document is only 1 page long then
		  // the 2nd page is empty.
		  if (prtData->FromPage == prtData->MaxPage)
		   {
			 if (prtData->FromPage > 1)
			  {
			 	 prtData->FromPage--;
			 	 prtData->ToPage = prtData->FromPage + 1;
			 	 Page1->SetPageNumber(prtData->FromPage);
			 	 Page2->SetPageNumber(prtData->ToPage);
			  }
			 else	 Page2->SetPageNumber(0);
		   }
		  else
		   {
			 prtData->ToPage = prtData->FromPage + 1;
			 Page2->SetPageNumber(prtData->ToPage);
		   }

		  SpeedBarState();
		}
}

void
ALFFPreviewWindow::PPR_Done ()
{
	 // Don't call the base class EvClose we do not want ALFFPreviewWindow to be destructed.
	 GetApplication()->EndModal(IDCANCEL);
}


void
ALFFPreviewWindow::CmPrint ()
{
	 int fromPage = prtData->FromPage;
	 int toPage   = prtData->ToPage;
	 TWindow *client = GetApplication()->GetMainWindow()->GetClientWindow();
	 if (client)
		  client->SendMessage(WM_COMMAND, CM_ALFFPRINT, 0);
	 Printout->Paginate();
	 prtData->FromPage = fromPage;
	 prtData->ToPage = toPage;
	 Page1->SetPageNumber(prtData->FromPage);
	 if (Page2)
		Page2->SetPageNumber(prtData->ToPage);
}


void
ALFFPreviewWindow::CmPrintEnable (TCommandEnabler &tce)
{
	tce.Enable(true);
}
