Chris@916: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@916: 
Chris@916: /*
Chris@916:     Sonic Visualiser
Chris@916:     An audio file viewer and annotation editor.
Chris@916:     Centre for Digital Music, Queen Mary, University of London.
Chris@916:     
Chris@916:     This program is free software; you can redistribute it and/or
Chris@916:     modify it under the terms of the GNU General Public License as
Chris@916:     published by the Free Software Foundation; either version 2 of the
Chris@916:     License, or (at your option) any later version.  See the file
Chris@916:     COPYING included with this distribution for more information.
Chris@916: */
Chris@916: 
Chris@916: #ifndef LAYER_GEOMETRY_PROVIDER_H
Chris@916: #define LAYER_GEOMETRY_PROVIDER_H
Chris@916: 
Chris@916: #include "base/BaseTypes.h"
Chris@916: 
Chris@1030: #include <QMutex>
Chris@1030: #include <QMutexLocker>
Chris@1031: #include <QPainter>
Chris@1030: 
Chris@916: class ViewManager;
Chris@918: class View;
Chris@916: class Layer;
Chris@916: 
Chris@1090: /**
Chris@1090:  * Interface for classes that provide geometry information (such as
Chris@1090:  * size, start frame, and a large number of other properties) about
Chris@1090:  * the disposition of a layer. The main implementor of this interface
Chris@1090:  * is the View class, but other implementations may be used in
Chris@1090:  * different circumstances, e.g. as a proxy to handle hi-dpi
Chris@1090:  * coordinate mapping.
Chris@1090:  *
Chris@1090:  * Note it is expected that some implementations of this may be
Chris@1090:  * disposable, created on-the-fly for a single use. Code that receives
Chris@1090:  * a LayerGeometryProvider pointer as an argument to something should
Chris@1090:  * not, in general, store that pointer as it may be invalidated before
Chris@1090:  * the next use. Use getId() to instead obtain a persistent identifier
Chris@1090:  * for a LayerGeometryProvider, for example to establish whether the
Chris@1090:  * same one is being provided in two separate calls.
Chris@1090:  */
Chris@916: class LayerGeometryProvider
Chris@916: {
Chris@1044: protected:
Chris@1044:     static int getNextId() {
Chris@1030:         static QMutex idMutex;
Chris@1030:         static int nextId = 1;
Chris@1044:         static int maxId = INT_MAX;
Chris@1030:         QMutexLocker locker(&idMutex);
Chris@1044:         int id = nextId;
Chris@1044:         if (nextId == maxId) {
Chris@1044:             // we don't expect this to happen in the lifetime of a
Chris@1044:             // process, but it would be undefined behaviour if it did
Chris@1044:             // since we're using a signed int, so we should really
Chris@1044:             // guard for it...
Chris@1044:             nextId = 1;
Chris@1044:         } else {
Chris@1044:             nextId++;
Chris@1044:         }
Chris@1044:         return id;
Chris@1044:     }            
Chris@1044:     
Chris@1044: public:
Chris@1044:     LayerGeometryProvider() { }
Chris@1030:     
Chris@1030:     /**
Chris@1044:      * Retrieve the id of this object.
Chris@1030:      */
Chris@1044:     virtual int getId() const = 0;
Chris@1030: 
Chris@916:     /**
Chris@916:      * Retrieve the first visible sample frame on the widget.
Chris@916:      * This is a calculated value based on the centre-frame, widget
Chris@916:      * width and zoom level.  The result may be negative.
Chris@916:      */
Chris@916:     virtual sv_frame_t getStartFrame() const = 0;
Chris@916: 
Chris@916:     /**
Chris@916:      * Return the centre frame of the visible widget.  This is an
Chris@916:      * exact value that does not depend on the zoom block size.  Other
Chris@916:      * frame values (start, end) are calculated from this based on the
Chris@916:      * zoom and other factors.
Chris@916:      */
Chris@916:     virtual sv_frame_t getCentreFrame() const = 0;
Chris@916: 
Chris@916:     /**
Chris@916:      * Retrieve the last visible sample frame on the widget.
Chris@916:      * This is a calculated value based on the centre-frame, widget
Chris@916:      * width and zoom level.
Chris@916:      */
Chris@916:     virtual sv_frame_t getEndFrame() const = 0;
Chris@916: 
Chris@916:     /**
Chris@916:      * Return the pixel x-coordinate corresponding to a given sample
Chris@916:      * frame (which may be negative).
Chris@916:      */
Chris@916:     virtual int getXForFrame(sv_frame_t frame) const = 0;
Chris@916: 
Chris@916:     /**
Chris@916:      * Return the closest frame to the given pixel x-coordinate.
Chris@916:      */
Chris@916:     virtual sv_frame_t getFrameForX(int x) const = 0;
Chris@916: 
Chris@919:     virtual sv_frame_t getModelsStartFrame() const = 0;
Chris@919:     virtual sv_frame_t getModelsEndFrame() const = 0;
Chris@919: 
Chris@916:     /**
Chris@1030:      * Return the closest pixel x-coordinate corresponding to a given
Chris@1030:      * view x-coordinate.
Chris@1030:      */
Chris@1030:     virtual int getXForViewX(int viewx) const = 0;
Chris@1030:     
Chris@1030:     /**
Chris@1030:      * Return the closest view x-coordinate corresponding to a given
Chris@1030:      * pixel x-coordinate.
Chris@1030:      */
Chris@1030:     virtual int getViewXForX(int x) const = 0;
Chris@1030:     
Chris@1030:     /**
Chris@1085:      * Return the (maybe fractional) pixel y-coordinate corresponding
Chris@1085:      * to a given frequency, if the frequency range is as specified.
Chris@1085:      * This does not imply any policy about layer frequency ranges,
Chris@1085:      * but it might be useful for layers to match theirs up if
Chris@1085:      * desired.
Chris@916:      *
Chris@916:      * Not thread-safe in logarithmic mode.  Call only from GUI thread.
Chris@916:      */
Chris@1085:     virtual double getYForFrequency(double frequency,
Chris@1085:                                     double minFreq, double maxFreq, 
Chris@916:                                     bool logarithmic) const = 0;
Chris@916: 
Chris@916:     /**
Chris@1085:      * Return the closest frequency to the given (maybe fractional)
Chris@1085:      * pixel y-coordinate, if the frequency range is as specified.
Chris@916:      *
Chris@916:      * Not thread-safe in logarithmic mode.  Call only from GUI thread.
Chris@916:      */
Chris@1085:     virtual double getFrequencyForY(double y,
Chris@1085:                                     double minFreq, double maxFreq,
Chris@1082:                                     bool logarithmic) const = 0;
Chris@916: 
Chris@918:     virtual int getTextLabelHeight(const Layer *layer, QPainter &) const = 0;
Chris@918: 
Chris@918:     virtual bool getValueExtents(QString unit, double &min, double &max,
Chris@918:                                  bool &log) const = 0;
Chris@918: 
Chris@916:     /**
Chris@916:      * Return the zoom level, i.e. the number of frames per pixel
Chris@916:      */
Chris@916:     virtual int getZoomLevel() const = 0;
Chris@916: 
Chris@916:     /**
Chris@916:      * To be called from a layer, to obtain the extent of the surface
Chris@916:      * that the layer is currently painting to. This may be the extent
Chris@916:      * of the view (if 1x display scaling is in effect) or of a larger
Chris@916:      * cached pixmap (if greater display scaling is in effect).
Chris@916:      */
Chris@916:     virtual QRect getPaintRect() const = 0;
Chris@916: 
Chris@916:     virtual QSize getPaintSize() const { return getPaintRect().size(); }
Chris@916:     virtual int getPaintWidth() const { return getPaintRect().width(); }
Chris@916:     virtual int getPaintHeight() const { return getPaintRect().height(); }
Chris@916: 
Chris@916:     virtual bool hasLightBackground() const = 0;
Chris@916:     virtual QColor getForeground() const = 0;
Chris@916:     virtual QColor getBackground() const = 0;
Chris@916: 
Chris@916:     virtual ViewManager *getViewManager() const = 0;
Chris@916: 
Chris@916:     virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const = 0;
Chris@919:     virtual bool shouldShowFeatureLabels() const = 0;
Chris@916: 
Chris@916:     virtual void drawMeasurementRect(QPainter &p, const Layer *,
Chris@916:                                      QRect rect, bool focus) const = 0;
Chris@916: 
Chris@1030:     virtual void updatePaintRect(QRect r) = 0;
Chris@1030:     
Chris@918:     virtual View *getView() = 0;
Chris@918:     virtual const View *getView() const = 0;
Chris@916: };
Chris@916: 
Chris@916: #endif