View Javadoc

1   /*
2   
3       dsh-piccolo-identify  Piccolo2D nodes for identifiable beans.
4       Copyright (c) 2007-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.piccolo.identify;
25  
26  import java.awt.BasicStroke;
27  import java.awt.Color;
28  import java.awt.Paint;
29  import java.awt.Shape;
30  import java.awt.Stroke;
31  
32  import java.awt.font.FontRenderContext;
33  import java.awt.font.TextLayout;
34  
35  import java.awt.geom.AffineTransform;
36  import java.awt.geom.Point2D;
37  import java.awt.geom.Rectangle2D;
38  import java.awt.geom.RoundRectangle2D;
39  
40  import org.piccolo2d.nodes.PPath;
41  
42  import org.piccolo2d.util.PBounds;
43  
44  import org.dishevelled.iconbundle.IconSize;
45  import org.dishevelled.iconbundle.IconState;
46  
47  /**
48   * Finder-style id node.
49   *
50   * @author  Michael Heuer
51   * @version $Revision$ $Date$
52   */
53  public final class FinderIdNode
54      extends AbstractIdNode
55  {
56      /** Icon selection node. */
57      private PPath iconSelection;
58  
59      /** Text selection node. */
60      private PPath textSelection;
61  
62      /** Text selection shadow node. */
63      private PPath textSelectionShadow;
64  
65      /** Text selection paint. */
66      private static final Paint TEXT_SELECTION_PAINT = new Color(0, 0, 0, 100);
67  
68      /** Text selection selected paint. */
69      private static final Paint TEXT_SELECTION_SELECTED_PAINT = new Color(56, 117, 215);
70  
71      /** Icon selection stroke. */
72      private static final Stroke ICON_SELECTION_STROKE = new BasicStroke(2.0f);
73  
74      /** Icon selection stroke paint. */
75      private static final Paint ICON_SELECTION_STROKE_PAINT = new Color(130, 130, 130);
76  
77  
78      /**
79       * Create a new finder-style id node.
80       */
81      public FinderIdNode()
82      {
83          this(null);
84      }
85  
86      /**
87       * Create a new finder-style id node with the specified value.
88       *
89       * @param value value for this id node
90       */
91      public FinderIdNode(final Object value)
92      {
93          super(value);
94          createNodes();
95          resetStateMachine();
96      }
97  
98      /**
99       * Create a new finder-style id node with the specified value and icon size.
100      *
101      * @param value value for this id node
102      * @param iconSize icon size for this id node, must not be null
103      */
104     public FinderIdNode(final Object value, final IconSize iconSize)
105     {
106         super(value);
107         setIconSize(iconSize);
108         createNodes();
109         resetStateMachine();
110     }
111 
112 
113     /**
114      * Create nodes.
115      */
116     private void createNodes()
117     {
118         iconSelection = new PPath.Double();
119         iconSelection.setPaint(TEXT_SELECTION_PAINT);
120         iconSelection.setStroke(ICON_SELECTION_STROKE);
121         iconSelection.setStrokePaint(ICON_SELECTION_STROKE_PAINT);
122 
123         textSelection = new PPath.Double();
124         textSelection.setPaint(TEXT_SELECTION_PAINT);
125         textSelection.setStroke(null);
126 
127         textSelectionShadow = new PPath.Double();
128         textSelectionShadow.setPaint(TEXT_SELECTION_PAINT);
129         textSelectionShadow.setStroke(null);
130 
131         addChild(iconSelection);
132         addChild(textSelectionShadow);
133         addChild(textSelection);
134         addChild(getIconBundleImageNode());
135         addChild(getNameTextNode());
136     }
137 
138     /**
139      * Normal state.
140      */
141     private void normal()
142     {
143         setTransparency(1.0f);
144         getNameTextNode().setTextPaint(Color.BLACK);
145         iconSelection.setVisible(false);
146         textSelection.setPaint(TEXT_SELECTION_PAINT);
147         textSelectionShadow.setVisible(false);
148         setIconState(IconState.NORMAL);
149     }
150 
151     /**
152      * Reverse normal state.
153      */
154     private void reverseNormal()
155     {
156         setTransparency(1.0f);
157         getNameTextNode().setTextPaint(Color.WHITE);
158         iconSelection.setVisible(false);
159         textSelection.setPaint(TEXT_SELECTION_PAINT);
160         textSelectionShadow.setVisible(false);
161         setIconState(IconState.NORMAL);
162     }
163 
164     /**
165      * Selected state.
166      */
167     private void selected()
168     {
169         setTransparency(1.0f);
170         getNameTextNode().setTextPaint(Color.WHITE);
171         iconSelection.setVisible(true);
172         textSelection.setPaint(TEXT_SELECTION_SELECTED_PAINT);
173         textSelectionShadow.setVisible(true);
174         setIconState(IconState.NORMAL);
175     }
176 
177     /**
178      * Selected mouseover state.
179      */
180     private void selectedMouseover()
181     {
182         selected();
183     }
184 
185     /**
186      * Reverse selected state.
187      */
188     private void reverseSelected()
189     {
190         selected();
191     }
192 
193     /**
194      * Reverse selected mouseover state.
195      */
196     private void reverseSelectedMouseover()
197     {
198         selected();
199     }
200 
201     /**
202      * Dragging state.
203      */
204     private void dragging()
205     {
206         setTransparency(0.66f);
207     }
208 
209     /**
210      * Reverse dragging state.
211      */
212     private void reverseDragging()
213     {
214         dragging();
215     }
216 
217     @Override
218     protected void layoutChildren()
219     {
220         PBounds iconBounds = getIconBundleImageNode().getBoundsReference();
221         Point2D iconCenter = iconBounds.getCenter2D();
222 
223         double iconSelectionMargin = Math.max(0.1d * iconBounds.getHeight(), 0.1d * iconBounds.getWidth());
224         iconSelectionMargin = Math.min(iconSelectionMargin, 2.0d);
225 
226         Shape iconSelectionRect = new RoundRectangle2D.Double(0.0d, 0.0d,
227                                                               iconBounds.getWidth() + 2.0d * iconSelectionMargin, iconBounds.getHeight() + 2.0d * iconSelectionMargin,
228                                                               2.0d, 2.0d);
229 
230         iconSelection.reset();
231         iconSelection.append(iconSelectionRect, false);
232 
233         PBounds iconSelectionBounds = iconSelection.getBoundsReference();
234         Point2D iconSelectionCenter = iconSelectionBounds.getCenter2D();
235 
236         // unfortunately, the height of the text node is larger than the Mac l&f desires it to be
237         //PBounds textBounds = getNameTextNode().getBoundsReference();
238         // TODO:  this method doesn't support multi-line text nodes
239         FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);
240         TextLayout textLayout = new TextLayout(getNameTextNode().getText(), getNameTextNode().getFont(), frc);
241         Rectangle2D textBounds = textLayout.getBounds();
242         Point2D textCenter = new Point2D.Double(textBounds.getCenterX(), textBounds.getCenterY());
243         PBounds textNodeBounds = getNameTextNode().getBoundsReference();
244         Point2D textNodeCenter = textNodeBounds.getCenter2D();
245         double textHeightAdjustment = (textNodeBounds.getHeight() - textBounds.getHeight()) * 0.66d;
246 
247         double textSelectionWidthMargin = 8.0d;
248         double textSelectionHeightTopMargin = 2.0d;
249         double textSelectionHeightBottomMargin = 1.0d;
250 
251         Shape textSelectionRect = new RoundRectangle2D.Double(0.0d, 0.0d,
252                                                               textBounds.getWidth() + 2.0d * textSelectionWidthMargin, textBounds.getHeight() + textSelectionHeightTopMargin + textSelectionHeightBottomMargin,
253                                                               12.0d, 12.0d);
254 
255         textSelection.reset();
256         textSelection.append(textSelectionRect, false);
257         textSelectionShadow.reset();
258         textSelectionShadow.append(textSelectionRect, false);
259         PBounds textSelectionBounds = textSelection.getBoundsReference();
260         Point2D textSelectionCenter = textSelectionBounds.getCenter2D();
261 
262         getIconBundleImageNode().setOffset(-iconCenter.getX(), -iconCenter.getY());
263         iconSelection.setOffset(-iconSelectionCenter.getX(), -iconSelectionCenter.getY());
264         getNameTextNode().setOffset(-textNodeCenter.getX(), iconCenter.getY() + textSelectionHeightTopMargin + textSelectionCenter.getY() - textHeightAdjustment);
265         textSelection.setOffset(-textSelectionCenter.getX(), iconCenter.getY() + textSelectionCenter.getY());
266         textSelectionShadow.setOffset(-textSelectionCenter.getX(), iconCenter.getY() + textSelectionCenter.getY() + 1.0d);
267     }
268 }