svgui  1.9
SingleColourLayer.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2007 QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "SingleColourLayer.h"
00017 #include "ColourDatabase.h"
00018 #include "view/View.h"
00019 
00020 #include <iostream>
00021 
00022 #include <QTextStream>
00023 #include <QApplication>
00024 
00025 //#define DEBUG_COLOUR_SELECTION 1
00026 
00027 SingleColourLayer::ColourRefCount 
00028 SingleColourLayer::m_colourRefCount;
00029 
00030 SingleColourLayer::SingleColourLayer() :
00031     m_colour(0),
00032     m_colourExplicitlySet(false),
00033     m_defaultColourSet(false)
00034 {
00035     // Reference current colour because setDefaulColourFor
00036     // will unreference it before (possibly) changing it.
00037     refColor();
00038     setDefaultColourFor(0);
00039 }
00040 
00041 SingleColourLayer::~SingleColourLayer()
00042 {
00043     unrefColor();
00044 }
00045 
00046 QPixmap
00047 SingleColourLayer::getLayerPresentationPixmap(QSize size) const
00048 {
00049     return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size);
00050 }
00051 
00052 bool
00053 SingleColourLayer::hasLightBackground() const
00054 {
00055     bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour);
00056     return !dark;
00057 }
00058 
00059 Layer::PropertyList
00060 SingleColourLayer::getProperties() const
00061 {
00062     PropertyList list = Layer::getProperties();
00063     list.push_back("Colour");
00064     return list;
00065 }
00066 
00067 QString
00068 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
00069 {
00070     if (name == "Colour") return tr("Colour");
00071     return "";
00072 }
00073 
00074 Layer::PropertyType
00075 SingleColourLayer::getPropertyType(const PropertyName &name) const
00076 {
00077     if (name == "Colour") return ColourProperty;
00078     return InvalidProperty;
00079 }
00080 
00081 QString
00082 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
00083 {
00084     return QString();
00085 }
00086 
00087 int
00088 SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name,
00089                                         int *min, int *max, int *deflt) const
00090 {
00091     int val = 0;
00092 
00093     int garbage0, garbage1, garbage2;
00094     if (!min) min = &garbage0;
00095     if (!max) max = &garbage1;
00096     if (!deflt) deflt = &garbage2;
00097 
00098     if (name == "Colour") {
00099 
00100         ColourDatabase::getInstance()->getColourPropertyRange(min, max);
00101         *deflt = 0; 
00102 
00103         val = m_colour;
00104 
00105     } else {
00106         val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
00107     }
00108 
00109     return val;
00110 }
00111 
00112 QString
00113 SingleColourLayer::getPropertyValueLabel(const PropertyName &name,
00114                                     int value) const
00115 {
00116     if (name == "Colour") {
00117         ColourDatabase *db = ColourDatabase::getInstance();
00118         if (value >= 0 && value < db->getColourCount()) {
00119             return db->getColourName(value);
00120         }
00121     }
00122     return tr("<unknown>");
00123 }
00124 
00125 RangeMapper *
00126 SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const
00127 {
00128     return 0;
00129 }
00130 
00131 void
00132 SingleColourLayer::setProperty(const PropertyName &name, int value)
00133 {
00134     if (name == "Colour") {
00135         setBaseColour(value);
00136     }
00137 }
00138 
00139 void
00140 SingleColourLayer::setDefaultColourFor(View *v)
00141 {
00142 #ifdef DEBUG_COLOUR_SELECTION
00143     SVDEBUG << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << endl;
00144 #endif
00145 
00146     if (m_colourExplicitlySet || m_defaultColourSet) return;
00147 
00148     if (v) m_defaultColourSet = true; // v==0 case doesn't really count
00149 
00150     bool dark = false;
00151     if (v) {
00152         dark = !v->hasLightBackground();
00153     } else {
00154         QColor bg = QApplication::palette().color(QPalette::Window);
00155         if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
00156     }
00157 
00158     ColourDatabase *cdb = ColourDatabase::getInstance();
00159 
00160     int hint = -1;
00161     bool impose = false;
00162     if (v) {
00163         // We don't want to call this if !v because that probably
00164         // means we're being called from the constructor, and this is
00165         // a virtual function
00166         hint = getDefaultColourHint(dark, impose);
00167 #ifdef DEBUG_COLOUR_SELECTION
00168         cerr << "hint = " << hint << ", impose = " << impose << endl;
00169 #endif
00170     } else {
00171 #ifdef DEBUG_COLOUR_SELECTION
00172         cerr << "(from ctor)" << endl;
00173 #endif
00174     }
00175 
00176     if (hint >= 0 && impose) {
00177         setBaseColour(hint);
00178         return;
00179     }
00180 
00181     unrefColor();
00182 
00183     int bestCount = 0, bestColour = -1;
00184     
00185     for (int i = 0; i < cdb->getColourCount(); ++i) {
00186 
00187         int index = i;
00188         if (hint > 0) index = (index + hint) % cdb->getColourCount();
00189         if (cdb->useDarkBackground(index) != dark) continue;
00190 
00191         int count = 0;
00192         if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
00193             count = m_colourRefCount[index];
00194         }
00195 
00196 #ifdef DEBUG_COLOUR_SELECTION
00197         cerr << "index = " << index << ", count = " << count;
00198 #endif
00199 
00200         if (bestColour < 0 || count < bestCount) {
00201             bestColour = index;
00202             bestCount = count;
00203 #ifdef DEBUG_COLOUR_SELECTION
00204             cerr << " *";
00205 #endif
00206         }
00207 
00208 #ifdef DEBUG_COLOUR_SELECTION
00209         cerr << endl;
00210 #endif
00211     }
00212 
00213     if (bestColour < 0) m_colour = 0;
00214     else m_colour = bestColour;
00215 
00216     refColor();
00217 }
00218 
00219 void
00220 SingleColourLayer::setBaseColour(int colour)
00221 {
00222     m_colourExplicitlySet = true;
00223 
00224     if (m_colour == colour) return;
00225 
00226     refColor();
00227     m_colour = colour;
00228     unrefColor();
00229 
00230     flagBaseColourChanged();
00231     emit layerParametersChanged();
00232 }
00233 
00234 int
00235 SingleColourLayer::getBaseColour() const
00236 {
00237     return m_colour;
00238 }
00239 
00240 QColor
00241 SingleColourLayer::getBaseQColor() const
00242 {
00243     return ColourDatabase::getInstance()->getColour(m_colour);
00244 }
00245 
00246 QColor
00247 SingleColourLayer::getBackgroundQColor(View *v) const
00248 {
00249     return v->getBackground();
00250 }
00251 
00252 QColor
00253 SingleColourLayer::getForegroundQColor(View *v) const
00254 {
00255     return v->getForeground();
00256 }
00257 
00258 std::vector<QColor>
00259 SingleColourLayer::getPartialShades(View *v) const
00260 {
00261     std::vector<QColor> s;
00262     QColor base = getBaseQColor();
00263     QColor bg = getBackgroundQColor(v);
00264     for (int i = 0; i < 3; ++i) {
00265         int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
00266         int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
00267         int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
00268         s.push_back(QColor(red, green, blue));
00269     }
00270     return s;
00271 }
00272 
00273 void
00274 SingleColourLayer::toXml(QTextStream &stream,
00275                          QString indent, QString extraAttributes) const
00276 {
00277     QString s;
00278     
00279     QString colourName, colourSpec, darkbg;
00280     ColourDatabase::getInstance()->getStringValues
00281         (m_colour, colourName, colourSpec, darkbg);
00282 
00283     s += QString("colourName=\"%1\" "
00284                  "colour=\"%2\" "
00285                  "darkBackground=\"%3\" ")
00286         .arg(colourName)
00287         .arg(colourSpec)
00288         .arg(darkbg);
00289 
00290     Layer::toXml(stream, indent, extraAttributes + " " + s);
00291 }
00292 
00293 void
00294 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
00295 {
00296     QString colourName = attributes.value("colourName");
00297     QString colourSpec = attributes.value("colour");
00298     QString darkbg = attributes.value("darkBackground");
00299 
00300     int colour = ColourDatabase::getInstance()->putStringValues
00301         (colourName, colourSpec, darkbg);
00302 
00303     if (colour == -1)
00304       return;
00305 
00306     m_colourExplicitlySet = true;
00307 
00308     if (m_colour != colour) {
00309 
00310 #ifdef DEBUG_COLOUR_SELECTION
00311         SVDEBUG << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << endl;
00312 #endif
00313 
00314         unrefColor();
00315         m_colour = colour;
00316         refColor();
00317 
00318         flagBaseColourChanged();
00319     }
00320 }
00321 
00322 void SingleColourLayer::refColor()
00323 {
00324     if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
00325         m_colourRefCount[m_colour] = 1;
00326     } else {
00327         m_colourRefCount[m_colour]++;
00328     }
00329 }
00330 
00331 void SingleColourLayer::unrefColor()
00332 {
00333     if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
00334         m_colourRefCount[m_colour] > 0) {
00335         m_colourRefCount[m_colour]--;
00336     }
00337 }