
/*=========================================================================

  Program:   CMB
  Module:    pqCMBSceneTree.h

Copyright (c) 1998-2005 Kitware Inc. 28 Corporate Drive, Suite 204,
Clifton Park, NY, 12065, USA.

All rights reserved. No part of this software may be reproduced,
distributed,
or modified, in any form or by any means, without permission in writing from
Kitware Inc.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
=========================================================================*/
// .NAME pqCMBSceneTree - represents a Scene Tree.
// .SECTION Description
// .SECTION Caveats

#ifndef __pqCMBSceneTree_h
#define __pqCMBSceneTree_h

#include "cmbAppCommonExport.h"
#include <QObject>
#include <QList>
#include <QPoint>
#include <QMap>
#include <QColor>

#include <map>
#include <vector>
#include <deque>
#include "cmbSceneUnits.h"
#include <QStringList>
#include "vtkType.h"
#include "vtkBoundingBox.h"
#include "pqVariableType.h"
#include "cmbSystemConfig.h"

class pqCMBSceneNode;
class pqCMBSceneNodeCreationEvent;
class pqCMBSceneNodeDeletionEvent;
class cmbSceneNodeReplaceEvent;
class CmbPolylineSceneNode;
class QAction;
class QIcon;
class QPixmap;
class QTreeWidget;
class QTreeWidgetItem;
class QMenu;
class cmbEvent;
class pqCMBSceneObjectBase;
class pqCMBGlyphObject;
class pqCMBLine;
class pqCMBArc;
class pqCMBTexturedObject;
class pqServer;
class pqRenderView;
class pqOutputPort;
class pqPipelineSource;
class pqCMBLineWidget;
class qtCMBArcWidgetManager;
class pqDataRepresentation;

class CMBAPPCOMMON_EXPORT pqCMBSceneTree : public  QObject {
  Q_OBJECT

  friend class pqCMBSceneNodeCreationEvent;
  friend class pqCMBSceneNodeDeletionEvent;
  friend class cmbSceneNodeReplaceEvent;

public:
  pqCMBSceneTree(QPixmap *visPixMap, QPixmap *ivisPixMap,
            QPixmap *snapPixMap, QPixmap *lockPixMap,
            QTreeWidget *widget,
            QTreeWidget *infoWidget = NULL);
  virtual ~pqCMBSceneTree();

  void empty();
  bool isEmpty() const {return (this->Root == NULL);}
  pqCMBSceneNode *createNode(const char *name, pqCMBSceneNode *parent,
                           pqCMBSceneObjectBase *obj, // Was NULL by default
                           cmbSceneNodeReplaceEvent *event);

  pqCMBSceneNode *createLineTypeNode();

  pqCMBSceneNode *createRoot(const char *name);
  void addPointsToGlyph(pqCMBSceneNode *node,
                        int count,
                        double *scaleFactor,
                        std::deque<double> *glyphPoints = NULL,
                        bool repositionOriginal = false,
                        QMap<pqCMBSceneNode*, int> *constraints = NULL,
                        bool useTextureConstraint = false,
                        int glyphPlaybackOption = -1);
  bool getGlyphPoint(double p[3],
                     std::deque<double> *glyphPoints,
                     int glyphPlaybackOption,
                     double bounds[6]);

  std::vector<pqCMBSceneNode *> duplicateNode(pqCMBSceneNode *node,
                                            std::deque<double> *glyphPoints = NULL,
                                            int count = 1,
                                            bool randomPlacement = false,
                                            bool repositionOriginal = false,
                                            QMap<pqCMBSceneNode*, int> *constraints = NULL,
                                            bool useGlyphs = false,
                                            bool useTextureConstraint = false,
                                            int glyphPlaybackOption = -1);

  pqCMBSceneNode *duplicateNode(pqCMBSceneNode *node, double zOffset);
  pqCMBSceneNode *getRoot() const { return this->Root;}
  const std::vector<pqCMBSceneNode *> &getSelected() const
    { return this->Selected;}
  pqCMBSceneNode *getLineTypeNode(bool createIfDoesntExist = true);
  pqCMBSceneNode *getArcTypeNode(bool createIfDoesntExist = true);

  pqCMBSceneNode *findNode(const char *name) const;
  pqCMBSceneNode *findNode(pqCMBSceneObjectBase *obj) const;
  pqCMBSceneNode *findNode(pqPipelineSource *obj) const;
  QIcon *getIconVisible() const { return this->IconVisible;}
  QIcon *getIconInvisible() const { return this->IconInvisible;}
  QIcon *getIconNull() const { return this->IconNULL;}
  QIcon *getIconLocked() const { return this->IconLocked;}
  QTreeWidget *getWidget() const { return this->TreeWidget;}
  QTreeWidget *getInfoWidget() const { return this->InfoTreeWidget;}
  std::string createUniqueName(const char *) const;
  void enterEditMode() { this->EditMode = true;}
  void exitEditMode()
    {
      this->EditMode = false;
      emit requestSceneUpdate();
    }

  void changeName(pqCMBSceneNode *node, const char *newName);

  void setApplyBathymetryAction(QAction *changeAction);
  void setArcActions(QAction *edit, QAction *mergeEndNodes,
                     QAction *mergeArcs, QAction *growArcSelection,
                     QAction *autoConnectArcs);
  void setChangeNumberOfPointsLoadedAction(QAction *action);
  void setChangeUserDefineObjectTypeAction(QAction *);
  void setColorActions(QAction *set, QAction *unset);
  void setConicalNodeActions(QAction *create, QAction *edit);
  void setConvertToGlyphAction(QAction *);
  void setCreateArcNodeAction(QAction *);
  void setCreateLineNodeAction(QAction *);
  void setCreatePolygonAction(QAction *);
  void setCreateVOINodeAction(QAction *);
  void setDefineVOIAction(QAction *);
  void setDeleteNodeAction(QAction *);
  void setDuplicateNodeAction(QAction *nonrandomAction,
                              QAction *randomAction);
  void setElevationAction(QAction *);
  void setExportSolidsAction(QAction *);
  void setExportPolygonsAction(QAction *);
  void setGenerateArcsAction(QAction *);
  void setGenerateImageMeshAction(QAction *);
  void setGroundPlaneActions(QAction *create, QAction *edit);
  void setImportObjectAction(QAction *);
  void setInsertNodeAction(QAction *);
  void setSelectSnapNodeAction(QAction *setAction, QAction *unsetAction);
  void setSnapObjectAction(QAction *);
  void setTextureAction(QAction *change);
  void setTINStackAction(QAction *);
  void setTINStitchAction(QAction *);
  void setUndoRedoActions(QAction *undoAction, QAction *redoAction);
//  void setUseGlyphPlaybackAction(QAction *useGlyphPlaybackAction);

  void setCurrentView(pqRenderView *view);
  pqRenderView *getCurrentView() const
    {return this->CurrentView;}

  void setCurrentServer(pqServer *server);
  pqServer *getCurrentServer() const
    {return this->CurrentServer;}

  void setUnits(cmbSceneUnits::Enum unitType);
  cmbSceneUnits::Enum getUnits() const
    { return this->Units;}

  void getVOIs(std::vector<pqCMBSceneNode *> *vois) const;
  void getArcs(std::vector<pqCMBSceneNode *> *Arcs) const;

  const QStringList &getTextureFileNames()
    { return this->TextureFiles;}

  const QStringList &getUserDefinedObjectTypes()
    { return this->UserObjectTypes;}

  pqCMBSceneNode* FindLineNode(pqCMBLineWidget*);
  void setLineWidgetCallbacks(pqCMBLine* obj);

  bool getRandomConstraintPoint(double p[3],
                                QMap<pqCMBSceneNode*, int> *constraints,
                                int glyphPlaybackOption = -1,
                                std::deque<double> *glyphPoints = NULL);
  bool IsTemporaryPtsFileForMesherNeeded(QStringList &surfaceNames);
  void  setSnapTarget(pqCMBSceneNode *node);
  // Add a typeName to the list of known types - the cleanList option will sort the
  // list and remove duplicates
  void addUserDefinedType(const char *typeName, bool cleanList=true);
  void cleanUpUserDefinedTypes();

  bool getDataObjectPickable(){return this->DataObjectPickable;}
  void setDataObjectPickable(bool val){this->DataObjectPickable = val;}

  qtCMBArcWidgetManager* getArcWidgetManager(){return ArcWidgetManager;}

  bool containsDataObjects() const;
  pqCMBSceneNode* getSceneObjectNode(pqCMBSceneObjectBase* obj);
  pqCMBSceneNode* getSceneNodeByName(const char* nodename);

  void setBoreHolesRadius(double radius);
  int createBorFileObjects(
    const QString& filename, pqPipelineSource* source);
  pqDataRepresentation* getABoreHoleRepresentation();
  pqDataRepresentation* getACrossSectionRepresentation();

  // This is used to insert Undo/Redo Events - USE WITH
  // CARE!
  void insertEvent(cmbEvent *event);

  // set/get the initial scene object color
  void setInitialSceneObjectColor(QColor& color)
    { this->InitialSceneObjectColor = color; }
  QColor& initialSceneObjectColor()
    { return this->InitialSceneObjectColor; }

public slots:
  void sceneObjectChanged();
  void convertNodesToGlyphs();
  void deleteSelected();
  void insertTypeNode();
  void duplicateSelected();
  void duplicateSelectedRandomly();
  void createCone();
  void editCone();
  void createVOI();
  void updateDefineVOIOption();
  void updateEditConeOption();
  void createGroundPlane();
  void editGroundPlane();
  void editArcObject();
  void setArcSnapping();
  void mergeArcs();
  void growArcSelection();
  void autoConnectArcs();
  void updateGroundPlaneOptions();
  void updateArcOptions();
  void createLineObject();
  void createArcObject();
  void createPolygonObject();
  pqCMBSceneNode* createBoreholeObject(pqPipelineSource*,
    pqCMBSceneNode *parent);
  pqCMBSceneNode* createCrossSectionObject(pqPipelineSource*,
    pqCMBSceneNode *parent);
  pqCMBSceneNode* createLineNode(double bounds[6]);
  void stitchTINs();
  void stackTINs();
  void generateArcsFromImage();
  void importObject();
  void setSnapTarget();
  void unsetSnapTarget();
  void snapSelected();
  void snapObject(pqCMBSceneNode *node);
  void setNodeColor();
  void unsetNodeColor();
  void updateSelectedColorMode();
  void updateSnapOptions();
  void updateTexturedObjectOptions();
  void updateBathymetryOptions();
  void editBathymetry();
  void updateTINStitchOptions();
  void updateTINStackOptions();
  void updateGenerateArcsOptions();
  void clearSelection();
  void clearSelectedGlyphPointsColor();
  void nodesSelected(bool clearSelection = false);
  void editTexture();
  void updateElevation();
  void changeNumberOfPointsLoadedAction();
  void selectLineNode();
  void updateLineNodeVisibility(bool);
  void collapseAllDataInfo();
  void recomputeInfo(QTreeWidgetItem*);
  // Description:
  // Exports Solids and Lines into a CMB file.
  void exportSelectedSolids();
  void exportSelectedPolygons();
  void defineSelectedVOI();
  void showContextMenu(const QPoint &pos);
  void changeUserDefineObjectTypeAction();
  void deleteNode(pqCMBSceneNode *node,
                  cmbSceneNodeReplaceEvent *event);
  void updateUseGlyphPlayback(bool checked);

  // These methods deal with the controlling of
  // events that can be Undone/Redone

  void turnOffEventRecording()
  { this->RecordEvents = false;}
  void turnOnEventRecording()
  { this->RecordEvents = true;}
  bool recordingEvents() const
  { return this->RecordEvents;}
  void emptyEventList();
  void deleteUndoEvents();
  void undo();
  void redo();
  void setTextureMap(const QString& filename,
    int numberOfRegistrationPoints, double *points);
  void unsetTextureMap();
  void addTextureFileName(const char *filename);
  void generateMeshFromImage();

signals:
  void requestSceneUpdate();
  void selectionUpdated(const QList<pqCMBSceneNode*> *,
                        const QList<pqCMBSceneNode*> *);
  void nodeUnselected(pqCMBSceneNode *);
  void nodeSelected(pqCMBSceneNode *);
  void nodeNameChanged(pqCMBSceneNode *);
  void noNodeSelected();
  void lockedNodesChanged();
  void requestTINStitch();
  void requestSolidExport();
  void requestPolygonsExport();

  void newCurrentView(pqRenderView*);
  void newCurrentServer(pqServer*);
  void enableMenuItems(bool);

  void focusOnSceneTab();
  void focusOnDisplayTab();
  void firstDataObjectAdded();

  void setCameraManipulationMode(int mode);
  void resetCameraManipulationMode();
  void resetViewDirection(double look_x, double look_y, double look_z,
                          double up_x, double up_y, double up_z);
  void enableToolbars(bool enable);

protected:

  void setNewObjectPosition(pqCMBSceneNode *node, bool randomPlacement,
                            bool translateBasedOnView, int repeatCount,
                            QMap<pqCMBSceneNode*, int> *constraints,
                            int glyphPlaybackOption,
                            QString glyphPlaybackFilename,
                            bool useTextureConstraint = false);

  void attachNode(pqCMBSceneNode *node);
  void detachNode(pqCMBSceneNode *node);
  void convertChildrenToGlyphs(pqCMBSceneNode *node,
                                const std::string &filename,
                                cmbSceneNodeReplaceEvent *event);
  //pass nothing to clear the color
  void setColorNodeIcon(double color[4]);
  void clearColorNodeIcon();
  bool boundingBoxContainsPoint(vtkBoundingBox *bb, double p[3]);
   QIcon *IconVisible;
  QIcon *IconInvisible;
  QIcon *IconSnap;
  QIcon *IconLocked;
  QIcon *IconNULL;
  pqCMBSceneNode *Root;
  pqCMBSceneNode *SnapTarget;
  std::map<std::string, pqCMBSceneNode *> NameMap;
  std::map<pqCMBSceneObjectBase *, pqCMBSceneNode *> ObjectMap;
  std::map<pqPipelineSource *, pqCMBSceneNode *> SourceMap;
  bool EditMode;
  QTreeWidget *TreeWidget;
  QTreeWidget *InfoTreeWidget;
  QAction *InsertAction;
  QAction *ImportAction;
  QAction *DeleteAction;
  QAction *DuplicateAction;
  QAction *DuplicateRandomlyAction;
  QAction *VOIAction;
  QAction *ConeCreateAction;
  QAction *ConeEditAction;
  QAction *ConvertToGlyphAction;
  QAction *ExportSolidsAction;
  QAction *ExportPolygonsAction;
  QAction *LineAction;
  QAction *ArcAction;
  QAction *EditArcAction;
  QAction *ArcSnappingAction;
  QAction *MergeArcsAction;
  QAction *GrowArcSelectionAction;
  QAction *AutoConnectArcsAction;
  QAction *CreatePolygonAction;
  QAction *SetSnapTargetAction;
  QAction *UnsetSnapTargetAction;
  QAction *SetSnapObjectAction;
  QAction *SetNodeColorAction;
  QAction *UnsetNodeColorAction;
  QAction *ChangeTextureAction;
  QAction *ApplyBathymetryAction;
  QAction *ChangeNumberOfPointsLoadedAction;
  QAction *TINStitchAction;
  QAction *TINStackAction;
  QAction *GenerateArcsAction;
  QAction *DefineVOIAction;
  QAction *CreateGroundPlaneAction;
  QAction *EditGroundPlaneAction;
  QAction *ChangeUserDefineObjectTypeAction;
  QAction *ElevationAction;
  QAction *RedoAction;
  QAction *UndoAction;
  QAction *GenerateImageMesh;
  pqRenderView *CurrentView;
  pqServer *CurrentServer;
  pqCMBTexturedObject* CurrentTextureObj;
  cmbSceneUnits::Enum Units;
  std::vector<pqCMBSceneNode *> Selected;
  QStringList TextureFiles;
  QStringList UserObjectTypes;
  QMenu *ContextMenu;
  QMenu *PropertiesMenu;
  QMenu *FileMenu;
  QMenu *EditMenu;
  QMenu *CreateMenu;
  QMenu *ToolsMenu;
  QList<cmbEvent*> UndoRedoList;
  int CurrentUndoIndex;
  const int MaxUndoRedoLimit;
  bool RecordEvents;
  QColor InitialSceneObjectColor;

  // if this is set to false, all the data object will not be pickable in the scene
  bool DataObjectPickable;

  //create the arc widget manager and setup the signal / slots
  void createArcWidgetManager();

  //controls the creation of arcs, and manages the singelton arc widget
  qtCMBArcWidgetManager* ArcWidgetManager;

  // If using glyph playback
  bool useGlyphPlayback;

protected slots:
  void nodeChanged(QTreeWidgetItem*, int);
  void nodeClicked(QTreeWidgetItem*, int);

  void arcWidgetReady();
  void arcWidgetBusy();
  void updateArcsAfterSplit(pqCMBSceneNode* arcNode,QList<vtkIdType> newArcIds);
  void updateArc(pqCMBSceneNode* arcNode);
  void refreshArcsAndPolygons();

  void enableSceneTree(const bool &lock);
};





#endif /* pqCMBSceneTree_h */
