Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@0: 
Chris@0: /*
Chris@59:     Sonic Visualiser
Chris@59:     An audio file viewer and annotation editor.
Chris@59:     Centre for Digital Music, Queen Mary, University of London.
Chris@182:     This file copyright 2006 Chris Cannam and QMUL.
Chris@0:     
Chris@59:     This program is free software; you can redistribute it and/or
Chris@59:     modify it under the terms of the GNU General Public License as
Chris@59:     published by the Free Software Foundation; either version 2 of the
Chris@59:     License, or (at your option) any later version.  See the file
Chris@59:     COPYING included with this distribution for more information.
Chris@0: */
Chris@0: 
Chris@0: #ifndef _COLOUR_3D_PLOT_H_
Chris@0: #define _COLOUR_3D_PLOT_H_
Chris@0: 
Chris@193: #include "SliceableLayer.h"
Chris@0: 
Chris@128: #include "data/model/DenseThreeDimensionalModel.h"
Chris@0: 
Chris@0: class View;
Chris@0: class QPainter;
Chris@0: class QImage;
Chris@0: 
Chris@0: /**
Chris@0:  * This is a view that displays dense 3-D data (time, some sort of
Chris@0:  * binned y-axis range, value) as a colour plot with value mapped to
Chris@0:  * colour range.  Its source is a DenseThreeDimensionalModel.
Chris@0:  *
Chris@0:  * This was the original implementation for the spectrogram view, but
Chris@0:  * it was replaced with a more efficient implementation that derived
Chris@0:  * the spectrogram itself from a DenseTimeValueModel instead of using
Chris@0:  * a three-dimensional model.  This class is retained in case it
Chris@0:  * becomes useful, but it will probably need some cleaning up if it's
Chris@0:  * ever actually used.
Chris@0:  */
Chris@0: 
Chris@193: class Colour3DPlotLayer : public SliceableLayer
Chris@0: {
Chris@0:     Q_OBJECT
Chris@0: 
Chris@0: public:
Chris@44:     Colour3DPlotLayer();
Chris@0:     ~Colour3DPlotLayer();
Chris@0: 
Chris@156:     virtual const ZoomConstraint *getZoomConstraint() const {
Chris@156:         return m_model ? m_model->getZoomConstraint() : 0;
Chris@156:     }
Chris@0:     virtual const Model *getModel() const { return m_model; }
Chris@44:     virtual void paint(View *v, QPainter &paint, QRect rect) const;
Chris@0: 
Chris@607:     virtual int getVerticalScaleWidth(View *v, bool, QPainter &) const;
Chris@607:     virtual void paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const;
Chris@25: 
Chris@44:     virtual QString getFeatureDescription(View *v, QPoint &) const;
Chris@25: 
Chris@44:     virtual bool snapToFeatureFrame(View *v, int &frame, 
Chris@28: 				    size_t &resolution,
Chris@28: 				    SnapType snap) const;
Chris@24: 
Chris@475:     virtual void setLayerDormant(const View *v, bool dormant);
Chris@475: 
Chris@44:     virtual bool isLayerScrollable(const View *v) const;
Chris@25: 
Chris@287:     virtual ColourSignificance getLayerColourSignificance() const {
Chris@287:         return ColourHasMeaningfulValue;
Chris@287:     }
Chris@183: 
Chris@0:     void setModel(const DenseThreeDimensionalModel *model);
Chris@0: 
Chris@115:     virtual int getCompletion(View *) const { return m_model->getCompletion(); }
Chris@24: 
Chris@0:     virtual PropertyList getProperties() const;
Chris@0:     virtual PropertyType getPropertyType(const PropertyName &) const;
Chris@159:     virtual QString getPropertyLabel(const PropertyName &) const;
Chris@346:     virtual QString getPropertyIconName(const PropertyName &) const;
Chris@159:     virtual QString getPropertyGroupName(const PropertyName &) const;
Chris@0:     virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216:                                          int *min, int *max, int *deflt) const;
Chris@0:     virtual QString getPropertyValueLabel(const PropertyName &,
Chris@0: 					  int value) const;
Chris@534:     virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
Chris@0:     virtual void setProperty(const PropertyName &, int value);
Chris@197:     virtual void setProperties(const QXmlAttributes &);
Chris@11:     
Chris@509:     enum ColourScale {
Chris@509:         LinearScale,
Chris@509:         LogScale,
Chris@509:         PlusMinusOneScale,
Chris@509:         AbsoluteScale
Chris@509:     };
Chris@159: 
Chris@159:     void setColourScale(ColourScale);
Chris@159:     ColourScale getColourScale() const { return m_colourScale; }
Chris@159: 
Chris@197:     void setColourMap(int map);
Chris@197:     int getColourMap() const;
Chris@197: 
Chris@534:     /**
Chris@534:      * Set the gain multiplier for sample values in this view.
Chris@534:      * The default is 1.0.
Chris@534:      */
Chris@534:     void setGain(float gain);
Chris@534:     float getGain() const;
Chris@534: 
Chris@531:     enum BinScale {
Chris@531: 	LinearBinScale,
Chris@531: 	LogBinScale
Chris@531:     };
Chris@531:     
Chris@531:     /**
Chris@531:      * Specify the scale for the y axis.
Chris@531:      */
Chris@531:     void setBinScale(BinScale);
Chris@531:     BinScale getBinScale() const;
Chris@531: 
Chris@719:     /**
Chris@719:      * Normalize each column to its maximum value, independent of its
Chris@719:      * neighbours.
Chris@719:      */
Chris@197:     void setNormalizeColumns(bool n);
Chris@197:     bool getNormalizeColumns() const;
Chris@197: 
Chris@719:     /**
Chris@719:      * Normalize each value against the maximum in the visible region.
Chris@719:      */
Chris@197:     void setNormalizeVisibleArea(bool n);
Chris@197:     bool getNormalizeVisibleArea() const;
Chris@197: 
Chris@719:     /**
Chris@719:      * Normalize each column to its maximum value, and then scale by
Chris@719:      * the log of the (absolute) maximum value.
Chris@719:      */
Chris@719:     void setNormalizeHybrid(bool n);
Chris@719:     bool getNormalizeHybrid() const;
Chris@719: 
Chris@357:     void setInvertVertical(bool i);
Chris@357:     bool getInvertVertical() const;
Chris@357: 
Chris@465:     void setOpaque(bool i);
Chris@465:     bool getOpaque() const;
Chris@465: 
Chris@535:     void setSmooth(bool i);
Chris@535:     bool getSmooth() const;
Chris@535: 
Chris@444:     virtual bool getValueExtents(float &min, float &max,
Chris@444:                                  bool &logarithmic, QString &unit) const;
Chris@444: 
Chris@444:     virtual bool getDisplayExtents(float &min, float &max) const;
Chris@444:     virtual bool setDisplayExtents(float min, float max);
Chris@444: 
Chris@725:     virtual bool getYScaleValue(const View *, int /* y */,
Chris@725:                                 float &/* value */, QString &/* unit */) const;
Chris@725: 
Chris@444:     virtual int getVerticalZoomSteps(int &defaultStep) const;
Chris@444:     virtual int getCurrentVerticalZoomStep() const;
Chris@444:     virtual void setVerticalZoomStep(int);
Chris@444:     virtual RangeMapper *getNewVerticalZoomRangeMapper() const;
Chris@444: 
Chris@193:     virtual const Model *getSliceableModel() const { return m_model; }
Chris@193: 
Chris@316:     virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316:                        QString extraAttributes = "") const;
Chris@197: 
Chris@0: protected slots:
Chris@0:     void cacheInvalid();
Chris@0:     void cacheInvalid(size_t startFrame, size_t endFrame);
Chris@461:     void modelChanged();
Chris@461:     void modelChanged(size_t, size_t);
Chris@0: 
Chris@0: protected:
Chris@0:     const DenseThreeDimensionalModel *m_model; // I do not own this
Chris@0:     
Chris@0:     mutable QImage *m_cache;
Chris@469:     mutable QImage *m_peaksCache;
Chris@461:     mutable size_t m_cacheValidStart;
Chris@461:     mutable size_t m_cacheValidEnd;
Chris@98: 
Chris@159:     ColourScale m_colourScale;
Chris@461:     bool        m_colourScaleSet;
Chris@197:     int         m_colourMap;
Chris@534:     float       m_gain;
Chris@531:     BinScale    m_binScale;
Chris@197:     bool        m_normalizeColumns;
Chris@197:     bool        m_normalizeVisibleArea;
Chris@719:     bool        m_normalizeHybrid;
Chris@357:     bool        m_invertVertical;
Chris@465:     bool        m_opaque;
Chris@535:     bool        m_smooth;
Chris@469:     size_t      m_peakResolution;
Chris@197: 
Chris@725:     // Minimum and maximum bin numbers visible within the view. We
Chris@725:     // always snap to whole bins at view edges.
Chris@444:     int         m_miny;
Chris@444:     int         m_maxy;
Chris@725: 
Chris@725:     /**
Chris@725:      * Return the y coordinate at which the given bin "starts"
Chris@725:      * (i.e. at the bottom of the bin, if the given bin is an integer
Chris@725:      * and the vertical scale is the usual way up). Bin number may be
Chris@725:      * fractional, to obtain a position part-way through a bin.
Chris@725:      */
Chris@725:     float getYForBin(View *, float bin) const;
Chris@725: 
Chris@725:     /**
Chris@725:      * Return the bin number, possibly fractional, at the given y
Chris@725:      * coordinate. Note that the whole numbers occur at the positions
Chris@725:      * at which the bins "start" (i.e. the bottom of the visible bin,
Chris@725:      * if the vertical scale is the usual way up).
Chris@725:      */
Chris@725:     float getBinForY(View *, float y) const;
Chris@444:     
Chris@467:     DenseThreeDimensionalModel::Column getColumn(size_t col) const;
Chris@159: 
Chris@469:     int getColourScaleWidth(QPainter &) const;
Chris@469:     void fillCache(size_t firstBin, size_t lastBin) const;
Chris@469:     void paintDense(View *v, QPainter &paint, QRect rect) const;
Chris@0: };
Chris@0: 
Chris@0: #endif