File indexing completed on 2024-04-21 05:46:52

0001 /*****************************************************************************
0002  *   Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 
0023 #include <stdarg.h>
0024 #include "common.h"
0025 
0026 // DO NOT unconditionally include QT/GTK headers here
0027 
0028 void
0029 qtcSetupGradient(Gradient *grad, EGradientBorder border, int numStops, ...)
0030 {
0031     va_list ap;
0032     int i;
0033 
0034     grad->border = border;
0035 #ifndef QTC_UTILS_QT
0036     grad->numStops = numStops;
0037     grad->stops = qtcNew(GradientStop, numStops);
0038 #endif
0039     va_start(ap, numStops);
0040     for (i = 0;i < numStops;++i) {
0041         double pos = va_arg(ap, double);
0042         double val = va_arg(ap, double);
0043 #ifdef QTC_UTILS_QT
0044         grad->stops.insert(GradientStop(pos, val));
0045 #else
0046         grad->stops[i].pos = pos;
0047         grad->stops[i].val = val;
0048         grad->stops[i].alpha = 1.0;
0049 #endif
0050     }
0051     va_end(ap);
0052 }
0053 
0054 const Gradient*
0055 qtcGetGradient(EAppearance app, const Options *opts)
0056 {
0057     if (IS_CUSTOM(app)) {
0058 #ifdef QTC_UTILS_QT
0059         auto grad = opts->customGradient.find(app);
0060 
0061         if (grad != opts->customGradient.end()) {
0062             return &grad->second;
0063         }
0064 #else
0065         Gradient *grad = opts->customGradient[app - APPEARANCE_CUSTOM1];
0066 
0067         if (grad) {
0068             return grad;
0069         }
0070 #endif
0071         app = APPEARANCE_RAISED;
0072     }
0073 
0074     static Gradient stdGradients[NUM_STD_APP];
0075     static bool init = false;
0076 
0077     if (!init) {
0078         qtcSetupGradient(&stdGradients[APPEARANCE_FLAT - APPEARANCE_FLAT],
0079                          GB_3D, 2, 0.0, 1.0, 1.0, 1.0);
0080         qtcSetupGradient(&stdGradients[APPEARANCE_RAISED - APPEARANCE_FLAT],
0081                          GB_3D_FULL, 2, 0.0, 1.0, 1.0, 1.0);
0082         qtcSetupGradient(&stdGradients[APPEARANCE_DULL_GLASS -
0083                                        APPEARANCE_FLAT], GB_LIGHT, 4, 0.0,
0084                          1.05, 0.499, 0.984, 0.5, 0.928,
0085                          1.0, 1.0);
0086         qtcSetupGradient(&stdGradients[APPEARANCE_SHINY_GLASS -
0087                                        APPEARANCE_FLAT], GB_LIGHT, 4, 0.0,
0088                          1.2, 0.499, 0.984, 0.5, 0.9,
0089                          1.0, 1.06);
0090         qtcSetupGradient(&stdGradients[APPEARANCE_AGUA - APPEARANCE_FLAT],
0091                          GB_SHINE, 2, 0.0, 0.6, 1.0, 1.1);
0092         qtcSetupGradient(&stdGradients[APPEARANCE_SOFT_GRADIENT -
0093                                        APPEARANCE_FLAT], GB_3D, 2, 0.0,
0094                          1.04, 1.0, 0.98);
0095         qtcSetupGradient(
0096             &stdGradients[APPEARANCE_GRADIENT - APPEARANCE_FLAT], GB_3D, 2,
0097             0.0, 1.1, 1.0, 0.94);
0098         qtcSetupGradient(&stdGradients[APPEARANCE_HARSH_GRADIENT -
0099                                        APPEARANCE_FLAT], GB_3D, 2, 0.0, 1.3,
0100                          1.0, 0.925);
0101         qtcSetupGradient(
0102             &stdGradients[APPEARANCE_INVERTED - APPEARANCE_FLAT], GB_3D, 2,
0103             0.0, 0.93, 1.0, 1.04);
0104         qtcSetupGradient(&stdGradients[APPEARANCE_DARK_INVERTED -
0105                                        APPEARANCE_FLAT], GB_NONE, 3, 0.0,
0106                          0.8, 0.7, 0.95, 1.0, 1.0);
0107         qtcSetupGradient(&stdGradients[APPEARANCE_SPLIT_GRADIENT -
0108                                        APPEARANCE_FLAT], GB_3D, 4, 0.0,
0109                          1.06, 0.499, 1.004, 0.5, 0.986,
0110                          1.0, 0.92);
0111         qtcSetupGradient(
0112             &stdGradients[APPEARANCE_BEVELLED - APPEARANCE_FLAT], GB_3D, 4,
0113             0.0, 1.05, 0.1, 1.02, 0.9, 0.985, 1.0, 0.94);
0114         qtcSetupGradient(&stdGradients[APPEARANCE_LV_BEVELLED -
0115                                        APPEARANCE_FLAT], GB_3D, 3, 0.0,
0116                          1.00, 0.85, 1.0, 1.0, 0.90);
0117         qtcSetupGradient(
0118             &stdGradients[APPEARANCE_AGUA_MOD - APPEARANCE_FLAT], GB_NONE,
0119             3, 0.0, 1.5, 0.49, 0.85, 1.0, 1.3);
0120         qtcSetupGradient(
0121             &stdGradients[APPEARANCE_LV_AGUA - APPEARANCE_FLAT], GB_NONE, 4,
0122             0.0, 0.98, 0.35, 0.95, 0.4, 0.93, 1.0, 1.15);
0123         init = true;
0124     }
0125 
0126     return &stdGradients[app - APPEARANCE_FLAT];
0127 }
0128 
0129 EAppearance
0130 #ifdef QTC_UTILS_QT
0131 qtcWidgetApp(EWidget w, const Options *opts, bool active)
0132 #else
0133 qtcWidgetApp(EWidget w, const Options *opts)
0134 #endif
0135 {
0136     switch (w) {
0137     case WIDGET_SB_BGND:
0138         return opts->sbarBgndAppearance;
0139     case WIDGET_LISTVIEW_HEADER:
0140         return opts->lvAppearance;
0141     case WIDGET_SB_BUTTON:
0142     case WIDGET_SLIDER:
0143     case WIDGET_SB_SLIDER:
0144         return opts->sliderAppearance;
0145     case WIDGET_FILLED_SLIDER_TROUGH:
0146         return opts->sliderFill;
0147     case WIDGET_TAB_TOP:
0148     case WIDGET_TAB_BOT:
0149         return opts->tabAppearance;
0150     case WIDGET_MENU_ITEM:
0151         return opts->menuitemAppearance;
0152     case WIDGET_PROGRESSBAR:
0153 #ifndef QTC_UTILS_QT
0154     case WIDGET_ENTRY_PROGRESSBAR:
0155 #endif
0156         return opts->progressAppearance;
0157     case WIDGET_PBAR_TROUGH:
0158         return opts->progressGrooveAppearance;
0159     case WIDGET_SELECTION:
0160         return opts->selectionAppearance;
0161 #ifdef QTC_UTILS_QT
0162     case WIDGET_DOCK_WIDGET_TITLE:
0163         return opts->dwtAppearance;
0164     case WIDGET_MDI_WINDOW:
0165     case WIDGET_MDI_WINDOW_TITLE:
0166         return (active ? opts->titlebarAppearance :
0167                 opts->inactiveTitlebarAppearance);
0168     case WIDGET_MDI_WINDOW_BUTTON:
0169         return opts->titlebarButtonAppearance;
0170     case WIDGET_DIAL:
0171         return qtcIsFlat(opts->appearance) ? APPEARANCE_RAISED :
0172         APPEARANCE_SOFT_GRADIENT;
0173 #endif
0174     case WIDGET_TROUGH:
0175     case WIDGET_SLIDER_TROUGH:
0176         return opts->grooveAppearance;
0177 #ifndef QTC_UTILS_QT
0178     case WIDGET_SPIN_UP:
0179     case WIDGET_SPIN_DOWN:
0180 #endif
0181     case WIDGET_SPIN:
0182         return MODIFY_AGUA(opts->appearance);
0183     case WIDGET_TOOLBAR_BUTTON:
0184         return (APPEARANCE_NONE == opts->tbarBtnAppearance ?
0185                 opts->appearance : opts->tbarBtnAppearance);
0186     default:
0187         break;
0188     }
0189     return opts->appearance;
0190 }
0191 
0192 #define CAN_EXTRA_ROUND(MOD)                                            \
0193     (QtCurve::isExtraRoundWidget(widget) &&                             \
0194      (IS_SLIDER(widget) || WIDGET_TROUGH == widget ||                   \
0195       (((w > (MIN_ROUND_EXTRA_SIZE(widget) + MOD)) ||                   \
0196         (WIDGET_NO_ETCH_BTN == widget || WIDGET_MENU_BUTTON == widget)) && \
0197        (h > (MIN_ROUND_EXTRA_SIZE(widget) + MOD)))))
0198 #define CAN_FULL_ROUND(MOD)                                             \
0199     (w > (MIN_ROUND_FULL_SIZE + MOD) && h > (MIN_ROUND_FULL_SIZE + MOD))
0200 
0201 // **NOTE** MUST KEEP IN SYNC WITH getRadius/RADIUS_ETCH !!!
0202 ERound
0203 qtcGetWidgetRound(const Options *opts, int w, int h, EWidget widget)
0204 {
0205     ERound r = opts->round;
0206 
0207     if ((QtCurve::oneOf(widget, WIDGET_PBAR_TROUGH, WIDGET_PROGRESSBAR) &&
0208          (opts->square & SQUARE_PROGRESS)) ||
0209         (widget == WIDGET_ENTRY && (opts->square & SQUARE_ENTRY)) ||
0210         (widget == WIDGET_SCROLLVIEW && (opts->square & SQUARE_SCROLLVIEW))) {
0211         return ROUND_NONE;
0212     }
0213 
0214     if (QtCurve::oneOf(widget, WIDGET_CHECKBOX, WIDGET_FOCUS) &&
0215         r != ROUND_NONE) {
0216         r = ROUND_SLIGHT;
0217     }
0218 
0219 #ifdef QTC_UTILS_QT
0220     if ((widget == WIDGET_MDI_WINDOW_BUTTON &&
0221          (opts->titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
0222         QtCurve::oneOf(widget, WIDGET_RADIO_BUTTON, WIDGET_DIAL)) {
0223         return ROUND_MAX;
0224     }
0225 #endif
0226 #ifndef QTC_UTILS_QT
0227     if (widget == WIDGET_RADIO_BUTTON) {
0228         return ROUND_MAX;
0229     }
0230 #endif
0231     if (QtCurve::oneOf(opts->sliderStyle, SLIDER_ROUND, SLIDER_ROUND_ROTATED,
0232                        SLIDER_CIRCULAR) && widget == WIDGET_SLIDER) {
0233         return ROUND_MAX;
0234     }
0235     switch (r) {
0236     case ROUND_MAX:
0237         if (IS_SLIDER(widget) || widget == WIDGET_TROUGH ||
0238             (w > (MIN_ROUND_MAX_WIDTH + 2) && h > (MIN_ROUND_MAX_HEIGHT + 2) &&
0239              QtCurve::isMaxRoundWidget(widget))) {
0240             return ROUND_MAX;
0241         }
0242         QTC_FALLTHROUGH();
0243     case ROUND_EXTRA:
0244         if (CAN_EXTRA_ROUND(2)) {
0245             return ROUND_EXTRA;
0246         }
0247         QTC_FALLTHROUGH();
0248     case ROUND_FULL:
0249         if (CAN_FULL_ROUND(2)) {
0250             return ROUND_FULL;
0251         }
0252         QTC_FALLTHROUGH();
0253     case ROUND_SLIGHT:
0254         return ROUND_SLIGHT;
0255     case ROUND_NONE:
0256         return ROUND_NONE;
0257     }
0258     return ROUND_NONE;
0259 }
0260 
0261 double
0262 qtcGetRadius(const Options *opts, int w, int h, EWidget widget, ERadius rad)
0263 {
0264     ERound r = opts->round;
0265 
0266     if (QtCurve::oneOf(widget, WIDGET_CHECKBOX, WIDGET_FOCUS) &&
0267         ROUND_NONE != r) {
0268         r = ROUND_SLIGHT;
0269     }
0270 
0271     if ((QtCurve::oneOf(widget, WIDGET_PBAR_TROUGH, WIDGET_PROGRESSBAR) &&
0272          (opts->square & SQUARE_PROGRESS)) ||
0273         (widget == WIDGET_ENTRY && (opts->square & SQUARE_ENTRY)) ||
0274         (widget == WIDGET_SCROLLVIEW && (opts->square & SQUARE_SCROLLVIEW))) {
0275         return 0.0;
0276     }
0277 
0278 #ifdef QTC_UTILS_QT
0279     if ((widget == WIDGET_MDI_WINDOW_BUTTON &&
0280          (opts->titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
0281         QtCurve::oneOf(widget, WIDGET_RADIO_BUTTON, WIDGET_DIAL)) {
0282         return (w > h ? h : w) / 2.0;
0283     }
0284 #endif
0285 #ifndef QTC_UTILS_QT
0286     if (widget == WIDGET_RADIO_BUTTON) {
0287         return (w > h ? h : w) / 2.0;
0288     }
0289 #endif
0290 
0291     if (QtCurve::oneOf(opts->sliderStyle, SLIDER_ROUND, SLIDER_ROUND_ROTATED,
0292                        SLIDER_CIRCULAR) && widget == WIDGET_SLIDER) {
0293         return (w > h ? h : w) / 2.0;
0294     }
0295 
0296     if (rad == RADIUS_EXTERNAL && !opts->fillProgress &&
0297         (widget == WIDGET_PROGRESSBAR
0298 #ifndef QTC_UTILS_QT
0299          || widget == WIDGET_ENTRY_PROGRESSBAR
0300 #endif
0301             )) {
0302         rad = RADIUS_INTERNAL;
0303     }
0304 
0305     switch (rad) {
0306     case RADIUS_SELECTION:
0307         switch (r) {
0308         case ROUND_MAX:
0309         case ROUND_EXTRA:
0310             if (/* (WIDGET_RUBBER_BAND==widget && w>14 && h>14) || */
0311                 (w > 48 && h > 48)) {
0312                 return 6.0;
0313             }
0314             QTC_FALLTHROUGH();
0315         case ROUND_FULL:
0316             /* if( /\*(WIDGET_RUBBER_BAND==widget && w>11 && h>11) || *\/ */
0317             /*     (w>48 && h>48)) */
0318             /*     return 3.0; */
0319             if (w > MIN_ROUND_FULL_SIZE && h > MIN_ROUND_FULL_SIZE) {
0320                 return 3.0;
0321             }
0322             QTC_FALLTHROUGH();
0323         case ROUND_SLIGHT:
0324             return 2.0;
0325         case ROUND_NONE:
0326             return 0;
0327         }
0328         QTC_FALLTHROUGH();
0329     case RADIUS_INTERNAL:
0330         switch (r) {
0331         case ROUND_MAX:
0332             if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
0333                 double r = ((w > h ? h : w) -
0334                             (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
0335                 return r > MAX_RADIUS_INTERNAL ? MAX_RADIUS_INTERNAL : r;
0336             }
0337             if (w > (MIN_ROUND_MAX_WIDTH - 2) &&
0338                 h > (MIN_ROUND_MAX_HEIGHT - 2) &&
0339                 QtCurve::isMaxRoundWidget(widget)) {
0340                 double r = ((w > h ? h : w) - 2.0) / 2.0;
0341                 return r > 9.5 ? 9.5 : r;
0342             }
0343             QTC_FALLTHROUGH();
0344         case ROUND_EXTRA:
0345             if (CAN_EXTRA_ROUND(-2)) {
0346                 return EXTRA_INNER_RADIUS;
0347             }
0348             QTC_FALLTHROUGH();
0349         case ROUND_FULL:
0350             if (CAN_FULL_ROUND(-2)) {
0351                 return FULL_INNER_RADIUS;
0352             }
0353             QTC_FALLTHROUGH();
0354         case ROUND_SLIGHT:
0355             return SLIGHT_INNER_RADIUS;
0356         case ROUND_NONE:
0357             return 0;
0358         }
0359         QTC_FALLTHROUGH();
0360     case RADIUS_EXTERNAL:
0361         switch (r) {
0362         case ROUND_MAX:
0363             if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
0364                 double r = ((w > h ? h : w) -
0365                             (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
0366                 return r > MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
0367             }
0368             if (w > MIN_ROUND_MAX_WIDTH && h > MIN_ROUND_MAX_HEIGHT &&
0369                 QtCurve::isMaxRoundWidget(widget)) {
0370                 double r = ((w > h ? h : w) - 2.0) / 2.0;
0371                 return r > 10.5 ? 10.5 : r;
0372             }
0373             QTC_FALLTHROUGH();
0374         case ROUND_EXTRA:
0375             if (CAN_EXTRA_ROUND(0)) {
0376                 return EXTRA_OUTER_RADIUS;
0377             }
0378             QTC_FALLTHROUGH();
0379         case ROUND_FULL:
0380             if (CAN_FULL_ROUND(0)) {
0381                 return FULL_OUTER_RADIUS;
0382             }
0383             QTC_FALLTHROUGH();
0384         case ROUND_SLIGHT:
0385             return SLIGHT_OUTER_RADIUS;
0386         case ROUND_NONE:
0387             return 0;
0388         }
0389         QTC_FALLTHROUGH();
0390     case RADIUS_ETCH:
0391         // **NOTE** MUST KEEP IN SYNC WITH getWidgetRound !!!
0392         switch (r) {
0393         case ROUND_MAX:
0394             if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
0395                 double r = ((w > h ? h : w) -
0396                             (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
0397                 return r > MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
0398             }
0399             if (w > (MIN_ROUND_MAX_WIDTH + 2) &&
0400                 h > (MIN_ROUND_MAX_HEIGHT + 2) &&
0401                 QtCurve::isMaxRoundWidget(widget)) {
0402                 double r = ((w > h ? h : w) - 2.0) / 2.0;
0403                 return r > 11.5 ? 11.5 : r;
0404             }
0405             QTC_FALLTHROUGH();
0406         case ROUND_EXTRA:
0407             if (CAN_FULL_ROUND(2)) {
0408                 return EXTRA_ETCH_RADIUS;
0409             }
0410             QTC_FALLTHROUGH();
0411         case ROUND_FULL:
0412             if (w > (MIN_ROUND_FULL_SIZE + 2) &&
0413                 h > (MIN_ROUND_FULL_SIZE + 2)) {
0414                 return FULL_ETCH_RADIUS;
0415             }
0416             QTC_FALLTHROUGH();
0417         case ROUND_SLIGHT:
0418             return SLIGHT_ETCH_RADIUS;
0419         case ROUND_NONE:
0420             return 0;
0421         }
0422         QTC_FALLTHROUGH();
0423     default:
0424         // (empty case required for the fall-through declaration above)
0425         break;
0426     }
0427     return 0;
0428 }