/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

// File SuperPage.CC
// Gilberto Camara and Fernando Ii - ECMWF Mar 97

#ifndef NOMETVIEW_QT
#include "uPlotBase.h"
#endif

#include "SuperPage.h"

#include <Assertions.hpp>
#include "MacroVisitor.h"
#include "MvApplication.h"
#include "MvScanFileType.h"
#include "ObjectList.h"
#include "Page.h"
#include "PlotMod.h"
#include "PmContext.h"

int SuperPage::nrSuperPages_ = 0;

#ifndef NOMETVIEW_QT
uPlotBase* SuperPage::plotApplication_=0;
#endif

SuperPage::SuperPage    ( const MvRequest& superpageRequest ):
	Presentable     ( superpageRequest   ),
	iconDataBase_   ( new MvIconDataBase ),
	preferences_    ( *this              ),
	pageIndex_      ( 1                  ),
	superPageIndex_ ( 1                  ),
	printIndex_     ( 0                  )

{
   // bool calledFromMacro = ObjectInfo::CalledFromMacro(superpageRequest);
   // Retrieve the subrequest describing the Pages
   MvRequest pagesRequest = superpageRequest.getSubrequest ( PAGES );

   // Check if the request is a PAGE request
   // If it does not exist, create one PAGE request
   Cached pageVerb = pagesRequest.getVerb();
   if ( pageVerb != PLOTPAGE )
       pagesRequest = ObjectList::CreateDefaultRequest ( "PLOT_PAGE" );

   // Rewind the request
   pagesRequest.rewind();

   // Loop through the request, create new Pages
   // and insert them as children of the superpage
   while ( pagesRequest )
   {
      // Extract the page request
      MvRequest newpageRequest = pagesRequest.justOneRequest();

      // Create a new page
      //Presentable* page = new Page ( newpageRequest );
      Page* page = new Page ( newpageRequest );
      ensure ( page != 0 );

      // Insert the page in the superpage's child list
      this->InsertOnePage ( page );

      // Goto the next page request
      pagesRequest.advance();
   }

   // Store my size
   double width  = superpageRequest ( "CUSTOM_WIDTH" );
   double height = superpageRequest ( "CUSTOM_HEIGHT" );
   if ( width <= 0 || height <= 0 )
   {
       // default A4 landscape
       width = 29.7;
       height = 21.0;
   }
   size_ = PaperSize ( width, height );

   // Create and store the device information
   this->SetDeviceInfo ( superpageRequest );

#ifndef NOMETVIEW_QT
   // Save information in uPlot
   if (PlotMod::Instance().IsWindow() && plotApplication_)
   plotApplication_->setPresentable(*this);
#endif

   nrSuperPages_++;
   // The purpose of this is to keep PlotMod alive when called in batch. Macro will die once it gets
   // a reply request from PlotMod, and take other modules down before plotting is finished.
   if ( nrSuperPages_ == 1 && ! PlotMod::Instance().IsInteractive() )
       MvApplication::setKeepAlive(true);
}


SuperPage::SuperPage(const SuperPage &old) :
    Presentable(old),
//  size_(old.size_),
//  macroFileName_(old.macroFileName_),
    preferences_(old.preferences_),
//  macroType_(old.macroType_),
//  zoomPageId_(0),
//  printPreview_(old.printPreview_),
//  contentsActive_(old.contentsActive_),
    pageIndex_(1),
    superPageIndex_(1),
//  paperPageIndex_(1),
//  backDrawEnabled_(old.backDrawEnabled_),
  printIndex_(0)
{
	// Make a new icon db from the old one
	auto_ptr<MvIconDataBase> iconDb( new MvIconDataBase(old.IconDataBase() ) );
	iconDataBase_ = iconDb;

	// Set new owner for preferences
	preferences_.Owner(*this);

	// Member myDevice_ is intentionally not copied
	nrSuperPages_++;

	// Should never kick in, nrSuperPages_ should be at least 2 here.
	if ( nrSuperPages_ == 1 && ! PlotMod::Instance().IsInteractive() )
		MvApplication::setKeepAlive(true);
}

SuperPage::~SuperPage()
{ 
	nrSuperPages_--;

        // If called from macro, we don't need to keep PlotMod artificially alive any more.
	if ( nrSuperPages_ == 0 && ! PlotMod::Instance().IsInteractive() )
	  MvApplication::setKeepAlive(false);
}

// -- METHOD  : Create Reply
//
// -- PURPOSE : Indicate to MetviewUI and to Macro the ids 
//              of the superpage and pages
//
// -- INPUT   : A reply request 
//
// -- OUTPUT  : An updated reply request (which is included 
//              in the Context)
//
// -- OBS     : Please see the PmContext class ( especially
//              the destructor )

void
SuperPage::CreateReply ( MvRequest& replyRequest )
{
	// First, for all its children, include the drop id
	MvChildIterator child = childList_.begin();

	int k = 0;
	while ( child != childList_.end() )
	{
		MvRequest pageReply ( "DROP" );
		pageReply.setValue  ( "DROP_ID", (*child)->Id() );

		//If the superpage  has been called from a Macro,
		//  then it needs to ask Macro to notify when finished.
		if ( PlotMod::Instance().CalledFromMacro () && k++ == 0)
			pageReply ( "_NOTIFY" ) = "NEWPAGE";

		replyRequest += pageReply;
		++child;
	}

// This facility was removed due to backward compatibilities.
// The "count(superpage)" command  should return only the number 
// of pages and not the number of pages plus one (the superpage id).
  // Return drop id for superpage at the end.
//  MvRequest myReply ( "DROP" );
//  myReply.setValue  ( "DROP_ID", Id() );
//  replyRequest = replyRequest + myReply;
}

struct DropFunctor {
	PmContext& context_;
	DropFunctor(PmContext& context) : context_(context) {}

	void operator()(Presentable* p) 
	{
		context_.RewindToAfterDrop(); p->Drop(context_);
	}
};

void
SuperPage::Drop ( PmContext& context )
{
  // Not dropped here, send to children
   if ( !this->DroppedHere () )
   {
      for_each ( childList_.begin(), childList_.end(), DropFunctor(context) );

      return;
   }

  // Icons dropped in the Super Page.
  // Icons not handled here will be send to
  // the children (e.g. dataunit)
   bool vdReplace = true;
   MvRequest dropRequest = context.InRequest();
   MvRequest remainingReq;
   while ( dropRequest )
   {
      // Process Visdefs
      MvRequest request =  dropRequest.justOneRequest();
      Cached verb = request.getVerb();
      if ( ObjectList::IsVisDef ( verb ) == true )
      {
         this->InsertVisDef ( request, vdReplace );
         vdReplace = false;
      }

      // Process Coastlines
      else if ( ObjectList::IsVisDefCoastlines ( verb ) )
         ProcessCoastlines ( request, PlotMod::Instance().CalledFromMacro() );

      // Process other icons
      else
      {
         if ( !this->InsertCommonIcons(request) )
            remainingReq = remainingReq + request;
      }

      dropRequest.advance();
   }

   // Send remaining requests to children
   if ( remainingReq )
   {
      // Update context
      context.Update(remainingReq);

      // Send requests to Page
      for_each ( childList_.begin(), childList_.end(), DropFunctor(context) );
   }
   else
      context.AdvanceToEnd();
}

#if 0
// -- METHOD  : Close
//
// -- PURPOSE : Save and delete a superpage
//
// -- OBS     : This is achieved by sending a request to PlotMod
//              indicating the presentable to be deleted

void
SuperPage::Close()
{
	// Delete all structures and exit
	//command exit(0) should do the job
        Presentable* treeNode = Root::Instance().FindBranch (Id());
          if (treeNode == 0)
          {
                   cout << "SuperPage::Close " << endl;
                   cout << " ** Error - Cannot associate page with DropId" << endl;
                   return;
          }
 
          // delete the tree node and its children
          delete treeNode;
//	  exit(0);

MvRequest closeRequest ("CLOSE");
closeRequest ("DROP_ID") = Id();
MvApplication::callService ( "uPlotBatch", closeRequest, 0 );
}

// -- METHOD  : Save in File
//
// -- PURPOSE : Save the contents of the superpage

void
SuperPage::SaveInFile()
{
	// Don't save if called from a macro

	if ( ObjectInfo::CalledFromMacro ( myRequest_ ) == false )
	{
	}
		// My pages may have changed their views

// SuperPage shouldn't save the views associated to the pages, 
// unless the users ask explicitly for that. A tool for that 
// should be built.
// It will make sense only when the view associated to the page 
// can be replaced.
//		this->SaveChildren ();

}
#endif


// -- METHOD :  Name 
//
// -- PURPOSE:  Inform the superpage's name 
//
// -- INPUT  :  (none)
//
// -- OUTPUT :  The name of the superpage
string
SuperPage::Name()
{
	return  (const char*)ObjectInfo::ObjectName ( myRequest_, "SuperPage", Id() );
}

// -- METHOD :   Draw
// 
// -- PURPOSE:   Draws a superpage
//
// -- INPUT  :   (none)
//
// -- OUTPUT : 	 Drawing on window or paper
//	
void
SuperPage::Draw()
{
	HasDrawTask ( true );

	printIndex_ = 0;

	// Draw all my children
	DrawChildren ();

	this->HasDrawTask ( false );
}

void
SuperPage::DrawProlog()
{
     // Call all my children
	MvChildIterator child;
	for ( child = childList_.begin(); child != childList_.end(); ++child )
		(*child)->DrawProlog();
}

void
SuperPage::DrawTrailer( MvRequest& fullReq )
{
   // Nothing to be drawn
   if ( !this->HasDrawTask () )
      return;

   // This was needed to send the driver info to Magics for each newpage.
   // Now, Magics only receive the driver info once (FAMI20150514)
   // Retrieve from the request the Output Device description
   //   fullReq = fullReq + myRequest_("_OUTPUT_DEVICES");

   // Get all requests
   GetAllRequests( fullReq );

   // Reset the draw task
   this->HasDrawTask ( false );
}

void
SuperPage::GetAllRequests( MvRequest& fullReq, bool checkIconStatus )
{
   // Add the superpage request
   MvIcon temp = MvIcon(true);
   MvRequest sp("SUPERPAGE");
   sp( "SUPER_PAGE_X_LENGTH") = size_.GetWidth();
   sp( "SUPER_PAGE_Y_LENGTH") = size_.GetHeight();
   sp( "_ID") = temp.Id();
   sp( "_PRESENTABLE_ID" ) = this->Id();
   fullReq += sp;

   // Get all page requests
   MvChildIterator child;
   for ( child = childList_.begin(); child != childList_.end(); ++child )
      (*child)->DrawTrailer ( fullReq );

   // Take into consideration the icon status
   if ( checkIconStatus )
   {
      MvRequest inReq = fullReq;
      SortRequest( inReq, fullReq );
   }
}

void
SuperPage::SortRequest( MvRequest& in, MvRequest& out, bool save_layer )
{
   // Hold pairs <order,index>, where:
   // order : parameter _STACKING_ORDER
   // index : position of an individual request in the full request
   std::map<float,int> mymap;
   std::map<float,int>::iterator it;

   // Build pairs
   MvIconDataBase& dataBase = this->IconDataBase();
   bool sorted = true;
   int index = 0;
   float order = -1.;
   float delta = 0.001;
   const string slayer("LAYER");
   in.rewind();
   while ( in )
   {
      MvRequest req =  in.justOneRequest();

      // Handle SuperPage and Page requests.
      // They have both parameters _PRESENTABLE_ID and _ID.
      // The _ID should be unique for each icon (MvIcon class generates this value),
      // but in this particular case (Superpage and Page), it contains the value of
      // the Presentable Id. At this moment (20170127), it is not possible to update
      // this code, because Magics is using this information (_ID).
      // Remove this code when Magics starting using _PRESENTABLE_ID and _ID properly.
      if ( (const char*)req("_PRESENTABLE_ID") )
      {
        // Create a new pair
         order = order+delta;
         mymap[order] = index;

         // Next interation
         index++;
         in.advance();
         continue;
      }

      // Skip Layer request
      if ( req.getVerb() == slayer )
      {
         index++;
         in.advance();
         continue;
      }

      // Skip icon if its visibility is off
      if ( !dataBase.IconVisibility(req("_ID")) )
      {
         // Icon not to be drawn, skip it
         index++;
         in.advance();
         sorted = false;

         // If icon is a dataunit then it is followed by a visdef,
         // which needs to be skipped too.
         if ( in && string(in.getVerb()) == "VISDEFS")
         {
            index++;
            in.advance();
         }
         continue;
      }

      // Get stacking order value.
      // If it is not available, e.g. value=-1, then apply a computed value,
      // which should allow this request to retain its position in the stack.
      int stack = dataBase.IconStackingOrder(req("_ID"));
      order = (stack != -1) ? (float)stack : order+delta;

      // Create a new pair
      mymap[order] = index;

      // Next interation
      index++;
      in.advance();

      // If the next icon is a visdef then it does not have the visibility
      // and stacking order tags. So, it needs to be added to the list now.
      if ( in && string(in.getVerb()) == "VISDEFS")
      {
         order += delta;
         mymap[order] = index++;

         in.advance();
      }
   }

   // First check: if there is a need to sort the input request
   if ( sorted )
   {
      // It means that all icons have visibility tag = true,
      // but still needs to check if the stacking order has changed.
      int index1,index2;
      it = mymap.begin();
      index1 = it->second;
      it++;
      while ( it != mymap.end() )
      {
         index2 = it->second;
         if ( index2 < index1 )
         {
            sorted = false;
            break;
         }
         index1 = index2;
         it++;
      }
   }

   // Second check: if there is a need to sort the input request
   if ( sorted )
   {
      // It is already sorted
      // Output request set may contain Layer requests
      in.rewind();
      if ( save_layer )
      {
         out = in;
         return;
      }

      // Output request set should not contain Layer requests
      while ( in )
      {
         if ( in.getVerb() != slayer )
            out += in.justOneRequest();

         in.advance();
      }
      return;
   }

   // Build an output request sorted by the plotting order
   out.clean();
   int i;
   for (it = mymap.begin(); it != mymap.end(); ++it)
   {
      // Position the list of requests to the target one
      in.rewind();
      for ( i = 0; i < it->second; i++ )
         in.advance();

      // Check if the correspondent Layer request needs to be added
      if ( save_layer )
      {
         MvIcon iconLayer;
         if ( dataBase.RetrieveIcon( ICON_LAYER_REL,in("_ID"),iconLayer ) )
            out = out + iconLayer.Request();
      }

      // Add request to the output list
      out = out + in.justOneRequest();
   }
}

#if 0
void
SuperPage::HasReceivedNewpage( bool isLast )
{
        if ( NeedsRedrawing ( ) ) this->Draw ();

//D	if ( this->IsAWindow () ) return;

	if ( isLast )
	{
//D		MvChildIterator child = childList_.begin();
//D		Page* page = (Page*) (*child);			  
//D		page->DrawTrailer ();
		this->DrawTrailer();
		hasNewpage_ = true;
	}
	else
		superPageIndex_ = paperPageIndex_ + 1;
}
#endif

// -- METHOD :  SetDeviceInfo
//
// -- PURPOSE:   Create and initialise the superpage's device
//               (called by the constructor)
// -- INPUT  :   The request which created the superpage
//
// -- OUTPUT :   (none)
//
// -- OBS    :   The device class will implement the "Visitor"
//               pattern, and this method will enable it
//               to "visit" the superpage and its children

void
SuperPage::SetDeviceInfo ( const MvRequest& inRequest )
{
	// The input request contains the necessary information
	// for creating a device driver
	
	// The Create Request method will generate an
	// appropriate device Request
	MvRequest deviceRequest = Device::CreateRequest ( inRequest );

	auto_ptr <Device> dev ( DeviceFactory::Make ( deviceRequest ) );

	myDevice_ = dev;

	// The device is a visitor - this command will trigger
	// its visit (i.e., its traversal through the page hierarchy)
	myDevice_->Initialise( *this );
}

void
SuperPage::SetDeviceInfo ( )
{
//	ensure ( myDevice_ == 0);

	// The device is a visitor - this command will trigger
	// its visit (i.e., its traversal through the page hierarchy)
	myDevice_->Initialise( *this );
}

// --- METHOD : GenerateMacro
// --- PURPOSE: Generate a macro file with the contents of the superpage
//
// --- INPUT  : Name of the macro file the be written
//              Type of the macro (can be:
//                  SCREEN_MACRO - Reproduce the output of the screen
//       	    ZOOM_AREA    - Zoom into a single page
//
// --- OUTPUT : Macro program written (by the class MacroDevice)

void
SuperPage::GenerateMacro( )
{
  // Restart the page index count (used later)
  pageIndex_ = 1;

   // Update the macro type for later use
//	macroType_ = type;

   // Update the macrofile name, if screenmacro, put file in the superpage directory,
   // otherwise put in temporary directory.
   macroFileName_ = MacroVisitor::CreateFileName ( myRequest_ );

   // Generate plotting requests without output formats
   MvRequest plotReq;
   this->DrawProlog();  // clean the main Request
   this->Draw();        // update drawing structure with the latest Contents info
   GetAllRequests( plotReq, true ); // collect all plotting requests

   // Create a new visitor
   auto_ptr <Visitor> vis ( new MacroVisitor ( macroFileName_, plotReq) );

   // Visit me
   vis->Visit (*this);

   // Visit all my children
   Presentable::Visit ( *vis );

   // Post a message on the screen
   string message = "Macro Generated in File " + macroFileName_;
   PlotMod::Instance().UserMessage (message);
}

// -- METHOD :  Visit
//
// -- PURPOSE:  Implement the visitor pattern
//
// -- INPUT  :  visitor (XDevice or PSDevice or MacroVisitor)
//
// -- OUTPUT :  (none)
void
SuperPage::Visit ( Visitor& v )
{ 
	// Visit me
	v.Visit (*this);

	// Visit all my children
	Presentable::Visit ( v );
}

// -- METHOD :  GetMySize
//
// -- PURPOSE:  Return the presentable's size 
//
// -- INPUT  :  (none)
//
// -- OUTPUT :  The size of the superpage window
//              (which is always in paper coordinates)
PaperSize
SuperPage::GetMySize()
{
	return size_;
}

#if 0
// -- METHOD :  SetMySize
//
// -- PURPOSE:  Update the presentable's size 
//
// -- INPUT  :  Dimensions width and height
//
// -- OUTPUT :  (none)

void
SuperPage::SetMySize ( double width, double height )
{
	size_ = PaperSize ( width, height );

	SuperPageWidget* myWidget = (SuperPageWidget*) deviceData_.get();
	myWidget->UpdateSize();
}
#endif

#if 0
// -- METHOD :  IsAWindow
//
// -- PURPOSE:  Determine if the superpage is a window 
//
// -- INPUT  :  (none)
//
// -- OUTPUT :  true/false

bool
SuperPage::IsAWindow ()
{
	MvRequest req = myDevice_->DeviceRequest();

        if ( IsParameterSet(req,"OUTPUT_DEVICES") )
	{
		MvRequest req1 = req("OUTPUT_DEVICES");
                if ( strcmp(req1.getVerb(),"QtDriver") == 0 )
		     return true;
	}

	return false;
}
#endif


#if 0
// -- METHOD: PrintPreview
//
// -- PURPOSE: set printing mode to Preview'

void
SuperPage::PrintPreview()
{
	printPreview_ = true;
}

// -- METHOD: Print
//
// -- PURPOSE: Print the current request.
//			   This is done in three steps:
//             1. Create a temporary ps file by calling SuperPage::PrintJob (see below)
//			   2. Call the following printer command:
//			    	 <$METVIEW_PRINTER_COMMAND> -P<$METVIEW_PRINTER> <temp.ps>
//				  If environment variable $METVIEW_PRINTER_COMMAND is not defined
//				  then uses the lpr command.
//				  If environment variable $METVIEW_PRINTER is not defined
//				  then uses the default lpr printer.
//             3. Delete the temporary ps file
//                

//This is done in five steps:
//             1. Ask the preferences member to establish the
//                user's printer choices
//             2. The "preferences" object will ask GenApp to
//                show an Editor with the Printer Preferences menu
//             3. After GenApp returns, the "preferences" object
//                will call the superpage's method "PrintJob" (see below)
//             4. The SuperPage::PrintJob will duplicate the hierarchy,
//                including all dataunits and visdefs, set device according
//                to given printrequest, and just call DrawProlog, Draw and
//                DrawTrailer to draw the new superpage.
//             5. Printing is finalised from MagicsPicturAction. When the 
//                trailer is received, plotmod generates the postscript file
//                and sends itself a close request. The CloseAction will delete
//                the superpage, and the PSDevice destructor will put the file
//                where it should be ( file,preview, printer).
//                
void
SuperPage::Print()
{
	printPreview_ = false;

	// Create the ps file
	// Get the process number to build the ps temporary file name
	// This file should be deleted in the uPlot destructor
    stringstream sid;
	sid << getpid();
    string psname = sid.str() + "tmpfile.ps";
	string tmpfile = MakeTmpPath(psname.c_str());
	PrintJob(tmpfile);
	
	// Call printer command
	string com;
	const char* prcom = getenv("METVIEW_PRINTER_COMMAND");
	const char* printer = getenv ("METVIEW_PRINTER");
	prcom ? com = prcom : com = "lpr";
	if ( printer )
	{
		com += " -P";
		com += printer;
	}
	com += " " + tmpfile;

//	/opt/kde3/bin/kprinter
	system(com.c_str());
	
	// Send message to the user, if printer command is not defined
	if ( !prcom )
	{
		string message = "Print Job sent to printer: ";
		printer ? message += printer : message += "default";
    	PlotMod::UserMessage ( message );
	}

// Need to move this command to the destructor???
// Maybe it should destroy all the temporary files
// together: rm -f <pid>*
	// Delete the temporary ps file
	string del = "rm -f " + tmpfile;
	system(del.c_str());
}

// -- METHOD: PrintJob
//
// -- PURPOSE: Duplicates SuperPage hierarchy, including all dataunits
//		       and visdefs, set device according to given printrequest,
//			   and just call DrawProlog, Draw and DrawTrailer to draw 
//			   the new superpage.

// Remove this routine
void SuperPage::PrintJob()
{
#if 0 //D It is not need anymore
  MvRequest printReq = preferences_.PrinterRequest();

  MvRequest superpageReq = myRequest_;
  superpageReq("_DRIVER") = printReq;
  superpageReq("_PRINT_OPTION")  = printReq("PRINT_OPTION");

  SuperPage *printSuperPage = new SuperPage(*this);
  Root::Instance().Insert(printSuperPage);
  printSuperPage->DuplicateChildren(*this);

  myRequest_ = superpageReq;
  printSuperPage->SetDeviceInfo(superpageReq);

  printSuperPage->NeedsRedrawing(true);

  printSuperPage->hasNewpage_ = true;  

  // Refresh tag: do not need to rebuild the visualization tree
  printSuperPage->myRequest_("_REFRESH") = "OFF";

  // Draw 
  AddTask( *printSuperPage, &SuperPage::DrawProlog );
  AddTask( *printSuperPage, &SuperPage::Draw );
  AddTask( *printSuperPage, &SuperPage::DrawTrailer );

  TaskBase::Flush();
 
 #endif
 }
 
void SuperPage::PrintJob( string& tmpfile )
{
	// Define postscript driver
	MvRequest subreq("PSDriver");
	subreq("OUTPUT_NAME") = tmpfile.c_str();
	
	// Add postscript driver to the printer manager
	MvRequest printReq("PRINTER_MANAGER");
	printReq("OUTPUT_DEVICES") = subreq;

	// Add printer manager to the request
  	MvRequest superpageReq = myRequest_;
  	superpageReq("_DRIVER") = printReq;
  	superpageReq("_PRINT_OPTION")  = printReq("PRINT_OPTION");

	// Clone the visualized superpage
  	SuperPage *printSuperPage = new SuperPage(*this);
 	Root::Instance().Insert(printSuperPage);
  	printSuperPage->DuplicateChildren(*this);

	// Update variables
  	myRequest_ = superpageReq;
  	printSuperPage->SetDeviceInfo(superpageReq);
 	printSuperPage->NeedsRedrawing(true);
  	printSuperPage->hasNewpage_ = true;  

  	// Refresh tag: do not need to rebuild the visualization tree
 	printSuperPage->myRequest_("_REFRESH") = "OFF";

  	// Draw 
  	printSuperPage->DrawProlog();
  	printSuperPage->Draw();
  	printSuperPage->DrawTrailer();
	
	// Check if it is destroying everything, including
	// removing it from the list of superpages????????????
	// The object has not been destroyed because variable
	// nrSuperPages_ is static and > 1.
	delete printSuperPage;
}

// -- METHOD: PrintingFinished
//   Probably not needed anymore.
// -- PURPOSE: Called by MacroService after the macro has 
//             finished printing to print a message indicating
//             if the job has been completed
//
// -- INPUT:   The reply Request from the Macro Service
//
void
SuperPage::PrintingFinished( MvRequest& replyRequest )
{
	int errCode = replyRequest ( "ERR_CODE" );

	// If we are not in print preview mode, generate a message
	// on the screen

	if ( printPreview_ == false )
	{
		if ( errCode == 0 )
			PlotMod::UserMessage ( "Print Job Finished" );
		else
		{
			PlotMod::SystemError ( (const char*) replyRequest ( "ERROR" ), "Printing" );
		}
	}
}




// -- METHOD:  PostMessage
//
// -- PURPOSE: Put a warning on the screen
//			   (done by the SuperPageWidget)
//
void
SuperPage::PostMessage ( const char* title, const char* message )
{
	// Are we in interactive mode ?
	if ( PlotMod::IsInteractive() == true )
	{
		SuperPageWidget* myWidget = (SuperPageWidget*) deviceData_.get();
		myWidget->PostMessage ( title, message );
	}
}

// -- METHOD:  EditPrinterPreferences
//
// -- PURPOSE: Called by the interface to edit the
//             printer preferences
//
void
SuperPage::EditPrinterPreferences()
{
	preferences_.EditPrinterPreferences();

}

void
SuperPage::EditInterfacePreferences()
{
	preferences_.EditInterfacePreferences();
}

void
SuperPage::SetCursorType ( CursorType option )
{
	preferences_.SetCursorType ( option );
}

void
SuperPage::SetInputType ( InputType option )
{
	preferences_.SetCursorType ( POINTERCURSOR );
	preferences_.SetInputType ( option );
}

#if 0
void
SuperPage::StartMapEditor()
{
	// Call a Request which is sent directly to PlotMod

	MvRequest mapRequest ("EDIT_MAP");

	mapRequest ( "CUSTOM_WIDTH"  ) = size_.GetWidth();
	mapRequest ( "CUSTOM_HEIGHT" ) = size_.GetHeight();

	mapRequest ( "PATH"   ) = ObjectInfo::ObjectPath ( myRequest_ );

	MvApplication::callService ( "uPlot", mapRequest, 0 );	
}	
#endif

void
SuperPage::MouseMode()
{
	cout << "SuperPage::MouseMode" << endl;
}

void
SuperPage::UpdateWidget ( MvRequest& newpageRequest, const int treeNodeId, int& newTreeNodeId)
{
        // Find a sub-branch in the tree hierarchy
	Presentable* oldPage = FindBranch ( treeNodeId );

	// Delete old page
	// ????????? IMPORTANTE ????????????
	// FAMI0698 PLEASE CHECK IF ALL THE DESTRUCTORS HAS BEEN
	// CALLED (THE MEMORY SHOULD BE CLEANED PROPERLY)
	delete oldPage;

	// Create a new page	
	Presentable* page = new Page ( newpageRequest );
	ensure ( page != 0 );
	newTreeNodeId = page->Id();

	// Insert the page in the superpage's child list
	this->InsertOnePage ( page );

	// Create and store the device information
	page->Visit ( *myDevice_ );
}
#endif

// --  METHOD  : MacroPlotIndexName
//
// --  PURPOSE : Provide a sequential index to all pages
//                associated to the superpage
// --  INPUT   : none
//
// --  OUTPUT  : An index into the name returned by plot_superpage.
//
//               Has the side effect of updating member pageIndex_.
//
string
SuperPage::MacroPlotIndexName(bool useIndex)
{
	int index;
  	if ( useIndex)
        index = pageIndex_++;
	else
		index = childList_.size() + 1;

	ostringstream ostr;
	ostr << "dw[" << index << "]";
	return ostr.str();
}

// -- METHOD :  Describe Device
//
// -- PURPOSE:  Generate the device description in macro syntax
//
// -- INPUT  :  a description object
//
// -- OUTPUT :  an updated description object
//
void
SuperPage::DescribeDevice ( ObjectInfo& myDescription )
{
   myDescription.PutNewLine ( "" );
   myDescription.PutNewLine ( "# Device description" );

   // Generate description for file
   MvRequest reqDev( "PDFOUTPUT" );
   string filename = (const char*)ObjectInfo::ObjectPath ( myRequest_ );
   filename += "/pdf";
   reqDev("OUTPUT_NAME") = filename.c_str();
   myDescription.ConvertRequestToMacro ( reqDev,PUT_END,"File","pdf_output"  );

   // Check running mode 
   myDescription.PutNewLine ( "" );
   myDescription.PutNewLine ( "# Checks running mode" );
   myDescription.PutNewLine ( "mode = runmode()" );
   myDescription.PutNewLine ( "if mode = 'batch' or mode = 'execute' then" );
   myDescription.PutNewLine ( "   setoutput(File)" );
   myDescription.PutNewLine ( "end if" );
}

// -- METHOD :  Describe Yourself
//
// -- PURPOSE:  Generate the superpage description in macro syntax
//
// -- INPUT  :  a description object
//
// -- OUTPUT :  an updated description object
//
void
SuperPage::DescribeYourself ( ObjectInfo& myDescription )
{
   myDescription.PutNewLine ( "" );
   myDescription.PutNewLine ( "# SuperPage description" );

   set<Cached> skipSet;
   skipSet.insert("PAGES");
   myDescription.ConvertRequestToMacro ( myRequest_, PUT_LAST_COMMA,
                                         MacroName().c_str(),"plot_superpage",
                                         skipSet);

   // Print the page list
   int size = myDescription.MaximumParameterNameLength(myRequest_);
   string pageList = ListMyPages();
   myDescription.FormatLine ("PAGES",pageList.c_str(),"",size);

   // Close superpage request
   myDescription.PutNewLine ( ")"  );
   myDescription.PutNewLine ( "# plot_superpage returns a list of drop identifiers." );
   myDescription.PutNewLine ( "# Index 1 is for first page, and so on.\n" );
   string ret = "return " + MacroName();
   myDescription.PutNewLine( ret.c_str() );
}

// --  METHOD  : ListMyPages
//
// --  PURPOSE : Provide a listing all all pages
//                associated to the superpage
// --  INPUT   : none
//
// --  OUTPUT  : list of page name ( enclosed in [..] )
//
string
SuperPage::ListMyPages()
{
	// Put an enclosing brace
 	string pageNames = "[ ";
 
 	MvChildIterator child = childList_.begin();
	int npages = 1;
	while ( child != childList_.end() )
	{
		// Put a comma separator
		if ( npages > 1 )
			pageNames += ", ";

		// Get the name of the page
		pageNames += (*child)->MacroName();

		++child;
		++npages;
	}
 	
	// Put a termination brace
	pageNames += " ]";

	return pageNames;
}

void
SuperPage:: PrintAll ( bool printAll )
{
	if ( printAll )
		myRequest_ ( "_PRINT_OPTION" ) = "ALL";
	else
		myRequest_ ( "_PRINT_OPTION" ) = "VISIBLE";
}

bool
SuperPage:: PrintAll ()
{
	return ( myRequest_ ( "_PRINT_OPTION" ) == Cached ( "ALL" ) );
}

void
SuperPage::InsertVisDef ( MvRequest& visdefRequest, bool vdReplace  )
{
   // Retrieve the Icon Data Base
   MvIconDataBase& dataBase = this->IconDataBase();

   // Test if Visdef came from Contents edition window
   int visdefId = visdefRequest( "_CONTENTS_ICON_EDITED" );
   if (visdefId != 0)
   {
      // Visdef already exists in the data base, replace it
      dataBase.UpdateIcon ( DB_VISDEF, visdefId, visdefRequest );
   }
   else
   {
      // Insert visdef in the data base
      MvIcon visDef ( visdefRequest, true );
      dataBase.InsertIcon( PRES_VISDEF_REL, Id(), visDef, -1, vdReplace );
   }

   // Draw me later on
   RedrawIfWindow();
   NotifyObservers();
}

void
SuperPage::RemoveIcon ( MvIcon& icon )
{
	Cached verb =  icon.Request().getVerb();
	if ( ObjectList::IsVisDef     ( verb ) ||
	     ObjectList::IsVisDefText ( verb )    )
	{
		MvChildIterator child;
		for ( child = childList_.begin(); child != childList_.end(); ++child )
			(*child)->RemoveIcon ( icon );
	}
}

#if 0
void
SuperPage::NeedsRedrawing(bool yesno)
{
	for (MvChildIterator ii = childList_.begin(); ii != childList_.end(); ii++)
		(*ii)->NeedsRedrawing(yesno);
}

bool
SuperPage::NeedsRedrawing()
{
	for (MvChildIterator ii = childList_.begin(); ii != childList_.end(); ii++)
		if ( (*ii)->NeedsRedrawing() )
			return true;

	return false;
}


void
SuperPage::EraseDraw (int visdefId)
{
	for ( MvChildIterator ii = childList_.begin(); ii != childList_.end(); ii++ )
		(*ii)->EraseDraw (visdefId);
}


void
SuperPage::EraseForeDraw ()
{
  for ( MvChildIterator ii = childList_.begin(); ii != childList_.end(); ii++ )
    (*ii)->EraseForeDraw ();		
}

void SuperPage::RedrawIfWindow(int visdefId)
{
  for ( MvChildIterator ii = childList_.begin(); ii != childList_.end(); ii++ )
    (*ii)->RedrawIfWindow (visdefId);		
}

void
SuperPage::SetInputPresentableId ( int presentableId )
{
      	// Build heading request with drop id
	MvRequest vistool = "VISTOOL";

	MvRequest window = "DROP";
	window ( "DROP_ID" ) = presentableId;
	vistool ( "WINDOW" ) = window;

	MvRequest setup = "vistool";
	setup ( "service" ) = "gribtool";
	setup ( "mode" ) = "Default";
	setup ( "type" ) = "button";
	setup ( "interest" ) = "POSITION";
	setup.addValue  ( "interest", "CHANGE_WINDOW" );
	setup.addValue  ( "interest", "CONTENTS" );
	setup.addValue  ( "interest", "CLOSE_WINDOW" );
	setup ( "pixmap" ) = "/cc/od/graphics/icons/pw_sight.icon" ;
	vistool ( "SETUP" ) = setup;

	vistool ( "TITLE" ) = "Plot Window 1";
	vistool ( "SOURCE" ) = "uPlot";

//	VISTOOL,
//	    WINDOW     = (DROP,
//	    DROP_ID    = 1
//
//	),
//	    SETUP      = (vistool,
//	    service    = gribtool,
//	    mode       = Default,
//	    type       = button,
//	    interest   = POSITION/CHANGE_WINDOW/CONTENTS/CLOSE_WINDOW,
//	    pixmap     = '/cc/od/graphics/icons/pw_sight.icon'
//
//	),
//	    TITLE      = Plot Window 1

//	MvApplication::callService ( "gribtool", vistool, 0 );
	GribToolService::Instance().CallGribTool ( vistool );
}
#endif

// -- METHOD  :  RetrieveTextTitle
//
// -- PURPOSE : This method will retrieve the Text Title list. If there is no
//              title it will go up to the Root treeNode (the top of the tree)
//              to retrieve the user's default Text Title.
bool
SuperPage::RetrieveTextTitle ( MvIconList& textList )
{
   bool usingDefault = false;

   // Find Texts associated to this presentable
   MvIconList tList;
   int nIcons = iconDataBase_->RetrieveIcon ( PRES_TEXT_REL, presentableId_, tList );

   // Find a Title
   if ( nIcons )
   {
      // Check if type is Title
      MvListCursor lCursor;
      for ( lCursor = tList.begin(); lCursor != tList.end(); ++lCursor)
      {
         if ( ObjectList::IsVisDefTextTitle((*lCursor).Request()) )
         {
            textList.push_back((*lCursor));
            return false;
         }
      }
   }

   // Title not found. Search up to the tree.
   usingDefault = myParent_->RetrieveTextTitle(textList);
   ensure(textList.size() > 0);

   // It is a Text default and I am the SuperPage
   // Save Texts default in the DataBase
   if ( usingDefault )
   {
      MvListCursor  vdCursor;
      for ( vdCursor = textList.begin(); vdCursor != textList.end(); ++vdCursor)
      {
         MvIcon& text = *( vdCursor );
         iconDataBase_->InsertIcon( PRES_TEXT_REL, presentableId_, text );
      }
   }

   return usingDefault;
}

void
SuperPage::RetrieveTextAnnotation ( MvIconList& textList )
{
   // Find Texts associated to this presentable
   MvIconList tList;
   int nIcons = iconDataBase_->RetrieveIcon ( PRES_TEXT_REL, presentableId_, tList );

   // Find Text Annotations
   if ( nIcons )
   {
      // Check if type is Annotation
      MvListCursor lCursor;
      for ( lCursor = tList.begin(); lCursor != tList.end(); ++lCursor)
      {
         if ( ObjectList::IsVisDefTextAnnotation((*lCursor).Request()) )
            textList.push_back((*lCursor));
      }
   }

   // Return even if no Annotation was found. There is no need to search up to
   // the tree (i.e. the Root) because Text Annotation is not mandatory to have.
   return;
}

// -- METHOD  :  RetrieveLegend
//
// -- PURPOSE : This method will retrieve the Legend. If there is no
//              Legend it will go up to the Root treeNode (the top of
//              the tree) to retrieve the user's default Legend.
bool
SuperPage::RetrieveLegend ( MvIcon& legIcon )
{
   bool usingDefault = false;

   // Try to find a visdef associated to the presentable
   if (!iconDataBase_->RetrieveIcon ( PRES_LEGEND_REL,presentableId_,legIcon ))
      usingDefault = myParent_->RetrieveLegend(legIcon);

   // It is a Legend default and I am the SuperPage
   // Save Legend default in the DataBase
   if ( usingDefault )
      iconDataBase_->InsertIcon( PRES_LEGEND_REL,presentableId_ ,legIcon);

   return usingDefault;
}

#if 0
void
SuperPage::SetBackgroundDraw ( bool truefalse )
{
	backDrawEnabled_ = truefalse;
//D	this->NotifyObservers();

	//Temporary code to test the animation procedure
	if (backDrawEnabled_)
	{
                // Draw only the first page (test)
		MvChildIterator child = childList_.begin();
		Page* page = (Page*) (*child);
		page->DrawProlog();
		page->Draw();

		// Change PGRIB to GRIBLOOP
		MvRequest fullReq;
		GetAllRequests(fullReq);

		MvRequest fullNewReq;
		while (fullReq)
		{
			MvRequest newReq = fullReq.justOneRequest();
			if ( strcmp(newReq.getVerb(),"PGRIB") == 0 )
			{
				newReq.setVerb("GRIBLOOP");
			}
			fullNewReq = fullNewReq + newReq;
			fullReq.advance();
		}

      // Call MAGICS to process the request
      MagPlusService::Instance().SetRequest( fullNewReq );
	}
}

void
SuperPage::PrintInfo ()
{
	cout << "SuperPage " << presentableId_ << endl;
	MvChildIterator child = childList_.begin();
	while ( child != childList_.end() )
	{
		Page *page = (Page*) (*child);
		page->PrintInfo(); 

		++child;
	}
}
#endif

int
SuperPage::IncrementPrintIndex ()
{
	printIndex_++;
	return printIndex_;
}

#if 0
void
SuperPage::ZoomRequest( int treeNodeId, const Location& zoomCoord )
{
	// Find which child to send the information
	MvChildConstIterator child;
	for (child = childList_.begin(); child != childList_.end(); ++child)
	{
		if ( treeNodeId == (*child)->Id() )
		{
			// Update page geographical area
			Page *page = (Page*) (*child);
			page->ZoomRequest(zoomCoord);

			// Rebuild page request
         page->HasDrawTask(true);
         page->DrawTask();

            // Process pending actions
            TaskBase::Flush();
            return;
        }
    }

    PlotMod::Instance().UserMessage ( "Page to perform the zoom not found" );
}
#endif

void
SuperPage::ZoomRequest( int treeNodeId, const string& zoomInfo)
{
    // Find which child to send the information
    MvChildConstIterator child;
    for (child = childList_.begin(); child != childList_.end(); ++child)
    {
        if ( treeNodeId == (*child)->Id() )
        {
            // Update page info
            Page *page = (Page*) (*child);
            page->ZoomRequest(zoomInfo);

            // Rebuild page request
            page->HasDrawTask(true);
            page->DrawTask();
            return;
        }
    }

    PlotMod::Instance().UserMessage ( "Page to perform the zoom not found" );
}

void
SuperPage::ZoomRequest( int treeNodeId, int izoom )
{
   // Find which child to send the information
   MvChildConstIterator child;
   for (child = childList_.begin(); child != childList_.end(); ++child)
   {
      if ( treeNodeId == (*child)->Id() )
      {
         // Update page geographical area
         Page *page = (Page*) (*child);
         page->ZoomRequest(izoom);

         // Rebuild page request
         page->HasDrawTask(true);
         page->DrawTask();
         return;
      }
   }

   PlotMod::Instance().UserMessage ( "Page to perform the zoom not found" );
}

bool
SuperPage::UpdateLayerTransparency ( int id, int value )
{
    // Retrieve the Icon Data Base
    MvIconDataBase& dataBase = this->IconDataBase();

    // Update transparency value in the data base
    return dataBase.LayerTransparency( id, value );
}

bool
SuperPage::UpdateLayerVisibility ( int id, bool onoff )
{
    // Retrieve the Icon Data Base
    MvIconDataBase& dataBase = this->IconDataBase();

    // Update visibility value in the Data Base
    return dataBase.LayerVisibility( id, onoff );
}

bool
SuperPage::UpdateLayerStackingOrder ( int id, int value )
{
    // Retrieve the Icon Data Base
    MvIconDataBase& dataBase = this->IconDataBase();

    // Update plotting order value in the Data Base
    return dataBase.LayerStackingOrder(id,value);
}

bool
SuperPage::ExportPlot ( MvRequest* req, bool sync )
{
   MvRequest inReq = *req;

   // Create printer request
   MvRequest printerReq( "PRINTER_MANAGER" );
   printerReq("DESTINATION") = MVFILE;
   printerReq("OUTPUT_DEVICES") = inReq;

   // Redraw in order to get the latest icon status (transparency,
   // order and visibility). These information are saved in the
   // MvDataBase but are not updated in the main Request directly
   // (i.e. MagicsGraphicsEngine::fullRequest_)
   this->DrawProlog();  // clean the main Request
   this->Draw();

   // Retrieve current plot request without output formats
   MvRequest plotReq;
   GetAllRequests( plotReq, true );

   // Create the full request: output formats + plot requests
   MvRequest newReq = printerReq + plotReq;

   // Call uPlotBatch (syncronous or asyncronous) to do the job
   if ( sync )
   {
      int err;
      MvApplication::waitService ( "uPlotBatch", newReq, err );
      if ( err )
         return false;
   }
   else
      MvApplication::callService ( "uPlotBatch", newReq, 0 );

   return true;
}

//typedef map<int, string> ecVisDefMap;

MvRequest
SuperPage::ExportToEcCharts ()
{
   // There are a few implementation's options
   // 1. Create a Visitor similar to Macro Visitor (see GenerateMacro function)
   // 2. Because we are assuming that there will be only one
   //    PAGE then the Visitor functionality can be simplified
   // 3. Function DescribeDrops(ObjectInfo,ecVisDefMap) can be
   //    replaced by DescribeDrops(ObjectInfo,MvRequest)
   // 4. Get all the requests and select only the relevant ones 
   //    with a special treatment for dataunits.

#if 0
   // Option 2

   // Visit me
   //   vis->Visit (*this);
   ObjectInfo spDrops;
   ecVisDefMap vdMap;
   this->DescribeDrops ( spDrops,vdMap );

   // Visit all my children
   //   Presentable::Visit ( *vis );
   MvChildIterator child = childList_.begin();
   ObjectInfo pageDrops;
   (*child)->DescribeDrops ( pageDrops,vdMap );

   FILE* filePtr = fopen ( "/home/graphics/cgk/metview/toto.eccharts", "w" );
   fprintf(filePtr,"\n# Drops to SuperPage\n");
   spDrops.WriteDescription ( filePtr );

   fprintf(filePtr,"\n# Drops to Page\n");
   pageDrops.WriteDescription ( filePtr );
   fclose ( filePtr );  // close the output file
#endif

#if 1
   // Option 4

   // Generate plotting requests without output formats
   MvRequest plotReq;
   this->DrawProlog();  // clean the main Request
   this->Draw();        // update drawing structure with the latest Contents info
   GetAllRequests( plotReq, true ); // collect all plotting requests

   // Filter only dataunits and visdefs. If a dataunit is not a
   // data file then it needs to be decoded (e.g. Mars Retrieval,
   // Simple Formula, ...)
   MvRequest ecReq;
   while ( plotReq )
   {
      // Process Visdefs
      MvRequest request = plotReq.justOneRequest();
      const char* verb = request.getVerb();
      if ( ObjectList::IsVisDef ( verb )       ||
           ObjectList::IsVisDefText ( verb )   ||
           ObjectList::IsVisDefLegend ( verb ) ||
           ObjectList::IsVisDefImport ( verb ) ||
           ObjectList::IsVisDefCoastlines ( verb )
         )
            ecReq = ecReq + request;

      // Process Dataunits. At the moment, only decode data from
      // MARS or from disk. Implement later data coming from a
      // Formula, Simple Formula, Grib Filter, ...
      else if ( ObjectList::IsDataUnit ( verb ) ||
                strcmp(verb,"PGRIB") == 0 )
      {
         ecReq = ecReq + request;
         string iclass = (const char*)ObjectInfo::IconClass(request);
         string fileName = ObjectInfo::FileName(request);
          if ( ! IsBinaryOrMissingFile( fileName.c_str() ) )
          {
             MvRequest fileReq;
             fileReq.read(fileName.c_str(),true);
 
             // Just in case further expansion is needed
             if ( !(const char*)fileReq("_PATH") && (const char*)request("_PATH") )
                fileReq("_PATH") = request("_PATH");
             if ( !(const char*)fileReq("_NAME") && (const char*)request("_NAME") )
                fileReq("_NAME") = request("_NAME");

             ecReq = ecReq + fileReq;
          }
      }
      else if ( strcmp(verb,"VISDEFS") == 0 )
      {
         ecReq = ecReq + request("ACTIONS");
      }

      plotReq.advance();
   }
#endif

   return ecReq;
}

void
SuperPage::PrintFile ( MvRequest& req )
{
   // Create output format request
   MvRequest driverReq("PDFOUTPUT");
   string fileName = tempnam(getenv("METVIEW_TMPDIR"),"plot");
   fileName += ".pdf";
   driverReq("OUTPUT_FULLNAME") = fileName.c_str();
   if ( (const char*)req("_OUTPUT_FRAME_LIST") )
   {
      for ( int i = 0; i < req.countValues("_OUTPUT_FRAME_LIST"); i++ )
         driverReq.addValue("OUTPUT_FRAME_LIST",(int)req("_OUTPUT_FRAME_LIST",i));
      req.unsetParam(("_OUTPUT_FRAME_LIST"));
   }

   // To avoid the printer to clip the bottom and left sides of the plot
   driverReq("OUTPUT_PDF_SCALE") = 0.96;

   // Create printer request
   MvRequest printerReq = req;
   printerReq("OUTPUT_DEVICES") = driverReq;

    // Redraw in order to get the latest icon status (transparency,
   // order and visibility). These information are saved in the
   // MvDataBase but are not updated in the main Request directly
   // (i.e. MagicsGraphicsEngine::fullRequest_)
   this->DrawProlog();  // clean the main Request
   this->Draw();

   // Retrieve current plot requests
   MvRequest fullReq;
   GetAllRequests( fullReq, true );

   // Create the full request: printer request + plot requests
   MvRequest newReq = printerReq + fullReq;

   // Call uPlotBatch to do the job
   MvApplication::callService ( "uPlotBatch", newReq, 0 );

   return;
}

Page*
SuperPage::InsertOnePage(MvRequest& superpageRequest)
{
	// Retrieve the subrequest describing the Page
	MvRequest pagesRequest = superpageRequest.getSubrequest ( PAGES );

	// Check if the request is a PAGE request
	// If it does not exist, create one PAGE request
	const char* pageVerb = pagesRequest.getVerb();
	if ( strcmp(pageVerb,PLOTPAGE) )
		pagesRequest = ObjectList::CreateDefaultRequest ( "PLOT_PAGE" );

	// Create a new Page 
	// and insert it as a child of the superpage
	// Extract the page request 
	MvRequest newpageRequest = pagesRequest.justOneRequest();

	// Create a new page
	Page* page = new Page ( newpageRequest );
	ensure ( page != 0 );
		
	// Insert the page in the superpage's child list
	this->InsertOnePage ( page );

	// Create and store the device information	
	this->SetDeviceInfo ( );

	return page;
}

void
SuperPage::InsertOnePage( Page* page)
{
   // Add page to the childlist
   this->Insert(page);

   // Update DataBase
   MvIcon iconView(page->GetView().ViewRequest(),true);
   iconDataBase_->InsertIcon( PRES_VIEW_REL, page->Id(), iconView, -1, true );
}

void
SuperPage::contentsRequest( MvRequest& req)
{
    // Find which child to send the information
    int treeNodeId = req("DROP_ID");
    MvChildConstIterator child;
    for (child = childList_.begin(); child != childList_.end(); ++child)
    {
        if ( treeNodeId == (*child)->Id() )
        {
            // Update page geographical area
            Page *page = (Page*) (*child);
            page->contentsRequest(req);

            // Rebuild page request
            page->HasDrawTask(true);
            page->DrawTask();
            return;
        }
    }

     PlotMod::Instance().UserMessage ( "Page to perform the zoom not found" );
}

#ifndef NOMETVIEW_QT
#ifdef METVIEW_WEATHER_ROOM
void
SuperPage::plotWeatherRoom( bool sync )
{
   plotApplication_->plotWeatherRoom(sync);
}
#endif
#endif
