1 /*****************************************************************************
2 * Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com> *
3 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Lesser General Public License as *
7 * published by the Free Software Foundation; either version 2.1 of the *
8 * License, or (at your option) version 3, or any later version accepted *
9 * by the membership of KDE e.V. (or its successor approved by the *
10 * membership of KDE e.V.), which shall act as a proxy defined in *
11 * Section 6 of version 3 of the license. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library. If not, *
20 * see <http://www.gnu.org/licenses/>. *
21 *****************************************************************************/
22
23 #include <stdarg.h>
24 #include "common.h"
25
26 void
qtcSetupGradient(Gradient * grad,EGradientBorder border,int numStops,...)27 qtcSetupGradient(Gradient *grad, EGradientBorder border, int numStops, ...)
28 {
29 va_list ap;
30 int i;
31
32 grad->border = border;
33 #ifndef QTC_UTILS_QT
34 grad->numStops = numStops;
35 grad->stops = qtcNew(GradientStop, numStops);
36 #endif
37 va_start(ap, numStops);
38 for (i = 0;i < numStops;++i) {
39 double pos = va_arg(ap, double);
40 double val = va_arg(ap, double);
41 #ifdef QTC_UTILS_QT
42 grad->stops.insert(GradientStop(pos, val));
43 #else
44 grad->stops[i].pos = pos;
45 grad->stops[i].val = val;
46 grad->stops[i].alpha = 1.0;
47 #endif
48 }
49 va_end(ap);
50 }
51
52 const Gradient*
qtcGetGradient(EAppearance app,const Options * opts)53 qtcGetGradient(EAppearance app, const Options *opts)
54 {
55 if (IS_CUSTOM(app)) {
56 #ifdef QTC_UTILS_QT
57 auto grad = opts->customGradient.find(app);
58
59 if (grad != opts->customGradient.end()) {
60 return &grad->second;
61 }
62 #else
63 Gradient *grad = opts->customGradient[app - APPEARANCE_CUSTOM1];
64
65 if (grad) {
66 return grad;
67 }
68 #endif
69 app = APPEARANCE_RAISED;
70 }
71
72 static Gradient stdGradients[NUM_STD_APP];
73 static bool init = false;
74
75 if (!init) {
76 qtcSetupGradient(&stdGradients[APPEARANCE_FLAT - APPEARANCE_FLAT],
77 GB_3D, 2, 0.0, 1.0, 1.0, 1.0);
78 qtcSetupGradient(&stdGradients[APPEARANCE_RAISED - APPEARANCE_FLAT],
79 GB_3D_FULL, 2, 0.0, 1.0, 1.0, 1.0);
80 qtcSetupGradient(&stdGradients[APPEARANCE_DULL_GLASS -
81 APPEARANCE_FLAT], GB_LIGHT, 4, 0.0,
82 1.05, 0.499, 0.984, 0.5, 0.928,
83 1.0, 1.0);
84 qtcSetupGradient(&stdGradients[APPEARANCE_SHINY_GLASS -
85 APPEARANCE_FLAT], GB_LIGHT, 4, 0.0,
86 1.2, 0.499, 0.984, 0.5, 0.9,
87 1.0, 1.06);
88 qtcSetupGradient(&stdGradients[APPEARANCE_AGUA - APPEARANCE_FLAT],
89 GB_SHINE, 2, 0.0, 0.6, 1.0, 1.1);
90 qtcSetupGradient(&stdGradients[APPEARANCE_SOFT_GRADIENT -
91 APPEARANCE_FLAT], GB_3D, 2, 0.0,
92 1.04, 1.0, 0.98);
93 qtcSetupGradient(
94 &stdGradients[APPEARANCE_GRADIENT - APPEARANCE_FLAT], GB_3D, 2,
95 0.0, 1.1, 1.0, 0.94);
96 qtcSetupGradient(&stdGradients[APPEARANCE_HARSH_GRADIENT -
97 APPEARANCE_FLAT], GB_3D, 2, 0.0, 1.3,
98 1.0, 0.925);
99 qtcSetupGradient(
100 &stdGradients[APPEARANCE_INVERTED - APPEARANCE_FLAT], GB_3D, 2,
101 0.0, 0.93, 1.0, 1.04);
102 qtcSetupGradient(&stdGradients[APPEARANCE_DARK_INVERTED -
103 APPEARANCE_FLAT], GB_NONE, 3, 0.0,
104 0.8, 0.7, 0.95, 1.0, 1.0);
105 qtcSetupGradient(&stdGradients[APPEARANCE_SPLIT_GRADIENT -
106 APPEARANCE_FLAT], GB_3D, 4, 0.0,
107 1.06, 0.499, 1.004, 0.5, 0.986,
108 1.0, 0.92);
109 qtcSetupGradient(
110 &stdGradients[APPEARANCE_BEVELLED - APPEARANCE_FLAT], GB_3D, 4,
111 0.0, 1.05, 0.1, 1.02, 0.9, 0.985, 1.0, 0.94);
112 qtcSetupGradient(&stdGradients[APPEARANCE_LV_BEVELLED -
113 APPEARANCE_FLAT], GB_3D, 3, 0.0,
114 1.00, 0.85, 1.0, 1.0, 0.90);
115 qtcSetupGradient(
116 &stdGradients[APPEARANCE_AGUA_MOD - APPEARANCE_FLAT], GB_NONE,
117 3, 0.0, 1.5, 0.49, 0.85, 1.0, 1.3);
118 qtcSetupGradient(
119 &stdGradients[APPEARANCE_LV_AGUA - APPEARANCE_FLAT], GB_NONE, 4,
120 0.0, 0.98, 0.35, 0.95, 0.4, 0.93, 1.0, 1.15);
121 init = true;
122 }
123
124 return &stdGradients[app - APPEARANCE_FLAT];
125 }
126
127 EAppearance
128 #ifdef QTC_UTILS_QT
qtcWidgetApp(EWidget w,const Options * opts,bool active)129 qtcWidgetApp(EWidget w, const Options *opts, bool active)
130 #else
131 qtcWidgetApp(EWidget w, const Options *opts)
132 #endif
133 {
134 switch (w) {
135 case WIDGET_SB_BGND:
136 return opts->sbarBgndAppearance;
137 case WIDGET_LISTVIEW_HEADER:
138 return opts->lvAppearance;
139 case WIDGET_SB_BUTTON:
140 case WIDGET_SLIDER:
141 case WIDGET_SB_SLIDER:
142 return opts->sliderAppearance;
143 case WIDGET_FILLED_SLIDER_TROUGH:
144 return opts->sliderFill;
145 case WIDGET_TAB_TOP:
146 case WIDGET_TAB_BOT:
147 return opts->tabAppearance;
148 case WIDGET_MENU_ITEM:
149 return opts->menuitemAppearance;
150 case WIDGET_PROGRESSBAR:
151 #ifndef QTC_UTILS_QT
152 case WIDGET_ENTRY_PROGRESSBAR:
153 #endif
154 return opts->progressAppearance;
155 case WIDGET_PBAR_TROUGH:
156 return opts->progressGrooveAppearance;
157 case WIDGET_SELECTION:
158 return opts->selectionAppearance;
159 #ifdef QTC_UTILS_QT
160 case WIDGET_DOCK_WIDGET_TITLE:
161 return opts->dwtAppearance;
162 case WIDGET_MDI_WINDOW:
163 case WIDGET_MDI_WINDOW_TITLE:
164 return (active ? opts->titlebarAppearance :
165 opts->inactiveTitlebarAppearance);
166 case WIDGET_MDI_WINDOW_BUTTON:
167 return opts->titlebarButtonAppearance;
168 case WIDGET_DIAL:
169 return qtcIsFlat(opts->appearance) ? APPEARANCE_RAISED :
170 APPEARANCE_SOFT_GRADIENT;
171 #endif
172 case WIDGET_TROUGH:
173 case WIDGET_SLIDER_TROUGH:
174 return opts->grooveAppearance;
175 #ifndef QTC_UTILS_QT
176 case WIDGET_SPIN_UP:
177 case WIDGET_SPIN_DOWN:
178 #endif
179 case WIDGET_SPIN:
180 return MODIFY_AGUA(opts->appearance);
181 case WIDGET_TOOLBAR_BUTTON:
182 return (APPEARANCE_NONE == opts->tbarBtnAppearance ?
183 opts->appearance : opts->tbarBtnAppearance);
184 default:
185 break;
186 }
187 return opts->appearance;
188 }
189
190 #define CAN_EXTRA_ROUND(MOD) \
191 (QtCurve::isExtraRoundWidget(widget) && \
192 (IS_SLIDER(widget) || WIDGET_TROUGH == widget || \
193 (((w > (MIN_ROUND_EXTRA_SIZE(widget) + MOD)) || \
194 (WIDGET_NO_ETCH_BTN == widget || WIDGET_MENU_BUTTON == widget)) && \
195 (h > (MIN_ROUND_EXTRA_SIZE(widget) + MOD)))))
196 #define CAN_FULL_ROUND(MOD) \
197 (w > (MIN_ROUND_FULL_SIZE + MOD) && h > (MIN_ROUND_FULL_SIZE + MOD))
198
199 // **NOTE** MUST KEEP IN SYNC WITH getRadius/RADIUS_ETCH !!!
200 ERound
qtcGetWidgetRound(const Options * opts,int w,int h,EWidget widget)201 qtcGetWidgetRound(const Options *opts, int w, int h, EWidget widget)
202 {
203 ERound r = opts->round;
204
205 if ((QtCurve::oneOf(widget, WIDGET_PBAR_TROUGH, WIDGET_PROGRESSBAR) &&
206 (opts->square & SQUARE_PROGRESS)) ||
207 (widget == WIDGET_ENTRY && (opts->square & SQUARE_ENTRY)) ||
208 (widget == WIDGET_SCROLLVIEW && (opts->square & SQUARE_SCROLLVIEW))) {
209 return ROUND_NONE;
210 }
211
212 if (QtCurve::oneOf(widget, WIDGET_CHECKBOX, WIDGET_FOCUS) &&
213 r != ROUND_NONE) {
214 r = ROUND_SLIGHT;
215 }
216
217 #ifdef QTC_UTILS_QT
218 if ((widget == WIDGET_MDI_WINDOW_BUTTON &&
219 (opts->titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
220 QtCurve::oneOf(widget, WIDGET_RADIO_BUTTON, WIDGET_DIAL)) {
221 return ROUND_MAX;
222 }
223 #endif
224 #ifndef QTC_UTILS_QT
225 if (widget == WIDGET_RADIO_BUTTON) {
226 return ROUND_MAX;
227 }
228 #endif
229 if (QtCurve::oneOf(opts->sliderStyle, SLIDER_ROUND, SLIDER_ROUND_ROTATED,
230 SLIDER_CIRCULAR) && widget == WIDGET_SLIDER) {
231 return ROUND_MAX;
232 }
233 switch (r) {
234 case ROUND_MAX:
235 if (IS_SLIDER(widget) || widget == WIDGET_TROUGH ||
236 (w > (MIN_ROUND_MAX_WIDTH + 2) && h > (MIN_ROUND_MAX_HEIGHT + 2) &&
237 QtCurve::isMaxRoundWidget(widget))) {
238 return ROUND_MAX;
239 }
240 case ROUND_EXTRA:
241 if (CAN_EXTRA_ROUND(2)) {
242 return ROUND_EXTRA;
243 }
244 case ROUND_FULL:
245 if (CAN_FULL_ROUND(2)) {
246 return ROUND_FULL;
247 }
248 case ROUND_SLIGHT:
249 return ROUND_SLIGHT;
250 case ROUND_NONE:
251 return ROUND_NONE;
252 }
253 return ROUND_NONE;
254 }
255
256 double
qtcGetRadius(const Options * opts,int w,int h,EWidget widget,ERadius rad)257 qtcGetRadius(const Options *opts, int w, int h, EWidget widget, ERadius rad)
258 {
259 ERound r = opts->round;
260
261 if (QtCurve::oneOf(widget, WIDGET_CHECKBOX, WIDGET_FOCUS) &&
262 ROUND_NONE != r) {
263 r = ROUND_SLIGHT;
264 }
265
266 if ((QtCurve::oneOf(widget, WIDGET_PBAR_TROUGH, WIDGET_PROGRESSBAR) &&
267 (opts->square & SQUARE_PROGRESS)) ||
268 (widget == WIDGET_ENTRY && (opts->square & SQUARE_ENTRY)) ||
269 (widget == WIDGET_SCROLLVIEW && (opts->square & SQUARE_SCROLLVIEW))) {
270 return 0.0;
271 }
272
273 #ifdef QTC_UTILS_QT
274 if ((widget == WIDGET_MDI_WINDOW_BUTTON &&
275 (opts->titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
276 QtCurve::oneOf(widget, WIDGET_RADIO_BUTTON, WIDGET_DIAL)) {
277 return (w > h ? h : w) / 2.0;
278 }
279 #endif
280 #ifndef QTC_UTILS_QT
281 if (widget == WIDGET_RADIO_BUTTON) {
282 return (w > h ? h : w) / 2.0;
283 }
284 #endif
285
286 if (QtCurve::oneOf(opts->sliderStyle, SLIDER_ROUND, SLIDER_ROUND_ROTATED,
287 SLIDER_CIRCULAR) && widget == WIDGET_SLIDER) {
288 return (w > h ? h : w) / 2.0;
289 }
290
291 if (rad == RADIUS_EXTERNAL && !opts->fillProgress &&
292 (widget == WIDGET_PROGRESSBAR
293 #ifndef QTC_UTILS_QT
294 || widget == WIDGET_ENTRY_PROGRESSBAR
295 #endif
296 )) {
297 rad = RADIUS_INTERNAL;
298 }
299
300 switch (rad) {
301 case RADIUS_SELECTION:
302 switch (r) {
303 case ROUND_MAX:
304 case ROUND_EXTRA:
305 if (/* (WIDGET_RUBBER_BAND==widget && w>14 && h>14) || */
306 (w > 48 && h > 48)) {
307 return 6.0;
308 }
309 case ROUND_FULL:
310 /* if( /\*(WIDGET_RUBBER_BAND==widget && w>11 && h>11) || *\/ */
311 /* (w>48 && h>48)) */
312 /* return 3.0; */
313 if (w > MIN_ROUND_FULL_SIZE && h > MIN_ROUND_FULL_SIZE) {
314 return 3.0;
315 }
316 case ROUND_SLIGHT:
317 return 2.0;
318 case ROUND_NONE:
319 return 0;
320 }
321 case RADIUS_INTERNAL:
322 switch (r) {
323 case ROUND_MAX:
324 if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
325 double r = ((w > h ? h : w) -
326 (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
327 return r > MAX_RADIUS_INTERNAL ? MAX_RADIUS_INTERNAL : r;
328 }
329 if (w > (MIN_ROUND_MAX_WIDTH - 2) &&
330 h > (MIN_ROUND_MAX_HEIGHT - 2) &&
331 QtCurve::isMaxRoundWidget(widget)) {
332 double r = ((w > h ? h : w) - 2.0) / 2.0;
333 return r > 9.5 ? 9.5 : r;
334 }
335 case ROUND_EXTRA:
336 if (CAN_EXTRA_ROUND(-2)) {
337 return EXTRA_INNER_RADIUS;
338 }
339 case ROUND_FULL:
340 if (CAN_FULL_ROUND(-2)) {
341 return FULL_INNER_RADIUS;
342 }
343 case ROUND_SLIGHT:
344 return SLIGHT_INNER_RADIUS;
345 case ROUND_NONE:
346 return 0;
347 }
348 case RADIUS_EXTERNAL:
349 switch (r) {
350 case ROUND_MAX:
351 if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
352 double r = ((w > h ? h : w) -
353 (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
354 return r > MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
355 }
356 if (w > MIN_ROUND_MAX_WIDTH && h > MIN_ROUND_MAX_HEIGHT &&
357 QtCurve::isMaxRoundWidget(widget)) {
358 double r = ((w > h ? h : w) - 2.0) / 2.0;
359 return r > 10.5 ? 10.5 : r;
360 }
361 case ROUND_EXTRA:
362 if (CAN_EXTRA_ROUND(0)) {
363 return EXTRA_OUTER_RADIUS;
364 }
365 case ROUND_FULL:
366 if (CAN_FULL_ROUND(0)) {
367 return FULL_OUTER_RADIUS;
368 }
369 case ROUND_SLIGHT:
370 return SLIGHT_OUTER_RADIUS;
371 case ROUND_NONE:
372 return 0;
373 }
374 case RADIUS_ETCH:
375 // **NOTE** MUST KEEP IN SYNC WITH getWidgetRound !!!
376 switch (r) {
377 case ROUND_MAX:
378 if (IS_SLIDER(widget) || WIDGET_TROUGH == widget) {
379 double r = ((w > h ? h : w) -
380 (WIDGET_SLIDER == widget ? 1 : 0)) / 2.0;
381 return r > MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
382 }
383 if (w > (MIN_ROUND_MAX_WIDTH + 2) &&
384 h > (MIN_ROUND_MAX_HEIGHT + 2) &&
385 QtCurve::isMaxRoundWidget(widget)) {
386 double r = ((w > h ? h : w) - 2.0) / 2.0;
387 return r > 11.5 ? 11.5 : r;
388 }
389 case ROUND_EXTRA:
390 if (CAN_FULL_ROUND(2)) {
391 return EXTRA_ETCH_RADIUS;
392 }
393 case ROUND_FULL:
394 if (w > (MIN_ROUND_FULL_SIZE + 2) &&
395 h > (MIN_ROUND_FULL_SIZE + 2)) {
396 return FULL_ETCH_RADIUS;
397 }
398 case ROUND_SLIGHT:
399 return SLIGHT_ETCH_RADIUS;
400 case ROUND_NONE:
401 return 0;
402 }
403 }
404 return 0;
405 }
406