View Javadoc
1   package fr.ifremer.dali.ui.swing.util.image;
2   
3   /*
4    * #%L
5    * Dali :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import fr.ifremer.dali.config.DaliConfiguration;
27  import org.jdesktop.swingx.JXPanel;
28  import org.jdesktop.swingx.painter.MattePainter;
29  import org.jdesktop.swingx.util.PaintUtils;
30  
31  import javax.swing.*;
32  import javax.swing.border.Border;
33  import java.awt.*;
34  import java.awt.image.BufferedImage;
35  
36  /*
37   *  Support custom painting on a panel in the form of
38   *
39   *  a) images - that can be scaled, tiled or painted at original size
40   *  b) non solid painting - that can be done by using a Paint object
41   *
42   *  Also, any component added directly to this panel will be made
43   *  non-opaque so that the custom painting can show through.
44   */
45  /**
46   * <p>BackgroundPanel class.</p>
47   *
48   */
49  public class BackgroundPanel extends JXPanel {
50  
51      private Image image;
52      private BufferedImage scaledImage;
53      private boolean selected = false;
54  
55      private static final Border outsideBorder = BorderFactory.createEmptyBorder(10, 10, 10, 10);
56      private float alignmentX = 0.5f;
57      private float alignmentY = 0.5f;
58      public static final double NO_SCALE = 1d;
59      private boolean scaled = false;
60      private double ratio = NO_SCALE;
61  
62      /**
63       * <p>Constructor for BackgroundPanel.</p>
64       */
65      public BackgroundPanel() {
66          this(null, false);
67      }
68  
69      /*
70       *  Set image as the background
71       */
72      /**
73       * <p>Constructor for BackgroundPanel.</p>
74       *
75       * @param image a {@link java.awt.Image} object.
76       * @param withBackground a boolean.
77       */
78      public BackgroundPanel(Image image, boolean withBackground) {
79          setLayout(new BorderLayout());
80          if (withBackground) {
81              setBackgroundPainter(new MattePainter(PaintUtils.getCheckerPaint(Color.white, new Color(250, 250, 250), 50)));
82          }
83          setImage(image);
84          setSelected(false);
85      }
86  
87      /*
88       *	Set the image used as the background
89       */
90      /**
91       * <p>Setter for the field <code>image</code>.</p>
92       *
93       * @param image a {@link java.awt.Image} object.
94       */
95      public void setImage(Image image) {
96          this.image = image;
97          repaint();
98      }
99  
100     /**
101      * <p>isSelected.</p>
102      *
103      * @return a boolean.
104      */
105     public boolean isSelected() {
106         return selected;
107     }
108 
109     /**
110      * <p>Setter for the field <code>selected</code>.</p>
111      *
112      * @param selected a boolean.
113      */
114     public void setSelected(boolean selected) {
115         this.selected = selected;
116         setBorder(BorderFactory.createCompoundBorder(outsideBorder,
117                 selected ? BorderFactory.createMatteBorder(2, 2, 2, 2, DaliConfiguration.getInstance().getColorSelectedRow()) : null));
118     }
119 
120     /*
121      *  Specify the horizontal alignment of the image when using ACTUAL style
122      */
123     /**
124      * <p>setImageAlignmentX.</p>
125      *
126      * @param alignmentX a float.
127      */
128     public void setImageAlignmentX(float alignmentX) {
129         this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX;
130         repaint();
131     }
132 
133     /*
134      *  Specify the horizontal alignment of the image when using ACTUAL style
135      */
136     /**
137      * <p>setImageAlignmentY.</p>
138      *
139      * @param alignmentY a float.
140      */
141     public void setImageAlignmentY(float alignmentY) {
142         this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY;
143         repaint();
144     }
145 
146     /**
147      * <p>Setter for the field <code>scaled</code>.</p>
148      *
149      * @param scaled a boolean.
150      */
151     public void setScaled(boolean scaled) {
152         this.scaled = scaled;
153         scaleImage();
154         repaint();
155     }
156 
157     public void setRatio(double ratio) {
158         this.ratio = ratio;
159         setScaled(ratio != NO_SCALE);
160     }
161 
162     /**
163      * <p>scaleImage.</p>
164      */
165     private void scaleImage() {
166         if (scaled && image != null) {
167 
168             int imageWidth = image.getWidth(this);
169             int imageHeight = image.getHeight(this);
170 
171             if (ratio == NO_SCALE) {
172                 int pw = super.getPreferredSize().width;   //panel width
173                 int ph = super.getPreferredSize().height;  //panel height
174 
175                 // use doubles so division below won't round
176                 if (pw < imageWidth || ph < imageHeight) {
177 
178                     double rw = (double) pw / (double) imageWidth;
179                     double rh = (double) ph / (double) imageHeight;
180 
181                     ratio = Math.min(rw, rh);
182 
183                 }
184             }
185             int newWidth = Math.max((int) (imageWidth * ratio), 1);
186             int newHeight = Math.max((int) (imageHeight * ratio), 1);
187 
188             scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
189             Graphics2D g = scaledImage.createGraphics();
190             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
191             g.drawImage(image, 0, 0, newWidth, newHeight, 0, 0, imageWidth, imageHeight, null);
192             g.dispose();
193 
194         } else {
195             scaledImage = null;
196         }
197     }
198     /*
199      *  Override method so we can make the component transparent
200      */
201 
202     /**
203      * <p>add.</p>
204      *
205      * @param component a {@link javax.swing.JComponent} object.
206      */
207     public void add(JComponent component) {
208         add(component, null);
209     }
210 
211     /*
212      *  Override to provide a preferred size equal to the image size
213      */
214     /** {@inheritDoc} */
215     @Override
216     public Dimension getPreferredSize() {
217         Image imageToRender = scaled ? scaledImage : image;
218         if (imageToRender != null) {
219             Insets insets = getInsets();
220             return new Dimension(imageToRender.getWidth(this) + insets.left + insets.right, imageToRender.getHeight(this) + insets.top + insets.bottom);
221         } else {
222             return super.getPreferredSize();
223         }
224     }
225 
226     /*
227      *  Add custom painting
228      */
229     /** {@inheritDoc} */
230     @Override
231     protected void paintComponent(Graphics g) {
232         super.paintComponent(g);
233 
234         //  Draw the image
235         Image imageToDraw = scaled ? scaledImage : image;
236         if (imageToDraw != null) {
237             Dimension d = getSize();
238             Insets insets = getInsets();
239             int width = d.width - insets.left - insets.right;
240             int height = d.height - insets.top - insets.left;
241             float x = (width - imageToDraw.getWidth(null)) * alignmentX;
242             float y = (height - imageToDraw.getHeight(null)) * alignmentY;
243             g.drawImage(imageToDraw, (int) x + insets.left, (int) y + insets.top, this);
244         }
245     }
246 
247 }