annotate layer/SingleColourLayer.cpp @ 369:63971199663a

* Allow entry of numbers smaller than 1 in the Set Counters dialog * Renumber Selected Instants now starts its count at the next counter value -- previously it always started at 1:1 and the values that you had set were only used when tapping * pull Reset Counters up a menu level to make it easier to get to
author Chris Cannam
date Tue, 12 Feb 2008 15:41:01 +0000
parents 06360ed99cd1
children e1a9e478b7f2
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@287 17 #include "base/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 {
Chris@287 35 setDefaultColourFor(0);
Chris@287 36 }
Chris@287 37
Chris@299 38 QPixmap
Chris@299 39 SingleColourLayer::getLayerPresentationPixmap(QSize size) const
Chris@299 40 {
Chris@299 41 return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size);
Chris@299 42 }
Chris@299 43
Chris@287 44 bool
Chris@287 45 SingleColourLayer::hasLightBackground() const
Chris@287 46 {
Chris@287 47 bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour);
Chris@287 48 return !dark;
Chris@287 49 }
Chris@287 50
Chris@287 51 Layer::PropertyList
Chris@287 52 SingleColourLayer::getProperties() const
Chris@287 53 {
Chris@287 54 PropertyList list = Layer::getProperties();
Chris@287 55 list.push_back("Colour");
Chris@287 56 return list;
Chris@287 57 }
Chris@287 58
Chris@287 59 QString
Chris@287 60 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
Chris@287 61 {
Chris@287 62 if (name == "Colour") return tr("Colour");
Chris@287 63 return "";
Chris@287 64 }
Chris@287 65
Chris@287 66 Layer::PropertyType
Chris@287 67 SingleColourLayer::getPropertyType(const PropertyName &name) const
Chris@287 68 {
Chris@287 69 if (name == "Colour") return ColourProperty;
Chris@287 70 return InvalidProperty;
Chris@287 71 }
Chris@287 72
Chris@287 73 QString
Chris@287 74 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
Chris@287 75 {
Chris@287 76 return QString();
Chris@287 77 }
Chris@287 78
Chris@287 79 int
Chris@287 80 SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@287 81 int *min, int *max, int *deflt) const
Chris@287 82 {
Chris@287 83 int val = 0;
Chris@287 84
Chris@287 85 int garbage0, garbage1, garbage2;
Chris@287 86 if (!min) min = &garbage0;
Chris@287 87 if (!max) max = &garbage1;
Chris@287 88 if (!deflt) deflt = &garbage2;
Chris@287 89
Chris@287 90 if (name == "Colour") {
Chris@287 91
Chris@287 92 ColourDatabase::getInstance()->getColourPropertyRange(min, max);
Chris@287 93 *deflt = 0; //!!!
Chris@287 94
Chris@287 95 val = m_colour;
Chris@287 96
Chris@287 97 } else {
Chris@287 98 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@287 99 }
Chris@287 100
Chris@287 101 return val;
Chris@287 102 }
Chris@287 103
Chris@287 104 QString
Chris@287 105 SingleColourLayer::getPropertyValueLabel(const PropertyName &name,
Chris@287 106 int value) const
Chris@287 107 {
Chris@287 108 if (name == "Colour") {
Chris@287 109 return Layer::getPropertyValueLabel(name, value);
Chris@287 110 }
Chris@287 111 return tr("<unknown>");
Chris@287 112 }
Chris@287 113
Chris@287 114 RangeMapper *
Chris@287 115 SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@287 116 {
Chris@287 117 return 0;
Chris@287 118 }
Chris@287 119
Chris@287 120 void
Chris@287 121 SingleColourLayer::setProperty(const PropertyName &name, int value)
Chris@287 122 {
Chris@287 123 if (name == "Colour") {
Chris@287 124 setBaseColour(value);
Chris@287 125 }
Chris@287 126 }
Chris@287 127
Chris@287 128 void
Chris@287 129 SingleColourLayer::setDefaultColourFor(View *v)
Chris@287 130 {
Chris@367 131 #ifdef DEBUG_COLOUR_SELECTION
Chris@366 132 std::cerr << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << std::endl;
Chris@367 133 #endif
Chris@366 134
Chris@366 135 if (m_colourExplicitlySet || m_defaultColourSet) return;
Chris@294 136
Chris@367 137 if (v) m_defaultColourSet = true; // v==0 case doesn't really count
Chris@367 138
Chris@287 139 bool dark = false;
Chris@287 140 if (v) {
Chris@287 141 dark = !v->hasLightBackground();
Chris@287 142 } else {
Chris@287 143 QColor bg = QApplication::palette().color(QPalette::Window);
Chris@287 144 if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
Chris@287 145 }
Chris@287 146
Chris@287 147 ColourDatabase *cdb = ColourDatabase::getInstance();
Chris@287 148
Chris@287 149 int hint = -1;
Chris@287 150 bool impose = false;
Chris@287 151 if (v) {
Chris@293 152 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 153 m_colourRefCount[m_colour] > 0) {
Chris@293 154 m_colourRefCount[m_colour]--;
Chris@293 155 }
Chris@287 156 // We don't want to call this if !v because that probably
Chris@287 157 // means we're being called from the constructor, and this is
Chris@287 158 // a virtual function
Chris@287 159 hint = getDefaultColourHint(dark, impose);
Chris@367 160 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 161 std::cerr << "hint = " << hint << ", impose = " << impose << std::endl;
Chris@367 162 #endif
Chris@293 163 } else {
Chris@367 164 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 165 std::cerr << "(from ctor)" << std::endl;
Chris@367 166 #endif
Chris@287 167 }
Chris@287 168
Chris@287 169 if (hint >= 0 && impose) {
Chris@293 170 setBaseColour(hint);
Chris@287 171 return;
Chris@287 172 }
Chris@287 173
Chris@293 174 int bestCount = 0, bestColour = -1;
Chris@293 175
Chris@287 176 for (int i = 0; i < cdb->getColourCount(); ++i) {
Chris@293 177
Chris@287 178 int index = i;
Chris@287 179 if (hint > 0) index = (index + hint) % cdb->getColourCount();
Chris@287 180 if (cdb->useDarkBackground(index) != dark) continue;
Chris@293 181
Chris@293 182 int count = 0;
Chris@293 183 if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
Chris@293 184 count = m_colourRefCount[index];
Chris@287 185 }
Chris@293 186
Chris@367 187 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 188 std::cerr << "index = " << index << ", count = " << count;
Chris@367 189 #endif
Chris@293 190
Chris@293 191 if (bestColour < 0 || count < bestCount) {
Chris@293 192 bestColour = index;
Chris@293 193 bestCount = count;
Chris@367 194 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 195 std::cerr << " *";
Chris@367 196 #endif
Chris@293 197 }
Chris@293 198
Chris@367 199 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 200 std::cerr << std::endl;
Chris@367 201 #endif
Chris@287 202 }
Chris@293 203
Chris@293 204 if (bestColour < 0) m_colour = 0;
Chris@293 205 else m_colour = bestColour;
Chris@287 206
Chris@293 207 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 208 m_colourRefCount[m_colour] = 1;
Chris@293 209 } else {
Chris@293 210 m_colourRefCount[m_colour]++;
Chris@293 211 }
Chris@287 212 }
Chris@287 213
Chris@287 214 void
Chris@287 215 SingleColourLayer::setBaseColour(int colour)
Chris@287 216 {
Chris@294 217 m_colourExplicitlySet = true;
Chris@294 218
Chris@287 219 if (m_colour == colour) return;
Chris@293 220
Chris@293 221 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 222 m_colourRefCount[m_colour] > 0) {
Chris@293 223 m_colourRefCount[m_colour]--;
Chris@293 224 }
Chris@293 225
Chris@287 226 m_colour = colour;
Chris@293 227
Chris@293 228 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 229 m_colourRefCount[m_colour] = 1;
Chris@293 230 } else {
Chris@293 231 m_colourRefCount[m_colour]++;
Chris@293 232 }
Chris@293 233
Chris@287 234 flagBaseColourChanged();
Chris@287 235 emit layerParametersChanged();
Chris@287 236 }
Chris@287 237
Chris@287 238 int
Chris@287 239 SingleColourLayer::getBaseColour() const
Chris@287 240 {
Chris@287 241 return m_colour;
Chris@287 242 }
Chris@287 243
Chris@287 244 QColor
Chris@287 245 SingleColourLayer::getBaseQColor() const
Chris@287 246 {
Chris@287 247 return ColourDatabase::getInstance()->getColour(m_colour);
Chris@287 248 }
Chris@287 249
Chris@287 250 QColor
Chris@287 251 SingleColourLayer::getBackgroundQColor(View *v) const
Chris@287 252 {
Chris@287 253 return v->getBackground();
Chris@287 254 }
Chris@287 255
Chris@287 256 QColor
Chris@287 257 SingleColourLayer::getForegroundQColor(View *v) const
Chris@287 258 {
Chris@287 259 return v->getForeground();
Chris@287 260 }
Chris@287 261
Chris@287 262 std::vector<QColor>
Chris@287 263 SingleColourLayer::getPartialShades(View *v) const
Chris@287 264 {
Chris@287 265 std::vector<QColor> s;
Chris@287 266 QColor base = getBaseQColor();
Chris@287 267 QColor bg = getBackgroundQColor(v);
Chris@287 268 for (int i = 0; i < 3; ++i) {
Chris@287 269 int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
Chris@287 270 int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
Chris@287 271 int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
Chris@287 272 s.push_back(QColor(red, green, blue));
Chris@287 273 }
Chris@287 274 return s;
Chris@287 275 }
Chris@287 276
Chris@316 277 void
Chris@316 278 SingleColourLayer::toXml(QTextStream &stream,
Chris@316 279 QString indent, QString extraAttributes) const
Chris@287 280 {
Chris@287 281 QString s;
Chris@287 282
Chris@287 283 QString colourName, colourSpec, darkbg;
Chris@287 284 ColourDatabase::getInstance()->getStringValues
Chris@287 285 (m_colour, colourName, colourSpec, darkbg);
Chris@287 286
Chris@287 287 s += QString("colourName=\"%1\" "
Chris@287 288 "colour=\"%2\" "
Chris@287 289 "darkBackground=\"%3\" ")
Chris@287 290 .arg(colourName)
Chris@287 291 .arg(colourSpec)
Chris@287 292 .arg(darkbg);
Chris@287 293
Chris@316 294 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@287 295 }
Chris@287 296
Chris@287 297 void
Chris@287 298 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
Chris@287 299 {
Chris@287 300 QString colourName = attributes.value("colourName");
Chris@287 301 QString colourSpec = attributes.value("colour");
Chris@287 302 QString darkbg = attributes.value("darkBackground");
Chris@296 303
Chris@296 304 int colour = ColourDatabase::getInstance()->putStringValues
Chris@287 305 (colourName, colourSpec, darkbg);
Chris@296 306
Chris@296 307 m_colourExplicitlySet = true;
Chris@296 308
Chris@296 309 if (m_colour != colour) {
Chris@296 310
Chris@367 311 #ifdef DEBUG_COLOUR_SELECTION
Chris@296 312 std::cerr << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << std::endl;
Chris@367 313 #endif
Chris@296 314
Chris@296 315 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@296 316 m_colourRefCount[m_colour] > 0) {
Chris@296 317 m_colourRefCount[m_colour]--;
Chris@296 318 }
Chris@296 319
Chris@296 320 m_colour = colour;
Chris@296 321
Chris@296 322 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@296 323 m_colourRefCount[m_colour] = 1;
Chris@296 324 } else {
Chris@296 325 m_colourRefCount[m_colour]++;
Chris@296 326 }
Chris@296 327
Chris@296 328 flagBaseColourChanged();
Chris@294 329 }
Chris@287 330 }
Chris@287 331