[kdevplatform] shell: Favour strongly distinct working set icons
Leon Pollak
leonp at plris.com
Tue Dec 24 11:21:03 GMT 2013
Is it totally discarded to make icons with simple numbers 1,2,3...?
On Tuesday 24 December 2013 01:40:00 Sven Brauch wrote:
> Git commit 0b4e46220da82a6cc50bc8554bc9778632f7b51e by Sven Brauch.
> Committed on 24/12/2013 at 01:39.
> Pushed by brauch into branch 'master'.
>
> Favour strongly distinct working set icons
>
> When a new working set is created, the code will try to pick an icon
> which is sufficiently distinct from the existing icons. This should
> work nicely unless you have dozens of sets opened. Tell me if it does
> not. ;)
>
> CCMAIL:kdevelop at kde.org
>
> M +27 -2 shell/workingsetcontroller.cpp
> M +1 -0 shell/workingsetcontroller.h
> M +11 -16 shell/workingsets/workingset.cpp
> M +35 -0 shell/workingsets/workingset.h
>
> http://commits.kde.org/kdevplatform/0b4e46220da82a6cc50bc8554bc9778632
> f7b51e
>
> diff --git a/shell/workingsetcontroller.cpp
> b/shell/workingsetcontroller.cpp index 417a3b4..1b40750 100644
> --- a/shell/workingsetcontroller.cpp
> +++ b/shell/workingsetcontroller.cpp
> @@ -97,10 +97,35 @@ void WorkingSetController::cleanup()
> m_emptyWorkingSet = 0;
> }
>
> +const QString WorkingSetController::makeSetId(const QString& prefix)
> const +{
> + QString newId;
> + const int maxRetries = 10;
> + for(unsigned int retry = 2; retry <= maxRetries; retry++) {
> + newId = QString("%1_%2").arg(prefix).arg(qrand() % 10000000);
> + WorkingSetIconParameters params(newId);
> + foreach(WorkingSet* set, m_workingSets) {
> + if(set->isEmpty()) {
> + continue;
> + }
> + // The last retry will always generate a valid set
> + const int maxSimilarity = retry > maxRetries / 2 ? 55 :
> 35; + if(retry != maxRetries &&
> WorkingSetIconParameters(set->id()).similarity(params) >= retry*8) {
> + newId = QString();
> + break;
> + }
> + }
> + if(! newId.isEmpty()) {
> + break;
> + }
> + }
> + return newId;
> +}
> +
> WorkingSet* WorkingSetController::newWorkingSet(const QString&
> prefix) {
> - QString newId = QString("%1_%2").arg(prefix).arg(qrand() %
> 10000000); - return getWorkingSet(newId);
> +
> + return getWorkingSet(makeSetId(prefix));
> }
>
> WorkingSet* WorkingSetController::getWorkingSet(const QString& id)
> diff --git a/shell/workingsetcontroller.h
> b/shell/workingsetcontroller.h index ea6985b..1bd2138 100644
> --- a/shell/workingsetcontroller.h
> +++ b/shell/workingsetcontroller.h
> @@ -103,6 +103,7 @@ private slots:
>
> private:
> void setupActions();
> + const QString makeSetId(const QString& prefix) const;
>
> QSet<QString> m_usedIcons;
> QMap<QString, WorkingSet*> m_workingSets;
> diff --git a/shell/workingsets/workingset.cpp
> b/shell/workingsets/workingset.cpp index bfe93ca..bc4f430 100644
> --- a/shell/workingsets/workingset.cpp
> +++ b/shell/workingsets/workingset.cpp
> @@ -42,21 +42,16 @@ bool WorkingSet::m_loading = false;
>
> namespace {
>
> -QIcon generateIcon(const QString& id)
> +QIcon generateIcon(const WorkingSetIconParameters& params)
> {
> QImage pixmap(16, 16, QImage::Format_ARGB32);
> // fill the background with a transparent color
> pixmap.fill(QColor::fromRgba(qRgba(0, 0, 0, 0)));
> - // calculate layout and colors depending on the working set ID
> - // modulo it so it's around 2^28, leaving some space before uint
> overflows - const uint setId = qHash(id) % 268435459;
> - // amount of colored squares in this icon (the rest is grey or
> whatever you set as default color) - // use 4-6-4-1 weighting for
> 1, 2, 3, 4 squares, because that's the number of arrangements for
> each - const uint coloredCount = (setId % 15 < 4) ? 1 : (setId %
> 15 < 10) ? 2 : (setId % 15 == 14) ? 4 : 3; + const uint
> coloredCount = params.coloredCount;
> // coordinates of the rectangles to draw, for 16x16 icons
> specifically QList<QRect> rects;
> rects << QRect(1, 1, 5, 5) << QRect(1, 9, 5, 5) << QRect(9, 1, 5,
> 5) << QRect(9, 9, 5, 5); - if ( setId % 31 < 16 ) {
> + if ( params.swapDiagonal ) {
> rects.swap(1, 2);
> }
>
> @@ -67,31 +62,31 @@ QIcon generateIcon(const QString& id)
> // color for colored squares
> // this code is not fragile, you can just tune the magic formulas
> at random and see what looks good. // just make sure to keep it
> within the 0-360 / 0-255 / 0-255 space of the HSV model - QColor
> brightColor = QColor::fromHsv((setId % 273 * 81) % 360,
> qMin<uint>(255, 215 + (setId*5) % 150), -
> 205 + (setId*11) % 50); + QColor brightColor =
> QColor::fromHsv(params.hue, qMin<uint>(255, 215 + (params.setId*5) %
> 150), + 205 +
> (params.setId*11) % 50); // Y'UV "Y" value, the approximate
> "lightness" of the color // If it is above 0.6, then making the color
> darker a bit is okay, // if it is below 0.35, then the color should
> be a bit brighter. float brightY = 0.299 * brightColor.redF() + 0.587
> * brightColor.greenF() + 0.114 * brightColor.blueF(); if ( brightY >
> 0.6 ) {
> - if ( setId % 7 < 2 ) {
> + if ( params.setId % 7 < 2 ) {
> // 2/7 chance to make the color significantly darker
> - brightColor = brightColor.darker(120 + (setId*7) % 35);
> + brightColor = brightColor.darker(120 + (params.setId*7) %
> 35); }
> - else if ( setId % 5 == 0 ) {
> + else if ( params.setId % 5 == 0 ) {
> // 1/5 chance to make it a bit darker
> - brightColor = brightColor.darker(110 + (setId*3) % 10);
> + brightColor = brightColor.darker(110 + (params.setId*3) %
> 10); }
> }
> if ( brightY < 0.35 ) {
> // always make the color brighter to avoid very dark colors
> (like rgb(0, 0, 255)) - brightColor = brightColor.lighter(120
> + (setId*13) % 55); + brightColor = brightColor.lighter(120 +
> (params.setId*13) % 55); }
> int at = 0;
> foreach ( const QRect& rect, rects ) {
> QColor currentColor;
> // pick the colored squares; you can get different patterns
> by re-ordering the "rects" list - if ( (at + setId*7) % 4 <
> coloredCount ) {
> + if ( (at + params.setId*7) % 4 < coloredCount ) {
> currentColor = brightColor;
> }
> else {
> diff --git a/shell/workingsets/workingset.h
> b/shell/workingsets/workingset.h index 047240f..98fbff3 100644
> --- a/shell/workingsets/workingset.h
> +++ b/shell/workingsets/workingset.h
> @@ -23,6 +23,7 @@
> #include <QIcon>
> #include <KConfigGroup>
> #include <QPointer>
> +#include <QDebug>
>
> namespace Sublime {
> class Area;
> @@ -32,6 +33,40 @@ class View;
>
> namespace KDevelop {
>
> +/// Contains all significant parameters which control the appearance
> of a working set icon +struct WorkingSetIconParameters {
> + WorkingSetIconParameters(const QString& id)
> + : setId(qHash(id) % 268435459)
> + , coloredCount((setId % 15 < 4) ? 1 : (setId % 15 < 10) ? 2 :
> (setId % 15 == 14) ? 4 : 3) + , hue((setId % 273 * 83) % 360)
> + , swapDiagonal(setId % 31 < 16)
> + { };
> + // calculate layout and colors depending on the working set ID
> + // modulo it so it's around 2^28, leaving some space before uint
> overflows + const uint setId;
> + // amount of colored squares in this icon (the rest is grey or
> whatever you set as default color) + // use 4-6-4-1 weighting for
> 1, 2, 3, 4 squares, because that's the number of arrangements for
> each + const uint coloredCount;
> + const uint hue;
> + bool swapDiagonal;
> + // between 0 and 100, 100 = very similar, 0 = very different
> + // 20 points should make a significantly different icon.
> + uint similarity(const WorkingSetIconParameters& other) const {
> + int sim = 100;
> + uint hueDiff = qAbs<int>(hue - other.hue);
> + hueDiff = hueDiff > 180 ? 360 - hueDiff : hueDiff;
> + sim -= hueDiff > 35 ? 50 : (hueDiff * 50) / 180;
> + if ( coloredCount != other.coloredCount ) {
> + sim -= 50;
> + }
> + else if ( coloredCount == 2 && swapDiagonal !=
> other.swapDiagonal ) { + sim -= 35;
> + }
> + return sim;
> + };
> +};
> +
> +
> class WorkingSet : public QObject {
> Q_OBJECT
>
> _______________________________________________
> KDevelop mailing list
> KDevelop at kde.org
> https://mail.kde.org/mailman/listinfo/kdevelop
--
Dr.Leon M.Pollak
Director
PLR Information Systems Ltd.
Tel.:+972-98657670 | POB 8130, Giborei Israel 5a,
Fax.:+972-98657621 | Poleg Industrial Zone,
Mob.:+972-544739246 | Netanya, 42504, Israel.
More information about the KDevelop
mailing list