annotate layer/SingleColourLayer.cpp @ 359:020c485aa7e0

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