Source Code Cross Referenced for ColorDistributionParameter.java in  » Profiler » ejp » ejp » presenter » api » filters » parameters » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Profiler » ejp » ejp.presenter.api.filters.parameters 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         $Id: ColorDistributionParameter.java,v 1.8 2005/02/14 12:06:19 vauclair Exp $
003:
004:         Copyright (C) 2002-2005 Sebastien Vauclair
005:
006:         This file is part of Extensible Java Profiler.
007:
008:         Extensible Java Profiler is free software; you can redistribute it and/or
009:         modify it under the terms of the GNU General Public License as published by
010:         the Free Software Foundation; either version 2 of the License, or
011:         (at your option) any later version.
012:
013:         Extensible Java Profiler is distributed in the hope that it will be useful,
014:         but WITHOUT ANY WARRANTY; without even the implied warranty of
015:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016:         GNU General Public License for more details.
017:
018:         You should have received a copy of the GNU General Public License
019:         along with Extensible Java Profiler; if not, write to the Free Software
020:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
021:         */
022:
023:        package ejp.presenter.api.filters.parameters;
024:
025:        import java.awt.Color;
026:        import java.awt.Component;
027:        import java.awt.Dimension;
028:        import java.awt.Graphics;
029:        import java.awt.event.ActionEvent;
030:        import java.awt.event.ActionListener;
031:        import java.awt.event.InputEvent;
032:        import java.awt.event.MouseAdapter;
033:        import java.awt.event.MouseEvent;
034:        import java.awt.image.BufferedImage;
035:        import java.text.DecimalFormat;
036:        import java.util.ArrayList;
037:        import java.util.StringTokenizer;
038:
039:        import javax.swing.DefaultListCellRenderer;
040:        import javax.swing.JComboBox;
041:        import javax.swing.JComponent;
042:        import javax.swing.JList;
043:        import javax.swing.JPanel;
044:        import javax.swing.JSpinner;
045:        import javax.swing.SpinnerNumberModel;
046:        import javax.swing.event.ChangeEvent;
047:        import javax.swing.event.ChangeListener;
048:
049:        import ejp.presenter.api.util.CustomLogger;
050:        import ejp.presenter.gui.ColorChooserDialog;
051:        import ejp.presenter.gui.Utils;
052:
053:        /**
054:         * A color distribution parameter, which associates a color to every value in
055:         * the <code>[0, 1]</code> interval.
056:         * 
057:         * The interval is actually split into by a user-provided divider and a color
058:         * can be associated to every sub-range. A convenience system allows to
059:         * automatically build up a gradient of colors between the first and the last
060:         * ones.
061:         * 
062:         * <p>
063:         * <b>Known issue </b>: due to Swing's error #4497301, the combo box might not
064:         * be selectable the second time the dialog is showed. There is currently no
065:         * acceptable workaround to this. The solution used here consists on limiting
066:         * the count of rows to a maximum.
067:         * 
068:         * @author Sebastien Vauclair
069:         * @version 1.0
070:         */
071:        public class ColorDistributionParameter extends AbstractParameter
072:                implements  ActionListener, ChangeListener {
073:            // ///////////////////////////////////////////////////////////////////////////
074:            // CONSTANTS
075:            // ///////////////////////////////////////////////////////////////////////////
076:
077:            /**
078:             * Decimal numbers formatter used to render percents.
079:             */
080:            public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat(
081:                    "##0.0%");
082:
083:            /**
084:             * Separator character between colors in text descriptions.
085:             */
086:            public static final String COLORS_SEPARATOR = ";";
087:
088:            // ///////////////////////////////////////////////////////////////////////////
089:            // MEMBERS
090:            // ///////////////////////////////////////////////////////////////////////////
091:
092:            /**
093:             * Current list of colors.
094:             * 
095:             * <p>
096:             * Additional colors (after index <code>divisions</code> are kept in memory
097:             * for possible later usage.
098:             */
099:            protected final ArrayList colors = new ArrayList();
100:
101:            /**
102:             * Number of divisions.
103:             * 
104:             * <p>
105:             * <code>number of divisions = number of colors - 1</code>.
106:             */
107:            protected int divisions = 0;
108:
109:            /**
110:             * Spinner model.
111:             */
112:            protected final SpinnerNumberModel spinnerModel = new SpinnerNumberModel(
113:                    divisions /* value */, 0 /* minimum */,
114:                    1000 /* maximum */, 1 /* step size */);
115:
116:            /**
117:             * Avoids reentrancy into <code>divisionsUpdated()</code>.
118:             */
119:            protected boolean divisionsUpdatedIsWorking = false;
120:
121:            /**
122:             * Current read-only state of the parameter.
123:             */
124:            protected boolean readOnly = false;
125:
126:            // ///////////////////////////////////////////////////////////////////////////
127:            // COMPONENTS
128:            // ///////////////////////////////////////////////////////////////////////////
129:
130:            /**
131:             * Divisions spinner.
132:             */
133:            protected final JSpinner jsDivisions;
134:
135:            /**
136:             * Intervals combo box.
137:             */
138:            protected final JComboBox jcbIntervals;
139:
140:            /**
141:             * Panel that displays current color distribution.
142:             */
143:            protected final ColorsDisplay cdSamples;
144:
145:            // ///////////////////////////////////////////////////////////////////////////
146:            // CONSTRUCTOR
147:            // ///////////////////////////////////////////////////////////////////////////
148:
149:            /**
150:             * Creates a new color distribution parameter instance.
151:             * 
152:             * @param aName
153:             *          the parameter's name.
154:             * @param aTitle
155:             *          parameter's caption.
156:             * @param aToolTipText
157:             *          a tool-tip text.
158:             */
159:            public ColorDistributionParameter(String aName, String aTitle,
160:                    String aToolTipText) {
161:                super (aName, aTitle, aToolTipText);
162:
163:                // default color
164:                colors.add(Color.black);
165:
166:                jsDivisions = new JSpinner(spinnerModel);
167:                Utils.setCommonProperties(jsDivisions);
168:                jsDivisions.addChangeListener(this );
169:                addLine("Number of divisions",
170:                        "Number of separations of the interval.", jsDivisions,
171:                        null);
172:
173:                jcbIntervals = new JComboBox();
174:                Utils.setCommonProperties(jcbIntervals);
175:                jcbIntervals.setRenderer(new ComboCellRenderer());
176:                jcbIntervals
177:                        .setPrototypeDisplayValue(new ComboItem(1, 1, null));
178:                jcbIntervals.addActionListener(this );
179:
180:                // Workaround for Swing's error #4497301
181:                // The maximum count of rows is choosen so that the popup does not
182:                // exceed the dialog's (ParametersDialog) bounds, so that a light-weight
183:                // popup can be used by Swing.
184:                jcbIntervals.setMaximumRowCount(3);
185:
186:                cdSamples = new ColorsDisplay(ColorsDisplay.DEFAULT_WIDTH,
187:                        (int) jcbIntervals.getPreferredSize().getHeight());
188:                cdSamples
189:                        .setToolTipText("Double-click to automatically build a gradient");
190:                cdSamples.addMouseListener(new MouseAdapter() {
191:                    public void mouseClicked(MouseEvent aEvent) {
192:                        if (!readOnly
193:                                && aEvent.getButton() == MouseEvent.BUTTON1
194:                                && aEvent.getClickCount() == 2)
195:                            buildGradient();
196:                    }
197:                });
198:
199:                addLine("Colors", "Colors of each sub-range.", jcbIntervals,
200:                        cdSamples);
201:
202:                divisionsUpdated();
203:            }
204:
205:            // ///////////////////////////////////////////////////////////////////////////
206:            // READ-ONLY
207:            // ///////////////////////////////////////////////////////////////////////////
208:
209:            /**
210:             * Sets the paramter as read-only.
211:             * 
212:             * <p>
213:             * Locks divisions spinner and no longer popups a color selection dialog when
214:             * an interval is selected.
215:             */
216:            public void setReadOnly() {
217:                readOnly = true;
218:                jsDivisions.setEnabled(false);
219:
220:                cdSamples.setToolTipText(null); // remove tool tip text
221:                jcbIntervals.setRenderer(new ComboCellRenderer()); // remove tool tip text
222:                // (note - this is
223:                // dirty!)
224:            }
225:
226:            // ///////////////////////////////////////////////////////////////////////////
227:            // ACCESSORS
228:            // ///////////////////////////////////////////////////////////////////////////
229:
230:            /**
231:             * Sets value from object.
232:             * 
233:             * Wrapper to <code>setValue(Color[])</code>.
234:             */
235:            public void setValue(Object aObject) throws ClassCastException {
236:                setValue((Color[]) aObject);
237:            }
238:
239:            /**
240:             * Sets value from a color array.
241:             * 
242:             * Updates divisions and intervals values.
243:             * 
244:             * @param aColors
245:             *          a non-empty <code>Color[]</code> value.
246:             */
247:            public void setValue(Color[] aColors) {
248:                int nb = aColors.length;
249:
250:                if (nb < 1)
251:                    throw new IllegalArgumentException("Set of colors is empty");
252:
253:                divisions = nb - 1;
254:                spinnerModel.setValue(new Integer(divisions));
255:
256:                for (int i = 0; i < nb; i++)
257:                    if (i < colors.size())
258:                        colors.set(i, aColors[i]);
259:                    else
260:                        colors.add(aColors[i]);
261:
262:                divisionsUpdated();
263:            }
264:
265:            /**
266:             * Sets value from text.
267:             * 
268:             * <p>
269:             * Input text is first tokenized using <code>COLORS_SEPARATOR</code>, then
270:             * each token is processed using <code>Color.decode(String)</code>.
271:             * 
272:             * @exception NumberFormatException
273:             *              if a number cannot be parsed to a color.
274:             * @exception IllegalStateException
275:             *              if an error occurs in the tokenizer.
276:             */
277:            public void setValueAsText(String aTextValue)
278:                    throws NumberFormatException, IllegalStateException {
279:                StringTokenizer st = new StringTokenizer(aTextValue,
280:                        COLORS_SEPARATOR, false);
281:                int nb = st.countTokens();
282:
283:                Color[] tmpColors = new Color[nb];
284:                int i = 0;
285:                while (st.hasMoreTokens())
286:                    tmpColors[i++] = Color.decode(st.nextToken()); // throws NFE
287:
288:                if (i != nb)
289:                    throw new IllegalStateException(
290:                            "Actual count of colors is smaller than expected");
291:
292:                setValue(tmpColors);
293:            }
294:
295:            /**
296:             * Gets value as an object.
297:             */
298:            public Object getValue() {
299:                return getColorsValue();
300:            }
301:
302:            /**
303:             * Gets value as text.
304:             * 
305:             * <p>
306:             * Colors are exported as integers using <code>Color.getRGB()</code>. They
307:             * are separated by <code>COLORS_SEPARATOR</code> character.
308:             */
309:            public String getValueAsText() {
310:                StringBuffer buffer = new StringBuffer();
311:                for (int i = 0; i <= divisions; i++) {
312:                    if (i > 0)
313:                        buffer.append(COLORS_SEPARATOR);
314:                    buffer.append(((Color) colors.get(i)).getRGB());
315:                }
316:                return buffer.toString();
317:            }
318:
319:            /**
320:             * Get current value of the parameter.
321:             * 
322:             * @return a <code>Color[]</code> value.
323:             */
324:            public Color[] getColorsValue() {
325:                Color[] result = new Color[divisions + 1];
326:                for (int i = 0; i <= divisions; i++)
327:                    result[i] = (Color) colors.get(i);
328:                return result;
329:            }
330:
331:            /**
332:             * Gets the color currently associated to a real number.
333:             * 
334:             * @param aRatio
335:             *          a <code>double</code> value in the <code>[0, 1]</code>
336:             *          interval.
337:             * @return the associated <code>Color</code> value.
338:             */
339:            public Color colorForRatio(double aRatio) {
340:                int index = (aRatio == 1d ? divisions // last color
341:                        : (int) (aRatio * (divisions + 1)));
342:
343:                return (Color) colors.get(index);
344:            }
345:
346:            // ///////////////////////////////////////////////////////////////////////////
347:            // PROTECTED MEMBERS
348:            // ///////////////////////////////////////////////////////////////////////////
349:
350:            /**
351:             * Builds up a gradient between the first and last colors.
352:             */
353:            protected void buildGradient() {
354:                if (divisions < 2)
355:                    return;
356:
357:                Color first = (Color) colors.get(0);
358:                Color last = (Color) colors.get(divisions);
359:
360:                int firstR = first.getRed();
361:                int firstG = first.getGreen();
362:                int firstB = first.getBlue();
363:
364:                double deltaR = ((double) (last.getRed() - firstR))
365:                        / ((double) divisions);
366:                double deltaG = ((double) (last.getGreen() - firstG))
367:                        / ((double) divisions);
368:                double deltaB = ((double) (last.getBlue() - firstB))
369:                        / ((double) divisions);
370:
371:                for (int i = 1; i <= divisions - 1; i++)
372:                    colors.set(i, new Color(firstR + (int) (deltaR * i), firstG
373:                            + (int) (deltaG * i), firstB + (int) (deltaB * i)));
374:
375:                divisionsUpdated();
376:            }
377:
378:            /**
379:             * Updates all fields to match a new divisions number.
380:             * 
381:             * <p>
382:             * When the number of divisions grows, previously selected colors are used or
383:             * if there are none, last color is repeated.
384:             * 
385:             * <p>
386:             * This method updates fields and calls <code>divisionsUpdated()</code> to
387:             * update the graphical representation.
388:             * 
389:             * @param aNewDivisions
390:             *          new <code>int</code> value.
391:             */
392:            protected void updateDivisions(int aNewDivisions) {
393:                int diff = aNewDivisions - divisions;
394:                if (diff == 0)
395:                    return;
396:
397:                if (diff > 0) {
398:                    Object last = colors.get(divisions);
399:                    for (int i = 0; i < diff; i++)
400:                        if (divisions + i + 1 >= colors.size())
401:                            colors.add(last);
402:                }
403:
404:                divisions = aNewDivisions;
405:                divisionsUpdated();
406:            }
407:
408:            /**
409:             * Updates graphical representation of color intervals.
410:             * 
411:             * <p>
412:             * Uses <code>divisions</code> and <code>colors</code>.
413:             */
414:            protected void divisionsUpdated() {
415:                divisionsUpdatedIsWorking = true;
416:
417:                // build combo items
418:                int index = jcbIntervals.getSelectedIndex();
419:                jcbIntervals.removeAllItems();
420:                for (int i = 0; i <= divisions; i++) {
421:                    double floor = ((double) i) / ((double) (divisions + 1));
422:                    double ceil = ((double) (i + 1))
423:                            / ((double) (divisions + 1));
424:                    jcbIntervals.addItem(new ComboItem(floor, ceil,
425:                            (Color) colors.get(i)));
426:                }
427:                jcbIntervals.setSelectedIndex(Math.max(0, Math.min(index,
428:                        divisions)));
429:                updateSelectedColor();
430:
431:                // render colors display
432:                cdSamples.invalidateGraphics();
433:
434:                divisionsUpdatedIsWorking = false;
435:            }
436:
437:            /**
438:             * Updates combo box to render currently selected colors.
439:             * 
440:             * <p>
441:             * This must be done because of an error in Swing's Metal UI, which does call
442:             * the renderer for the selected item but then overrides the foreground color.
443:             */
444:            protected void updateSelectedColor() {
445:                ComboItem item = (ComboItem) jcbIntervals.getSelectedItem();
446:
447:                // update display of selected item
448:                jcbIntervals.setForeground(item.color);
449:            }
450:
451:            // ///////////////////////////////////////////////////////////////////////////
452:            // ChangeListener INTERFACE
453:            // ///////////////////////////////////////////////////////////////////////////
454:
455:            /**
456:             * Called when the spinner's value is considered as changed.
457:             * 
458:             * <p>
459:             * Updates intervals.
460:             */
461:            public void stateChanged(ChangeEvent aEvent) {
462:                Object src = aEvent.getSource();
463:                if (src == jsDivisions)
464:                    updateDivisions(spinnerModel.getNumber().intValue());
465:                else
466:                    CustomLogger.INSTANCE
467:                            .warning("Unable to handle state change event from unknwon source");
468:            }
469:
470:            // ///////////////////////////////////////////////////////////////////////////
471:            // ActionListener INTERFACE
472:            // ///////////////////////////////////////////////////////////////////////////
473:
474:            /**
475:             * Called when an interval is selected in combo box.
476:             */
477:            public void actionPerformed(ActionEvent aEvent) {
478:                Object src = aEvent.getSource();
479:                if (src == jcbIntervals) {
480:                    if (!divisionsUpdatedIsWorking
481:                            && ((aEvent.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) {
482:                        if (!readOnly) {
483:                            ComboItem item = (ComboItem) jcbIntervals
484:                                    .getSelectedItem();
485:                            ColorChooserDialog ccd = new ColorChooserDialog(
486:                                    dialog /* parent */, item.color /*
487:                             * initial
488:                             * color
489:                             */);
490:                            Color newColor = ccd.showDialog();
491:                            if (newColor != null) {
492:                                colors.set(jcbIntervals.getSelectedIndex(),
493:                                        newColor);
494:                                item.setColor(newColor);
495:
496:                                cdSamples.invalidateGraphics();
497:                            }
498:                        }
499:
500:                        updateSelectedColor();
501:                    }
502:                } else
503:                    CustomLogger.INSTANCE
504:                            .warning("Unable to handle action event from unknown source");
505:            }
506:
507:            // ///////////////////////////////////////////////////////////////////////////
508:            // NESTED CLASSES - ColorsDisplay
509:            // ///////////////////////////////////////////////////////////////////////////
510:
511:            /**
512:             * Graphical panel that displays the current color distribution.
513:             */
514:            protected class ColorsDisplay extends JPanel {
515:                /**
516:                 * Default preferred width.
517:                 */
518:                public static final int DEFAULT_WIDTH = 102;
519:
520:                /**
521:                 * Current width.
522:                 */
523:                protected final int width;
524:
525:                /**
526:                 * Current height.
527:                 */
528:                protected final int height;
529:
530:                /**
531:                 * Current dimension.
532:                 */
533:                protected final Dimension dimension;
534:
535:                /**
536:                 * Image used to hold paint of color distribution.
537:                 */
538:                protected final BufferedImage image;
539:
540:                /**
541:                 * Graphics used to paint color distribution.
542:                 * 
543:                 */
544:                protected Graphics graphics;
545:
546:                /**
547:                 * Creates a new <code>ColorsDisplay</code> instance.
548:                 * 
549:                 * @param aWidth
550:                 *          preferred width.
551:                 * @param aHeight
552:                 *          preferred height.
553:                 */
554:                public ColorsDisplay(int aWidth, int aHeight) {
555:                    width = aWidth;
556:                    height = aHeight;
557:                    dimension = new Dimension(aWidth, aHeight);
558:                    image = new BufferedImage(aWidth, aHeight,
559:                            BufferedImage.TYPE_INT_RGB);
560:                }
561:
562:                /**
563:                 * Implementation of minimum size.
564:                 */
565:                public Dimension getMinimumSize() {
566:                    return dimension;
567:                }
568:
569:                /**
570:                 * Implementation of preferred size.
571:                 */
572:                public Dimension getPreferredSize() {
573:                    return dimension;
574:                }
575:
576:                /**
577:                 * Implementation of maximum size.
578:                 */
579:                public Dimension getMaximumSize() {
580:                    return dimension;
581:                }
582:
583:                /**
584:                 * Called to paint the panel to the specified graphics.
585:                 * 
586:                 * @param aGraphics
587:                 *          a <code>Graphics</code> value.
588:                 */
589:                protected void paintComponent(Graphics aGraphics) {
590:                    super .paintComponent(aGraphics); // paint background
591:
592:                    if (graphics == null) {
593:                        graphics = image.createGraphics();
594:
595:                        graphics.setColor(Color.black);
596:                        graphics.drawRect(0, 0, width - 1, height - 1);
597:
598:                        int bottomY = height - 2; // constant
599:                        for (int x = 1; x <= width - 2; x++) {
600:                            int index = (int) (((double) x)
601:                                    / ((double) (width - 1)) * (divisions + 1));
602:
603:                            Color color = (Color) colors.get(index);
604:                            graphics.setColor(color);
605:                            graphics.drawLine(x, 1, x, bottomY);
606:                        }
607:                    }
608:
609:                    aGraphics
610:                            .drawImage(image, 0, 0, null /* image observer */);
611:                }
612:
613:                /**
614:                 * Invalidates current graphics and repaints it.
615:                 */
616:                public void invalidateGraphics() {
617:                    graphics = null;
618:                    repaint();
619:                }
620:            }
621:
622:            // ///////////////////////////////////////////////////////////////////////////
623:            // NESTED CLASSES - ComboItem
624:            // ///////////////////////////////////////////////////////////////////////////
625:
626:            /**
627:             * An item (interval and associated color) of the combo box.
628:             */
629:            protected class ComboItem {
630:                /**
631:                 * Floor value of the interval.
632:                 */
633:                public final double floor;
634:
635:                /**
636:                 * Ceil value of the interval.
637:                 */
638:                public final double ceil;
639:
640:                /**
641:                 * Text defining the interval.
642:                 * 
643:                 */
644:                public final String text;
645:
646:                /**
647:                 * Current color of the item.
648:                 */
649:                protected Color color;
650:
651:                /**
652:                 * Creates a new <code>ComboItem</code> instance.
653:                 * 
654:                 * @param aFloor
655:                 *          floor value.
656:                 * @param aCeil
657:                 *          ceil value.
658:                 * @param aColor
659:                 *          default color.
660:                 */
661:                public ComboItem(double aFloor, double aCeil, Color aColor) {
662:                    floor = aFloor;
663:                    ceil = aCeil;
664:                    color = aColor;
665:                    text = renderRatio(aFloor) + " \u2264 value "
666:                            + (aCeil == 1.0d ? "\u2264" : "<") + " "
667:                            + renderRatio(aCeil);
668:                }
669:
670:                /**
671:                 * Sets current color of the item.
672:                 * 
673:                 * @param aColor
674:                 *          a <code>Color</code> value.
675:                 */
676:                public void setColor(Color aColor) {
677:                    color = aColor;
678:                }
679:
680:                /**
681:                 * Gets current color of the item.
682:                 * 
683:                 * @return a <code>Color</code> value.
684:                 */
685:                public Color getColor() {
686:                    return color;
687:                }
688:
689:                /**
690:                 * Returns the caption of the item.
691:                 * 
692:                 * @return a <code>String</code> value.
693:                 */
694:                public String toString() {
695:                    return text;
696:                }
697:
698:                /**
699:                 * Convenience method to display a decimal ratio as a percent.
700:                 * 
701:                 * @param aDouble
702:                 *          a <code>double</code> value.
703:                 * @return a <code>String</code> value.
704:                 */
705:                protected String renderRatio(double aDouble) {
706:                    return DECIMAL_FORMAT.format(aDouble);
707:                }
708:            }
709:
710:            // ///////////////////////////////////////////////////////////////////////////
711:            // NESTED CLASSES - ComboCellRenderer
712:            // ///////////////////////////////////////////////////////////////////////////
713:
714:            /**
715:             * Renderer for combo box cells (intervals).
716:             */
717:            protected class ComboCellRenderer extends DefaultListCellRenderer {
718:                /**
719:                 * Renderer implementation.
720:                 */
721:                public Component getListCellRendererComponent(JList aList,
722:                        Object aValue, int aIndex, boolean aIsSelected,
723:                        boolean aCellHasFocus) {
724:                    Component result = super .getListCellRendererComponent(
725:                            aList, aValue, aIndex, aIsSelected, aCellHasFocus);
726:                    result.setForeground(((ComboItem) aValue).color);
727:
728:                    // note - when in readOnly mode, the tooltip should be changed
729:                    if (!readOnly && result instanceof  JComponent)
730:                        ((JComponent) result)
731:                                .setToolTipText("Left-click this item to change its color");
732:                    return result;
733:                }
734:            }
735:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.