annotate layer/SingleColourLayer.cpp @ 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 c8a6fd3f9dff
children
rev   line source
Chris@287 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@287 2
Chris@287 3 /*
Chris@287 4 Sonic Visualiser
Chris@287 5 An audio file viewer and annotation editor.
Chris@287 6 Centre for Digital Music, Queen Mary, University of London.
Chris@287 7 This file copyright 2007 QMUL.
Chris@287 8
Chris@287 9 This program is free software; you can redistribute it and/or
Chris@287 10 modify it under the terms of the GNU General Public License as
Chris@287 11 published by the Free Software Foundation; either version 2 of the
Chris@287 12 License, or (at your option) any later version. See the file
Chris@287 13 COPYING included with this distribution for more information.
Chris@287 14 */
Chris@287 15
Chris@287 16 #include "SingleColourLayer.h"
Chris@376 17 #include "ColourDatabase.h"
Chris@287 18 #include "view/View.h"
Chris@287 19
Chris@287 20 #include <iostream>
Chris@287 21
Chris@316 22 #include <QTextStream>
Chris@287 23 #include <QApplication>
Chris@287 24
Chris@367 25 //#define DEBUG_COLOUR_SELECTION 1
Chris@367 26
Chris@293 27 SingleColourLayer::ColourRefCount
Chris@293 28 SingleColourLayer::m_colourRefCount;
Chris@287 29
Chris@287 30 SingleColourLayer::SingleColourLayer() :
Chris@294 31 m_colour(0),
Chris@366 32 m_colourExplicitlySet(false),
Chris@366 33 m_defaultColourSet(false)
Chris@287 34 {
jakob@768 35 // Reference current colour because setDefaulColourFor
jakob@768 36 // will unreference it before (possibly) changing it.
jakob@768 37 refColor();
Chris@1408 38 setDefaultColourFor(nullptr);
Chris@287 39 }
Chris@287 40
jakob@768 41 SingleColourLayer::~SingleColourLayer()
jakob@768 42 {
jakob@768 43 unrefColor();
jakob@768 44 }
jakob@768 45
Chris@299 46 QPixmap
Chris@299 47 SingleColourLayer::getLayerPresentationPixmap(QSize size) const
Chris@299 48 {
Chris@299 49 return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size);
Chris@299 50 }
Chris@299 51
Chris@287 52 bool
Chris@287 53 SingleColourLayer::hasLightBackground() const
Chris@287 54 {
Chris@287 55 bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour);
Chris@287 56 return !dark;
Chris@287 57 }
Chris@287 58
Chris@287 59 Layer::PropertyList
Chris@287 60 SingleColourLayer::getProperties() const
Chris@287 61 {
Chris@287 62 PropertyList list = Layer::getProperties();
Chris@287 63 list.push_back("Colour");
Chris@287 64 return list;
Chris@287 65 }
Chris@287 66
Chris@287 67 QString
Chris@287 68 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
Chris@287 69 {
Chris@287 70 if (name == "Colour") return tr("Colour");
Chris@287 71 return "";
Chris@287 72 }
Chris@287 73
Chris@287 74 Layer::PropertyType
Chris@287 75 SingleColourLayer::getPropertyType(const PropertyName &name) const
Chris@287 76 {
Chris@287 77 if (name == "Colour") return ColourProperty;
Chris@287 78 return InvalidProperty;
Chris@287 79 }
Chris@287 80
Chris@287 81 QString
Chris@287 82 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
Chris@287 83 {
Chris@287 84 return QString();
Chris@287 85 }
Chris@287 86
Chris@287 87 int
Chris@287 88 SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@287 89 int *min, int *max, int *deflt) const
Chris@287 90 {
Chris@287 91 int val = 0;
Chris@287 92
Chris@287 93 int garbage0, garbage1, garbage2;
Chris@287 94 if (!min) min = &garbage0;
Chris@287 95 if (!max) max = &garbage1;
Chris@287 96 if (!deflt) deflt = &garbage2;
Chris@287 97
Chris@287 98 if (name == "Colour") {
Chris@287 99
Chris@287 100 ColourDatabase::getInstance()->getColourPropertyRange(min, max);
Chris@287 101 *deflt = 0; //!!!
Chris@287 102
Chris@287 103 val = m_colour;
Chris@287 104
Chris@287 105 } else {
Chris@1266 106 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@287 107 }
Chris@287 108
Chris@287 109 return val;
Chris@287 110 }
Chris@287 111
Chris@287 112 QString
Chris@287 113 SingleColourLayer::getPropertyValueLabel(const PropertyName &name,
Chris@1266 114 int value) const
Chris@287 115 {
Chris@287 116 if (name == "Colour") {
Chris@376 117 ColourDatabase *db = ColourDatabase::getInstance();
Chris@805 118 if (value >= 0 && value < db->getColourCount()) {
Chris@376 119 return db->getColourName(value);
Chris@376 120 }
Chris@287 121 }
Chris@287 122 return tr("<unknown>");
Chris@287 123 }
Chris@287 124
Chris@287 125 RangeMapper *
Chris@287 126 SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@287 127 {
Chris@1408 128 return nullptr;
Chris@287 129 }
Chris@287 130
Chris@287 131 void
Chris@287 132 SingleColourLayer::setProperty(const PropertyName &name, int value)
Chris@287 133 {
Chris@287 134 if (name == "Colour") {
Chris@287 135 setBaseColour(value);
Chris@287 136 }
Chris@287 137 }
Chris@287 138
Chris@287 139 void
Chris@919 140 SingleColourLayer::setDefaultColourFor(LayerGeometryProvider *v)
Chris@287 141 {
Chris@367 142 #ifdef DEBUG_COLOUR_SELECTION
Chris@587 143 SVDEBUG << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << endl;
Chris@367 144 #endif
Chris@366 145
Chris@366 146 if (m_colourExplicitlySet || m_defaultColourSet) return;
Chris@294 147
Chris@367 148 if (v) m_defaultColourSet = true; // v==0 case doesn't really count
Chris@367 149
Chris@287 150 bool dark = false;
Chris@287 151 if (v) {
Chris@287 152 dark = !v->hasLightBackground();
Chris@287 153 } else {
Chris@287 154 QColor bg = QApplication::palette().color(QPalette::Window);
Chris@287 155 if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
Chris@287 156 }
Chris@287 157
Chris@287 158 ColourDatabase *cdb = ColourDatabase::getInstance();
Chris@287 159
Chris@287 160 int hint = -1;
Chris@287 161 bool impose = false;
Chris@287 162 if (v) {
Chris@287 163 // We don't want to call this if !v because that probably
Chris@287 164 // means we're being called from the constructor, and this is
Chris@287 165 // a virtual function
Chris@287 166 hint = getDefaultColourHint(dark, impose);
Chris@367 167 #ifdef DEBUG_COLOUR_SELECTION
Chris@682 168 cerr << "hint = " << hint << ", impose = " << impose << endl;
Chris@367 169 #endif
Chris@293 170 } else {
Chris@367 171 #ifdef DEBUG_COLOUR_SELECTION
Chris@682 172 cerr << "(from ctor)" << endl;
Chris@367 173 #endif
Chris@287 174 }
Chris@287 175
Chris@287 176 if (hint >= 0 && impose) {
Chris@293 177 setBaseColour(hint);
Chris@287 178 return;
Chris@287 179 }
Chris@287 180
jakob@768 181 unrefColor();
jakob@768 182
Chris@293 183 int bestCount = 0, bestColour = -1;
Chris@293 184
Chris@287 185 for (int i = 0; i < cdb->getColourCount(); ++i) {
Chris@293 186
Chris@287 187 int index = i;
Chris@287 188 if (hint > 0) index = (index + hint) % cdb->getColourCount();
Chris@287 189 if (cdb->useDarkBackground(index) != dark) continue;
Chris@293 190
Chris@293 191 int count = 0;
Chris@293 192 if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
Chris@293 193 count = m_colourRefCount[index];
Chris@287 194 }
Chris@293 195
Chris@367 196 #ifdef DEBUG_COLOUR_SELECTION
Chris@682 197 cerr << "index = " << index << ", count = " << count;
Chris@367 198 #endif
Chris@293 199
Chris@293 200 if (bestColour < 0 || count < bestCount) {
Chris@293 201 bestColour = index;
Chris@293 202 bestCount = count;
Chris@367 203 #ifdef DEBUG_COLOUR_SELECTION
Chris@682 204 cerr << " *";
Chris@367 205 #endif
Chris@293 206 }
Chris@293 207
Chris@367 208 #ifdef DEBUG_COLOUR_SELECTION
Chris@682 209 cerr << endl;
Chris@367 210 #endif
Chris@287 211 }
jakob@768 212
Chris@293 213 if (bestColour < 0) m_colour = 0;
Chris@293 214 else m_colour = bestColour;
Chris@287 215
jakob@768 216 refColor();
Chris@287 217 }
Chris@287 218
Chris@287 219 void
Chris@287 220 SingleColourLayer::setBaseColour(int colour)
Chris@287 221 {
Chris@294 222 m_colourExplicitlySet = true;
Chris@294 223
Chris@287 224 if (m_colour == colour) return;
Chris@293 225
jakob@768 226 refColor();
Chris@287 227 m_colour = colour;
jakob@768 228 unrefColor();
Chris@293 229
Chris@287 230 flagBaseColourChanged();
Chris@287 231 emit layerParametersChanged();
Chris@287 232 }
Chris@287 233
Chris@287 234 int
Chris@287 235 SingleColourLayer::getBaseColour() const
Chris@287 236 {
Chris@287 237 return m_colour;
Chris@287 238 }
Chris@287 239
Chris@287 240 QColor
Chris@287 241 SingleColourLayer::getBaseQColor() const
Chris@287 242 {
Chris@287 243 return ColourDatabase::getInstance()->getColour(m_colour);
Chris@287 244 }
Chris@287 245
Chris@287 246 QColor
Chris@919 247 SingleColourLayer::getBackgroundQColor(LayerGeometryProvider *v) const
Chris@287 248 {
Chris@287 249 return v->getBackground();
Chris@287 250 }
Chris@287 251
Chris@287 252 QColor
Chris@919 253 SingleColourLayer::getForegroundQColor(LayerGeometryProvider *v) const
Chris@287 254 {
Chris@287 255 return v->getForeground();
Chris@287 256 }
Chris@287 257
Chris@287 258 std::vector<QColor>
Chris@919 259 SingleColourLayer::getPartialShades(LayerGeometryProvider *v) const
Chris@287 260 {
Chris@287 261 std::vector<QColor> s;
Chris@287 262 QColor base = getBaseQColor();
Chris@287 263 QColor bg = getBackgroundQColor(v);
Chris@287 264 for (int i = 0; i < 3; ++i) {
Chris@287 265 int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
Chris@287 266 int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
Chris@287 267 int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
Chris@287 268 s.push_back(QColor(red, green, blue));
Chris@287 269 }
Chris@287 270 return s;
Chris@287 271 }
Chris@287 272
Chris@316 273 void
Chris@316 274 SingleColourLayer::toXml(QTextStream &stream,
Chris@316 275 QString indent, QString extraAttributes) const
Chris@287 276 {
Chris@287 277 QString s;
Chris@287 278
Chris@287 279 QString colourName, colourSpec, darkbg;
Chris@287 280 ColourDatabase::getInstance()->getStringValues
Chris@287 281 (m_colour, colourName, colourSpec, darkbg);
Chris@287 282
Chris@287 283 s += QString("colourName=\"%1\" "
Chris@287 284 "colour=\"%2\" "
Chris@287 285 "darkBackground=\"%3\" ")
Chris@1266 286 .arg(colourName)
Chris@287 287 .arg(colourSpec)
Chris@287 288 .arg(darkbg);
Chris@287 289
Chris@316 290 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@287 291 }
Chris@287 292
Chris@287 293 void
Chris@287 294 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
Chris@287 295 {
Chris@287 296 QString colourName = attributes.value("colourName");
Chris@287 297 QString colourSpec = attributes.value("colour");
Chris@287 298 QString darkbg = attributes.value("darkBackground");
Chris@296 299
Chris@296 300 int colour = ColourDatabase::getInstance()->putStringValues
Chris@287 301 (colourName, colourSpec, darkbg);
Chris@296 302
jakob@767 303 if (colour == -1)
jakob@767 304 return;
jakob@767 305
Chris@296 306 m_colourExplicitlySet = true;
Chris@296 307
Chris@296 308 if (m_colour != colour) {
Chris@296 309
Chris@367 310 #ifdef DEBUG_COLOUR_SELECTION
Chris@587 311 SVDEBUG << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << endl;
Chris@367 312 #endif
Chris@296 313
jakob@768 314 unrefColor();
Chris@296 315 m_colour = colour;
jakob@768 316 refColor();
Chris@296 317
Chris@296 318 flagBaseColourChanged();
Chris@294 319 }
Chris@287 320 }
Chris@287 321
jakob@768 322 void SingleColourLayer::refColor()
jakob@768 323 {
jakob@768 324 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
jakob@768 325 m_colourRefCount[m_colour] = 1;
jakob@768 326 } else {
jakob@768 327 m_colourRefCount[m_colour]++;
jakob@768 328 }
jakob@768 329 }
jakob@768 330
jakob@768 331 void SingleColourLayer::unrefColor()
jakob@768 332 {
jakob@768 333 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
jakob@768 334 m_colourRefCount[m_colour] > 0) {
jakob@768 335 m_colourRefCount[m_colour]--;
jakob@768 336 }
jakob@768 337 }