File indexing completed on 2024-12-22 04:13:59

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef KCOLORSCHEME_H
0008 #define KCOLORSCHEME_H
0009 
0010 #include <kritawidgetutils_export.h>
0011 #include <ksharedconfig.h>
0012 
0013 #include <QExplicitlySharedDataPointer>
0014 
0015 #include <QPalette>
0016 
0017 class QColor;
0018 class QBrush;
0019 
0020 class KColorSchemePrivate;
0021 
0022 /**
0023  * A set of methods used to work with colors.
0024  *
0025  * KColorScheme currently provides access to the system color palette that the
0026  * user has selected (in the future, it is expected to do more).  It greatly
0027  * expands on QPalette by providing five distinct "sets" with several color
0028  * choices each, covering background, foreground, and decoration colors.
0029  *
0030  * A KColorScheme instance represents colors corresponding to a "set", where a
0031  * set consists of those colors used to draw a particular type of element, such
0032  * as a menu, button, view, selected text, or tooltip. Each set has a distinct
0033  * set of colors, so you should always use the correct set for drawing and
0034  * never assume that a particular foreground for one set is the same as the
0035  * foreground for any other set. Individual colors may be quickly referenced by
0036  * creating an anonymous instance and invoking a lookup member.
0037  *
0038  * @note
0039  * The color palettes for the various states of a widget (active, inactive,
0040  * disabled) may be wildly different.  Therefore, it is important to take the
0041  * state into account. This is why the KColorScheme constructor requires a
0042  * QPalette::ColorGroup as an argument.
0043  *
0044  * To facilitate working with potentially-varying states, two convenience API's
0045  * are provided. These are KColorScheme::adjustBackground and its sister
0046  * KColorScheme::adjustForeground, and the helper class ::KStatefulBrush.
0047  *
0048  * @see KColorScheme::ColorSet, KColorScheme::ForegroundRole,
0049  * KColorScheme::BackgroundRole, KColorScheme::DecorationRole,
0050  * KColorScheme::ShadeRole
0051  */
0052 class KRITAWIDGETUTILS_EXPORT KColorScheme
0053 {
0054 public:
0055 
0056     /**
0057      * This enumeration describes the color set for which a color is being
0058      * selected.
0059      *
0060      * Color sets define a color "environment", suitable for drawing all parts
0061      * of a given region. Colors from different sets should not be combined.
0062      */
0063     enum ColorSet {
0064         /**
0065          * Views; for example, frames, input fields, etc.
0066          *
0067          * If it contains things that can be selected, it is probably a View.
0068          */
0069         View,
0070         /**
0071          * Non-editable window elements; for example, menus.
0072          *
0073          * If it isn't a Button, View, or Tooltip, it is probably a Window.
0074          */
0075         Window,
0076         /**
0077          * Buttons and button-like controls.
0078          *
0079          * In addition to buttons, "button-like" controls such as non-editable
0080          * dropdowns, scrollbar sliders, slider handles, etc. should also use
0081          * this role.
0082          */
0083         Button,
0084         /**
0085          * Selected items in views.
0086          *
0087          * Note that unfocused or disabled selections should use the Window
0088          * role. This makes it more obvious to the user that the view
0089          * containing the selection does not have input focus.
0090          */
0091         Selection,
0092         /**
0093          * Tooltips.
0094          *
0095          * The tooltip set can often be substituted for the view
0096          * set when editing is not possible, but the Window set is deemed
0097          * inappropriate. "What's This" help is an excellent example, another
0098          * might be pop-up notifications (depending on taste).
0099          */
0100         Tooltip
0101     };
0102 
0103     /**
0104      * This enumeration describes the background color being selected from the
0105      * given set.
0106      *
0107      * Background colors are suitable for drawing under text, and should never
0108      * be used to draw text. In combination with one of the overloads of
0109      * KColorScheme::shade, they may be used to generate colors for drawing
0110      * frames, bevels, and similar decorations.
0111      */
0112     enum BackgroundRole {
0113         /**
0114          * Normal background.
0115          */
0116         NormalBackground = 0,
0117         /**
0118          * Alternate background; for example, for use in lists.
0119          *
0120          * This color may be the same as BackgroundNormal, especially in sets
0121          * other than View and Window.
0122          */
0123         AlternateBackground = 1,
0124         /**
0125          * Third color; for example, items which are new, active, requesting
0126          * attention, etc.
0127          *
0128          * Alerting the user that a certain field must be filled out would be a
0129          * good usage (although NegativeBackground could be used to the same
0130          * effect, depending on what you are trying to achieve). Unlike
0131          * ActiveText, this should not be used for mouseover effects.
0132          */
0133         ActiveBackground = 2,
0134         /**
0135          * Fourth color; corresponds to (unvisited) links.
0136          *
0137          * Exactly what this might be used for is somewhat harder to qualify;
0138          * it might be used for bookmarks, as a 'you can click here' indicator,
0139          * or to highlight recent content (i.e. in a most-recently-accessed
0140          * list).
0141          */
0142         LinkBackground = 3,
0143         /**
0144          * Fifth color; corresponds to visited links.
0145          *
0146          * This can also be used to indicate "not recent" content, especially
0147          * when a color is needed to denote content which is "old" or
0148          * "archival".
0149          */
0150         VisitedBackground = 4,
0151         /**
0152          * Sixth color; for example, errors, untrusted content, etc.
0153          */
0154         NegativeBackground = 5,
0155         /**
0156          * Seventh color; for example, warnings, secure/encrypted content.
0157          */
0158         NeutralBackground = 6,
0159         /**
0160          * Eighth color; for example, success messages, trusted content.
0161          */
0162         PositiveBackground = 7
0163     };
0164 
0165     /**
0166      * This enumeration describes the foreground color being selected from the
0167      * given set.
0168      *
0169      * Foreground colors are suitable for drawing text or glyphs (such as the
0170      * symbols on window decoration buttons, assuming a suitable background
0171      * brush is used), and should never be used to draw backgrounds.
0172      *
0173      * For window decorations, the following is suggested, but not set in
0174      * stone:
0175      * @li Maximize - PositiveText
0176      * @li Minimize - NeutralText
0177      * @li Close - NegativeText
0178      * @li WhatsThis - LinkText
0179      * @li Sticky - ActiveText
0180      */
0181     enum ForegroundRole {
0182         /**
0183          * Normal foreground.
0184          */
0185         NormalText = 0,
0186         /**
0187          * Second color; for example, comments, items which are old, inactive
0188          * or disabled. Generally used for things that are meant to be "less
0189          * important". InactiveText is not the same role as NormalText in the
0190          * inactive state.
0191          */
0192         InactiveText = 1,
0193         /**
0194          * Third color; for example items which are new, active, requesting
0195          * attention, etc. May be used as a hover color for clickable items.
0196          */
0197         ActiveText = 2,
0198         /**
0199          * Fourth color; use for (unvisited) links. May also be used for other
0200          * clickable items or content that indicates relationships, items that
0201          * indicate somewhere the user can visit, etc.
0202          */
0203         LinkText = 3,
0204         /**
0205          * Fifth color; used for (visited) links. As with LinkText, may be used
0206          * for items that have already been "visited" or accessed. May also be
0207          * used to indicate "historical" (i.e. "old") items or information,
0208          * especially if InactiveText is being used in the same context to
0209          * express something different.
0210          */
0211         VisitedText = 4,
0212         /**
0213          * Sixth color; for example, errors, untrusted content, deletions,
0214          * etc.
0215          */
0216         NegativeText = 5,
0217         /**
0218          * Seventh color; for example, warnings, secure/encrypted content.
0219          */
0220         NeutralText = 6,
0221         /**
0222          * Eighth color; for example, additions, success messages, trusted
0223          * content.
0224          */
0225         PositiveText = 7
0226     };
0227 
0228     /**
0229      * This enumeration describes the decoration color being selected from the
0230      * given set.
0231      *
0232      * Decoration colors are used to draw decorations (such as frames) for
0233      * special purposes. Like color shades, they are neither foreground nor
0234      * background colors. Text should not be painted over a decoration color,
0235      * and decoration colors should not be used to draw text.
0236      */
0237     enum DecorationRole {
0238         /**
0239          * Color used to draw decorations for items which have input focus.
0240          */
0241         FocusColor,
0242         /**
0243          * Color used to draw decorations for items which will be activated by
0244          * clicking.
0245          */
0246         HoverColor
0247     };
0248 
0249     /**
0250      * This enumeration describes the color shade being selected from the given
0251      * set.
0252      *
0253      * Color shades are used to draw "3d" elements, such as frames and bevels.
0254      * They are neither foreground nor background colors. Text should not be
0255      * painted over a shade, and shades should not be used to draw text.
0256      */
0257     enum ShadeRole {
0258         /**
0259          * The light color is lighter than dark() or shadow() and contrasts
0260          * with the base color.
0261          */
0262         LightShade,
0263         /**
0264          * The midlight color is in between base() and light().
0265          */
0266         MidlightShade,
0267         /**
0268          * The mid color is in between base() and dark().
0269          */
0270         MidShade,
0271         /**
0272          * The dark color is in between mid() and shadow().
0273          */
0274         DarkShade,
0275         /**
0276          * The shadow color is darker than light() or midlight() and contrasts
0277          * the base color.
0278          */
0279         ShadowShade
0280     };
0281 
0282     /** Construct a copy of another KColorScheme. */
0283     KColorScheme(const KColorScheme &);
0284 
0285     /** Destructor */
0286     virtual ~KColorScheme();
0287 
0288     /** Standard assignment operator */
0289     KColorScheme &operator=(const KColorScheme &);
0290 
0291     /**
0292      * Construct a palette from given color set and state, using the colors
0293      * from the given KConfig (if null, the system colors are used).
0294      *
0295      * @note KColorScheme provides direct access to the color scheme for users
0296      * that deal directly with widget states. Unless you are a low-level user
0297      * or have a legitimate reason to only care about a fixed, limited number
0298      * of states (e.g. windows that cannot be inactive), consider using a
0299      * ::KStatefulBrush instead.
0300      */
0301     explicit KColorScheme(QPalette::ColorGroup, ColorSet = View, KSharedConfigPtr = KSharedConfigPtr());
0302 
0303     /**
0304      * Retrieve the requested background brush.
0305      */
0306     QBrush background(BackgroundRole = NormalBackground) const;
0307 
0308     /**
0309      * Retrieve the requested foreground brush.
0310      */
0311     QBrush foreground(ForegroundRole = NormalText) const;
0312 
0313     /**
0314      * Retrieve the requested decoration brush.
0315      */
0316     QBrush decoration(DecorationRole) const;
0317 
0318     /**
0319      * Retrieve the requested shade color, using
0320      * KColorScheme::background(KColorScheme::NormalBackground)
0321      * as the base color and the contrast setting from the KConfig used to
0322      * create this KColorScheme instance (the system contrast setting, if no
0323      * KConfig was specified).
0324      *
0325      * @note Shades are chosen such that all shades would contrast with the
0326      * base color. This means that if base is very dark, the 'dark' shades will
0327      * be lighter than the base color, with midlight() == shadow().
0328      * Conversely, if the base color is very light, the 'light' shades will be
0329      * darker than the base color, with light() == mid().
0330      */
0331     QColor shade(ShadeRole) const;
0332 
0333     /**
0334      * Returns the contrast for borders.
0335      * @return the contrast (between 0 for minimum and 10 for maximum
0336      *         contrast)
0337      */
0338     static int contrast();
0339 
0340     /**
0341      * Returns the contrast for borders as a floating point value.
0342      * @param config pointer to the config from which to read the contrast
0343      * setting (the default is to use KSharedConfig::openConfig())
0344      * @return the contrast (between 0.0 for minimum and 1.0 for maximum
0345      *         contrast)
0346      */
0347     static qreal contrastF(const KSharedConfigPtr &config = KSharedConfigPtr());
0348 
0349     /**
0350      * Retrieve the requested shade color, using the specified color as the
0351      * base color and the system contrast setting.
0352      *
0353      * @note Shades are chosen such that all shades would contrast with the
0354      * base color. This means that if base is very dark, the 'dark' shades will
0355      * be lighter than the base color, with midlight() == shadow().
0356      * Conversely, if the base color is very light, the 'light' shades will be
0357      * darker than the base color, with light() == mid().
0358      */
0359     static QColor shade(const QColor &, ShadeRole);
0360 
0361     /**
0362      * Retrieve the requested shade color, using the specified color as the
0363      * base color and the specified contrast.
0364      *
0365      * @param color the shade color
0366      * @param role the shade role
0367      * @param contrast Amount roughly specifying the contrast by which to
0368      * adjust the base color, between -1.0 and 1.0 (values between 0.0 and 1.0
0369      * correspond to the value from KColorScheme::contrastF)
0370      * @param chromaAdjust (optional) Amount by which to adjust the chroma of
0371      * the shade (1.0 means no adjustment)
0372      *
0373      * @note Shades are chosen such that all shades would contrast with the
0374      * base color. This means that if base is very dark, the 'dark' shades will
0375      * be lighter than the base color, with midlight() == shadow().
0376      * Conversely, if the base color is very light, the 'light' shades will be
0377      * darker than the base color, with light() == mid().
0378      *
0379      * @see KColorUtils::shade
0380      */
0381     static QColor shade(const QColor &, ShadeRole,
0382                         qreal contrast, qreal chromaAdjust = 0.0);
0383 
0384     /**
0385      * Adjust a QPalette by replacing the specified QPalette::ColorRole with
0386      * the requested background color for all states. Using this method is
0387      * safer than replacing individual states, as it insulates you against
0388      * changes in QPalette::ColorGroup.
0389      *
0390      * @note Although it is possible to replace a foreground color using this
0391      * method, it's bad usability to do so. Just say "no".
0392      */
0393     static void adjustBackground(QPalette &,
0394                                  BackgroundRole newRole = NormalBackground,
0395                                  QPalette::ColorRole color = QPalette::Base,
0396                                  ColorSet set = View,
0397                                  KSharedConfigPtr = KSharedConfigPtr());
0398 
0399     /**
0400      * Adjust a QPalette by replacing the specified QPalette::ColorRole with
0401      * the requested foreground color for all states. Using this method is
0402      * safer than replacing individual states, as it insulates you against
0403      * changes in QPalette::ColorGroup.
0404      *
0405      * @note Although it is possible to replace a background color using this
0406      * method, it's bad usability to do so. Just say "no".
0407      */
0408     static void adjustForeground(QPalette &,
0409                                  ForegroundRole newRole = NormalText,
0410                                  QPalette::ColorRole color = QPalette::Text,
0411                                  ColorSet set = View,
0412                                  KSharedConfigPtr = KSharedConfigPtr());
0413 
0414     /**
0415      * Used to obtain the QPalette that will be used to set the application
0416      * palette from KDE Platform theme.
0417      *
0418      * @param config KConfig from which to load the colors
0419      *
0420      * @returns the QPalette
0421      *
0422      * @since 5.0
0423      */
0424     static QPalette createApplicationPalette(const KSharedConfigPtr &config);
0425 
0426 private:
0427     QExplicitlySharedDataPointer<KColorSchemePrivate> d;
0428 };
0429 
0430 /**
0431  * A container for a "state-aware" brush.
0432  *
0433  * KStatefulBrush provides an easy and safe way to store a color for use in a
0434  * user interface. It is "safe" both in that it will make it easy to deal with
0435  * widget states in a correct manner, and that it insulates you against changes
0436  * in QPalette::ColorGroup.
0437  *
0438  * Basically, a stateful brush is used to cache a particular "color" from the
0439  * KDE system palette (usually, one which does not live in QPalette). When you
0440  * are ready to draw using the brush, you use the current state to retrieve the
0441  * appropriate brush.
0442  *
0443  * Stateful brushes can also be used to apply state effects to arbitrary
0444  * brushes, for example when working with a application specific user-defined
0445  * color palette.
0446  *
0447  * @note As of Qt 4.3, QPalette::ColorGroup is missing a state for disabled
0448  * widgets in an inactive window. Hopefully Trolltech will fix this bug, at
0449  * which point KColorScheme and KStatefulBrush will be updated to recognize the
0450  * new state. Using KStatefulBrush will allow your application to inherit these
0451  * changes "for free", without even recompiling.
0452  */
0453 class KRITAWIDGETUTILS_EXPORT KStatefulBrush
0454 {
0455 public:
0456     /**
0457      * Construct a "default" stateful brush. For such an instance, all
0458      * overloads of KStatefulBrush::brush will return a default brush (i.e.
0459      * <tt>QBrush()</tt>).
0460      */
0461     explicit KStatefulBrush();
0462 
0463     /**
0464      * Construct a stateful brush from given color set and foreground role,
0465      * using the colors from the given KConfig (if null, the system colors are
0466      * used).
0467      */
0468     explicit KStatefulBrush(KColorScheme::ColorSet,
0469                             KColorScheme::ForegroundRole,
0470                             KSharedConfigPtr = KSharedConfigPtr());
0471 
0472     /**
0473      * Construct a stateful brush from given color set and background role,
0474      * using the colors from the given KConfig (if null, the system colors are
0475      * used).
0476      */
0477     explicit KStatefulBrush(KColorScheme::ColorSet,
0478                             KColorScheme::BackgroundRole,
0479                             KSharedConfigPtr = KSharedConfigPtr());
0480 
0481     /**
0482      * Construct a stateful brush from given color set and decoration role,
0483      * using the colors from the given KConfig (if null, the system colors are
0484      * used).
0485      */
0486     explicit KStatefulBrush(KColorScheme::ColorSet,
0487                             KColorScheme::DecorationRole,
0488                             KSharedConfigPtr = KSharedConfigPtr());
0489 
0490     /**
0491      * Construct a stateful background brush from a specified QBrush (or
0492      * QColor, via QBrush's implicit constructor). The various states are
0493      * determined from the base QBrush (which fills in the Active state)
0494      * according to the same rules used to build stateful color schemes from
0495      * the system color scheme. The state effects from the given KConfig are
0496      * used (if null, the system state effects are used).
0497      */
0498     explicit KStatefulBrush(const QBrush &, KSharedConfigPtr = KSharedConfigPtr());
0499 
0500     /**
0501      * Construct a stateful foreground/decoration brush from a specified
0502      * QBrush (or QColor, via QBrush's implicit constructor). The various
0503      * states are determined from the base QBrush (which fills in the Active
0504      * state) according to the same rules used to build stateful color schemes
0505      * from the system color scheme. The state effects from the given KConfig
0506      * are used (if null, the system state effects are used).
0507      *
0508      * @param brush The foreground brush
0509      * @param background The background brush (or color) corresponding to the
0510      * KColorScheme::NormalBackground role and QPalette::Active state for this
0511      * foreground/decoration color.
0512      * @param config The configuration.
0513      */
0514     explicit KStatefulBrush(const QBrush &, const QBrush &background,
0515                             KSharedConfigPtr = KSharedConfigPtr());
0516 
0517     /** Construct a copy of another KStatefulBrush. */
0518     KStatefulBrush(const KStatefulBrush &);
0519 
0520     /** Destructor */
0521     ~KStatefulBrush();
0522 
0523     /** Standard assignment operator */
0524     KStatefulBrush &operator=(const KStatefulBrush &);
0525 
0526     /**
0527      * Retrieve the brush for the specified widget state. This is used when you
0528      * know explicitly what state is wanted. Otherwise one of overloads is
0529      * often more convenient.
0530      */
0531     QBrush brush(QPalette::ColorGroup) const;
0532 
0533     /**
0534      * Retrieve the brush, using a QPalette reference to determine the correct
0535      * state. Use when your painting code has easy access to the QPalette that
0536      * it is supposed to be using. The state used in this instance is the
0537      * currentColorGroup of the palette.
0538      */
0539     QBrush brush(const QPalette &) const;
0540 
0541     /**
0542      * Retrieve the brush, using a QWidget pointer to determine the correct
0543      * state. Use when you have a pointer to the widget that you are painting.
0544      * The state used is the current state of the widget.
0545      *
0546      * @note If you pass an invalid widget, you will get a default brush (i.e.
0547      * <tt>QBrush()</tt>).
0548      */
0549     QBrush brush(const QWidget *) const;
0550 
0551 private:
0552     class KStatefulBrushPrivate *d;
0553 };
0554 
0555 Q_DECLARE_METATYPE(KStatefulBrush) /* so we can pass it in QVariant's */
0556 
0557 #endif // KCOLORSCHEME_H