~ubuntu-branches/debian/stretch/insubstantial/stretch

« back to all changes in this revision

Viewing changes to substance/src/main/java/org/pushingpixels/substance/internal/utils/SubstanceImageCreator.java

  • Committer: Package Import Robot
  • Author(s): Felix Natter
  • Date: 2016-01-18 20:58:45 UTC
  • Revision ID: package-import@ubuntu.com-20160118205845-crbmrkda61qsi5qa
Tags: upstream-7.3+dfsg2
ImportĀ upstreamĀ versionĀ 7.3+dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
7
 *  o Redistributions of source code must retain the above copyright notice,
 
8
 *    this list of conditions and the following disclaimer.
 
9
 *
 
10
 *  o Redistributions in binary form must reproduce the above copyright notice,
 
11
 *    this list of conditions and the following disclaimer in the documentation
 
12
 *    and/or other materials provided with the distribution.
 
13
 *
 
14
 *  o Neither the name of Substance Kirill Grouchnikov nor the names of
 
15
 *    its contributors may be used to endorse or promote products derived
 
16
 *    from this software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
20
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
21
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
22
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
23
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
24
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
25
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
26
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 
27
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 
28
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
package org.pushingpixels.substance.internal.utils;
 
31
 
 
32
import java.awt.*;
 
33
import java.awt.MultipleGradientPaint.CycleMethod;
 
34
import java.awt.geom.*;
 
35
import java.awt.image.*;
 
36
 
 
37
import javax.swing.*;
 
38
import javax.swing.text.JTextComponent;
 
39
 
 
40
import org.pushingpixels.lafwidget.LafWidgetUtilities;
 
41
import org.pushingpixels.substance.api.*;
 
42
import org.pushingpixels.substance.api.SubstanceConstants.Side;
 
43
import org.pushingpixels.substance.api.painter.border.FlatBorderPainter;
 
44
import org.pushingpixels.substance.api.painter.border.SubstanceBorderPainter;
 
45
import org.pushingpixels.substance.api.painter.fill.SubstanceFillPainter;
 
46
import org.pushingpixels.substance.api.watermark.SubstanceWatermark;
 
47
import org.pushingpixels.substance.internal.colorscheme.ShiftColorScheme;
 
48
import org.pushingpixels.substance.internal.painter.SimplisticFillPainter;
 
49
import org.pushingpixels.substance.internal.utils.filters.*;
 
50
 
 
51
/**
 
52
 * Provides utility functions for creating various images for <b>Substance </b>
 
53
 * look and feel. This class is <b>for internal use only</b>.
 
54
 * 
 
55
 * @author Kirill Grouchnikov
 
56
 */
 
57
public final class SubstanceImageCreator {
 
58
        /**
 
59
         * Custom fill painter for filling the checkmarks of checkboxes and radio
 
60
         * buttons.
 
61
         * 
 
62
         * @author Kirill Grouchnikov
 
63
         */
 
64
        public static class SimplisticSoftBorderReverseFillPainter extends
 
65
                        SimplisticFillPainter {
 
66
                /**
 
67
                 * Singleton instance.
 
68
                 */
 
69
                public static final SubstanceFillPainter INSTANCE = new SimplisticSoftBorderReverseFillPainter();
 
70
 
 
71
                /**
 
72
                 * Private constructor.
 
73
                 */
 
74
                private SimplisticSoftBorderReverseFillPainter() {
 
75
                }
 
76
 
 
77
                @Override
 
78
                public String getDisplayName() {
 
79
                        return "Simplistic Soft Border Reverse";
 
80
                }
 
81
 
 
82
                @Override
 
83
                public Color getTopFillColor(SubstanceColorScheme fillScheme) {
 
84
                        return super.getBottomFillColor(fillScheme);
 
85
                }
 
86
 
 
87
                @Override
 
88
                public Color getBottomFillColor(SubstanceColorScheme fillScheme) {
 
89
                        return super.getTopFillColor(fillScheme);
 
90
                }
 
91
        }
 
92
 
 
93
        /**
 
94
         * Paints border instance of specified dimensions and status.
 
95
         * 
 
96
         * @param c
 
97
         *            Component.
 
98
         * @param graphics
 
99
         *            Graphics context.
 
100
         * @param x
 
101
         *            Component left X (in graphics context).
 
102
         * @param y
 
103
         *            Component top Y (in graphics context).
 
104
         * @param width
 
105
         *            Border width.
 
106
         * @param height
 
107
         *            Border height.
 
108
         * @param radius
 
109
         *            Border radius.
 
110
         * @param borderScheme
 
111
         *            border color scheme.
 
112
         */
 
113
        public static void paintBorder(Component c, Graphics2D graphics, int x,
 
114
                        int y, int width, int height, float radius,
 
115
                        SubstanceColorScheme borderScheme) {
 
116
 
 
117
                SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
 
118
                                .getBorderPainter(c);
 
119
                graphics.translate(x, y);
 
120
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
121
                int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
122
                                .getBorderStrokeWidth(componentFontSize) / 2.0);
 
123
                Shape contour = SubstanceOutlineUtilities.getBaseOutline(width, height,
 
124
                                radius, null, borderDelta);
 
125
                int borderThickness = (int) SubstanceSizeUtils
 
126
                                .getBorderStrokeWidth(componentFontSize);
 
127
                boolean skipInnerBorder = (c instanceof JTextComponent)
 
128
                                || ((SwingUtilities.getAncestorOfClass(CellRendererPane.class,
 
129
                                                c) != null) && (SwingUtilities.getAncestorOfClass(
 
130
                                                JFileChooser.class, c) != null));
 
131
                GeneralPath contourInner = skipInnerBorder ? null
 
132
                                : SubstanceOutlineUtilities.getBaseOutline(width, height,
 
133
                                                radius - borderThickness, null, borderThickness
 
134
                                                                + borderDelta);
 
135
                borderPainter.paintBorder(graphics, c, width, height, contour,
 
136
                                contourInner, borderScheme);
 
137
                graphics.translate(-x, -y);
 
138
        }
 
139
 
 
140
        /**
 
141
         * Paints border instance of specified dimensions and status.
 
142
         * 
 
143
         * @param c
 
144
         *            Component.
 
145
         * @param graphics
 
146
         *            Graphics context.
 
147
         * @param x
 
148
         *            Component left X (in graphics context).
 
149
         * @param y
 
150
         *            Component top Y (in graphics context).
 
151
         * @param width
 
152
         *            Border width.
 
153
         * @param height
 
154
         *            Border height.
 
155
         * @param radius
 
156
         *            Border radius.
 
157
         * @param borderScheme
 
158
         *            Border color scheme.
 
159
         */
 
160
        public static void paintTextComponentBorder(JComponent c,
 
161
                        Graphics graphics, int x, int y, int width, int height,
 
162
                        float radius, SubstanceColorScheme borderScheme) {
 
163
 
 
164
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
165
                int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
166
                                .getBorderStrokeWidth(componentFontSize) / 2.0);
 
167
                Shape contour = SubstanceOutlineUtilities
 
168
                                .getBaseOutline(width, height, radius,
 
169
                                                SubstanceCoreUtilities.getSides(c,
 
170
                                                                SubstanceLookAndFeel.BUTTON_SIDE_PROPERTY),
 
171
                                                borderDelta);
 
172
                int borderThickness = (int) SubstanceSizeUtils
 
173
                                .getBorderStrokeWidth(componentFontSize);
 
174
                GeneralPath contourInner = SubstanceOutlineUtilities.getBaseOutline(
 
175
                                width, height, radius - borderThickness, null, borderThickness
 
176
                                                + borderDelta);
 
177
 
 
178
                Graphics2D g2d = (Graphics2D) graphics.create();
 
179
                g2d.translate(x, y);
 
180
 
 
181
                ComponentState stateForOuterBorder = c.isEnabled() ? ComponentState.ENABLED
 
182
                                : ComponentState.DISABLED_UNSELECTED;
 
183
                Color lightColor = SubstanceColorUtilities.getDefaultBackgroundColor(c,
 
184
                                stateForOuterBorder);
 
185
 
 
186
                if (stateForOuterBorder.isDisabled()) {
 
187
                        float alpha = SubstanceColorSchemeUtilities.getAlpha(c,
 
188
                                        stateForOuterBorder);
 
189
                        lightColor = SubstanceColorUtilities.getAlphaColor(lightColor,
 
190
                                        (int) (255 * alpha));
 
191
                }
 
192
 
 
193
                Color outerColor = SubstanceColorUtilities
 
194
                                .getOuterTextComponentBorderColor(lightColor);
 
195
                float[] hsb = Color.RGBtoHSB(lightColor.getRed(),
 
196
                                lightColor.getGreen(), lightColor.getBlue(), null);
 
197
                // hsb[1] = hsb[1] * 0.5f;
 
198
                // System.out.println(lightColor + " -> " + hsb[1] + ":" + hsb[2]);
 
199
                double bottomInnerBlend = 0.85;
 
200
                double topInnerBlend = 0.8;
 
201
                if (hsb[2] < 0.3f) {
 
202
                        bottomInnerBlend = 0.6;
 
203
                        topInnerBlend = 0.95;
 
204
                } else if (hsb[2] < 0.5f) {
 
205
                        bottomInnerBlend = 0.8;
 
206
                } else if (hsb[2] < 0.75f) {
 
207
                        bottomInnerBlend = 0.7;
 
208
                } else {
 
209
                }
 
210
                Color darkColor = borderScheme.getDarkColor();
 
211
 
 
212
                Color topInnerColor = SubstanceColorUtilities.getInterpolatedColor(
 
213
                                darkColor, lightColor, topInnerBlend);
 
214
                Color bottomInnerColor = SubstanceColorUtilities.getInterpolatedColor(
 
215
                                lightColor, darkColor, bottomInnerBlend);
 
216
 
 
217
                // darkColor = SubstanceColorUtilities.getAlphaColor(darkColor, 196);
 
218
 
 
219
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
220
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
221
                g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
 
222
                                RenderingHints.VALUE_STROKE_NORMALIZE);
 
223
 
 
224
                float strokeWidth = SubstanceSizeUtils
 
225
                                .getBorderStrokeWidth(SubstanceSizeUtils
 
226
                                                .getComponentFontSize(c));
 
227
                g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_BUTT,
 
228
                                BasicStroke.JOIN_ROUND));
 
229
 
 
230
                g2d.setPaint(new GradientPaint(0, 0, outerColor, 0, height, outerColor));
 
231
                // g2d.setColor(Color.red);
 
232
                g2d.draw(contour);
 
233
                g2d.setPaint(new GradientPaint(0, 0, topInnerColor, 0, height,
 
234
                                bottomInnerColor));
 
235
                // g2d.setColor(Color.green);
 
236
                g2d.draw(contourInner);
 
237
 
 
238
                // System.out.println("Outer : " + outerColor + "[" + lightColor
 
239
                // + "] from " + borderScheme.getDisplayName());
 
240
 
 
241
                g2d.dispose();
 
242
        }
 
243
 
 
244
        /**
 
245
         * Retrieves check mark image.
 
246
         * 
 
247
         * @param dimension
 
248
         *            Check mark dimension.
 
249
         * @param isEnabled
 
250
         *            Enabled status.
 
251
         * @param scheme
 
252
         *            Color scheme for the check mark.
 
253
         * @param checkMarkVisibility
 
254
         *            Checkmark visibility in 0.0-1.0 range.
 
255
         * @return Check mark image.
 
256
         */
 
257
        private static BufferedImage getCheckMark(int dimension, boolean isEnabled,
 
258
                        SubstanceColorScheme scheme, float checkMarkVisibility) {
 
259
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(dimension,
 
260
                                dimension);
 
261
 
 
262
                // get graphics and set hints
 
263
                Graphics2D graphics = (Graphics2D) result.getGraphics();
 
264
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
265
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
266
 
 
267
                // create curved checkbox path
 
268
                GeneralPath path = new GeneralPath();
 
269
 
 
270
                path.moveTo(0.25f * dimension, 0.5f * dimension);
 
271
                path.quadTo(0.37f * dimension, 0.6f * dimension, 0.47f * dimension,
 
272
                                0.8f * dimension);
 
273
                path.quadTo(0.55f * dimension, 0.5f * dimension, 0.85f * dimension, 0f);
 
274
 
 
275
                // compute the x-based clip for the visibility
 
276
                float xClipStart = 0.15f * dimension;
 
277
                float xClipEnd = 0.95f * dimension;
 
278
 
 
279
                float xClipRealEnd = xClipStart + (xClipEnd - xClipStart)
 
280
                                * checkMarkVisibility;
 
281
 
 
282
                graphics.setClip(0, 0, (int) Math.ceil(xClipRealEnd), dimension);
 
283
 
 
284
                graphics.setColor(SubstanceColorUtilities.getMarkColor(scheme,
 
285
                                isEnabled));
 
286
                Stroke stroke = new BasicStroke((float) 0.15 * dimension,
 
287
                                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
 
288
                graphics.setStroke(stroke);
 
289
                graphics.draw(path);
 
290
 
 
291
                return result;
 
292
        }
 
293
 
 
294
        /**
 
295
         * Returns arrow icon for the specified parameters.
 
296
         * 
 
297
         * @param fontSize
 
298
         *            Font size.
 
299
         * @param direction
 
300
         *            Arrow direction.
 
301
         * @param colorScheme
 
302
         *            Arrow icon color scheme.
 
303
         * @return Arrow icon.
 
304
         */
 
305
        public static Icon getArrowIcon(int fontSize, int direction,
 
306
                        SubstanceColorScheme colorScheme) {
 
307
                float width = SubstanceSizeUtils.getArrowIconWidth(fontSize);
 
308
                float height = SubstanceSizeUtils.getArrowIconHeight(fontSize);
 
309
                if (direction == SwingConstants.CENTER)
 
310
                        height *= 2;
 
311
                float strokeWidth = SubstanceSizeUtils.getArrowStrokeWidth(fontSize);
 
312
                return new ImageIcon(getArrow(width, height, strokeWidth, direction,
 
313
                                colorScheme));
 
314
        }
 
315
 
 
316
        /**
 
317
         * Retrieves arrow icon.
 
318
         * 
 
319
         * @param width
 
320
         *            Arrow width.
 
321
         * @param height
 
322
         *            Arrow height.
 
323
         * @param strokeWidth
 
324
         *            Stroke width.
 
325
         * @param direction
 
326
         *            Arrow direction.
 
327
         * @param scheme
 
328
         *            Color scheme for the arrow.
 
329
         * @return Arrow image.
 
330
         * @see SwingConstants#NORTH
 
331
         * @see SwingConstants#WEST
 
332
         * @see SwingConstants#SOUTH
 
333
         * @see SwingConstants#EAST
 
334
         */
 
335
        public static Icon getArrowIcon(float width, float height,
 
336
                        float strokeWidth, int direction, SubstanceColorScheme scheme) {
 
337
                return new ImageIcon(getArrow(width, height, strokeWidth, direction,
 
338
                                scheme));
 
339
        }
 
340
 
 
341
        /**
 
342
         * Retrieves arrow image.
 
343
         * 
 
344
         * @param width
 
345
         *            Arrow width.
 
346
         * @param height
 
347
         *            Arrow height.
 
348
         * @param strokeWidth
 
349
         *            Stroke width.
 
350
         * @param direction
 
351
         *            Arrow direction.
 
352
         * @param scheme
 
353
         *            Color scheme for the arrow.
 
354
         * @return Arrow image.
 
355
         * @see SwingConstants#NORTH
 
356
         * @see SwingConstants#WEST
 
357
         * @see SwingConstants#SOUTH
 
358
         * @see SwingConstants#EAST
 
359
         * @see SwingConstants#CENTER
 
360
         */
 
361
        public static BufferedImage getArrow(float width, float height,
 
362
                        float strokeWidth, int direction, SubstanceColorScheme scheme) {
 
363
                BufferedImage arrowImage = SubstanceCoreUtilities.getBlankImage(
 
364
                                (int) width, (int) height);
 
365
 
 
366
                // System.out.println(width + ":" + height + ":" + strokeWidth);
 
367
 
 
368
                // get graphics and set hints
 
369
                Graphics2D graphics = (Graphics2D) arrowImage.getGraphics();
 
370
 
 
371
                // graphics.setColor(Color.red);
 
372
                // graphics.fillRect(0, 0, width, height);
 
373
 
 
374
                graphics.translate(1, 1);
 
375
                width -= 2;
 
376
                height -= 2;
 
377
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
378
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
379
 
 
380
                Color arrowColor = SubstanceColorUtilities.getMarkColor(scheme, true);
 
381
 
 
382
                graphics.setColor(arrowColor);
 
383
                int cap = (width < 15) ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
 
384
                Stroke stroke = new BasicStroke(strokeWidth, cap,
 
385
                                BasicStroke.JOIN_MITER);
 
386
 
 
387
                graphics.setStroke(stroke);
 
388
 
 
389
                int cushion = (int) strokeWidth / 2;
 
390
                if (direction == SwingConstants.CENTER) {
 
391
                        BufferedImage top = getArrow(width, height / 2, strokeWidth,
 
392
                                        SwingConstants.NORTH, scheme);
 
393
                        BufferedImage bottom = getArrow(width, height / 2, strokeWidth,
 
394
                                        SwingConstants.SOUTH, scheme);
 
395
                        graphics.drawImage(top, 0, 1, null);
 
396
                        graphics.drawImage(bottom, 0, (int) height / 2 - 1, null);
 
397
                        return arrowImage;
 
398
                } else {
 
399
                        GeneralPath gp = new GeneralPath();
 
400
                        gp.moveTo(cushion, strokeWidth);
 
401
                        gp.lineTo((float) 0.5 * (width - 1), height - 1 - cushion);
 
402
                        gp.lineTo(width - 1 - cushion, strokeWidth);
 
403
                        graphics.draw(gp);
 
404
 
 
405
                        // graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
406
                        // RenderingHints.VALUE_ANTIALIAS_OFF);
 
407
                        // graphics.setStroke(new BasicStroke(1.0f, cap,
 
408
                        // BasicStroke.JOIN_MITER));
 
409
                        // graphics.setColor(Color.red);
 
410
                        // graphics.drawRect(0, 0, (int)width - 1, (int)height - 1);
 
411
 
 
412
                        int quadrantCounterClockwise = 0;
 
413
                        switch (direction) {
 
414
                        case SwingConstants.NORTH:
 
415
                                quadrantCounterClockwise = 2;
 
416
                                break;
 
417
                        case SwingConstants.WEST:
 
418
                                quadrantCounterClockwise = 1;
 
419
                                break;
 
420
                        case SwingConstants.SOUTH:
 
421
                                quadrantCounterClockwise = 0;
 
422
                                break;
 
423
                        case SwingConstants.EAST:
 
424
                                quadrantCounterClockwise = 3;
 
425
                                break;
 
426
                        }
 
427
                        BufferedImage rotatedImage = SubstanceImageCreator.getRotated(
 
428
                                        arrowImage, quadrantCounterClockwise);
 
429
 
 
430
                        return rotatedImage;
 
431
                }
 
432
        }
 
433
 
 
434
        /**
 
435
         * Returns double arrow icon for the specified parameters.
 
436
         * 
 
437
         * @param fontSize
 
438
         *            Font size.
 
439
         * @param deltaWidth
 
440
         *            Arrow width delta.
 
441
         * @param deltaHeight
 
442
         *            Arrow height delta.
 
443
         * @param deltaStrokeWidth
 
444
         *            Arrow stroke width delta.
 
445
         * @param direction
 
446
         *            Arrow direction.
 
447
         * @param colorScheme
 
448
         *            Color scheme for the arrow.
 
449
         * @return Double arrow icon.
 
450
         */
 
451
        public static Icon getDoubleArrowIconDelta(int fontSize, float deltaWidth,
 
452
                        float deltaHeight, float deltaStrokeWidth, int direction,
 
453
                        SubstanceColorScheme colorScheme) {
 
454
                float arrowWidth = SubstanceSizeUtils.getArrowIconWidth(fontSize)
 
455
                                + deltaWidth;
 
456
                float arrowHeight = SubstanceSizeUtils.getArrowIconHeight(fontSize)
 
457
                                + deltaHeight;
 
458
                float arrowStrokeWidth = SubstanceSizeUtils
 
459
                                .getDoubleArrowStrokeWidth(fontSize) + deltaStrokeWidth;
 
460
                return getDoubleArrowIcon(fontSize, arrowWidth, arrowHeight,
 
461
                                arrowStrokeWidth, direction, colorScheme);
 
462
        }
 
463
 
 
464
        /**
 
465
         * Retrieves arrow icon.
 
466
         * 
 
467
         * @param width
 
468
         *            Arrow width.
 
469
         * @param height
 
470
         *            Arrow height.
 
471
         * @param strokeWidth
 
472
         *            Stroke width.
 
473
         * @param direction
 
474
         *            Arrow direction.
 
475
         * @param colorScheme
 
476
         *            Color scheme for the arrow.
 
477
         * @return Arrow image.
 
478
         * @see SwingConstants#NORTH
 
479
         * @see SwingConstants#WEST
 
480
         * @see SwingConstants#SOUTH
 
481
         * @see SwingConstants#EAST
 
482
         */
 
483
        public static Icon getDoubleArrowIcon(int fontSize, float width,
 
484
                        float height, float strokeWidth, int direction,
 
485
                        SubstanceColorScheme colorScheme) {
 
486
                int delta = 3 + 2 * SubstanceSizeUtils.getExtraPadding(fontSize) / 3;
 
487
                boolean toggle = (direction == SwingConstants.WEST)
 
488
                                || (direction == SwingConstants.EAST);
 
489
                if (toggle) {
 
490
                        float temp = width;
 
491
                        width = height;
 
492
                        height = temp;
 
493
                }
 
494
                BufferedImage downArrowImage = SubstanceCoreUtilities.getBlankImage(
 
495
                                (int) width, (int) height);
 
496
 
 
497
                BufferedImage singleArrow = getArrow(width,
 
498
                                Math.max(1, height - delta), strokeWidth, SwingConstants.SOUTH,
 
499
                                colorScheme);
 
500
 
 
501
                // get graphics and set hints
 
502
                Graphics2D graphics = (Graphics2D) downArrowImage.getGraphics();
 
503
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
504
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
505
 
 
506
                int arrowHeight = singleArrow.getHeight();
 
507
                int arrowWidth = singleArrow.getWidth();
 
508
                int offset = toggle ? (int) (height - arrowHeight - delta) / 2
 
509
                                : (int) (width - arrowWidth - delta) / 2;
 
510
                graphics.drawImage(singleArrow, 0, offset, null);
 
511
                graphics.drawImage(singleArrow, 0, offset + delta, null);
 
512
 
 
513
                int quadrantCounterClockwise = 0;
 
514
                switch (direction) {
 
515
                case SwingConstants.NORTH:
 
516
                        quadrantCounterClockwise = 2;
 
517
                        break;
 
518
                case SwingConstants.WEST:
 
519
                        quadrantCounterClockwise = 1;
 
520
                        break;
 
521
                case SwingConstants.SOUTH:
 
522
                        quadrantCounterClockwise = 0;
 
523
                        break;
 
524
                case SwingConstants.EAST:
 
525
                        quadrantCounterClockwise = 3;
 
526
                        break;
 
527
                }
 
528
                BufferedImage arrowImage = SubstanceImageCreator.getRotated(
 
529
                                downArrowImage, quadrantCounterClockwise);
 
530
 
 
531
                return new ImageIcon(arrowImage);
 
532
        }
 
533
 
 
534
        /**
 
535
         * Returns rotated image.
 
536
         * 
 
537
         * @param bi
 
538
         *            Image to rotate.
 
539
         * @param quadrantClockwise
 
540
         *            Amount of quadrants to rotate in clockwise directio. The
 
541
         *            rotation angle is 90 times this value.
 
542
         * @return Rotated image.
 
543
         */
 
544
        public static BufferedImage getRotated(BufferedImage bi,
 
545
                        int quadrantClockwise) {
 
546
                quadrantClockwise = quadrantClockwise % 4;
 
547
                int width = bi.getWidth();
 
548
                int height = bi.getHeight();
 
549
                if ((quadrantClockwise == 1) || (quadrantClockwise == 3)) {
 
550
                        width = bi.getHeight();
 
551
                        height = bi.getWidth();
 
552
                }
 
553
                BufferedImage biRot = SubstanceCoreUtilities.getBlankImage(width,
 
554
                                height);
 
555
                AffineTransform at = null;
 
556
                switch (quadrantClockwise) {
 
557
                case 1:
 
558
                        at = AffineTransform.getTranslateInstance(width, 0);
 
559
                        at.rotate(Math.PI / 2);
 
560
                        break;
 
561
                case 2:
 
562
                        at = AffineTransform.getTranslateInstance(width, height);
 
563
                        at.rotate(Math.PI);
 
564
                        break;
 
565
                case 3:
 
566
                        at = AffineTransform.getTranslateInstance(0, height);
 
567
                        at.rotate(-Math.PI / 2);
 
568
                }
 
569
                Graphics2D rotg = biRot.createGraphics();
 
570
                if (at != null)
 
571
                        rotg.setTransform(at);
 
572
                rotg.drawImage(bi, 0, 0, null);
 
573
                rotg.dispose();
 
574
                return biRot;
 
575
        }
 
576
 
 
577
        /**
 
578
         * Returns rotated image.
 
579
         * 
 
580
         * @param bi
 
581
         *            Image to rotate.
 
582
         * @param quadrantClockwise
 
583
         *            Amount of quadrants to rotate in clockwise directio. The
 
584
         *            rotation angle is 90 times this value.
 
585
         * @return Rotated image.
 
586
         */
 
587
        public static VolatileImage getRotated(final VolatileImage bi,
 
588
                        int quadrantClockwise) {
 
589
                quadrantClockwise = quadrantClockwise % 4;
 
590
                int width = bi.getWidth();
 
591
                int height = bi.getHeight();
 
592
                if ((quadrantClockwise == 1) || (quadrantClockwise == 3)) {
 
593
                        width = bi.getHeight();
 
594
                        height = bi.getWidth();
 
595
                }
 
596
                VolatileImage biRot = SubstanceCoreUtilities.getBlankVolatileImage(
 
597
                                width, height);
 
598
                AffineTransform at = null;
 
599
                switch (quadrantClockwise) {
 
600
                case 1:
 
601
                        at = AffineTransform.getTranslateInstance(width, 0);
 
602
                        at.rotate(Math.PI / 2);
 
603
                        break;
 
604
                case 2:
 
605
                        at = AffineTransform.getTranslateInstance(width, height);
 
606
                        at.rotate(Math.PI);
 
607
                        break;
 
608
                case 3:
 
609
                        at = AffineTransform.getTranslateInstance(0, height);
 
610
                        at.rotate(-Math.PI / 2);
 
611
                }
 
612
                Graphics2D rotg = biRot.createGraphics();
 
613
                if (at != null)
 
614
                        rotg.setTransform(at);
 
615
                rotg.drawImage(bi, 0, 0, null);
 
616
                rotg.dispose();
 
617
                return biRot;
 
618
        }
 
619
 
 
620
        /**
 
621
         * Translated the specified icon to grey scale.
 
622
         * 
 
623
         * @param icon
 
624
         *            Icon.
 
625
         * @return Greyscale version of the specified icon.
 
626
         */
 
627
        public static Icon toGreyscale(Icon icon) {
 
628
                if (icon == null) {
 
629
                        return null;
 
630
                }
 
631
 
 
632
                int width = icon.getIconWidth();
 
633
                int height = icon.getIconHeight();
 
634
 
 
635
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
636
                                height);
 
637
 
 
638
                icon.paintIcon(null, result.getGraphics(), 0, 0);
 
639
                return new ImageIcon(new GrayscaleFilter().filter(result, null));
 
640
        }
 
641
 
 
642
        /**
 
643
         * Makes the specified icon transparent.
 
644
         * 
 
645
         * @param c
 
646
         *            Component.
 
647
         * @param icon
 
648
         *            Icon.
 
649
         * @param alpha
 
650
         *            The alpha of the resulting image. The closer this value is to
 
651
         *            0.0, the more transparent resulting image will be.
 
652
         * @return Transparent version of the specified icon.
 
653
         */
 
654
        public static Icon makeTransparent(Component c, Icon icon, double alpha) {
 
655
                if (icon == null) {
 
656
                        return null;
 
657
                }
 
658
 
 
659
                int width = icon.getIconWidth();
 
660
                int height = icon.getIconHeight();
 
661
 
 
662
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
663
                                height);
 
664
                icon.paintIcon(c, result.getGraphics(), 0, 0);
 
665
                return new ImageIcon(new TranslucentFilter(alpha).filter(result, null));
 
666
        }
 
667
 
 
668
        // /**
 
669
        // * Retrieves radio button of the specified size that matches the specified
 
670
        // * parameters.
 
671
        // *
 
672
        // * @param component
 
673
        // * Component.
 
674
        // * @param dimension
 
675
        // * Radio button dimension.
 
676
        // * @param componentState
 
677
        // * Component state.
 
678
        // * @param prevState
 
679
        // * Previous component state.
 
680
        // * @param offsetX
 
681
        // * Offset on X axis - should be positive in order to see the
 
682
        // * entire radio button.
 
683
        // * @param scheme1
 
684
        // * First color scheme.
 
685
        // * @param scheme2
 
686
        // * Second color scheme.
 
687
        // * @param interpolationCyclePos
 
688
        // * Interpolation cycle.
 
689
        // * @param checkMarkVisibility
 
690
        // * Checkmark visibility in 0.0-1.0 range.
 
691
        // * @return Radio button of the specified size that matches the specified
 
692
        // * parameters.
 
693
        // */
 
694
        // public static BufferedImage getRadioButton(JComponent component,
 
695
        // SubstanceFillPainter fillPainter,
 
696
        // SubstanceBorderPainter borderPainter, int dimension,
 
697
        // ComponentState componentState, ComponentState prevState,
 
698
        // int offsetX, SubstanceColorScheme currFillColorScheme,
 
699
        // SubstanceColorScheme prevFillColorScheme,
 
700
        // SubstanceColorScheme currMarkColorScheme,
 
701
        // SubstanceColorScheme prevMarkColorScheme,
 
702
        // SubstanceColorScheme currBorderColorScheme,
 
703
        // SubstanceColorScheme prevBorderColorScheme,
 
704
        // float interpolationCyclePos, float checkMarkVisibility) {
 
705
        //
 
706
        // // ComponentState.ColorSchemeKind kind = componentState
 
707
        // // .getColorSchemeKind();
 
708
        //
 
709
        // float cyclePos = (currFillColorScheme != prevFillColorScheme) ?
 
710
        // interpolationCyclePos
 
711
        // : componentState.getCyclePosition();
 
712
        // float borderCyclePos = (currBorderColorScheme != prevBorderColorScheme) ?
 
713
        // interpolationCyclePos
 
714
        // : componentState.getCyclePosition();
 
715
        // float markCyclePos = (currMarkColorScheme != prevMarkColorScheme) ?
 
716
        // interpolationCyclePos
 
717
        // : componentState.getCyclePosition();
 
718
        //
 
719
        // if (componentState.getColorSchemeKind() != ColorSchemeKind.CURRENT) {
 
720
        // fillPainter = SimplisticSoftBorderReverseFillPainter.INSTANCE;
 
721
        // }
 
722
        //
 
723
        // float borderThickness = SubstanceSizeUtils
 
724
        // .getBorderStrokeWidth(dimension);
 
725
        // int delta = (int) (borderThickness - 0.6);
 
726
        // // System.out.println(dimension + ":" + borderThickness + ":" + delta);
 
727
        //
 
728
        // // float fDelta = borderThickness / 2.0f;
 
729
        // Shape contourBorder = new Ellipse2D.Float(delta, delta, dimension - 2
 
730
        // * delta - 1, dimension - 2 * delta - 1);
 
731
        //
 
732
        // BufferedImage offBackground = SubstanceCoreUtilities.getBlankImage(
 
733
        // dimension + offsetX, dimension);
 
734
        // Graphics2D graphics = (Graphics2D) offBackground.getGraphics();
 
735
        // float alpha = SubstanceColorSchemeUtilities.getAlpha(component,
 
736
        // componentState);
 
737
        // graphics.setComposite(AlphaComposite.getInstance(
 
738
        // AlphaComposite.SRC_OVER, alpha));
 
739
        //
 
740
        // graphics.translate(offsetX, 0);
 
741
        // fillPainter.paintContourBackground(graphics, component, dimension,
 
742
        // dimension, contourBorder, false, currFillColorScheme,
 
743
        // prevFillColorScheme, cyclePos, true,
 
744
        // currFillColorScheme != prevFillColorScheme);
 
745
        //
 
746
        // Shape contourInner = new Ellipse2D.Float(delta + borderThickness, delta
 
747
        // + borderThickness, dimension - 2 * delta - 2 * borderThickness,
 
748
        // dimension - 2 * delta - 2 * borderThickness);
 
749
        //
 
750
        // borderPainter.paintBorder(graphics, component, dimension, dimension,
 
751
        // contourBorder, contourInner, currBorderColorScheme,
 
752
        // prevBorderColorScheme, borderCyclePos,
 
753
        // currBorderColorScheme != prevBorderColorScheme);
 
754
        // graphics.setComposite(AlphaComposite.SrcOver);
 
755
        // // graphics.translate(-offsetX, 0);
 
756
        //
 
757
        // float rc = dimension / 2.0f;
 
758
        // float radius = dimension / 4.5f;
 
759
        // // graphics.translate(offsetX, 0);
 
760
        //
 
761
        // graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
762
        // RenderingHints.VALUE_ANTIALIAS_ON);
 
763
        //
 
764
        // if (componentState.isFacetActive(AnimationFacet.SELECTION)
 
765
        // || (checkMarkVisibility > 0.0)) {
 
766
        // // mark
 
767
        // Shape markOval = new Ellipse2D.Double(rc - radius, rc - radius,
 
768
        // 2 * radius, 2 * radius);
 
769
        //
 
770
        // graphics.setComposite(AlphaComposite.getInstance(
 
771
        // AlphaComposite.SRC_OVER, alpha * checkMarkVisibility));
 
772
        // drawRadioMark(graphics, SubstanceColorUtilities
 
773
        // .getMarkColor(currMarkColorScheme, componentState
 
774
        // .getColorSchemeKind() != ColorSchemeKind.DISABLED),
 
775
        // markOval);
 
776
        // graphics.setComposite(AlphaComposite.getInstance(
 
777
        // AlphaComposite.SRC_OVER, alpha * checkMarkVisibility
 
778
        // * markCyclePos));
 
779
        // drawRadioMark(graphics, SubstanceColorUtilities
 
780
        // .getMarkColor(prevMarkColorScheme, componentState
 
781
        // .getColorSchemeKind() != ColorSchemeKind.DISABLED),
 
782
        // markOval);
 
783
        // } else {
 
784
        // // draw ghost mark holder
 
785
        // graphics.setPaint(new GradientPaint(rc + radius, rc - radius,
 
786
        // currFillColorScheme.getDarkColor(), rc - radius, rc
 
787
        // + radius, currFillColorScheme.getLightColor()));
 
788
        // Shape markOval = new Ellipse2D.Double(rc - radius, rc - radius,
 
789
        // 2 * radius, 2 * radius);
 
790
        // graphics.setComposite(AlphaComposite.getInstance(
 
791
        // AlphaComposite.SRC_OVER, alpha * 0.3f));
 
792
        // graphics.fill(markOval);
 
793
        // }
 
794
        // graphics.translate(-offsetX, 0);
 
795
        //
 
796
        // return offBackground;
 
797
        // }
 
798
 
 
799
        /**
 
800
         * Retrieves radio button of the specified size that matches the specified
 
801
         * parameters.
 
802
         * 
 
803
         * @param component
 
804
         *            Component.
 
805
         * @param dimension
 
806
         *            Radio button dimension.
 
807
         * @param componentState
 
808
         *            Component state.
 
809
         * @param offsetX
 
810
         *            Offset on X axis - should be positive in order to see the
 
811
         *            entire radio button.
 
812
         * @param fillColorScheme
 
813
         *            Color scheme for the inner fill.
 
814
         * @param markColorScheme
 
815
         *            Color scheme for the check mark.
 
816
         * @param borderColorScheme
 
817
         *            Color scheme for the border.
 
818
         * @param checkMarkVisibility
 
819
         *            Check mark visibility in 0.0-1.0 range.
 
820
         * @return Radio button of the specified size that matches the specified
 
821
         *         parameters.
 
822
         */
 
823
        public static BufferedImage getRadioButton(JComponent component,
 
824
                        SubstanceFillPainter fillPainter,
 
825
                        SubstanceBorderPainter borderPainter, int dimension,
 
826
                        ComponentState componentState, int offsetX,
 
827
                        SubstanceColorScheme fillColorScheme,
 
828
                        SubstanceColorScheme markColorScheme,
 
829
                        SubstanceColorScheme borderColorScheme, float checkMarkVisibility) {
 
830
 
 
831
                // ComponentState.ColorSchemeKind kind = componentState
 
832
                // .getColorSchemeKind();
 
833
 
 
834
                if (!componentState.isActive()) {
 
835
                        fillPainter = SimplisticSoftBorderReverseFillPainter.INSTANCE;
 
836
                }
 
837
 
 
838
                float borderThickness = SubstanceSizeUtils
 
839
                                .getBorderStrokeWidth(dimension);
 
840
                int delta = (int) (borderThickness - 0.6);
 
841
                // System.out.println(dimension + ":" + borderThickness + ":" + delta);
 
842
 
 
843
                // float fDelta = borderThickness / 2.0f;
 
844
                Shape contourBorder = new Ellipse2D.Float(delta, delta, dimension - 2
 
845
                                * delta - 1, dimension - 2 * delta - 1);
 
846
 
 
847
                BufferedImage offBackground = SubstanceCoreUtilities.getBlankImage(
 
848
                                dimension + offsetX, dimension);
 
849
                Graphics2D graphics = (Graphics2D) offBackground.getGraphics();
 
850
                float alpha = SubstanceColorSchemeUtilities.getAlpha(component,
 
851
                                componentState);
 
852
                graphics.setComposite(AlphaComposite.getInstance(
 
853
                                AlphaComposite.SRC_OVER, alpha));
 
854
 
 
855
                graphics.translate(offsetX, 0);
 
856
                fillPainter.paintContourBackground(graphics, component, dimension,
 
857
                                dimension, contourBorder, false, fillColorScheme, true);
 
858
 
 
859
                Shape contourInner = new Ellipse2D.Float(delta + borderThickness, delta
 
860
                                + borderThickness, dimension - 2 * delta - 2 * borderThickness,
 
861
                                dimension - 2 * delta - 2 * borderThickness);
 
862
 
 
863
                borderPainter.paintBorder(graphics, component, dimension, dimension,
 
864
                                contourBorder, contourInner, borderColorScheme);
 
865
                graphics.setComposite(AlphaComposite.SrcOver);
 
866
                // graphics.translate(-offsetX, 0);
 
867
 
 
868
                float rc = dimension / 2.0f;
 
869
                float radius = dimension / 4.5f;
 
870
                // graphics.translate(offsetX, 0);
 
871
 
 
872
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
873
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
874
 
 
875
                if (checkMarkVisibility > 0.0) {
 
876
                        // mark
 
877
                        Shape markOval = new Ellipse2D.Double(rc - radius, rc - radius,
 
878
                                        2 * radius, 2 * radius);
 
879
 
 
880
                        graphics.setComposite(AlphaComposite.getInstance(
 
881
                                        AlphaComposite.SRC_OVER, alpha * checkMarkVisibility));
 
882
                        drawRadioMark(graphics, SubstanceColorUtilities.getMarkColor(
 
883
                                        markColorScheme, !componentState.isDisabled()), markOval);
 
884
                } else {
 
885
                        // draw ghost mark holder
 
886
                        graphics.setPaint(new GradientPaint(rc + radius, rc - radius,
 
887
                                        fillColorScheme.getDarkColor(), rc - radius, rc + radius,
 
888
                                        fillColorScheme.getLightColor()));
 
889
                        Shape markOval = new Ellipse2D.Double(rc - radius, rc - radius,
 
890
                                        2 * radius, 2 * radius);
 
891
                        graphics.setComposite(AlphaComposite.getInstance(
 
892
                                        AlphaComposite.SRC_OVER, alpha * 0.3f));
 
893
                        graphics.fill(markOval);
 
894
                }
 
895
                graphics.translate(-offsetX, 0);
 
896
 
 
897
                return offBackground;
 
898
        }
 
899
 
 
900
        /**
 
901
         * Draws radio mark.
 
902
         * 
 
903
         * @param graphics
 
904
         *            Graphics context.
 
905
         * @param color
 
906
         *            Radio mark color.
 
907
         * @param markOval
 
908
         *            Radio mark shape.
 
909
         */
 
910
        private static void drawRadioMark(Graphics2D graphics, Color color,
 
911
                        Shape markOval) {
 
912
                graphics.setColor(color);
 
913
                graphics.fill(markOval);
 
914
        }
 
915
 
 
916
        /**
 
917
         * Retrieves check box of the specified size that matches the specified
 
918
         * component state.
 
919
         * 
 
920
         * @param button
 
921
         *            Button for the check mark.
 
922
         * @param dimension
 
923
         *            Check box size.
 
924
         * @param componentState
 
925
         *            Component state.
 
926
         * @param fillColorScheme
 
927
         *            Color scheme for the inner fill.
 
928
         * @param markColorScheme
 
929
         *            Color scheme for the check mark.
 
930
         * @param borderColorScheme
 
931
         *            Color scheme for the border.
 
932
         * @param checkMarkVisibility
 
933
         *            Check mark visibility in 0.0-1.0 range.
 
934
         * @param isCheckMarkFadingOut
 
935
         *            if <code>true</code>, the value of
 
936
         *            <code>interpolationCyclePos10</code> is used as the alpha
 
937
         *            channel.
 
938
         * @return Check box of the specified size that matches the specified
 
939
         *         component state.
 
940
         */
 
941
        public static BufferedImage getCheckBox(AbstractButton button,
 
942
                        SubstanceFillPainter fillPainter,
 
943
                        SubstanceBorderPainter borderPainter, int dimension,
 
944
                        ComponentState componentState,
 
945
                        SubstanceColorScheme fillColorScheme,
 
946
                        SubstanceColorScheme markColorScheme,
 
947
                        SubstanceColorScheme borderColorScheme, float checkMarkVisibility,
 
948
                        boolean isCheckMarkFadingOut) {
 
949
 
 
950
                // int checkMarkSize = SubstanceSizeUtils
 
951
                // .getCheckBoxMarkSize(SubstanceSizeUtils
 
952
                // .getComponentFontSize(button));
 
953
                int offset = SubstanceSizeUtils
 
954
                                .getAdjustedSize(
 
955
                                                SubstanceSizeUtils.getComponentFontSize(button), 3, 9,
 
956
                                                1, false);
 
957
                int delta = offset;
 
958
                float cornerRadius = SubstanceSizeUtils
 
959
                                .getClassicButtonCornerRadius(SubstanceSizeUtils
 
960
                                                .getComponentFontSize(button));
 
961
                if (dimension <= 10) {
 
962
                        offset = 2;
 
963
                        cornerRadius = 2;
 
964
                }
 
965
 
 
966
                int contourDim = dimension - delta;
 
967
                int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
968
                                .getBorderStrokeWidth(SubstanceSizeUtils
 
969
                                                .getComponentFontSize(button)) / 2.0);
 
970
                GeneralPath contour = SubstanceOutlineUtilities.getBaseOutline(
 
971
                                contourDim, contourDim, cornerRadius, null, borderDelta);
 
972
 
 
973
                if (!componentState.isActive()) {
 
974
                        fillPainter = SimplisticSoftBorderReverseFillPainter.INSTANCE;
 
975
                }
 
976
 
 
977
                BufferedImage offBackground = SubstanceCoreUtilities.getBlankImage(
 
978
                                dimension, dimension);
 
979
                Graphics2D graphics = (Graphics2D) offBackground.getGraphics();
 
980
                float alpha = SubstanceColorSchemeUtilities.getAlpha(button,
 
981
                                componentState);
 
982
                graphics.setComposite(AlphaComposite.getInstance(
 
983
                                AlphaComposite.SRC_OVER, alpha));
 
984
 
 
985
                graphics.translate(delta - 1, delta - 1);
 
986
                fillPainter.paintContourBackground(graphics, button, contourDim,
 
987
                                contourDim, contour, false, fillColorScheme, true);
 
988
 
 
989
                // graphics.drawImage(background, 0, 0, null);
 
990
                int borderThickness = (int) SubstanceSizeUtils
 
991
                                .getBorderStrokeWidth(dimension);
 
992
                GeneralPath contourInner = SubstanceOutlineUtilities.getBaseOutline(
 
993
                                contourDim, contourDim, cornerRadius - borderThickness, null,
 
994
                                borderThickness + borderDelta);
 
995
                borderPainter.paintBorder(graphics, button, contourDim, contourDim,
 
996
                                contour, contourInner, borderColorScheme);
 
997
                graphics.translate(-delta, 1 - delta);
 
998
                if (checkMarkVisibility > 0.0) {
 
999
                        if (isCheckMarkFadingOut) {
 
1000
                                graphics.setComposite(AlphaComposite.getInstance(
 
1001
                                                AlphaComposite.SRC_OVER, alpha * checkMarkVisibility));
 
1002
                                checkMarkVisibility = 1.0f;
 
1003
                        }
 
1004
 
 
1005
                        BufferedImage checkMark = SubstanceImageCreator.getCheckMark(
 
1006
                                        dimension - 2 * offset / 3, !componentState.isDisabled(),
 
1007
                                        markColorScheme, checkMarkVisibility);
 
1008
                        graphics.drawImage(checkMark, 1 + 2 * offset / 3,
 
1009
                                        (dimension < 14) ? 0 : -1, null);
 
1010
                }
 
1011
 
 
1012
                return offBackground;
 
1013
        }
 
1014
 
 
1015
        /**
 
1016
         * Retrieves composite background for the specified parameters. The
 
1017
         * composite background consists of three layers:
 
1018
         * <ol>
 
1019
         * <li>Layer that matches the <code>increased</code> state.
 
1020
         * <li>Layer that matches the <code>decreased</code> state.
 
1021
         * <li>Regular layer with rounded background.
 
1022
         * </ol>
 
1023
         * The layers are drawn in the following order:
 
1024
         * <ol>
 
1025
         * <li>The left half of the first layer
 
1026
         * <li>The right half of the second layer
 
1027
         * <li>The third layer
 
1028
         * </ol>
 
1029
         * Combined together, the layers create the image for scrollbar track with
 
1030
         * continuation of the arrow increase and decrease buttons.
 
1031
         * 
 
1032
         * @param component
 
1033
         *            Component.
 
1034
         * @param width
 
1035
         *            Image width.
 
1036
         * @param height
 
1037
         *            Image height.
 
1038
         * @param cornerRadius
 
1039
         *            Corner radius.
 
1040
         * @param decrButton
 
1041
         *            The <code>decrease</code> button.
 
1042
         * @param incrButton
 
1043
         *            The <code>increase</code> button.
 
1044
         * @param flipSides
 
1045
         *            If <code>true</code>, the drawn halves of the first and the
 
1046
         *            second layers above will be swapped.
 
1047
         */
 
1048
        public static void paintCompositeRoundedBackground(JComponent component,
 
1049
                        Graphics g, int width, int height, int cornerRadius,
 
1050
                        AbstractButton decrButton, AbstractButton incrButton,
 
1051
                        boolean flipSides) {
 
1052
 
 
1053
                int delta = 3;
 
1054
 
 
1055
                if (decrButton != null) {
 
1056
                        Graphics2D graphics = (Graphics2D) g.create();
 
1057
                        if (!flipSides) {
 
1058
                                graphics.clip(new Rectangle(-delta, 0, width / 2, height));
 
1059
                                graphics.translate(-delta, 0);
 
1060
                        } else {
 
1061
                                graphics.clip(new Rectangle(width / 2, 0, width / 2 + 1, height));
 
1062
                        }
 
1063
                        PairwiseButtonBackgroundDelegate.updatePairwiseBackground(graphics,
 
1064
                                        decrButton, width + 2 * delta, height,
 
1065
                                        flipSides ? Side.RIGHT : Side.LEFT, true);
 
1066
                        graphics.dispose();
 
1067
                }
 
1068
 
 
1069
                if (incrButton != null) {
 
1070
                        Graphics2D graphics = (Graphics2D) g.create();
 
1071
                        if (!flipSides) {
 
1072
                                graphics.clip(new Rectangle(width / 2, 0, width / 2 + 1, height));
 
1073
                        } else {
 
1074
                                graphics.clip(new Rectangle(-delta, 0, width / 2, height));
 
1075
                                graphics.translate(-delta, 0);
 
1076
                        }
 
1077
                        PairwiseButtonBackgroundDelegate.updatePairwiseBackground(graphics,
 
1078
                                        incrButton, width + 2 * delta, height,
 
1079
                                        flipSides ? Side.LEFT : Side.RIGHT, true);
 
1080
                        graphics.dispose();
 
1081
                }
 
1082
        }
 
1083
 
 
1084
        /**
 
1085
         * Overlays light-colored echo below the specified image.
 
1086
         * 
 
1087
         * @param image
 
1088
         *            The input image.
 
1089
         * @param echoAlpha
 
1090
         *            Alpha channel for the echo image.
 
1091
         * @param offsetX
 
1092
         *            X offset of the echo.
 
1093
         * @param offsetY
 
1094
         *            Y offset of the echo.
 
1095
         * @return Image with overlayed echo.
 
1096
         */
 
1097
        private static BufferedImage overlayEcho(BufferedImage image,
 
1098
                        float echoAlpha, int offsetX, int offsetY) {
 
1099
                int width = image.getWidth();
 
1100
                int height = image.getHeight();
 
1101
 
 
1102
                // blur the original image
 
1103
                // ConvolveOp convolve = new ConvolveOp(new Kernel(3, 3, new float[] {
 
1104
                // .4f, .4f, .4f, .4f, .0f, .4f, .4f, .4f, .4f }),
 
1105
                // ConvolveOp.EDGE_NO_OP, null);
 
1106
                offsetX = offsetY = 0;
 
1107
                BufferedImage negated = getNegated(image);
 
1108
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
1109
                                height);
 
1110
                Graphics2D graphics = (Graphics2D) result.getGraphics().create();
 
1111
                graphics.setComposite(AlphaComposite.getInstance(
 
1112
                                AlphaComposite.SRC_OVER, 0.2f * echoAlpha * echoAlpha
 
1113
                                                * echoAlpha));
 
1114
                graphics.drawImage(negated, offsetX - 1, offsetY - 1, null);
 
1115
                graphics.drawImage(negated, offsetX + 1, offsetY - 1, null);
 
1116
                graphics.drawImage(negated, offsetX - 1, offsetY + 1, null);
 
1117
                graphics.drawImage(negated, offsetX + 1, offsetY + 1, null);
 
1118
                graphics.setComposite(AlphaComposite.getInstance(
 
1119
                                AlphaComposite.SRC_OVER, 0.7f * echoAlpha * echoAlpha
 
1120
                                                * echoAlpha));
 
1121
                graphics.drawImage(negated, offsetX, offsetY - 1, null);
 
1122
                graphics.drawImage(negated, offsetX, offsetY + 1, null);
 
1123
                graphics.drawImage(negated, offsetX - 1, offsetY, null);
 
1124
                graphics.drawImage(negated, offsetX + 1, offsetY, null);
 
1125
 
 
1126
                graphics.setComposite(AlphaComposite.getInstance(
 
1127
                                AlphaComposite.SRC_OVER, 1.0f));
 
1128
                graphics.drawImage(image, 0, 0, null);
 
1129
 
 
1130
                graphics.dispose();
 
1131
                return result;
 
1132
        }
 
1133
 
 
1134
        /**
 
1135
         * Returns <code>minimize</code> icon.
 
1136
         * 
 
1137
         * @param scheme
 
1138
         *            Color scheme for the icon.
 
1139
         * @return <code>Minimize</code> icon.
 
1140
         */
 
1141
        public static Icon getMinimizeIcon(SubstanceColorScheme scheme,
 
1142
                        SubstanceColorScheme backgroundScheme) {
 
1143
                int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
 
1144
                return getMinimizeIcon(iSize, scheme, backgroundScheme);
 
1145
        }
 
1146
 
 
1147
        /**
 
1148
         * Returns <code>minimize</code> icon.
 
1149
         * 
 
1150
         * @param iSize
 
1151
         *            Icon dimension.
 
1152
         * @param scheme
 
1153
         *            Color scheme for the icon.
 
1154
         * @return <code>Minimize</code> icon.
 
1155
         */
 
1156
        public static Icon getMinimizeIcon(int iSize, SubstanceColorScheme scheme,
 
1157
                        SubstanceColorScheme backgroundScheme) {
 
1158
                BufferedImage image = SubstanceCoreUtilities
 
1159
                                .getBlankImage(iSize, iSize);
 
1160
                Graphics2D graphics = (Graphics2D) image.getGraphics();
 
1161
                int start = (iSize / 4) - 2;
 
1162
                int end = (3 * iSize / 4);// - 1;
 
1163
                int size = end - start - 3;
 
1164
                Color color = SubstanceColorUtilities.getMarkColor(scheme, true);
 
1165
                graphics.setColor(color);
 
1166
                graphics.fillRect(start + 2, end - 2, size, 3);
 
1167
 
 
1168
                int fgStrength = SubstanceColorUtilities.getColorBrightness(color
 
1169
                                .getRGB());
 
1170
                int fgNegativeStrength = SubstanceColorUtilities
 
1171
                                .getColorBrightness(SubstanceColorUtilities
 
1172
                                                .getNegativeColor(color.getRGB()));
 
1173
                int bgStrength = SubstanceColorUtilities
 
1174
                                .getColorBrightness(backgroundScheme.getLightColor().getRGB());
 
1175
                boolean noEcho = (fgStrength > fgNegativeStrength)
 
1176
                                && (fgStrength < bgStrength);
 
1177
 
 
1178
                return new ImageIcon(SubstanceImageCreator.overlayEcho(image,
 
1179
                                noEcho ? 0 : SubstanceColorUtilities.getColorStrength(color),
 
1180
                                1, 1));
 
1181
        }
 
1182
 
 
1183
        /**
 
1184
         * Returns <code>restore</code> icon.
 
1185
         * 
 
1186
         * @param scheme
 
1187
         *            Color scheme for the icon.
 
1188
         * @return <code>Restore</code> icon.
 
1189
         */
 
1190
        public static Icon getRestoreIcon(SubstanceColorScheme scheme,
 
1191
                        SubstanceColorScheme backgroundScheme) {
 
1192
                int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
 
1193
                BufferedImage image = SubstanceCoreUtilities
 
1194
                                .getBlankImage(iSize, iSize);
 
1195
                Graphics2D graphics = (Graphics2D) image.getGraphics();
 
1196
                int start = (iSize / 4) - 2;
 
1197
                int end = (3 * iSize / 4) - 1;
 
1198
                int size = end - start - 3;
 
1199
                Color color = SubstanceColorUtilities.getMarkColor(scheme, true);
 
1200
                graphics.setColor(color);
 
1201
                graphics.drawRect(start, end - size + 1, size, size);
 
1202
                graphics.drawLine(start, end - size + 2, start + size, end - size + 2);
 
1203
                graphics.fillRect(end - size, start + 1, size + 1, 2);
 
1204
                graphics.drawLine(end, start + 1, end, start + size + 1);
 
1205
                graphics.drawLine(start + size + 2, start + size + 1, end, start + size
 
1206
                                + 1);
 
1207
 
 
1208
                int fgStrength = SubstanceColorUtilities.getColorBrightness(color
 
1209
                                .getRGB());
 
1210
                int fgNegativeStrength = SubstanceColorUtilities
 
1211
                                .getColorBrightness(SubstanceColorUtilities
 
1212
                                                .getNegativeColor(color.getRGB()));
 
1213
                int bgStrength = SubstanceColorUtilities
 
1214
                                .getColorBrightness(backgroundScheme.getLightColor().getRGB());
 
1215
                boolean noEcho = (fgStrength > fgNegativeStrength)
 
1216
                                && (fgStrength < bgStrength);
 
1217
 
 
1218
                return new ImageIcon(SubstanceImageCreator.overlayEcho(image,
 
1219
                                noEcho ? 0 : SubstanceColorUtilities.getColorStrength(color),
 
1220
                                1, 1));
 
1221
        }
 
1222
 
 
1223
        /**
 
1224
         * Returns <code>maximize</code> icon.
 
1225
         * 
 
1226
         * @param scheme
 
1227
         *            Color scheme for the icon.
 
1228
         * @return <code>Maximize</code> icon.
 
1229
         */
 
1230
        public static Icon getMaximizeIcon(SubstanceColorScheme scheme,
 
1231
                        SubstanceColorScheme backgroundScheme) {
 
1232
                int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
 
1233
                return getMaximizeIcon(iSize, scheme, backgroundScheme);
 
1234
        }
 
1235
 
 
1236
        /**
 
1237
         * Returns <code>maximize</code> icon.
 
1238
         * 
 
1239
         * @param iSize
 
1240
         *            Icon dimension.
 
1241
         * @param scheme
 
1242
         *            Color scheme for the icon.
 
1243
         * @return <code>Maximize</code> icon.
 
1244
         */
 
1245
        public static Icon getMaximizeIcon(int iSize, SubstanceColorScheme scheme,
 
1246
                        SubstanceColorScheme backgroundScheme) {
 
1247
                BufferedImage image = SubstanceCoreUtilities
 
1248
                                .getBlankImage(iSize, iSize);
 
1249
                Graphics2D graphics = (Graphics2D) image.getGraphics();
 
1250
                int start = (iSize / 4) - 1;
 
1251
                int end = iSize - start - 1;// (3 * iSize / 4);
 
1252
                Color color = SubstanceColorUtilities.getMarkColor(scheme, true);
 
1253
                graphics.setColor(color);
 
1254
                graphics.drawRect(start, start, end - start, end - start);
 
1255
                graphics.drawLine(start, start + 1, end, start + 1);
 
1256
 
 
1257
                int fgStrength = SubstanceColorUtilities.getColorBrightness(color
 
1258
                                .getRGB());
 
1259
                int fgNegativeStrength = SubstanceColorUtilities
 
1260
                                .getColorBrightness(SubstanceColorUtilities
 
1261
                                                .getNegativeColor(color.getRGB()));
 
1262
                int bgStrength = SubstanceColorUtilities
 
1263
                                .getColorBrightness(backgroundScheme.getLightColor().getRGB());
 
1264
                boolean noEcho = (fgStrength > fgNegativeStrength)
 
1265
                                && (fgStrength < bgStrength);
 
1266
 
 
1267
                return new ImageIcon(SubstanceImageCreator.overlayEcho(image,
 
1268
                                noEcho ? 0 : SubstanceColorUtilities.getColorStrength(color),
 
1269
                                1, 1));
 
1270
        }
 
1271
 
 
1272
        /**
 
1273
         * Returns <code>close</code> icon.
 
1274
         * 
 
1275
         * @param scheme
 
1276
         *            Color scheme for the icon.
 
1277
         * @return <code>Close</code> icon.
 
1278
         */
 
1279
        public static Icon getCloseIcon(SubstanceColorScheme scheme,
 
1280
                        SubstanceColorScheme backgroundScheme) {
 
1281
                return SubstanceImageCreator.getCloseIcon(
 
1282
                                SubstanceSizeUtils.getTitlePaneIconSize(), scheme,
 
1283
                                backgroundScheme);
 
1284
        }
 
1285
 
 
1286
        /**
 
1287
         * Returns <code>close</code> icon.
 
1288
         * 
 
1289
         * @param iSize
 
1290
         *            Icon dimension.
 
1291
         * @param colorScheme
 
1292
         *            Color scheme for the icon.
 
1293
         * @return <code>Close</code> icon.
 
1294
         */
 
1295
        public static Icon getCloseIcon(int iSize,
 
1296
                        SubstanceColorScheme colorScheme,
 
1297
                        SubstanceColorScheme backgroundScheme) {
 
1298
                BufferedImage image = SubstanceCoreUtilities
 
1299
                                .getBlankImage(iSize, iSize);
 
1300
                Graphics2D graphics = (Graphics2D) image.getGraphics();
 
1301
                if (iSize < 15) {
 
1302
                        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1303
                                        RenderingHints.VALUE_ANTIALIAS_ON);
 
1304
                } else {
 
1305
                        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1306
                                        RenderingHints.VALUE_ANTIALIAS_OFF);
 
1307
                }
 
1308
                int start = (iSize / 4);// - 1;
 
1309
                int end = (3 * iSize / 4);
 
1310
 
 
1311
                // System.out.println(iSize + ":" + start + ":" + end);
 
1312
 
 
1313
                Stroke stroke = new BasicStroke(
 
1314
                                SubstanceSizeUtils.getFocusStrokeWidth(iSize),
 
1315
                                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
 
1316
 
 
1317
                graphics.setStroke(stroke);
 
1318
                Color color = SubstanceColorUtilities.getMarkColor(colorScheme, true);
 
1319
                graphics.setColor(color);
 
1320
                graphics.drawLine(start, start, end, end);
 
1321
                graphics.drawLine(start, end, end, start);
 
1322
 
 
1323
                int fgStrength = SubstanceColorUtilities.getColorBrightness(color
 
1324
                                .getRGB());
 
1325
                int fgNegativeStrength = SubstanceColorUtilities
 
1326
                                .getColorBrightness(SubstanceColorUtilities
 
1327
                                                .getNegativeColor(color.getRGB()));
 
1328
                int bgStrength = SubstanceColorUtilities
 
1329
                                .getColorBrightness(backgroundScheme.getLightColor().getRGB());
 
1330
                boolean noEcho = (fgStrength > fgNegativeStrength)
 
1331
                                && (fgStrength < bgStrength);
 
1332
                // System.out.println(SubstanceColorUtilities.getColorBrightness(color
 
1333
                // .getRGB())
 
1334
                // + ":"
 
1335
                // + SubstanceColorUtilities
 
1336
                // .getColorBrightness(SubstanceColorUtilities
 
1337
                // .getNegativeColor(color.getRGB()))
 
1338
                // + ":"
 
1339
                // + SubstanceColorUtilities.getColorBrightness(backgroundScheme
 
1340
                // .getLightColor().getRGB()));
 
1341
 
 
1342
                return new ImageIcon(SubstanceImageCreator.overlayEcho(image,
 
1343
                                noEcho ? 0 : SubstanceColorUtilities.getColorStrength(color),
 
1344
                                1, 1));
 
1345
        }
 
1346
 
 
1347
        /**
 
1348
         * Paints rectangular gradient background.
 
1349
         * 
 
1350
         * @param g
 
1351
         *            Graphic context.
 
1352
         * @param startX
 
1353
         *            Background starting X coord.
 
1354
         * @param startY
 
1355
         *            Background starting Y coord.
 
1356
         * @param width
 
1357
         *            Background width.
 
1358
         * @param height
 
1359
         *            Background height.
 
1360
         * @param colorScheme
 
1361
         *            Color scheme for the background.
 
1362
         * @param borderAlpha
 
1363
         *            Border alpha.
 
1364
         * @param isVertical
 
1365
         *            if <code>true</code>, the gradient will be vertical, if
 
1366
         *            <code>false</code>, the gradient will be horizontal.
 
1367
         */
 
1368
        public static void paintRectangularBackground(Component c, Graphics g,
 
1369
                        int startX, int startY, int width, int height,
 
1370
                        SubstanceColorScheme colorScheme, float borderAlpha,
 
1371
                        boolean isVertical) {
 
1372
                Graphics2D graphics = (Graphics2D) g.create();
 
1373
                graphics.translate(startX, startY);
 
1374
 
 
1375
                if (!isVertical) {
 
1376
                        LinearGradientPaint paint = new LinearGradientPaint(0, 0, 0,
 
1377
                                        height, new float[] { 0.0f, 0.4f, 0.5f, 1.0f },
 
1378
                                        new Color[] { colorScheme.getUltraLightColor(),
 
1379
                                                        colorScheme.getLightColor(),
 
1380
                                                        colorScheme.getMidColor(),
 
1381
                                                        colorScheme.getUltraLightColor() },
 
1382
                                        CycleMethod.REPEAT);
 
1383
                        graphics.setPaint(paint);
 
1384
                        graphics.fillRect(0, 0, width, height);
 
1385
                } else {
 
1386
                        LinearGradientPaint paint = new LinearGradientPaint(0, 0, width, 0,
 
1387
                                        new float[] { 0.0f, 0.4f, 0.5f, 1.0f }, new Color[] {
 
1388
                                                        colorScheme.getUltraLightColor(),
 
1389
                                                        colorScheme.getLightColor(),
 
1390
                                                        colorScheme.getMidColor(),
 
1391
                                                        colorScheme.getUltraLightColor() },
 
1392
                                        CycleMethod.REPEAT);
 
1393
                        graphics.setPaint(paint);
 
1394
                        graphics.fillRect(0, 0, width, height);
 
1395
                }
 
1396
 
 
1397
                if (borderAlpha > 0.0f) {
 
1398
                        Graphics2D g2d = (Graphics2D) graphics.create();
 
1399
                        g2d.setComposite(LafWidgetUtilities.getAlphaComposite(null,
 
1400
                                        borderAlpha, graphics));
 
1401
 
 
1402
                        paintSimpleBorderAliased(c, g2d, width, height, colorScheme);
 
1403
 
 
1404
                        g2d.dispose();
 
1405
                }
 
1406
                graphics.dispose();
 
1407
        }
 
1408
 
 
1409
        /**
 
1410
         * Paints simple border.
 
1411
         * 
 
1412
         * @param g2d
 
1413
         *            Graphics context.
 
1414
         * @param width
 
1415
         *            Border width.
 
1416
         * @param height
 
1417
         *            Border height.
 
1418
         * @param borderColorScheme
 
1419
         *            Border color scheme.
 
1420
         */
 
1421
        public static void paintSimpleBorder(Component c, Graphics2D g2d,
 
1422
                        int width, int height, SubstanceColorScheme borderColorScheme) {
 
1423
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
1424
                // int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
1425
                // .getBorderStrokeWidth(componentFontSize) / 2.0);
 
1426
                // int borderDelta2 = (int) Math.floor(SubstanceSizeUtils
 
1427
                // .getBorderStrokeWidth(componentFontSize));
 
1428
                float borderThickness = (float) Math.floor(SubstanceSizeUtils
 
1429
                                .getBorderStrokeWidth(componentFontSize));
 
1430
 
 
1431
                g2d.setColor(SubstanceColorUtilities
 
1432
                                .getMidBorderColor(borderColorScheme));
 
1433
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1434
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1435
                g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
 
1436
                                RenderingHints.VALUE_STROKE_NORMALIZE);
 
1437
                int joinKind = BasicStroke.JOIN_ROUND;
 
1438
                int capKind = BasicStroke.CAP_BUTT;
 
1439
                g2d.setStroke(new BasicStroke(borderThickness, capKind, joinKind));
 
1440
                g2d.draw(new Rectangle2D.Float((borderThickness - 1.0f) / 2.0f,
 
1441
                                (borderThickness - 1.0f) / 2.0f, width - 1
 
1442
                                                - (borderThickness - 1.5f), height - 1
 
1443
                                                - (borderThickness - 1.5f)));
 
1444
                // g2d.drawRect(borderDelta, borderDelta, width - 1 - borderDelta2,
 
1445
                // height
 
1446
                // - 1 - borderDelta2);
 
1447
        }
 
1448
 
 
1449
        public static void paintSimpleBorderAliased(Component c, Graphics2D g2d,
 
1450
                        int width, int height, SubstanceColorScheme colorScheme) {
 
1451
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
1452
                // int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
1453
                // .getBorderStrokeWidth(componentFontSize) / 2.0);
 
1454
                // int borderDelta2 = (int) Math.floor(SubstanceSizeUtils
 
1455
                // .getBorderStrokeWidth(componentFontSize));
 
1456
                float borderThickness = (float) Math.floor(SubstanceSizeUtils
 
1457
                                .getBorderStrokeWidth(componentFontSize));
 
1458
 
 
1459
                g2d.setColor(SubstanceColorUtilities.getMidBorderColor(colorScheme));
 
1460
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1461
                                RenderingHints.VALUE_ANTIALIAS_OFF);
 
1462
                g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
 
1463
                                RenderingHints.VALUE_STROKE_NORMALIZE);
 
1464
                int joinKind = BasicStroke.JOIN_MITER;
 
1465
                int capKind = BasicStroke.CAP_SQUARE;
 
1466
                g2d.setStroke(new BasicStroke(borderThickness, capKind, joinKind));
 
1467
                g2d.draw(new Rectangle2D.Float(borderThickness / 2.0f,
 
1468
                                borderThickness / 2.0f, width - borderThickness, height
 
1469
                                                - borderThickness));
 
1470
        }
 
1471
 
 
1472
        /**
 
1473
         * Paints rectangular gradient background with spots and optional replicated
 
1474
         * stripe image.
 
1475
         * 
 
1476
         * @param g
 
1477
         *            Graphics context.
 
1478
         * @param startX
 
1479
         *            X start coordinate.
 
1480
         * @param startY
 
1481
         *            Y start coordinate.
 
1482
         * @param width
 
1483
         *            Background width.
 
1484
         * @param height
 
1485
         *            Background height.
 
1486
         * @param colorScheme
 
1487
         *            Color scheme for the background.
 
1488
         * @param stripeImage
 
1489
         *            Stripe image to replicate.
 
1490
         * @param stripeOffset
 
1491
         *            Offset of the first stripe replication.
 
1492
         * @param borderAlpha
 
1493
         *            Border alpha.
 
1494
         * @param isVertical
 
1495
         *            Indication of horizontal / vertical orientation.
 
1496
         */
 
1497
        public static void paintRectangularStripedBackground(Component c,
 
1498
                        Graphics g, int startX, int startY, int width, int height,
 
1499
                        SubstanceColorScheme colorScheme, BufferedImage stripeImage,
 
1500
                        int stripeOffset, float borderAlpha, boolean isVertical) {
 
1501
                Graphics2D graphics = (Graphics2D) g.create(startX, startY, width,
 
1502
                                height);
 
1503
                if (!isVertical) {
 
1504
                        LinearGradientPaint paint = new LinearGradientPaint(0, 0, 0,
 
1505
                                        height, new float[] { 0.0f, 0.2f, 0.5f, 0.8f, 1.0f },
 
1506
                                        new Color[] { colorScheme.getDarkColor(),
 
1507
                                                        colorScheme.getLightColor(),
 
1508
                                                        colorScheme.getMidColor(),
 
1509
                                                        colorScheme.getLightColor(),
 
1510
                                                        colorScheme.getDarkColor() }, CycleMethod.REPEAT);
 
1511
                        graphics.setPaint(paint);
 
1512
                        graphics.fillRect(0, 0, width, height);
 
1513
 
 
1514
                        if (stripeImage != null) {
 
1515
                                int stripeSize = stripeImage.getHeight();
 
1516
                                int stripeCount = width / stripeSize;
 
1517
                                stripeOffset = stripeOffset % (2 * stripeSize);
 
1518
                                for (int stripe = -2; stripe <= stripeCount; stripe += 2) {
 
1519
                                        int stripePos = stripe * stripeSize + stripeOffset;
 
1520
 
 
1521
                                        graphics.drawImage(stripeImage, stripePos, 0, null);
 
1522
                                }
 
1523
                        }
 
1524
                } else {
 
1525
                        LinearGradientPaint paint = new LinearGradientPaint(0, 0, width, 0,
 
1526
                                        new float[] { 0.0f, 0.2f, 0.5f, 0.8f, 1.0f }, new Color[] {
 
1527
                                                        colorScheme.getDarkColor(),
 
1528
                                                        colorScheme.getLightColor(),
 
1529
                                                        colorScheme.getMidColor(),
 
1530
                                                        colorScheme.getLightColor(),
 
1531
                                                        colorScheme.getDarkColor() }, CycleMethod.REPEAT);
 
1532
                        graphics.setPaint(paint);
 
1533
                        graphics.fillRect(0, 0, width, height);
 
1534
 
 
1535
                        if (stripeImage != null) {
 
1536
                                int stripeSize = stripeImage.getWidth();
 
1537
                                int stripeCount = height / stripeSize;
 
1538
                                stripeOffset = stripeOffset % (2 * stripeSize);
 
1539
                                for (int stripe = -2; stripe <= stripeCount; stripe += 2) {
 
1540
                                        int stripePos = stripe * stripeSize + stripeOffset;
 
1541
 
 
1542
                                        graphics.drawImage(stripeImage, 0, stripePos, null);
 
1543
                                }
 
1544
                        }
 
1545
                }
 
1546
 
 
1547
                if (borderAlpha > 0.0f) {
 
1548
                        Graphics2D g2d = (Graphics2D) graphics.create();
 
1549
                        g2d.setComposite(LafWidgetUtilities.getAlphaComposite(null,
 
1550
                                        borderAlpha, graphics));
 
1551
 
 
1552
                        paintSimpleBorderAliased(c, g2d, width, height, colorScheme);
 
1553
                        g2d.dispose();
 
1554
                }
 
1555
                graphics.dispose();
 
1556
        }
 
1557
 
 
1558
        /**
 
1559
         * Returns diagonal stripe image.
 
1560
         * 
 
1561
         * @param baseSize
 
1562
         *            Stripe base in pixels.
 
1563
         * @param color
 
1564
         *            Stripe color.
 
1565
         * @return Diagonal stripe image.
 
1566
         */
 
1567
        public static BufferedImage getStripe(int baseSize, Color color) {
 
1568
                int width = (int) (1.8 * baseSize);
 
1569
                int height = baseSize;
 
1570
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
1571
                                height);
 
1572
                Graphics2D graphics = (Graphics2D) result.getGraphics();
 
1573
 
 
1574
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1575
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1576
 
 
1577
                Polygon polygon = new Polygon();
 
1578
                polygon.addPoint(0, 0);
 
1579
                polygon.addPoint(width - 1 - baseSize, 0);
 
1580
                polygon.addPoint(width - 1, height - 1);
 
1581
                polygon.addPoint(baseSize, height - 1);
 
1582
 
 
1583
                graphics.setColor(color);
 
1584
                graphics.fillPolygon(polygon);
 
1585
                graphics.drawPolygon(polygon);
 
1586
 
 
1587
                float[] BLUR = { 0.10f, 0.10f, 0.10f, 0.10f, 0.30f, 0.10f, 0.10f,
 
1588
                                0.10f, 0.10f };
 
1589
                ConvolveOp vBlurOp = new ConvolveOp(new Kernel(3, 3, BLUR));
 
1590
                BufferedImage blurred = vBlurOp.filter(result, null);
 
1591
 
 
1592
                return blurred;
 
1593
        }
 
1594
 
 
1595
        /**
 
1596
         * Returns drag bumps image.
 
1597
         * 
 
1598
         * @param c
 
1599
         *            Component.
 
1600
         * @param colorScheme
 
1601
         *            Color scheme.
 
1602
         * @param width
 
1603
         *            Drag bumps width.
 
1604
         * @param height
 
1605
         *            Drag bumps height.
 
1606
         * @param maxNumberOfStripes
 
1607
         *            The maximum number of bump stripes (rows or columns).
 
1608
         * @return Drag bumps image.
 
1609
         */
 
1610
        public static BufferedImage getDragImage(Component c,
 
1611
                        SubstanceColorScheme colorScheme, int width, int height,
 
1612
                        int maxNumberOfStripes) {
 
1613
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
1614
                                height);
 
1615
                Graphics2D graphics = (Graphics2D) result.getGraphics();
 
1616
 
 
1617
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1618
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1619
 
 
1620
                boolean isDark = colorScheme.isDark();
 
1621
                Color back1 = isDark ? colorScheme.getLightColor()
 
1622
                                : SubstanceColorUtilities.getInterpolatedColor(
 
1623
                                                colorScheme.getLightColor(),
 
1624
                                                colorScheme.getDarkColor(), 0.8);
 
1625
                Color back2 = isDark ? colorScheme.getExtraLightColor()
 
1626
                                : SubstanceColorUtilities.getInterpolatedColor(
 
1627
                                                colorScheme.getMidColor(), colorScheme.getDarkColor(),
 
1628
                                                0.4);
 
1629
                Color fore = isDark ? colorScheme.getDarkColor() : colorScheme
 
1630
                                .getUltraLightColor();
 
1631
 
 
1632
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
1633
                int bumpDotDiameter = SubstanceSizeUtils
 
1634
                                .getDragBumpDiameter(componentFontSize);
 
1635
                int bumpCellSize = (int) (1.5 * bumpDotDiameter + 1);
 
1636
                int bumpRows = Math.max(1, height / bumpCellSize - 1);
 
1637
                int bumpColumns = Math.max(1, (width - 2) / bumpCellSize);
 
1638
                if (maxNumberOfStripes > 0) {
 
1639
                        if (height > width)
 
1640
                                bumpColumns = Math.min(bumpColumns, maxNumberOfStripes);
 
1641
                        else
 
1642
                                bumpRows = Math.min(bumpRows, maxNumberOfStripes);
 
1643
                }
 
1644
 
 
1645
                int bumpRowOffset = (height - bumpCellSize * bumpRows) / 2;
 
1646
                int bumpColOffset = 1 + (width - bumpCellSize * bumpColumns) / 2;
 
1647
 
 
1648
                for (int col = 0; col < bumpColumns; col++) {
 
1649
                        int cx = bumpColOffset + col * bumpCellSize;
 
1650
                        boolean isEvenCol = (col % 2 == 0);
 
1651
                        int offsetY = isEvenCol ? 0 : bumpDotDiameter;
 
1652
                        for (int row = 0; row < bumpRows; row++) {
 
1653
                                int cy = offsetY + bumpRowOffset + row * bumpCellSize;
 
1654
                                graphics.setColor(fore);
 
1655
                                graphics.fillOval(cx + 1, cy + 1, bumpDotDiameter,
 
1656
                                                bumpDotDiameter);
 
1657
                                // graphics.setColor(back1);
 
1658
                                graphics.setPaint(new GradientPaint(cx, cy, back1, cx
 
1659
                                                + bumpDotDiameter - 1, cy + bumpDotDiameter - 1, back2));
 
1660
                                graphics.fillOval(cx, cy, bumpDotDiameter, bumpDotDiameter);
 
1661
                        }
 
1662
                }
 
1663
                return result;
 
1664
        }
 
1665
 
 
1666
        /**
 
1667
         * Paints the bump dots on the split pane dividers.
 
1668
         * 
 
1669
         * @param g
 
1670
         *            Graphics context.
 
1671
         * @param divider
 
1672
         *            Split pane divider.
 
1673
         * @param x
 
1674
         *            X coordinate of the bump dots.
 
1675
         * @param y
 
1676
         *            Y coordinate of the bump dots.
 
1677
         * @param width
 
1678
         *            Width of the bump dots area.
 
1679
         * @param height
 
1680
         *            Height of the bump dots area.
 
1681
         * @param isHorizontal
 
1682
         *            Indicates whether the dots are horizontal.
 
1683
         * @param colorScheme
 
1684
         *            First color scheme.
 
1685
         */
 
1686
        public static void paintSplitDividerBumpImage(Graphics g,
 
1687
                        SubstanceSplitPaneDivider divider, int x, int y, int width,
 
1688
                        int height, boolean isHorizontal, SubstanceColorScheme colorScheme) {
 
1689
                Graphics2D graphics = (Graphics2D) g.create();
 
1690
                graphics.translate(x, y);
 
1691
 
 
1692
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1693
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1694
 
 
1695
                int componentFontSize = SubstanceSizeUtils
 
1696
                                .getComponentFontSize(divider);
 
1697
                int bumpDotDiameter = SubstanceSizeUtils
 
1698
                                .getBigDragBumpDiameter(componentFontSize);
 
1699
                int bumpCellSize = (int) (1.5 * bumpDotDiameter + 1);
 
1700
                int bumpRows = isHorizontal ? 1 : Math
 
1701
                                .max(1, height / bumpCellSize - 1);
 
1702
                int bumpColumns = isHorizontal ? Math
 
1703
                                .max(1, (width - 2) / bumpCellSize) : 1;
 
1704
 
 
1705
                int bumpRowOffset = (height - bumpCellSize * bumpRows) / 2;
 
1706
                int bumpColOffset = 1 + (width - bumpCellSize * bumpColumns) / 2;
 
1707
 
 
1708
                BufferedImage singleDot = SubstanceCoreUtilities.getBlankImage(
 
1709
                                bumpDotDiameter, bumpDotDiameter);
 
1710
                Graphics2D dotGraphics = (Graphics2D) singleDot.getGraphics();
 
1711
                dotGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1712
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1713
 
 
1714
                Color markColor = SubstanceColorUtilities.getMarkColor(colorScheme,
 
1715
                                divider.isEnabled());
 
1716
                dotGraphics.setColor(markColor);
 
1717
                dotGraphics.fillOval(0, 0, bumpDotDiameter, bumpDotDiameter);
 
1718
 
 
1719
                dotGraphics.setComposite(AlphaComposite.getInstance(
 
1720
                                AlphaComposite.SRC_OVER, 0.4f));
 
1721
                SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
 
1722
                                .getBorderPainter(divider);
 
1723
                borderPainter.paintBorder(dotGraphics, divider, width, height,
 
1724
                                new Ellipse2D.Float(0, 0, bumpDotDiameter - 1,
 
1725
                                                bumpDotDiameter - 1), null, colorScheme);
 
1726
 
 
1727
                graphics.setComposite(LafWidgetUtilities.getAlphaComposite(divider,
 
1728
                                0.8f, g));
 
1729
                for (int col = 0; col < bumpColumns; col++) {
 
1730
                        int cx = bumpColOffset + col * bumpCellSize;
 
1731
                        for (int row = 0; row < bumpRows; row++) {
 
1732
                                int cy = bumpRowOffset + row * bumpCellSize
 
1733
                                                + (bumpCellSize - bumpDotDiameter) / 2;
 
1734
                                graphics.drawImage(singleDot, cx, cy, null);
 
1735
                        }
 
1736
                }
 
1737
                graphics.dispose();
 
1738
        }
 
1739
 
 
1740
        /**
 
1741
         * Returns resize grip image.
 
1742
         * 
 
1743
         * @param c
 
1744
         *            Component.
 
1745
         * @param colorScheme
 
1746
         *            Color scheme.
 
1747
         * @param dimension
 
1748
         *            Resize grip width.
 
1749
         * @param isCrowded
 
1750
         *            Indicates whether the grips should be painted closely.
 
1751
         * @return Resize grip image.
 
1752
         */
 
1753
        public static BufferedImage getResizeGripImage(Component c,
 
1754
                        SubstanceColorScheme colorScheme, int dimension, boolean isCrowded) {
 
1755
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(dimension,
 
1756
                                dimension);
 
1757
                Graphics2D graphics = (Graphics2D) result.getGraphics();
 
1758
 
 
1759
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1760
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1761
 
 
1762
                boolean isDark = colorScheme.isDark();
 
1763
                // SubstanceCoreUtilities
 
1764
                // .getActiveScheme(null) : SubstanceCoreUtilities
 
1765
                // .getDefaultScheme(null);
 
1766
                Color back1 = isDark ? colorScheme.getLightColor()
 
1767
                                : SubstanceColorUtilities.getInterpolatedColor(
 
1768
                                                colorScheme.getLightColor(),
 
1769
                                                colorScheme.getDarkColor(), 0.8);
 
1770
                Color back2 = isDark ? colorScheme.getExtraLightColor()
 
1771
                                : SubstanceColorUtilities.getInterpolatedColor(
 
1772
                                                colorScheme.getMidColor(), colorScheme.getDarkColor(),
 
1773
                                                0.4);
 
1774
                Color fore = isDark ? colorScheme.getDarkColor() : colorScheme
 
1775
                                .getUltraLightColor();
 
1776
 
 
1777
                int bumpDotDiameter = SubstanceSizeUtils
 
1778
                                .getDragBumpDiameter(SubstanceSizeUtils.getComponentFontSize(c));
 
1779
                int bumpCellSize = (int) (1.5 * bumpDotDiameter + 1);
 
1780
                if (isCrowded)
 
1781
                        bumpCellSize--;
 
1782
                int bumpLines = dimension / bumpCellSize;
 
1783
 
 
1784
                int bumpOffset = (dimension - bumpCellSize * bumpLines) / 2;
 
1785
 
 
1786
                for (int col = 0; col < bumpLines; col++) {
 
1787
                        int cx = bumpOffset + col * bumpCellSize;
 
1788
                        for (int row = (bumpLines - col - 1); row < bumpLines; row++) {
 
1789
                                int cy = bumpOffset + row * bumpCellSize;
 
1790
                                graphics.setColor(fore);
 
1791
                                graphics.fillOval(cx + 1, cy + 1, bumpDotDiameter,
 
1792
                                                bumpDotDiameter);
 
1793
                                // graphics.setColor(back1);
 
1794
                                graphics.setPaint(new GradientPaint(cx, cy, back1, cx
 
1795
                                                + bumpDotDiameter - 1, cy + bumpDotDiameter - 1, back2));
 
1796
                                graphics.fillOval(cx, cy, bumpDotDiameter, bumpDotDiameter);
 
1797
                        }
 
1798
                }
 
1799
                return result;
 
1800
        }
 
1801
 
 
1802
        /**
 
1803
         * Retrieves tree icon.
 
1804
         * 
 
1805
         * @param tree
 
1806
         *            Tree.
 
1807
         * @param fillScheme
 
1808
         *            Icon fill color scheme.
 
1809
         * @param borderScheme
 
1810
         *            Icon border color scheme.
 
1811
         * @param isCollapsed
 
1812
         *            Collapsed state.
 
1813
         * @return Tree icon.
 
1814
         */
 
1815
        public static BufferedImage getTreeIcon(JTree tree,
 
1816
                        SubstanceColorScheme fillScheme, SubstanceColorScheme borderScheme,
 
1817
                        boolean isCollapsed) {
 
1818
                int fontSize = SubstanceSizeUtils.getComponentFontSize(tree);
 
1819
                int dim = SubstanceSizeUtils.getTreeIconSize(fontSize);
 
1820
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(dim + 2,
 
1821
                                dim);
 
1822
                Graphics2D graphics = (Graphics2D) result.getGraphics();
 
1823
 
 
1824
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1825
                                RenderingHints.VALUE_ANTIALIAS_OFF);
 
1826
 
 
1827
                Graphics2D g2 = (Graphics2D) graphics.create();
 
1828
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1829
                                RenderingHints.VALUE_ANTIALIAS_OFF);
 
1830
                SimplisticFillPainter gradPainter = new SimplisticSoftBorderReverseFillPainter();
 
1831
                FlatBorderPainter fbp = new FlatBorderPainter();
 
1832
 
 
1833
                int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
1834
                                .getBorderStrokeWidth(fontSize) / 2.0);
 
1835
                Shape contour = SubstanceOutlineUtilities.getBaseOutline(dim - 1,
 
1836
                                dim - 1, SubstanceSizeUtils.getClassicButtonCornerRadius(dim),
 
1837
                                null, borderDelta);
 
1838
 
 
1839
                g2.translate(0, 1);
 
1840
 
 
1841
                boolean isDark = fillScheme.isDark();
 
1842
 
 
1843
                fillScheme = new ShiftColorScheme(fillScheme,
 
1844
                                fillScheme.getExtraLightColor(), 0.7);
 
1845
 
 
1846
                gradPainter.paintContourBackground(g2, tree, dim - 1, dim - 1, contour,
 
1847
                                false, fillScheme, false);
 
1848
                borderScheme = new ShiftColorScheme(borderScheme,
 
1849
                                isDark ? borderScheme.getUltraLightColor()
 
1850
                                                : borderScheme.getLightColor(), 0.5);
 
1851
                fbp.paintBorder(g2, tree, dim - 1, dim - 1, contour, null, borderScheme);
 
1852
 
 
1853
                g2.translate(-1, -1);
 
1854
 
 
1855
                Color signColor = isDark ? borderScheme.getUltraLightColor().brighter()
 
1856
                                .brighter() : borderScheme.getUltraDarkColor();
 
1857
                if ((tree != null) && !tree.isEnabled())
 
1858
                        signColor = borderScheme.getForegroundColor();
 
1859
                g2.setColor(signColor);
 
1860
                int mid = dim / 2;
 
1861
                int length = 5 * dim / 12;
 
1862
                g2.drawLine(mid - length / 2, dim / 2, mid + length / 2, dim / 2);
 
1863
                if (isCollapsed) {
 
1864
                        g2.drawLine(dim / 2, mid - length / 2, dim / 2, mid + length / 2);
 
1865
                }
 
1866
                g2.dispose();
 
1867
 
 
1868
                return result;
 
1869
        }
 
1870
 
 
1871
        /**
 
1872
         * Retrieves a single crayon of the specified color and dimensions for the
 
1873
         * crayon panel in color chooser.
 
1874
         * 
 
1875
         * @param mainColor
 
1876
         *            Crayon main color.
 
1877
         * @param width
 
1878
         *            Crayon width.
 
1879
         * @param height
 
1880
         *            Crayon height.
 
1881
         * @return Crayon image.
 
1882
         */
 
1883
        public static BufferedImage getSingleCrayon(Color mainColor, int width,
 
1884
                        int height) {
 
1885
                BufferedImage image = SubstanceCoreUtilities.getBlankImage(width,
 
1886
                                height);
 
1887
 
 
1888
                int baseTop = (int) (0.2 * height);
 
1889
 
 
1890
                Graphics2D graphics = (Graphics2D) image.getGraphics().create();
 
1891
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
1892
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
1893
 
 
1894
                int r = mainColor.getRed();
 
1895
                int g = mainColor.getGreen();
 
1896
                int b = mainColor.getBlue();
 
1897
                // light coefficient
 
1898
                double lc = 0.8;
 
1899
                int lr = (int) (r + (255 - r) * lc);
 
1900
                int lg = (int) (g + (255 - g) * lc);
 
1901
                int lb = (int) (b + (255 - b) * lc);
 
1902
                // dark coefficient
 
1903
                double dc = 0.05;
 
1904
                int dr = (int) ((1.0 - dc) * r);
 
1905
                int dg = (int) ((1.0 - dc) * g);
 
1906
                int db = (int) ((1.0 - dc) * b);
 
1907
 
 
1908
                Color lightColor = new Color(lr, lg, lb);
 
1909
                Color darkColor = new Color(dr, dg, db);
 
1910
 
 
1911
                LinearGradientPaint paint = new LinearGradientPaint(0, 0, width, 0,
 
1912
                                new float[] { 0.0f, 0.3f, 0.5f, 0.9f, 1.0f }, new Color[] {
 
1913
                                                lightColor, darkColor, darkColor, lightColor,
 
1914
                                                lightColor }, CycleMethod.REPEAT);
 
1915
                graphics.setPaint(paint);
 
1916
                graphics.fillRect(0, baseTop, width, height);
 
1917
 
 
1918
                int dbwr = lr;
 
1919
                int dbwg = lg;
 
1920
                int dbwb = lb;
 
1921
                int lbwr = 128 + dr / 4;
 
1922
                int lbwg = 128 + dg / 4;
 
1923
                int lbwb = 128 + db / 4;
 
1924
 
 
1925
                Color lightStripeColor = new Color(lbwr, lbwg, lbwb);
 
1926
                Color darkStripeColor = new Color(dbwr, dbwg, dbwb);
 
1927
 
 
1928
                int stripeTop = (int) (0.35 * height);
 
1929
                int stripeHeight = (int) (0.04 * height);
 
1930
                LinearGradientPaint stripePaint = new LinearGradientPaint(0, 0, width,
 
1931
                                0, new float[] { 0.0f, 0.3f, 0.5f, 0.9f, 1.0f }, new Color[] {
 
1932
                                                lightStripeColor, darkStripeColor, darkStripeColor,
 
1933
                                                lightStripeColor, lightStripeColor },
 
1934
                                CycleMethod.REPEAT);
 
1935
                graphics.setPaint(stripePaint);
 
1936
                graphics.fillRect(0, stripeTop, width, stripeHeight);
 
1937
 
 
1938
                graphics.setColor(lightStripeColor);
 
1939
                graphics.drawRect(0, stripeTop, width - 1, stripeHeight);
 
1940
 
 
1941
                // create cap path
 
1942
                GeneralPath capPath = new GeneralPath();
 
1943
                capPath.moveTo(0.5f * width - 3, 4);
 
1944
                capPath.quadTo(0.5f * width, 0, 0.5f * width + 3, 4);
 
1945
                capPath.lineTo(width - 3, baseTop);
 
1946
                capPath.lineTo(2, baseTop);
 
1947
                capPath.lineTo(0.5f * width - 3, 4);
 
1948
 
 
1949
                graphics.setClip(capPath);
 
1950
 
 
1951
                graphics.setPaint(new GradientPaint(0, baseTop / 2, lightColor,
 
1952
                                (int) (0.6 * width), baseTop, mainColor));
 
1953
                graphics.fillRect(0, 0, width / 2, baseTop);
 
1954
                graphics.setPaint(new GradientPaint(width, baseTop / 2, lightColor,
 
1955
                                (int) (0.4 * width), baseTop, mainColor));
 
1956
                graphics.fillRect(width / 2, 0, width / 2, baseTop);
 
1957
 
 
1958
                graphics.setStroke(new BasicStroke((float) 1.3, BasicStroke.CAP_ROUND,
 
1959
                                BasicStroke.JOIN_ROUND));
 
1960
 
 
1961
                graphics.setClip(null);
 
1962
                graphics.setColor(new Color(64 + dr / 2, 64 + dg / 2, 64 + db / 2, 200));
 
1963
                graphics.drawRect(0, baseTop, width - 1, height - baseTop - 1);
 
1964
                graphics.draw(capPath);
 
1965
 
 
1966
                graphics.dispose();
 
1967
 
 
1968
                return image;
 
1969
        }
 
1970
 
 
1971
        /**
 
1972
         * Crayon colors.
 
1973
         */
 
1974
        private final static int[] crayonColors = { 0x800000, // Cayenne
 
1975
                        0x808000, // Asparagus
 
1976
                        0x008000, // Clover
 
1977
                        0x008080, // Teal
 
1978
                        0x000080, // Midnight
 
1979
                        0x800080, // Plum
 
1980
                        0x7f7f7f, // Tin
 
1981
                        0x808080, // Nickel
 
1982
 
 
1983
                        0x804000, // Mocha
 
1984
                        0x408000, // Fern
 
1985
                        0x008040, // Moss
 
1986
                        0x004080, // Ocean
 
1987
                        0x400080, // Eggplant
 
1988
                        0x800040, // Maroon
 
1989
                        0x666666, // Steel
 
1990
                        0x999999, // Aluminium
 
1991
 
 
1992
                        0xff0000, // Maraschino
 
1993
                        0xffff00, // Lemon
 
1994
                        0x00ff00, // Spring
 
1995
                        0x00ffff, // Turquoise
 
1996
                        0x0000ff, // Blueberry
 
1997
                        0xff00ff, // Magenta
 
1998
                        0x4c4c4c, // Iron
 
1999
                        0xb3b3b3, // Magnesium
 
2000
 
 
2001
                        0xff8000, // Tangerine
 
2002
                        0x80ff00, // Lime
 
2003
                        0x00ff80, // Sea Foam
 
2004
                        0x0080ff, // Aqua
 
2005
                        0x8000ff, // Grape
 
2006
                        0xff0080, // Strawberry
 
2007
                        0x333333, // Tungsten
 
2008
                        0xcccccc, // Silver
 
2009
 
 
2010
                        0xff6666, // Salmon
 
2011
                        0xffff66, // Banana
 
2012
                        0x66ff66, // Flora
 
2013
                        0x66ffff, // Ice
 
2014
                        0x6666ff, // Orchid
 
2015
                        0xff66ff, // Bubblegum
 
2016
                        0x191919, // Lead
 
2017
                        0xe6e6e6, // Mercury
 
2018
 
 
2019
                        0xffcc66, // Cantaloupe
 
2020
                        0xccff66, // Honeydew
 
2021
                        0x66ffcc, // Spindrift
 
2022
                        0x66ccff, // Sky
 
2023
                        0xcc66ff, // Lavender
 
2024
                        0xff6fcf, // Carnation
 
2025
                        0x000000, // Licorice
 
2026
                        0xffffff, // Snow
 
2027
        };
 
2028
 
 
2029
        /**
 
2030
         * Retrieves crayon X offset.
 
2031
         * 
 
2032
         * @param i
 
2033
         *            Crayon index.
 
2034
         * @return Crayon X offset.
 
2035
         */
 
2036
        private static int crayonX(int i) {
 
2037
                return (i % 8) * 22 + 4 + ((i / 8) % 2) * 11;
 
2038
        }
 
2039
 
 
2040
        /**
 
2041
         * Retrieves crayon Y offset.
 
2042
         * 
 
2043
         * @param i
 
2044
         *            Crayon index.
 
2045
         * @return Crayon Y offset.
 
2046
         */
 
2047
        private static int crayonY(int i) {
 
2048
                return (i / 8) * 20 + 23;
 
2049
        }
 
2050
 
 
2051
        /**
 
2052
         * Retrieves crayons image for the crayon panel of color chooser.
 
2053
         * 
 
2054
         * @return Crayons image.
 
2055
         */
 
2056
        public static Image getCrayonsImage() {
 
2057
                int iw = 195;
 
2058
                int ih = 208;
 
2059
                Image image = SubstanceCoreUtilities.getBlankImage(iw, ih);
 
2060
                Graphics2D graphics = (Graphics2D) image.getGraphics().create();
 
2061
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2062
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
2063
 
 
2064
                graphics.setColor(new Color(240, 240, 240));
 
2065
                graphics.fillRect(0, 0, iw, ih);
 
2066
 
 
2067
                for (int i = 0; i < SubstanceImageCreator.crayonColors.length; i++) {
 
2068
                        Color crayonColor = new Color(
 
2069
                                        0xff000000 | SubstanceImageCreator.crayonColors[i]);
 
2070
                        Image crayonImage = SubstanceImageCreator.getSingleCrayon(
 
2071
                                        crayonColor, 22, 120);
 
2072
                        graphics.drawImage(crayonImage, SubstanceImageCreator.crayonX(i),
 
2073
                                        SubstanceImageCreator.crayonY(i), null);
 
2074
                }
 
2075
 
 
2076
                graphics.setColor(new Color(190, 190, 190));
 
2077
                graphics.drawRoundRect(0, 1, iw - 1, ih - 2, 4, 4);
 
2078
 
 
2079
                graphics.dispose();
 
2080
                return image;
 
2081
        }
 
2082
 
 
2083
        /**
 
2084
         * Returns small icon representation of the specified integer value. The
 
2085
         * remainder of dividing the integer by 16 is translated to four circles
 
2086
         * arranged in 2*2 grid.
 
2087
         * 
 
2088
         * @param value
 
2089
         *            Integer value to represent.
 
2090
         * @param colorScheme
 
2091
         *            Icon color scheme.
 
2092
         * @return Icon representation of the specified integer value.
 
2093
         */
 
2094
        public static Icon getHexaMarker(int value, SubstanceColorScheme colorScheme) {
 
2095
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(9, 9);
 
2096
 
 
2097
                value %= 16;
 
2098
                Color offColor = null;
 
2099
                Color onColor = null;
 
2100
                if (colorScheme == null) {
 
2101
                        return new ImageIcon(result);
 
2102
                }
 
2103
                boolean isDark = colorScheme.isDark();
 
2104
                offColor = isDark ? colorScheme.getMidColor() : colorScheme
 
2105
                                .getMidColor().darker();
 
2106
                onColor = isDark ? SubstanceColorUtilities.getInterpolatedColor(
 
2107
                                colorScheme.getUltraLightColor(), Color.white, 0.2)
 
2108
                                : colorScheme.getUltraDarkColor().darker();
 
2109
 
 
2110
                boolean bit1 = ((value & 0x1) != 0);
 
2111
                boolean bit2 = ((value & 0x2) != 0);
 
2112
                boolean bit3 = ((value & 0x4) != 0);
 
2113
                boolean bit4 = ((value & 0x8) != 0);
 
2114
 
 
2115
                Graphics2D graphics = (Graphics2D) result.getGraphics().create();
 
2116
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2117
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
2118
 
 
2119
                graphics.setColor(bit1 ? onColor : offColor);
 
2120
                graphics.fillOval(5, 5, 4, 4);
 
2121
                graphics.setColor(bit2 ? onColor : offColor);
 
2122
                graphics.fillOval(5, 0, 4, 4);
 
2123
                graphics.setColor(bit3 ? onColor : offColor);
 
2124
                graphics.fillOval(0, 5, 4, 4);
 
2125
                graphics.setColor(bit4 ? onColor : offColor);
 
2126
                graphics.fillOval(0, 0, 4, 4);
 
2127
 
 
2128
                graphics.dispose();
 
2129
                return new ImageIcon(result);
 
2130
        }
 
2131
 
 
2132
        /**
 
2133
         * Returns search icon.
 
2134
         * 
 
2135
         * @param dimension
 
2136
         *            Icon dimension.
 
2137
         * @param colorScheme
 
2138
         *            Icon color scheme.
 
2139
         * @param leftToRight
 
2140
         *            LTR indication of the resulting icon.
 
2141
         * @return Search icon.
 
2142
         */
 
2143
        public static Icon getSearchIcon(int dimension,
 
2144
                        SubstanceColorScheme colorScheme, boolean leftToRight) {
 
2145
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(dimension,
 
2146
                                dimension);
 
2147
 
 
2148
                Graphics2D graphics = (Graphics2D) result.getGraphics().create();
 
2149
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2150
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
2151
 
 
2152
                Color color = SubstanceColorUtilities.getMarkColor(colorScheme, true);
 
2153
                graphics.setColor(color);
 
2154
 
 
2155
                graphics.setStroke(new BasicStroke(1.5f));
 
2156
                if (leftToRight) {
 
2157
                        int xc = (int) (0.6 * dimension);
 
2158
                        int yc = (int) (0.45 * dimension);
 
2159
                        int r = (int) (0.3 * dimension);
 
2160
 
 
2161
                        graphics.drawOval(xc - r, yc - r, 2 * r, 2 * r);
 
2162
 
 
2163
                        graphics.setStroke(new BasicStroke(3.0f));
 
2164
                        GeneralPath handle = new GeneralPath();
 
2165
                        handle.moveTo((float) (xc - r / Math.sqrt(2.0)), (float) (yc + r
 
2166
                                        / Math.sqrt(2.0)));
 
2167
                        handle.lineTo(1.8f, dimension - 2.2f);
 
2168
                        graphics.draw(handle);
 
2169
                } else {
 
2170
                        int xc = (int) (0.4 * dimension);
 
2171
                        int yc = (int) (0.45 * dimension);
 
2172
                        int r = (int) (0.3 * dimension);
 
2173
 
 
2174
                        graphics.drawOval(xc - r, yc - r, 2 * r, 2 * r);
 
2175
 
 
2176
                        graphics.setStroke(new BasicStroke(3.0f));
 
2177
                        GeneralPath handle = new GeneralPath();
 
2178
                        handle.moveTo((float) (xc + r / Math.sqrt(2.0)), (float) (yc + r
 
2179
                                        / Math.sqrt(2.0)));
 
2180
                        handle.lineTo(dimension - 2.5f, dimension - 2.2f);
 
2181
                        graphics.draw(handle);
 
2182
                }
 
2183
 
 
2184
                graphics.dispose();
 
2185
                return new ImageIcon(result);
 
2186
        }
 
2187
 
 
2188
        /**
 
2189
         * Returns an icon that matches the specified watermark.
 
2190
         * 
 
2191
         * @param watermark
 
2192
         *            Watermark instance.
 
2193
         * @return Icon that matches the specified watermark.
 
2194
         */
 
2195
        public static Icon getWatermarkIcon(SubstanceWatermark watermark) {
 
2196
                int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
 
2197
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(iSize,
 
2198
                                iSize);
 
2199
                Graphics2D graphics = (Graphics2D) result.getGraphics().create();
 
2200
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2201
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
2202
 
 
2203
                watermark
 
2204
                                .previewWatermark(graphics,
 
2205
                                                SubstanceColorSchemeUtilities.METALLIC_SKIN, 0, 0,
 
2206
                                                iSize, iSize);
 
2207
                graphics.dispose();
 
2208
                return new ImageIcon(result);
 
2209
        }
 
2210
 
 
2211
        /**
 
2212
         * Returns a lock icon that matches the specified scheme.
 
2213
         * 
 
2214
         * @param scheme
 
2215
         *            Scheme instance.
 
2216
         * @return Lock icon that matches the specified scheme.
 
2217
         */
 
2218
        public static Icon getSmallLockIcon(SubstanceColorScheme scheme, Component c) {
 
2219
                int componentFontSize = SubstanceSizeUtils.getComponentFontSize(c);
 
2220
                int extraPadding = SubstanceSizeUtils
 
2221
                                .getExtraPadding(componentFontSize);
 
2222
                int width = 6 + 2 * extraPadding;
 
2223
                int height = 9 + 2 * extraPadding;
 
2224
                BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
 
2225
                                height);
 
2226
 
 
2227
                Color fore = scheme.getForegroundColor();
 
2228
                Color fill = new Color(208, 208, 48);
 
2229
 
 
2230
                Graphics2D graphics = (Graphics2D) result.getGraphics().create();
 
2231
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2232
                                RenderingHints.VALUE_ANTIALIAS_ON);
 
2233
 
 
2234
                float borderStrokeWidth = SubstanceSizeUtils
 
2235
                                .getBorderStrokeWidth(componentFontSize) / 1.2f;
 
2236
                float extraInsets = borderStrokeWidth / 2.0f;
 
2237
                graphics.setStroke(new BasicStroke(borderStrokeWidth,
 
2238
                                BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
 
2239
 
 
2240
                float lockPadTop = height / 3.0f;
 
2241
                float lockPadBottom = height - extraInsets;
 
2242
                float lockPadLeft = extraInsets;
 
2243
                float lockPadRight = width - extraInsets;
 
2244
 
 
2245
                // lock pad fill
 
2246
                graphics.setColor(fill);
 
2247
                graphics.fill(new Rectangle2D.Float(lockPadLeft, lockPadTop,
 
2248
                                lockPadRight - lockPadLeft, lockPadBottom - lockPadTop));
 
2249
                // lock pad outline
 
2250
                graphics.setColor(fore);
 
2251
                graphics.draw(new Rectangle2D.Float(lockPadLeft, lockPadTop,
 
2252
                                lockPadRight - lockPadLeft, lockPadBottom - lockPadTop));
 
2253
 
 
2254
                // lock handle
 
2255
                graphics.setColor(fore);
 
2256
                float lockHandleLeft = width / 4.0f;
 
2257
                float lockHandleRight = width - width / 4.0f;
 
2258
 
 
2259
                GeneralPath handle = new GeneralPath();
 
2260
                handle.moveTo(lockHandleLeft, lockPadTop);
 
2261
                // up to top-left
 
2262
                handle.lineTo(lockHandleLeft, extraInsets);
 
2263
                // right to top-right
 
2264
                handle.lineTo(lockHandleRight, extraInsets);
 
2265
                // down
 
2266
                handle.lineTo(lockHandleRight, lockPadTop);
 
2267
 
 
2268
                graphics.draw(handle);
 
2269
 
 
2270
                // lock keyhole
 
2271
                graphics.setColor(fore);
 
2272
                float lockKeyholeTop = lockPadTop + 2 * borderStrokeWidth;
 
2273
                float lockKeyholeBottom = lockPadBottom - 2 * borderStrokeWidth + 1;
 
2274
                float lockKeyholeLeft = lockHandleLeft + 1;
 
2275
                float lockKeyholeRight = lockHandleRight;
 
2276
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 
2277
                                RenderingHints.VALUE_ANTIALIAS_OFF);
 
2278
                graphics.setStroke(new BasicStroke(1.0f));
 
2279
                graphics.fill(new Rectangle2D.Float(lockKeyholeLeft, lockKeyholeTop,
 
2280
                                lockKeyholeRight - lockKeyholeLeft, lockKeyholeBottom
 
2281
                                                - lockKeyholeTop));
 
2282
 
 
2283
                graphics.dispose();
 
2284
                return new ImageIcon(result);
 
2285
        }
 
2286
 
 
2287
        /**
 
2288
         * Returns the negative of the specified image.
 
2289
         * 
 
2290
         * @param bi
 
2291
         *            Image.
 
2292
         * @return The negative of the specified image.
 
2293
         */
 
2294
        public static BufferedImage getNegated(BufferedImage bi) {
 
2295
                return new NegatedFilter().filter(bi, null);
 
2296
        }
 
2297
 
 
2298
        /**
 
2299
         * Creates a new version of the specified icon that is rendered in the
 
2300
         * colors of the specified color scheme.
 
2301
         * 
 
2302
         * @param comp
 
2303
         *            Component.
 
2304
         * @param original
 
2305
         *            The original icon.
 
2306
         * @param colorScheme
 
2307
         *            Color scheme.
 
2308
         * @return Scheme-based version of the original icon.
 
2309
         */
 
2310
        public static BufferedImage getColorSchemeImage(Component comp,
 
2311
                        Icon original, SubstanceColorScheme colorScheme,
 
2312
                        float originalBrightnessFactor) {
 
2313
                int w = original.getIconWidth();
 
2314
                int h = original.getIconHeight();
 
2315
                BufferedImage origImage = SubstanceCoreUtilities.getBlankImage(w, h);
 
2316
                original.paintIcon(comp, origImage.getGraphics(), 0, 0);
 
2317
 
 
2318
                return getColorSchemeImage(origImage, colorScheme,
 
2319
                                originalBrightnessFactor);
 
2320
        }
 
2321
 
 
2322
        /**
 
2323
         * Creates a new version of the specified image that is rendered in the
 
2324
         * colors of the specified color scheme.
 
2325
         * 
 
2326
         * @param original
 
2327
         *            The original image.
 
2328
         * @param colorScheme
 
2329
         *            Color scheme.
 
2330
         * @return Scheme-based version of the original icon.
 
2331
         */
 
2332
        public static BufferedImage getColorSchemeImage(BufferedImage original,
 
2333
                        SubstanceColorScheme colorScheme, float originalBrightnessFactor) {
 
2334
                return ColorSchemeFilter.getColorSchemeFilter(colorScheme,
 
2335
                                originalBrightnessFactor).filter(original, null);
 
2336
        }
 
2337
}