/* Emacs, this is -*- C++ -*- */

#ifndef _PAGE_H_
#define _PAGE_H_

#include "pageobject.h"
#include "tree.h"
#include "plot.h"

#include <drag.h>

#include <qwidget.h>
#include <qarray.h>
#include <qpainter.h>
#include <qpixmap.h>


/** A Page for plots and other objects.


	The Page class represents a page as it would be printed. It has
	some properties such as a size (in cm) and a color. From the size
	in cm and the widget size in pixels, one can calculate the pageīs
	scaling factors. A page can be printed on a printer or on the
	pageīs widget (future extension: on a pixmap). On a page, there
	are zero or more objects, so-called PageObjects. A page can store
	and restore the objects on it.

	The objects on a page are PageObjectīs. The most common example
	for a PageObject is a Plot. (Also the first one implemented.) Other
	PageObjects (will) include Text, Images, and Arrows. The abstract
	base class, PageObject, defines the interface all objects on a page
	must conform. Note that plots are handled specially since they have
	a slot, plotSelectedColumns(), to plot data from the worksheet.
	Other PageObjects such as Text do not have this slot.

	Since plots and other objects can be dragged around on a page,
	a Page isa KDNDWidget. It also has a KDNDDropZone (the whole page,
	that is) where plots can be dropped. Maybe once in a time users
	can even drop text and images on a page. See @ref PageObject for 
	what can be on a page.

	@author Patrick Schemitz
*/

class Page : public KDNDWidget
{
  Q_OBJECT

public:

  /** Build an empty page, of size x times y cm.

	  This is a scientific application, therefore we use cm.
	  Some might call that SI units. (Well, almost. Meters
	  would be SI units.) Others might call it continental
	  European arrogance. Donīt hold back. You have ignored
	  our Umlaute long enough to take some revenge.

	  @param width width of the page in cm (0 for default from config.)
	  @param height height of the page in cm (0 for default from config.)
  */
  Page (double width, double height, QWidget* parent = 0,
		const char* name = 0);

  /** Destroy the page, and all plots on it.

	  Note that it is up to the page to delete the plots on
	  it; this is *not* task of the main tree view, since it
	  was the page who created them.

	    "Der Herr hatīs gegeben,
	     der Herr hatīs genommen,
	     der Name des Herrn sei gelobt."
  */
  ~Page ();

  /** Store overall options for the page.

	  Actually calls storeDefaults().

	  @see #storeDefaults()
	  @see #restoreOptions()
	  @see #optionsDialog()
  */
  void storeOptions (KConfig*);

  /** Restore overall options for the plot.

	  Actually calls loadDefaults().

	  @see #storeOptions()
	  @see #optionsDialog()
  */
  void restoreOptions (KConfig*);

  /** Static implementation of storeOptions().

	  Stores the page defaults.
	  That is, the default values for colors, size and the lot.

	  @see #storeOptions()
  */
  static void storeDefaults (KConfig*);

  /** Static equivalent to restoreOptions().

	  Restores the page defaults.
	  That is, the default values for colors, size and the lot.

	  @see #restoreOptions()
  */
  static void loadDefaults (KConfig*);

  /** Store a page to a QFile.

	  This function writes a page and, if with_obj==true, all its objects
	  (plots, text) to the given QFile.
	  Please note that QFile is already opened and positioned when
	  passed to store(). Also note that QFile may already contain
	  other plots and/or worksheets.

	  @see #restore()
  */
  bool store (QFile&, bool with_obj);

  /** Restore a page from a QFile.

	  This function reads a page from the given QFile.
	  Please note that QFile is already opened and positioned when
	  passed to restore(). Also note that QFile may already contain
	  other plots and/or worksheets.

	  @see #store()
  */
  static Page* restore_page (QFile&);
  bool restore_objects (QFile&, bool with_obj);
  
  /** Return the pixmap for the tree view.

	  This varies if the page is the active page or not.

	  @return pixmap for the page.
  */
  QPixmap* icon ();

  /** Return appropriate "Page" submenu.

	  This menu contains the entries "New plot", "Layout", and more.

	  @return the main menu entry for the page.
  */
  QPopupMenu* menu (QPopupMenu* predefined = 0);

  /** Return pointer to the tree item of the page.

	  The item is inserted into the main tree view.
	  Note that the item may change; the pointer, however,
	  remains the same until the page is deleted.

	  Oh, and BTW do *not* try to delete the treeitem! Deleting the
	  tree item causes a segfault when you delete the page later.
  */
  TreeItem* treeitem ();

  /** Set active page and icon.

	  This changes the pageīs icon to active.
  */
  virtual void activate ();

  /** Set inactive page icon.

	  This changes the pageīs icon to inactive.
  */
  virtual void deactivate ();

  /** Get the scaling factors of the page.

	  The scaling factors are needed for identifying plots
	  under mouse events, and for painting the page.
  */
  void getScaleFactors (double& xf, double& yf);

  /** Create a plot by colning the prototype, and let the
	  plot fill itself.

	  This function is called by the centre, when the user
	  wants to create a plot without creating an empty page
	  first.

	  @param prototype The plotīs prototype. (Which will be cloned!)
  */
  void make_plot (Plot* prototype, bool fill=false);

  /** Remove and delete an object from the page.

	  The object, a plot or some other PageObject, is removed
	  from the page and deleted. If the object is not found on
	  the page, nothing happens. (Only a message box pops up.)

	  @param obj the deliquent.
  */
  void remove_object (PageObject* obj);

  /** Mouse modes.

	  MoveMode drags plots around/resizes them.
	  TextMode will (later) manipulate text objects.
	  PlotMode passes mouse clicks on to the plot.

	  @see #mouseMode()
	  @see #setMouseMode()
  */
  enum MouseModes {
	MoveMode,
	TextMode,
	PlotMode
  };

  /** Query mouse mode.

	  Returns MoveMode or TextMode.

	  @see #MouseModes
	  @see #setMouseMode()
  */
  static int mouseMode ();

  /** Set the mouse mode to MoveMode or TextMode.

	  @see #MouseModes
	  @see #mouseMode()
  */
  static void setMouseMode (int);

  /** Beginning-of-page mark in files. */
  static const char* start_mark ();

  /** End-of-page mark in files. */
  static const char* end_mark ();

signals:

  /** This signal is emitted when the active page has changed.
	  (By clicking in an inactive page, which is activated this
	  way.)

	  @param p the page to be made active
  */
  void activePageChanged (Page* p);

  /** This signal is emitted when the active plot has changed.
	  (By clicking in an inactive plot, which is activated this
	  way.)

	  @param p the plot to be made active
  */
  void activePlotChanged (Plot* p);

  /** This signal is emitted when the tree item of the page has changed.
	  (By editing the caption, (de)activating the page, resizing,
	  deleteing/inserting plots on the page.)
  */
  void treeItemChanged ();

  /** Emitted to request insertion of a tree item to the tree.

	  This is the case whenever a new plot is created.
	  The first TreeItem is the (already existing) parent, the second
	  is the (to insert) child.

	  @param parent the parent TreeItem, i.e. the pageīs.
	  @param child the child TreeItem, to be inserted under parent.
  */
  void addTreeChild (TreeItem* parent, TreeItem* child);

public slots:

  /** Print a page on the QPrinter.

	  This function opens the QPrinter::setup() dialog,
	  and if the user selects OK, prints the page and all its
	  plots to the printer (or selected output file).
  */
  void printPage ();

  /** Display the pageīs options dialog.

	  That is, the default values for colors, size and the lot.

	  @see #storeOptions()
	  @see #restoreOptions()
  */
  void optionsDialog ();

  /** Actiavted when an object on the page changed its
	  tree entry. For example, when a plot is actiavted and
	  therefore changed its icon.
  */
  void pageObjectChanged ();

private:

  friend class PageInfoDialog;
  friend class PageOptionsDialog;

  /* Inherited and redefined functions from QWidget.
	 Actually, Page "isa" KDNDWidget which "isa" QWidget.
  */
  void enterEvent (QEvent*);
  void paintEvent (QPaintEvent*);
  void resizeEvent (QResizeEvent*);
  void mousePressEvent (QMouseEvent*);

  /* Inherited and redefined functions from KDNDWidget.
	 These functions are special to KDNDWidget, not QWidget;
	 and they are closely related to DND functionality.
  */
  bool pressed;
  KDNDDropZone* dropZone;
  void dndMouseMoveEvent(QMouseEvent*);
  void dndMouseReleaseEvent (QMouseEvent*);
  void startObjectDND (QMouseEvent*, PageObject*);

  /* Inherited and redefined functions from KDNDWidget.
	 These functions are special to KDNDWidget, not QWidget;
	 and they are closely related to resizing of plots.
  */
  bool resizing;
  int resizeX0, resizeY0;
  int resizeW0, resizeH0;
  PageObject* obj_being_resized;
  void startObjectResize (QMouseEvent*, PageObject*);
  void duringObjectResize (QMouseEvent*);
  void stopObjectResize ();

  /** Identify the PageObject at the given position.
	  This function is heavyly used when processing
	  mouse clicks, be it for resizing or for DND.
  */
  PageObject* identifyObject (QPoint p);

private slots:

  /* Slot for saving the page layout, i.e. empty plots only.
  */
  void saveLayout ();
  void savePageSettings (QFile&);
  void savePageObjects (QFile&,bool);
  static Page* loadPageSettings (QFile&);
  bool  loadPageObjects (QFile&, bool);

  /* Slot invoked by the KDE DīnīD mechanism.
	 In here, moved plots/texts are dropped.
  */
  void slotDropped (KDNDDropZone*);

  /* Dummy slot for unimplemented features.
  */
  void slotDummy ();

  /* Create new plot.
	 The integer gives the number of the plot type,
	 with respect to the plot list, Plots().
  */
  void slotNewPlot (int);

  /* Page info dialog.
	 Displays information about the page: name, format, objects on
	 it, a brief description.
  */
  void pageInfoDialog ();

private:

  /** Save the page settings to a file.
	  This saves the color and the page format. Does not
	  save plots or other page objects.
  */
  void storePageSettings (QFile&);

  /** Paint the page on a given painter.
	  This function can paint the page in a window,
	  on a QPrinter, and (planned) on a QPixmap.
  */
  void paint (QPainter*, bool with_tips=false);

  /** Paint the page in a window.
	  Calls paint() with a QPainter(this).
  */
  void paintPage ();

  /** Build the popup menu with the concrete plots.
	  Used in the Page menu.
  */
  QPopupMenu* buildPlotMenu ();

  /** Physical size of the page.
	  As a scientific (and European) application, length is
	  measured in cm (somewhat SI units).
  */
  double cm_width, cm_height;

  /** Brief description of what the page shows.
	  Martin has suggested that every page should have a short
	  "notes" field.
  */
  char* notes;

  /** The pageīs active/inactive icons.
	  These are loaded by the pageīs constructor, from the
	  applicationīs icon directory.
  */
  QPixmap* active_icon;
  QPixmap* inactive_icon;

  /** The pageīs entry in the main tree view.
	  Initialized by the constructor, but may change when the
	  page is resized etc. Actually, only *the_treeitem changes;
	  the_treeitem (the pointer) remains constant.
  */
  TreeItem* the_treeitem;

  /** The "Page" main menu entry.
	  Initialized by the constructor. Even though all pages have the
	  same menu, each page has its own copy, since the menu cannot be
	  static: it must be connected to slots, and these are *not*
	  static.
  */
  QPopupMenu* the_menu;

  /** Background color of this very page.
	  This is initialized to the defaultColor by the
	  constructor.
  */
  QColor the_background;

  /** List of all objects on the page.
	  In this list, all plots and text widgets are listed.
  */
  QList<PageObject> objectList;

  /** The mouse mode.
	  See mouseMode() etc. for description.

	  @see mouseMode()
	  @see MoveMode()
	  @see TextMode()
  */
  static int the_mouseMode;

  /** Default background color of the page.
	  Must be a pointer because it cannot be initialized to a
	  QColor instance before main() starts. defaultColor is
	  initialized by the first call to the Page::Page()
	  constructor.
  */
  static QColor* defaultColor;

  /** Default page size.
	  By default, this is A4 (20.0cm x 29.5cm). However, the
	  default can be redefined by the config file.
  */
  static double defaultWidth;
  static double defaultHeight;

  /** The running number of the page.
	  Used for loading default values from config file (if ==0),
	  and for the default title of new pages.
  */
  static int pageNumber;
};


extern Page* activePage;


#endif

Documentation generated by patrick@nemesis on Tue Feb 10 23:05:12 MET 1998