1/******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17package com.badlogic.gdx.tools.flame; 18import java.awt.Color; 19import java.awt.Dimension; 20import java.awt.GradientPaint; 21import java.awt.Graphics; 22import java.awt.Graphics2D; 23import java.awt.GridBagConstraints; 24import java.awt.GridBagLayout; 25import java.awt.Insets; 26import java.awt.event.MouseAdapter; 27import java.awt.event.MouseEvent; 28import java.awt.event.MouseMotionAdapter; 29import java.util.ArrayList; 30 31import javax.swing.BorderFactory; 32import javax.swing.JColorChooser; 33import javax.swing.JPanel; 34import javax.swing.JSlider; 35import javax.swing.event.ChangeEvent; 36import javax.swing.event.ChangeListener; 37 38import com.badlogic.gdx.graphics.g3d.particles.values.GradientColorValue; 39 40/** @author Inferno */ 41class GradientPanel extends ParticleValuePanel<GradientColorValue> { 42 private GradientEditor gradientEditor; 43 ColorSlider saturationSlider, lightnessSlider; 44 JPanel colorPanel; 45 private ColorSlider hueSlider; 46 47 public GradientPanel (FlameMain editor, GradientColorValue value, String name, String description, 48 boolean hideGradientEditor) { 49 super(editor, name, description); 50 setValue(value); 51 52 if (hideGradientEditor) { 53 gradientEditor.setVisible(false); 54 } 55 gradientEditor.percentages.clear(); 56 for (float percent : value.getTimeline()) 57 gradientEditor.percentages.add(percent); 58 59 gradientEditor.colors.clear(); 60 float[] colors = value.getColors(); 61 for (int i = 0; i < colors.length;) { 62 float r = colors[i++]; 63 float g = colors[i++]; 64 float b = colors[i++]; 65 gradientEditor.colors.add(new Color(r, g, b)); 66 } 67 if (gradientEditor.colors.isEmpty() || gradientEditor.percentages.isEmpty()) { 68 gradientEditor.percentages.clear(); 69 gradientEditor.percentages.add(0f); 70 gradientEditor.percentages.add(1f); 71 gradientEditor.colors.clear(); 72 gradientEditor.colors.add(Color.white); 73 } 74 setColor(gradientEditor.colors.get(0)); 75 } 76 77 public Dimension getPreferredSize () { 78 Dimension size = super.getPreferredSize(); 79 size.width = 10; 80 return size; 81 } 82 83 protected void initializeComponents () { 84 super.initializeComponents(); 85 JPanel contentPanel = getContentPanel(); 86 { 87 gradientEditor = new GradientEditor() { 88 public void handleSelected (Color color) { 89 GradientPanel.this.setColor(color); 90 } 91 }; 92 contentPanel.add(gradientEditor, new GridBagConstraints(0, 1, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER, 93 GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 10)); 94 } 95 { 96 hueSlider = new ColorSlider(new Color[] {Color.red, Color.yellow, Color.green, Color.cyan, Color.blue, Color.magenta, 97 Color.red}) { 98 protected void colorPicked () { 99 saturationSlider.setColors(new Color[] {new Color(Color.HSBtoRGB(getPercentage(), 1, 1)), Color.white}); 100 updateColor(); 101 } 102 }; 103 contentPanel.add(hueSlider, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, 104 GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0)); 105 } 106 { 107 saturationSlider = new ColorSlider(new Color[] {Color.red, Color.white}) { 108 protected void colorPicked () { 109 updateColor(); 110 } 111 }; 112 contentPanel.add(saturationSlider, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, 113 GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 6), 0, 0)); 114 } 115 { 116 lightnessSlider = new ColorSlider(new Color[0]) { 117 protected void colorPicked () { 118 updateColor(); 119 } 120 }; 121 contentPanel.add(lightnessSlider, new GridBagConstraints(2, 3, 1, 1, 1, 0.0, GridBagConstraints.CENTER, 122 GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 123 } 124 { 125 colorPanel = new JPanel() { 126 public Dimension getPreferredSize () { 127 Dimension size = super.getPreferredSize(); 128 size.width = 52; 129 return size; 130 } 131 }; 132 contentPanel.add(colorPanel, new GridBagConstraints(0, 2, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, 133 GridBagConstraints.BOTH, new Insets(3, 0, 0, 6), 0, 0)); 134 } 135 136 colorPanel.addMouseListener(new MouseAdapter() { 137 public void mouseClicked (MouseEvent e) { 138 Color color = JColorChooser.showDialog(colorPanel, "Set Color", colorPanel.getBackground()); 139 if (color != null) setColor(color); 140 } 141 }); 142 colorPanel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black)); 143 } 144 145 public void setColor (Color color) { 146 float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); 147 hueSlider.setPercentage(hsb[0]); 148 saturationSlider.setPercentage(1 - hsb[1]); 149 lightnessSlider.setPercentage(1 - hsb[2]); 150 colorPanel.setBackground(color); 151 } 152 153 void updateColor () { 154 Color color = new Color(Color.HSBtoRGB(hueSlider.getPercentage(), 1 - saturationSlider.getPercentage(), 1)); 155 lightnessSlider.setColors(new Color[] {color, Color.black}); 156 color = new Color(Color.HSBtoRGB(hueSlider.getPercentage(), 1 - saturationSlider.getPercentage(), 157 1 - lightnessSlider.getPercentage())); 158 colorPanel.setBackground(color); 159 gradientEditor.setColor(color); 160 161 float[] colors = new float[gradientEditor.colors.size() * 3]; 162 int i = 0; 163 for (Color c : gradientEditor.colors) { 164 colors[i++] = c.getRed() / 255f; 165 colors[i++] = c.getGreen() / 255f; 166 colors[i++] = c.getBlue() / 255f; 167 } 168 float[] percentages = new float[gradientEditor.percentages.size()]; 169 i = 0; 170 for (Float percent : gradientEditor.percentages) 171 percentages[i++] = percent; 172 value.setColors(colors); 173 value.setTimeline(percentages); 174 } 175 176 public class GradientEditor extends JPanel { 177 ArrayList<Color> colors = new ArrayList(); 178 ArrayList<Float> percentages = new ArrayList(); 179 180 int handleWidth = 12; 181 int handleHeight = 12; 182 int gradientX = handleWidth / 2; 183 int gradientY = 0; 184 int gradientWidth; 185 int gradientHeight; 186 int dragIndex = -1; 187 int selectedIndex; 188 189 public GradientEditor () { 190 setPreferredSize(new Dimension(100, 30)); 191 192 addMouseListener(new MouseAdapter() { 193 public void mousePressed (MouseEvent event) { 194 dragIndex = -1; 195 int mouseX = event.getX(); 196 int mouseY = event.getY(); 197 int y = gradientY + gradientHeight; 198 for (int i = 0, n = colors.size(); i < n; i++) { 199 int x = gradientX + (int)(percentages.get(i) * gradientWidth) - handleWidth / 2; 200 if (mouseX >= x && mouseX <= x + handleWidth && mouseY >= gradientY && mouseY <= y + handleHeight) { 201 dragIndex = selectedIndex = i; 202 handleSelected(colors.get(selectedIndex)); 203 repaint(); 204 break; 205 } 206 } 207 } 208 209 public void mouseReleased (MouseEvent event) { 210 if (dragIndex != -1) { 211 dragIndex = -1; 212 repaint(); 213 } 214 } 215 216 public void mouseClicked (MouseEvent event) { 217 int mouseX = event.getX(); 218 int mouseY = event.getY(); 219 if (event.getClickCount() == 2) { 220 if (percentages.size() <= 1) return; 221 if (selectedIndex == -1 || selectedIndex == 0) return; 222 int y = gradientY + gradientHeight; 223 int x = gradientX + (int)(percentages.get(selectedIndex) * gradientWidth) - handleWidth / 2; 224 if (mouseX >= x && mouseX <= x + handleWidth && mouseY >= gradientY && mouseY <= y + handleHeight) { 225 percentages.remove(selectedIndex); 226 colors.remove(selectedIndex); 227 selectedIndex--; 228 dragIndex = selectedIndex; 229 if (percentages.size() == 2) percentages.set(1, 1f); 230 handleSelected(colors.get(selectedIndex)); 231 repaint(); 232 } 233 return; 234 } 235 if (mouseX < gradientX || mouseX > gradientX + gradientWidth) return; 236 if (mouseY < gradientY || mouseY > gradientY + gradientHeight) return; 237 float percent = (event.getX() - gradientX) / (float)gradientWidth; 238 if (percentages.size() == 1) percent = 1f; 239 for (int i = 0, n = percentages.size(); i <= n; i++) { 240 if (i == n || percent < percentages.get(i)) { 241 percentages.add(i, percent); 242 colors.add(i, colors.get(i - 1)); 243 dragIndex = selectedIndex = i; 244 handleSelected(colors.get(selectedIndex)); 245 repaint(); 246 break; 247 } 248 } 249 } 250 }); 251 addMouseMotionListener(new MouseMotionAdapter() { 252 public void mouseDragged (MouseEvent event) { 253 if (dragIndex == -1 || dragIndex == 0 || dragIndex == percentages.size() - 1) return; 254 float percent = (event.getX() - gradientX) / (float)gradientWidth; 255 percent = Math.max(percent, percentages.get(dragIndex - 1) + 0.01f); 256 percent = Math.min(percent, percentages.get(dragIndex + 1) - 0.01f); 257 percentages.set(dragIndex, percent); 258 repaint(); 259 } 260 }); 261 } 262 263 public void setColor (Color color) { 264 if (selectedIndex == -1) return; 265 colors.set(selectedIndex, color); 266 repaint(); 267 } 268 269 public void handleSelected (Color color) { 270 } 271 272 protected void paintComponent (Graphics graphics) { 273 super.paintComponent(graphics); 274 Graphics2D g = (Graphics2D)graphics; 275 int width = getWidth() - 1; 276 int height = getHeight(); 277 278 gradientWidth = width - handleWidth; 279 gradientHeight = height - 16; 280 281 g.translate(gradientX, gradientY); 282 for (int i = 0, n = colors.size() == 1 ? 1 : colors.size() - 1; i < n; i++) { 283 Color color1 = colors.get(i); 284 Color color2 = colors.size() == 1 ? color1 : colors.get(i + 1); 285 float percent1 = percentages.get(i); 286 float percent2 = colors.size() == 1 ? 1 : percentages.get(i + 1); 287 int point1 = (int)(percent1 * gradientWidth); 288 int point2 = (int)Math.ceil(percent2 * gradientWidth); 289 g.setPaint(new GradientPaint(point1, 0, color1, point2, 0, color2, false)); 290 g.fillRect(point1, 0, point2 - point1, gradientHeight); 291 } 292 g.setPaint(null); 293 g.setColor(Color.black); 294 g.drawRect(0, 0, gradientWidth, gradientHeight); 295 296 int y = gradientHeight; 297 int[] yPoints = new int[3]; 298 yPoints[0] = y; 299 yPoints[1] = y + handleHeight; 300 yPoints[2] = y + handleHeight; 301 int[] xPoints = new int[3]; 302 for (int i = 0, n = colors.size(); i < n; i++) { 303 int x = (int)(percentages.get(i) * gradientWidth); 304 xPoints[0] = x; 305 xPoints[1] = x - handleWidth / 2; 306 xPoints[2] = x + handleWidth / 2; 307 if (i == selectedIndex) { 308 g.setColor(colors.get(i)); 309 g.fillPolygon(xPoints, yPoints, 3); 310 g.fillRect(xPoints[1], yPoints[1] + 2, handleWidth + 1, 2); 311 g.setColor(Color.black); 312 } 313 g.drawPolygon(xPoints, yPoints, 3); 314 } 315 g.translate(-gradientX, -gradientY); 316 } 317 } 318 319 static public class ColorSlider extends JPanel { 320 Color[] paletteColors; 321 JSlider slider; 322 private ColorPicker colorPicker; 323 324 public ColorSlider (Color[] paletteColors) { 325 this.paletteColors = paletteColors; 326 setLayout(new GridBagLayout()); 327 { 328 slider = new JSlider(0, 1000, 0); 329 slider.setPaintTrack(false); 330 add(slider, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 331 new Insets(0, 6, 0, 6), 0, 0)); 332 } 333 { 334 colorPicker = new ColorPicker(); 335 add(colorPicker, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, 336 GridBagConstraints.HORIZONTAL, new Insets(0, 6, 0, 6), 0, 0)); 337 } 338 339 slider.addChangeListener(new ChangeListener() { 340 public void stateChanged (ChangeEvent event) { 341 colorPicked(); 342 } 343 }); 344 } 345 346 public Dimension getPreferredSize () { 347 Dimension size = super.getPreferredSize(); 348 size.width = 10; 349 return size; 350 } 351 352 public void setPercentage (float percent) { 353 slider.setValue((int)(1000 * percent)); 354 } 355 356 public float getPercentage () { 357 return slider.getValue() / 1000f; 358 } 359 360 protected void colorPicked () { 361 } 362 363 public void setColors (Color[] colors) { 364 paletteColors = colors; 365 repaint(); 366 } 367 368 public class ColorPicker extends JPanel { 369 public ColorPicker () { 370 addMouseListener(new MouseAdapter() { 371 public void mouseClicked (MouseEvent event) { 372 slider.setValue((int)(event.getX() / (float)getWidth() * 1000)); 373 } 374 }); 375 } 376 377 protected void paintComponent (Graphics graphics) { 378 Graphics2D g = (Graphics2D)graphics; 379 int width = getWidth() - 1; 380 int height = getHeight() - 1; 381 for (int i = 0, n = paletteColors.length - 1; i < n; i++) { 382 Color color1 = paletteColors[i]; 383 Color color2 = paletteColors[i + 1]; 384 float point1 = i / (float)n * width; 385 float point2 = (i + 1) / (float)n * width; 386 g.setPaint(new GradientPaint(point1, 0, color1, point2, 0, color2, false)); 387 g.fillRect((int)point1, 0, (int)Math.ceil(point2 - point1), height); 388 } 389 g.setPaint(null); 390 g.setColor(Color.black); 391 g.drawRect(0, 0, width, height); 392 } 393 } 394 } 395} 396