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 java.awt.BorderLayout;
  36 import java.awt.Component;
  37 import java.awt.Dimension;
  38 import java.awt.Font;
  39 import java.awt.GridBagLayout;
  40 import java.awt.GridLayout;
  41 import java.awt.Image;
  42 import java.awt.event.ActionEvent;
  43 import java.awt.event.ActionListener;
  44 import java.awt.event.MouseAdapter;
  45 import java.awt.event.MouseEvent;
  46 import java.awt.event.WindowAdapter;
  47 import java.awt.event.WindowEvent;
  48 import javax.swing.JButton;
  49 import javax.swing.JCheckBox;
  50 import javax.swing.JCheckBoxMenuItem;
  51 import javax.swing.JFrame;
  52 import javax.swing.JPanel;
  53 import javax.swing.JTabbedPane;
  54 import javax.swing.JToggleButton;
  55 import javax.swing.border.BevelBorder;
  56 import javax.swing.border.CompoundBorder;
  57 import javax.swing.border.EmptyBorder;
  58 import javax.swing.border.SoftBevelBorder;
  59 import javax.swing.event.ChangeEvent;
  60 import javax.swing.event.ChangeListener;
  61 
  62 
  63 /**
  64  * DemoGroup handles multiple demos inside of a panel.  Demos are loaded
  65  * from the demos[][] string as listed in J2Ddemo.java.
  66  * Demo groups can be loaded individually, for example :
  67  *      java DemoGroup Fonts
  68  * Loads all the demos found in the demos/Fonts directory.
  69  */
  70 @SuppressWarnings("serial")
  71 public class DemoGroup extends JPanel
  72         implements ChangeListener, ActionListener {
  73     private final DemoInstVarsAccessor demoInstVars;
  74     public int columns = 2;
  75     private static final Font font = new Font(Font.SERIF, Font.PLAIN, 10);
  76     private final EmptyBorder emptyB = new EmptyBorder(5, 5, 5, 5);
  77     private final BevelBorder bevelB = new BevelBorder(BevelBorder.LOWERED);
  78     private String groupName;
  79     public JPanel clonePanels[];
  80     public JTabbedPane tabbedPane;
  81 
  82     public DemoGroup(String name, DemoInstVarsAccessor demoInstVars) {
  83 
  84         groupName = name;
  85         this.demoInstVars = demoInstVars;
  86 
  87         setLayout(new BorderLayout());
  88 
  89         JPanel p = new JPanel(new GridLayout(0, 2));
  90         p.setBorder(new CompoundBorder(emptyB, bevelB));
  91 
  92         // Find the named demo group in J2Ddemo.demos[].
  93         int ind = -1;
  94         while (!name.equals(J2Ddemo.demos[++ind][0])) {
  95         }
  96         String[] demos = J2Ddemo.demos[ind];
  97 
  98         // If there are an odd number of demos, use GridBagLayout.
  99         // Note that we don't use the first entry.
 100         int numDemos = demos.length - 1;
 101         if (numDemos % 2 == 1) {
 102             p.setLayout(new GridBagLayout());
 103         }
 104 
 105         MouseAdapter mouseListener = new MouseAdapter() {
 106 
 107             @Override
 108             public void mouseClicked(MouseEvent e) {
 109                 DemoGroup.this.mouseClicked(e.getComponent());
 110             }
 111         };
 112 
 113         // For each demo in the group, prepare a DemoPanel.
 114         for (int i = 1; i <= numDemos; i++) {
 115             DemoPanel dp =
 116                     new DemoPanel("java2d.demos." + name + "." + demos[i], demoInstVars);
 117             dp.setDemoBorder(p);
 118             if (dp.surface != null) {
 119                 dp.surface.addMouseListener(mouseListener);
 120                 dp.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null);
 121             }
 122             if (p.getLayout() instanceof GridBagLayout) {
 123                 int x = p.getComponentCount() % 2;
 124                 int y = p.getComponentCount() / 2;
 125                 int w = (i == numDemos) ? 2 : 1;
 126                 J2Ddemo.addToGridBag(p, dp, x, y, w, 1, 1, 1);
 127             } else {
 128                 p.add(dp);
 129             }
 130         }
 131 
 132         add(p);
 133     }
 134 
 135     public void mouseClicked(Component component) {
 136         String className = component.toString();
 137 
 138         if (tabbedPane == null) {
 139             shutDown(getPanel());
 140             JPanel p = new JPanel(new BorderLayout());
 141             p.setBorder(new CompoundBorder(emptyB, bevelB));
 142 
 143             tabbedPane = new JTabbedPane();
 144             tabbedPane.setFont(font);
 145 
 146             JPanel tmpP = (JPanel) getComponent(0);
 147             tabbedPane.addTab(groupName, tmpP);
 148 
 149             clonePanels = new JPanel[tmpP.getComponentCount()];
 150             for (int i = 0; i < clonePanels.length; i++) {
 151                 clonePanels[i] = new JPanel(new BorderLayout());
 152                 DemoPanel dp = (DemoPanel) tmpP.getComponent(i);
 153                 DemoPanel c = new DemoPanel(dp.className, demoInstVars);
 154                 c.setDemoBorder(clonePanels[i]);
 155                 if (c.surface != null) {
 156                     c.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null);
 157                     Image cloneImg = DemoImages.getImage("clone.gif", this);
 158                     c.tools.cloneB = c.tools.addTool(cloneImg,
 159                             "Clone the Surface", this);
 160                     Dimension d = c.tools.toolbar.getPreferredSize();
 161                     c.tools.toolbar.setPreferredSize(
 162                             new Dimension(d.width + 27, d.height));
 163                     if (demoInstVars.getBackgroundColor() != null) {
 164                         c.surface.setBackground(demoInstVars.getBackgroundColor());
 165                     }
 166                 }
 167                 clonePanels[i].add(c);
 168                 String s = dp.className.substring(dp.className.indexOf('.') + 1);
 169                 tabbedPane.addTab(s, clonePanels[i]);
 170             }
 171             p.add(tabbedPane);
 172             remove(tmpP);
 173             add(p);
 174 
 175             tabbedPane.addChangeListener(this);
 176             revalidate();
 177         }
 178 
 179         className = className.substring(0, className.indexOf('['));
 180 
 181         for (int i = 0; i < tabbedPane.getTabCount(); i++) {
 182             String s1 = className.substring(className.indexOf('.') + 1);
 183             if (tabbedPane.getTitleAt(i).equals(s1)) {
 184                 tabbedPane.setSelectedIndex(i);
 185                 break;
 186             }
 187         }
 188 
 189         revalidate();
 190     }
 191 
 192     @Override
 193     public void actionPerformed(ActionEvent e) {
 194         JButton b = (JButton) e.getSource();
 195         if (b.getToolTipText().startsWith("Clone")) {
 196             cloneDemo();
 197         } else {
 198             removeClone(b.getParent().getParent().getParent().getParent());
 199         }
 200     }
 201     private int index;
 202 
 203     @Override
 204     public void stateChanged(ChangeEvent e) {
 205         shutDown((JPanel) tabbedPane.getComponentAt(index));
 206         index = tabbedPane.getSelectedIndex();
 207         setup(false);
 208     }
 209 
 210     public JPanel getPanel() {
 211         if (tabbedPane != null) {
 212             return (JPanel) tabbedPane.getSelectedComponent();
 213         } else {
 214             return (JPanel) getComponent(0);
 215         }
 216     }
 217 
 218     public void setup(boolean issueRepaint) {
 219 
 220         JPanel p = getPanel();
 221 
 222         // Let PerformanceMonitor know which demos are running
 223         if (demoInstVars.getPerformanceMonitor() != null) {
 224             demoInstVars.getPerformanceMonitor().surf.setPanel(p);
 225             demoInstVars.getPerformanceMonitor().surf.setSurfaceState();
 226         }
 227 
 228         GlobalControls c = demoInstVars.getControls();
 229         // .. tools check against global controls settings ..
 230         // .. & start demo & custom control thread if need be ..
 231         for (int i = 0; i < p.getComponentCount(); i++) {
 232             DemoPanel dp = (DemoPanel) p.getComponent(i);
 233             if (dp.surface != null && c != null) {
 234                 Tools t = dp.tools;
 235                 t.setVisible(isValid());
 236                 t.issueRepaint = issueRepaint;
 237                 JToggleButton b[] = { t.toggleB, t.aliasB, t.renderB,
 238                     t.textureB, t.compositeB };
 239                 JCheckBox cb[] = { c.toolBarCB, c.aliasCB, c.renderCB,
 240                     c.textureCB, c.compositeCB };
 241                 for (int j = 0; j < b.length; j++) {
 242                     if (c.obj != null && c.obj.equals(cb[j])) {
 243                         if (b[j].isSelected() != cb[j].isSelected()) {
 244                             b[j].doClick();
 245                         }
 246                     } else if (c.obj == null) {
 247                         if (b[j].isSelected() != cb[j].isSelected()) {
 248                             b[j].doClick();
 249                         }
 250                     }
 251                 }
 252                 t.setVisible(true);
 253                 if (c.screenCombo.getSelectedIndex()
 254                         != t.screenCombo.getSelectedIndex()) {
 255                     t.screenCombo.setSelectedIndex(c.screenCombo.
 256                             getSelectedIndex());
 257                 }
 258                 if (demoInstVars.getVerboseCB().isSelected()) {
 259                     dp.surface.verbose(c);
 260                 }
 261                 dp.surface.setSleepAmount(c.slider.getValue());
 262                 if (demoInstVars.getBackgroundColor() != null) {
 263                     dp.surface.setBackground(demoInstVars.getBackgroundColor());
 264                 }
 265                 t.issueRepaint = true;
 266             }
 267             dp.start();
 268         }
 269         revalidate();
 270     }
 271 
 272     public void shutDown(JPanel p) {
 273         for (int i = 0; i < p.getComponentCount(); i++) {
 274             ((DemoPanel) p.getComponent(i)).stop();
 275         }
 276         System.gc();
 277     }
 278 
 279     public void cloneDemo() {
 280         JPanel panel = clonePanels[tabbedPane.getSelectedIndex() - 1];
 281         if (panel.getComponentCount() == 1) {
 282             panel.invalidate();
 283             panel.setLayout(new GridLayout(0, columns, 5, 5));
 284             panel.revalidate();
 285         }
 286         DemoPanel original = (DemoPanel) getPanel().getComponent(0);
 287         DemoPanel clone = new DemoPanel(original.className, demoInstVars);
 288         if (columns == 2) {
 289             clone.setDemoBorder(panel);
 290         }
 291         Image removeImg = DemoImages.getImage("remove.gif", this);
 292         clone.tools.cloneB =
 293                 clone.tools.addTool(removeImg, "Remove the Surface", this);
 294         Dimension d = clone.tools.toolbar.getPreferredSize();
 295         clone.tools.toolbar.setPreferredSize(
 296                 new Dimension(d.width + 27, d.height));
 297         if (demoInstVars.getBackgroundColor() != null) {
 298             clone.surface.setBackground(demoInstVars.getBackgroundColor());
 299         }
 300         if (demoInstVars.getControls() != null) {
 301             if (clone.tools.isExpanded
 302                     != demoInstVars.getControls().toolBarCB.isSelected()) {
 303                 clone.tools.toggleB.doClick();
 304             }
 305         }
 306         clone.start();
 307         clone.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null);
 308         panel.add(clone);
 309         panel.repaint();
 310         panel.revalidate();
 311     }
 312 
 313     public void removeClone(Component theClone) {
 314         JPanel panel = clonePanels[tabbedPane.getSelectedIndex() - 1];
 315         if (panel.getComponentCount() == 2) {
 316             Component cmp = panel.getComponent(0);
 317             panel.removeAll();
 318             panel.setLayout(new BorderLayout());
 319             panel.revalidate();
 320             panel.add(cmp);
 321         } else {
 322             panel.remove(theClone);
 323             int cmpCount = panel.getComponentCount();
 324             for (int j = 1; j < cmpCount; j++) {
 325                 int top = (j + 1 >= 3) ? 0 : 5;
 326                 int left = ((j + 1) % 2) == 0 ? 0 : 5;
 327                 EmptyBorder eb = new EmptyBorder(top, left, 5, 5);
 328                 SoftBevelBorder sbb = new SoftBevelBorder(BevelBorder.RAISED);
 329                 JPanel p = (JPanel) panel.getComponent(j);
 330                 p.setBorder(new CompoundBorder(eb, sbb));
 331             }
 332         }
 333         panel.repaint();
 334         panel.revalidate();
 335     }
 336 
 337     public static void main(String args[]) {
 338         class DemoInstVarsAccessorImpl extends DemoInstVarsAccessorImplBase {
 339             private volatile JCheckBoxMenuItem ccthreadCB;
 340 
 341             public void setCcthreadCB(JCheckBoxMenuItem ccthreadCB) {
 342                 this.ccthreadCB = ccthreadCB;
 343             }
 344 
 345             @Override
 346             public JCheckBoxMenuItem getCcthreadCB() {
 347                 return ccthreadCB;
 348             }
 349         }
 350         DemoInstVarsAccessorImpl demoInstVars = new DemoInstVarsAccessorImpl();
 351         final DemoGroup group = new DemoGroup(args[0], demoInstVars);
 352         JFrame f = new JFrame("Java2D(TM) Demo - DemoGroup");
 353         f.addWindowListener(new WindowAdapter() {
 354 
 355             @Override
 356             public void windowClosing(WindowEvent e) {
 357                 System.exit(0);
 358             }
 359 
 360             @Override
 361             public void windowDeiconified(WindowEvent e) {
 362                 group.setup(false);
 363             }
 364 
 365             @Override
 366             public void windowIconified(WindowEvent e) {
 367                 group.shutDown(group.getPanel());
 368             }
 369         });
 370         f.getContentPane().add("Center", group);
 371         f.pack();
 372         int FRAME_WIDTH = 620;
 373         int FRAME_HEIGHT = 530;
 374         f.setSize(FRAME_WIDTH, FRAME_HEIGHT);
 375         f.setLocationRelativeTo(null);  // centers f on screen
 376         f.setVisible(true);
 377         for (String arg : args) {
 378             if (arg.startsWith("-ccthread")) {
 379                 demoInstVars.setCcthreadCB(new JCheckBoxMenuItem("CCThread", true));
 380             }
 381         }
 382         group.setup(false);
 383     }
 384 }