1 /* 2 * 3 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * - Neither the name of Oracle nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package java2d; 33 34 35 import static java.awt.Color.BLACK; 36 import static java.awt.Color.GREEN; 37 import static java.awt.Color.LIGHT_GRAY; 38 import static java.awt.Color.WHITE; 39 import java.awt.BorderLayout; 40 import java.awt.Color; 41 import java.awt.Component; 42 import java.awt.Dimension; 43 import java.awt.FlowLayout; 44 import java.awt.Font; 45 import java.awt.Graphics; 46 import java.awt.Image; 47 import java.awt.Insets; 48 import java.awt.RenderingHints; 49 import java.awt.event.ActionEvent; 50 import java.awt.event.ActionListener; 51 import java.awt.event.MouseAdapter; 52 import java.awt.event.MouseEvent; 53 import java.awt.print.PrinterJob; 54 import java.text.DecimalFormat; 55 import java.util.logging.Level; 56 import java.util.logging.Logger; 57 import javax.print.attribute.HashPrintRequestAttributeSet; 58 import javax.print.attribute.PrintRequestAttributeSet; 59 import javax.swing.Icon; 60 import javax.swing.ImageIcon; 61 import javax.swing.JButton; 62 import javax.swing.JComboBox; 63 import javax.swing.JLabel; 64 import javax.swing.JOptionPane; 65 import javax.swing.JPanel; 66 import javax.swing.JSlider; 67 import javax.swing.JToggleButton; 68 import javax.swing.JToolBar; 69 import javax.swing.SwingConstants; 70 import javax.swing.border.EtchedBorder; 71 import javax.swing.event.ChangeEvent; 72 import javax.swing.event.ChangeListener; 73 74 75 /** 76 * Tools to control individual demo graphic attributes. Also, control for 77 * start & stop on animated demos; control for cloning the demo; control for 78 * printing the demo. Expand and collapse the Tools panel with ToggleIcon. 79 */ 80 @SuppressWarnings("serial") 81 public final class Tools extends JPanel implements ActionListener, 82 ChangeListener, Runnable { 83 private final DemoInstVarsAccessor demoInstVars; 84 private ImageIcon stopIcon, startIcon; 85 private Font font = new Font(Font.SERIF, Font.PLAIN, 10); 86 private Color roColor = new Color(187, 213, 238); 87 private Surface surface; 88 private Thread thread; 89 private JPanel toolbarPanel; 90 private JPanel sliderPanel; 91 private JLabel label; 92 private ToggleIcon bumpyIcon, rolloverIcon; 93 private DecimalFormat decimalFormat = new DecimalFormat("000"); 94 protected boolean focus; 95 public JToggleButton toggleB; 96 public JButton printB; 97 public JComboBox<String> screenCombo; 98 public JToggleButton renderB, aliasB; 99 public JToggleButton textureB, compositeB; 100 public JButton startStopB; 101 public JButton cloneB; 102 public boolean issueRepaint = true; 103 public JToolBar toolbar; 104 public JSlider slider; 105 public boolean doSlider; 106 public boolean isExpanded; 107 108 @SuppressWarnings("LeakingThisInConstructor") 109 public Tools(Surface surface, DemoInstVarsAccessor demoInstVars) { 110 this.surface = surface; 111 this.demoInstVars = demoInstVars; 112 113 setLayout(new BorderLayout()); 114 115 stopIcon = new ImageIcon(DemoImages.getImage("stop.gif", this)); 116 startIcon = new ImageIcon(DemoImages.getImage("start.gif", this)); 117 bumpyIcon = new ToggleIcon(this, LIGHT_GRAY); 118 rolloverIcon = new ToggleIcon(this, roColor); 119 toggleB = new JToggleButton(bumpyIcon); 120 toggleB.addMouseListener(new MouseAdapter() { 121 122 @Override 123 public void mouseEntered(MouseEvent e) { 124 focus = true; 125 bumpyIcon.start(); 126 } 127 128 @Override 129 public void mouseExited(MouseEvent e) { 130 focus = false; 131 bumpyIcon.stop(); 132 } 133 }); 134 isExpanded = false; 135 toggleB.addActionListener(this); 136 toggleB.setMargin(new Insets(0, 0, -4, 0)); 137 toggleB.setBorderPainted(false); 138 toggleB.setFocusPainted(false); 139 toggleB.setContentAreaFilled(false); 140 toggleB.setRolloverIcon(rolloverIcon); 141 add("North", toggleB); 142 143 toolbar = new JToolBar(); 144 toolbar.setPreferredSize(new Dimension(5*25, 26)); 145 toolbar.setFloatable(false); 146 147 String s = surface.AntiAlias == RenderingHints.VALUE_ANTIALIAS_ON 148 ? "On" : "Off"; 149 aliasB = addTool("A", "Antialiasing " + s, this); 150 151 s = surface.Rendering == RenderingHints.VALUE_RENDER_SPEED 152 ? "Speed" : "Quality"; 153 renderB = addTool("R", "Rendering " + s, this); 154 155 s = surface.texture != null ? "On" : "Off"; 156 textureB = addTool("T", "Texture " + s, this); 157 158 s = surface.composite != null ? "On" : "Off"; 159 compositeB = addTool("C", "Composite " + s, this); 160 161 Image printBImg = DemoImages.getImage("print.gif", this); 162 printB = addTool(printBImg, "Print the Surface", this); 163 164 if (surface instanceof AnimatingSurface) { 165 Image stopImg = DemoImages.getImage("stop.gif", this); 166 startStopB = addTool(stopImg, "Stop Animation", this); 167 toolbar.setPreferredSize(new Dimension(6*25, 26)); 168 } 169 170 screenCombo = new JComboBox<>(); 171 screenCombo.setPreferredSize(new Dimension(100, 18)); 172 screenCombo.setFont(font); 173 for (String name : GlobalControls.screenNames) { 174 screenCombo.addItem(name); 175 } 176 screenCombo.addActionListener(this); 177 toolbarPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); 178 toolbarPanel.setLocation(0, 6); 179 toolbarPanel.setVisible(false); 180 toolbarPanel.add(toolbar); 181 toolbarPanel.add(screenCombo); 182 toolbarPanel.setBorder(new EtchedBorder()); 183 add(toolbarPanel); 184 185 setPreferredSize(new Dimension(200, 8)); 186 187 if (surface instanceof AnimatingSurface) { 188 sliderPanel = new JPanel(new BorderLayout()); 189 label = new JLabel(" Sleep = 030 ms"); 190 label.setForeground(BLACK); 191 sliderPanel.add(label, BorderLayout.WEST); 192 slider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 30); 193 slider.addChangeListener(this); 194 sliderPanel.setBorder(new EtchedBorder()); 195 sliderPanel.add(slider); 196 197 addMouseListener(new MouseAdapter() { 198 199 @Override 200 public void mouseClicked(MouseEvent e) { 201 if (toolbarPanel.isVisible()) { 202 invalidate(); 203 if ((doSlider = !doSlider)) { 204 remove(toolbarPanel); 205 add(sliderPanel); 206 } else { 207 remove(sliderPanel); 208 add(toolbarPanel); 209 } 210 validate(); 211 repaint(); 212 } 213 } 214 }); 215 } 216 } 217 218 public JButton addTool(Image img, 219 String toolTip, 220 ActionListener al) { 221 JButton b = new JButton(new ImageIcon(img)) { 222 223 Dimension prefSize = new Dimension(25, 22); 224 225 @Override 226 public Dimension getPreferredSize() { 227 return prefSize; 228 } 229 230 @Override 231 public Dimension getMaximumSize() { 232 return prefSize; 233 } 234 235 @Override 236 public Dimension getMinimumSize() { 237 return prefSize; 238 } 239 }; 240 toolbar.add(b); 241 b.setFocusPainted(false); 242 b.setSelected(true); 243 b.setToolTipText(toolTip); 244 b.addActionListener(al); 245 return b; 246 } 247 248 public JToggleButton addTool(String name, 249 String toolTip, 250 ActionListener al) { 251 JToggleButton b = new JToggleButton(name) { 252 253 Dimension prefSize = new Dimension(25, 22); 254 255 @Override 256 public Dimension getPreferredSize() { 257 return prefSize; 258 } 259 260 @Override 261 public Dimension getMaximumSize() { 262 return prefSize; 263 } 264 265 @Override 266 public Dimension getMinimumSize() { 267 return prefSize; 268 } 269 }; 270 toolbar.add(b); 271 b.setFocusPainted(false); 272 if (toolTip.equals("Rendering Quality") || toolTip.equals( 273 "Antialiasing On") || toolTip.equals("Texture On") || toolTip. 274 equals("Composite On")) { 275 b.setSelected(true); 276 } else { 277 b.setSelected(false); 278 } 279 b.setToolTipText(toolTip); 280 b.addActionListener(al); 281 return b; 282 } 283 284 @Override 285 public void actionPerformed(ActionEvent e) { 286 Object obj = e.getSource(); 287 if (obj instanceof JButton) { 288 JButton b = (JButton) obj; 289 b.setSelected(!b.isSelected()); 290 if (b.getIcon() == null) { 291 b.setBackground(b.isSelected() ? GREEN : LIGHT_GRAY); 292 } 293 } 294 if (obj.equals(toggleB)) { 295 isExpanded = !isExpanded; 296 if (isExpanded) { 297 setPreferredSize(new Dimension(200, 38)); 298 } else { 299 setPreferredSize(new Dimension(200, 6)); 300 } 301 toolbarPanel.setVisible(isExpanded); 302 if (sliderPanel != null) { 303 sliderPanel.setVisible(isExpanded); 304 } 305 getParent().validate(); 306 toggleB.getModel().setRollover(false); 307 return; 308 } 309 if (obj.equals(printB)) { 310 start(); 311 return; 312 } 313 314 if (obj.equals(startStopB)) { 315 if (startStopB.getToolTipText().equals("Stop Animation")) { 316 startStopB.setIcon(startIcon); 317 startStopB.setToolTipText("Start Animation"); 318 surface.animating.stop(); 319 } else { 320 startStopB.setIcon(stopIcon); 321 startStopB.setToolTipText("Stop Animation"); 322 surface.animating.start(); 323 } 324 } else if (obj.equals(aliasB)) { 325 if (aliasB.getToolTipText().equals("Antialiasing On")) { 326 aliasB.setToolTipText("Antialiasing Off"); 327 } else { 328 aliasB.setToolTipText("Antialiasing On"); 329 } 330 surface.setAntiAlias(aliasB.isSelected()); 331 } else if (obj.equals(renderB)) { 332 if (renderB.getToolTipText().equals("Rendering Quality")) { 333 renderB.setToolTipText("Rendering Speed"); 334 } else { 335 renderB.setToolTipText("Rendering Quality"); 336 } 337 surface.setRendering(renderB.isSelected()); 338 } else if (obj.equals(textureB)) { 339 if (textureB.getToolTipText().equals("Texture On")) { 340 textureB.setToolTipText("Texture Off"); 341 surface.setTexture(null); 342 surface.clearSurface = true; 343 } else { 344 textureB.setToolTipText("Texture On"); 345 surface.setTexture(demoInstVars.getControls().texturechooser.texture); 346 } 347 } else if (obj.equals(compositeB)) { 348 if (compositeB.getToolTipText().equals("Composite On")) { 349 compositeB.setToolTipText("Composite Off"); 350 } else { 351 compositeB.setToolTipText("Composite On"); 352 } 353 surface.setComposite(compositeB.isSelected()); 354 } else if (obj.equals(screenCombo)) { 355 surface.setImageType(screenCombo.getSelectedIndex()); 356 } 357 358 if (issueRepaint && surface.animating != null) { 359 if (surface.getSleepAmount() != 0) { 360 if (surface.animating.running()) { 361 surface.animating.doRepaint(); 362 } 363 } 364 } else if (issueRepaint) { 365 surface.repaint(); 366 } 367 } 368 369 @Override 370 public void stateChanged(ChangeEvent e) { 371 int value = slider.getValue(); 372 label.setText(" Sleep = " + decimalFormat.format(value) + " ms"); 373 label.repaint(); 374 surface.setSleepAmount(value); 375 } 376 377 public void start() { 378 thread = new Thread(this); 379 thread.setPriority(Thread.MAX_PRIORITY); 380 thread.setName("Printing " + surface.name); 381 thread.start(); 382 } 383 384 public synchronized void stop() { 385 thread = null; 386 notifyAll(); 387 } 388 389 @Override 390 public void run() { 391 boolean stopped = false; 392 if (surface.animating != null && surface.animating.running()) { 393 stopped = true; 394 startStopB.doClick(); 395 } 396 397 try { 398 PrinterJob printJob = PrinterJob.getPrinterJob(); 399 printJob.setPrintable(surface); 400 boolean pDialogState = true; 401 PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); 402 403 if (!demoInstVars.getPrintCB().isSelected()) { 404 pDialogState = printJob.printDialog(aset); 405 } 406 if (pDialogState) { 407 printJob.print(aset); 408 } 409 } catch (java.security.AccessControlException ace) { 410 String errmsg = "Applet access control exception; to allow " 411 + "access to printer, set\n" 412 + "permission for \"queuePrintJob\" in " 413 + "RuntimePermission."; 414 JOptionPane.showMessageDialog(this, errmsg, "Printer Access Error", 415 JOptionPane.ERROR_MESSAGE); 416 } catch (Exception ex) { 417 Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, 418 null, ex); 419 } 420 421 if (stopped) { 422 startStopB.doClick(); 423 } 424 thread = null; 425 } 426 427 428 /** 429 * Expand and Collapse the Tools Panel with this bumpy button. 430 */ 431 static class ToggleIcon implements Icon, Runnable { 432 433 private Color shadowColor = new Color(102, 102, 153); 434 private Color fillColor; 435 private Tools tools; 436 private Thread thread; 437 438 public ToggleIcon(Tools tools, Color fillColor) { 439 this.tools = tools; 440 this.fillColor = fillColor; 441 } 442 443 @Override 444 public void paintIcon(Component c, Graphics g, int x, int y) { 445 int w = getIconWidth(); 446 int h = getIconHeight(); 447 g.setColor(fillColor); 448 g.fillRect(0, 0, w, h); 449 for (; x < w - 2; x += 4) { 450 g.setColor(WHITE); 451 g.fillRect(x, 1, 1, 1); 452 g.fillRect(x + 2, 3, 1, 1); 453 g.setColor(shadowColor); 454 g.fillRect(x + 1, 2, 1, 1); 455 g.fillRect(x + 3, 4, 1, 1); 456 } 457 } 458 459 @Override 460 public int getIconWidth() { 461 return tools.getSize().width; 462 } 463 464 @Override 465 public int getIconHeight() { 466 return 6; 467 } 468 469 public void start() { 470 thread = new Thread(this); 471 thread.setPriority(Thread.MIN_PRIORITY); 472 thread.setName("ToggleIcon"); 473 thread.start(); 474 } 475 476 public synchronized void stop() { 477 if (thread != null) { 478 thread.interrupt(); 479 } 480 thread = null; 481 } 482 483 @Override 484 public void run() { 485 try { 486 Thread.sleep(400); 487 } catch (InterruptedException e) { 488 } 489 if (tools.focus && thread != null) { 490 tools.toggleB.doClick(); 491 } 492 thread = null; 493 } 494 } 495 } // End Tools class 496