annotate view/ViewProxy.h @ 1534:bfd8b22fd67c

Fix #1904 Scrolling colour 3d plot does not always work when in View normalisation mode. We shouldn't imagine we've just invalidated the cache if the truth is that we've only just created the renderer
author Chris Cannam
date Wed, 09 Oct 2019 13:45:17 +0100
parents 2f505d843d14
children 4f8c72adbf43
rev   line source
Chris@919 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@919 2
Chris@919 3 /*
Chris@919 4 Sonic Visualiser
Chris@919 5 An audio file viewer and annotation editor.
Chris@919 6 Centre for Digital Music, Queen Mary, University of London.
Chris@919 7
Chris@919 8 This program is free software; you can redistribute it and/or
Chris@919 9 modify it under the terms of the GNU General Public License as
Chris@919 10 published by the Free Software Foundation; either version 2 of the
Chris@919 11 License, or (at your option) any later version. See the file
Chris@919 12 COPYING included with this distribution for more information.
Chris@919 13 */
Chris@919 14
Chris@919 15 #ifndef VIEW_PROXY_H
Chris@919 16 #define VIEW_PROXY_H
Chris@919 17
Chris@1077 18 #include "layer/LayerGeometryProvider.h"
Chris@919 19
Chris@1490 20 #include "data/model/AlignmentModel.h"
Chris@1490 21
Chris@919 22 class ViewProxy : public LayerGeometryProvider
Chris@919 23 {
Chris@919 24 public:
Chris@1490 25 /**
Chris@1490 26 * Create a standard ViewProxy for the given view, mapping using
Chris@1490 27 * the given scale factor. The scale factor is generally used with
Chris@1490 28 * pixel-doubled "retina" Mac displays and is usually 1 elsewhere.
Chris@1490 29 */
Chris@919 30 ViewProxy(View *view, int scaleFactor) :
Chris@1266 31 m_view(view), m_scaleFactor(scaleFactor) { }
Chris@919 32
Chris@1490 33 /**
Chris@1490 34 * Create a re-aligning ViewProxy for the given view, mapping
Chris@1490 35 * using the given scale factor. The scale factor is generally
Chris@1490 36 * used with pixel-doubled "retina" Mac displays and is usually 1
Chris@1490 37 * elsewhere.
Chris@1490 38 *
Chris@1490 39 * Coordinates are mapped through the given alignment model, such
Chris@1490 40 * that frame values passed from the caller are mapped "from
Chris@1490 41 * reference" by that alignment before being used by the view or
Chris@1490 42 * converted to pixel coordinates, and returned values are mapped
Chris@1490 43 * back "to reference" before being passed back to the caller.
Chris@1490 44 *
Chris@1490 45 * This form of proxy may be created specially for rendering a
Chris@1490 46 * single layer which comes from a different alignment to that of
Chris@1490 47 * the rest of the containing view.
Chris@1490 48 */
Chris@1490 49 ViewProxy(View *view, int scaleFactor, ModelId alignment) :
Chris@1490 50 m_view(view), m_scaleFactor(scaleFactor), m_alignment(alignment) { }
Chris@1490 51
Chris@1406 52 int getId() const override {
Chris@1044 53 return m_view->getId();
Chris@1044 54 }
Chris@1406 55 sv_frame_t getStartFrame() const override {
Chris@1490 56 return alignToReference(m_view->getStartFrame());
Chris@919 57 }
Chris@1406 58 sv_frame_t getCentreFrame() const override {
Chris@1490 59 return alignToReference(m_view->getCentreFrame());
Chris@919 60 }
Chris@1406 61 sv_frame_t getEndFrame() const override {
Chris@1490 62 return alignToReference(m_view->getEndFrame());
Chris@919 63 }
Chris@1406 64 int getXForFrame(sv_frame_t frame) const override {
Chris@950 65 //!!! not actually correct, if frame lies between view's pixels
Chris@1490 66 return m_scaleFactor * m_view->getXForFrame(alignFromReference(frame));
Chris@919 67 }
Chris@1406 68 sv_frame_t getFrameForX(int x) const override {
Chris@950 69 sv_frame_t f0 = m_view->getFrameForX(x / m_scaleFactor);
Chris@1491 70 if (m_scaleFactor == 1) return alignToReference(f0);
Chris@950 71 sv_frame_t f1 = m_view->getFrameForX((x / m_scaleFactor) + 1);
Chris@1490 72 sv_frame_t f = f0 + ((f1 - f0) * (x % m_scaleFactor)) / m_scaleFactor;
Chris@1490 73 return alignToReference(f);
Chris@919 74 }
Chris@1406 75 int getXForViewX(int viewx) const override {
Chris@1030 76 return viewx * m_scaleFactor;
Chris@1030 77 }
Chris@1406 78 int getViewXForX(int x) const override {
Chris@1030 79 return x / m_scaleFactor;
Chris@1030 80 }
Chris@1406 81 sv_frame_t getModelsStartFrame() const override {
Chris@1490 82 return alignToReference(m_view->getModelsStartFrame());
Chris@919 83 }
Chris@1406 84 sv_frame_t getModelsEndFrame() const override {
Chris@1490 85 return alignToReference(m_view->getModelsEndFrame());
Chris@919 86 }
Chris@1406 87 double getYForFrequency(double frequency,
Chris@1266 88 double minFreq, double maxFreq,
Chris@1406 89 bool logarithmic) const override {
Chris@1266 90 return m_scaleFactor *
Chris@1266 91 m_view->getYForFrequency(frequency, minFreq, maxFreq, logarithmic);
Chris@919 92 }
Chris@1406 93 double getFrequencyForY(double y, double minFreq, double maxFreq,
Chris@1406 94 bool logarithmic) const override {
Chris@1085 95 return m_view->getFrequencyForY
Chris@950 96 (y / m_scaleFactor, minFreq, maxFreq, logarithmic);
Chris@919 97 }
Chris@1406 98 int getTextLabelHeight(const Layer *layer, QPainter &paint) const override {
Chris@1266 99 return m_scaleFactor * m_view->getTextLabelHeight(layer, paint);
Chris@919 100 }
Chris@1406 101 bool getValueExtents(QString unit, double &min, double &max,
Chris@1406 102 bool &log) const override {
Chris@1266 103 return m_view->getValueExtents(unit, min, max, log);
Chris@919 104 }
Chris@1406 105 ZoomLevel getZoomLevel() const override {
Chris@1326 106 ZoomLevel z = m_view->getZoomLevel();
Chris@1326 107 //!!!
Chris@1329 108 // cerr << "getZoomLevel: from " << z << " to ";
Chris@1326 109 if (z.zone == ZoomLevel::FramesPerPixel) {
Chris@1326 110 z.level /= m_scaleFactor;
Chris@1326 111 if (z.level < 1) {
Chris@1326 112 z.level = 1;
Chris@1326 113 }
Chris@1326 114 } else {
Chris@1326 115 //!!!???
Chris@1326 116 z.level *= m_scaleFactor;
Chris@1326 117 }
Chris@1329 118 // cerr << z << endl;
Chris@1266 119 return z;
Chris@919 120 }
Chris@1406 121 QRect getPaintRect() const override {
Chris@1266 122 QRect r = m_view->getPaintRect();
Chris@1266 123 return QRect(r.x() * m_scaleFactor,
Chris@1266 124 r.y() * m_scaleFactor,
Chris@1266 125 r.width() * m_scaleFactor,
Chris@1266 126 r.height() * m_scaleFactor);
Chris@919 127 }
Chris@1406 128 QSize getPaintSize() const override {
Chris@954 129 return getPaintRect().size();
Chris@954 130 }
Chris@1406 131 int getPaintWidth() const override {
Chris@954 132 return getPaintRect().width();
Chris@954 133 }
Chris@1406 134 int getPaintHeight() const override {
Chris@954 135 return getPaintRect().height();
Chris@954 136 }
Chris@1406 137 bool hasLightBackground() const override {
Chris@1266 138 return m_view->hasLightBackground();
Chris@919 139 }
Chris@1406 140 QColor getForeground() const override {
Chris@1266 141 return m_view->getForeground();
Chris@919 142 }
Chris@1406 143 QColor getBackground() const override {
Chris@1266 144 return m_view->getBackground();
Chris@919 145 }
Chris@1406 146 ViewManager *getViewManager() const override {
Chris@1266 147 return m_view->getViewManager();
Chris@919 148 }
Chris@1266 149
Chris@1406 150 bool shouldIlluminateLocalFeatures(const Layer *layer,
Chris@1406 151 QPoint &point) const override {
Chris@954 152 QPoint p;
Chris@1266 153 bool should = m_view->shouldIlluminateLocalFeatures(layer, p);
Chris@954 154 point = QPoint(p.x() * m_scaleFactor, p.y() * m_scaleFactor);
Chris@954 155 return should;
Chris@919 156 }
Chris@954 157
Chris@1406 158 bool shouldShowFeatureLabels() const override {
Chris@1266 159 return m_view->shouldShowFeatureLabels();
Chris@919 160 }
Chris@919 161
Chris@1406 162 void drawMeasurementRect(QPainter &p, const Layer *layer,
Chris@1406 163 QRect rect, bool focus) const override {
Chris@1266 164 m_view->drawMeasurementRect(p, layer, rect, focus);
Chris@919 165 }
Chris@919 166
Chris@1406 167 void updatePaintRect(QRect r) override {
Chris@1030 168 m_view->update(r.x() / m_scaleFactor,
Chris@1030 169 r.y() / m_scaleFactor,
Chris@1030 170 r.width() / m_scaleFactor,
Chris@1030 171 r.height() / m_scaleFactor);
Chris@1030 172 }
Chris@1401 173
Chris@1401 174 /**
Chris@1401 175 * Scale up a size in pixels for a hi-dpi display without pixel
Chris@1401 176 * doubling. This is like ViewManager::scalePixelSize, but taking
Chris@1401 177 * and returning floating-point values rather than integer
Chris@1401 178 * pixels. It is also a little more conservative - it never
Chris@1401 179 * shrinks the size, it can only increase or leave it unchanged.
Chris@1401 180 */
Chris@1406 181 double scaleSize(double size) const override {
Chris@1401 182 return m_view->scaleSize(size * m_scaleFactor);
Chris@1401 183 }
Chris@1401 184
Chris@1401 185 /**
Chris@1402 186 * Integer version of scaleSize.
Chris@1402 187 */
Chris@1406 188 int scalePixelSize(int size) const override {
Chris@1402 189 return m_view->scalePixelSize(size * m_scaleFactor);
Chris@1402 190 }
Chris@1402 191
Chris@1402 192 /**
Chris@1401 193 * Scale up pen width for a hi-dpi display without pixel doubling.
Chris@1401 194 * This is like scaleSize except that it also scales the
Chris@1401 195 * zero-width case.
Chris@1401 196 */
Chris@1406 197 double scalePenWidth(double width) const override {
Chris@1401 198 if (width <= 0) { // zero-width pen, produce a scaled one-pixel pen
Chris@1401 199 width = 1;
Chris@1401 200 }
Chris@1401 201 width *= sqrt(double(m_scaleFactor));
Chris@1401 202 return m_view->scalePenWidth(width);
Chris@1401 203 }
Chris@1401 204
Chris@1401 205 /**
Chris@1401 206 * Apply scalePenWidth to a pen.
Chris@1401 207 */
Chris@1406 208 QPen scalePen(QPen pen) const override {
Chris@1401 209 return QPen(pen.color(), scalePenWidth(pen.width()));
Chris@1401 210 }
Chris@1030 211
Chris@1406 212 View *getView() override { return m_view; }
Chris@1406 213 const View *getView() const override { return m_view; }
Chris@919 214
Chris@919 215 private:
Chris@919 216 View *m_view;
Chris@919 217 int m_scaleFactor;
Chris@1490 218 ModelId m_alignment;
Chris@1490 219
Chris@1490 220 sv_frame_t alignToReference(sv_frame_t frame) const {
Chris@1490 221 if (auto am = ModelById::getAs<AlignmentModel>(m_alignment)) {
Chris@1490 222 return am->toReference(frame);
Chris@1490 223 } else {
Chris@1490 224 return frame;
Chris@1490 225 }
Chris@1490 226 }
Chris@1490 227
Chris@1490 228 sv_frame_t alignFromReference(sv_frame_t frame) const {
Chris@1490 229 if (auto am = ModelById::getAs<AlignmentModel>(m_alignment)) {
Chris@1490 230 return am->fromReference(frame);
Chris@1490 231 } else {
Chris@1490 232 return frame;
Chris@1490 233 }
Chris@1490 234 }
Chris@919 235 };
Chris@919 236
Chris@919 237 #endif