1/*
2 * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 *   - Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 *
11 *   - Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 *   - Neither the name of Oracle nor the names of its
16 *     contributors may be used to endorse or promote products derived
17 *     from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * This source code is provided to illustrate the usage of a given feature
34 * or technique and has been deliberately simplified. Additional steps
35 * required for a production-quality application, such as security checks,
36 * input validation and proper error handling, might not be present in
37 * this sample code.
38 */
39
40
41package j2dbench;
42
43import java.io.PrintWriter;
44import javax.swing.BoxLayout;
45import javax.swing.JComponent;
46import javax.swing.JPanel;
47import javax.swing.JScrollPane;
48import javax.swing.JTabbedPane;
49import javax.swing.border.TitledBorder;
50import java.util.NoSuchElementException;
51
52import j2dbench.ui.CompactLayout;
53import j2dbench.ui.EnableButton;
54
55public class Group extends Node {
56    public static Group root = new Group();
57
58    private Node children;
59    private boolean tabbed;
60    private boolean hidden;
61    private boolean horizontal;
62    private Boolean bordered;
63    private int tabPlacement;
64
65    private Group() {
66        setTabbed(JTabbedPane.LEFT);
67    }
68
69    public Group(String nodeName, String description) {
70        this(root, nodeName, description);
71    }
72
73    public Group(Group parent, String nodeName, String description) {
74        super(parent, nodeName, description);
75    }
76
77    public void addChild(Node child) {
78        Node prev = null;
79        for (Node node = children; node != null; node = node.getNext()) {
80            if (node.getNodeName().equalsIgnoreCase(child.getNodeName())) {
81                throw new RuntimeException("duplicate child added");
82            }
83            prev = node;
84        }
85        if (prev == null) {
86            children = child;
87        } else {
88            prev.setNext(child);
89        }
90    }
91
92    public Node.Iterator getChildIterator() {
93        return new ChildIterator();
94    }
95
96    public Node.Iterator getRecursiveChildIterator() {
97        return new RecursiveChildIterator();
98    }
99
100    public Node getFirstChild() {
101        return children;
102    }
103
104    public boolean isBordered() {
105        if (bordered == null) {
106            return (getParent() == null || !getParent().isTabbed());
107        }
108        return bordered.booleanValue();
109    }
110
111    public boolean isTabbed() {
112        return tabbed;
113    }
114
115    public boolean isHidden() {
116        return hidden;
117    }
118
119    public boolean isHorizontal() {
120        return horizontal;
121    }
122
123    public void setBordered(boolean b) {
124        bordered = b ? Boolean.TRUE : Boolean.FALSE;
125    }
126
127    public void setTabbed() {
128        setTabbed(JTabbedPane.TOP);
129    }
130
131    public void setTabbed(int tabPlacement) {
132        this.tabbed = true;
133        this.tabPlacement = tabPlacement;
134    }
135
136    public void setHidden() {
137        hidden = true;
138    }
139
140    public void setHorizontal() {
141        horizontal = true;
142    }
143
144    public void traverse(Visitor v) {
145        super.traverse(v);
146        for (Node node = children; node != null; node = node.getNext()) {
147            node.traverse(v);
148        }
149    }
150
151    public void restoreDefault() {
152    }
153
154    public String setOption(String key, String value) {
155        int index = key.indexOf('.');
156        String subkey;
157        if (index < 0) {
158            subkey = "";
159        } else {
160            subkey = key.substring(index+1);
161            key = key.substring(0, index);
162        }
163        for (Node node = children; node != null; node = node.getNext()) {
164            if (node.getNodeName().equalsIgnoreCase(key)) {
165                return node.setOption(subkey, value);
166            }
167        }
168        return "Key failed to match an existing option";
169    }
170
171    public void write(PrintWriter pw) {
172    }
173
174    public JComponent getJComponent() {
175        if (isHidden()) {
176            return null;
177        } else if (isTabbed()) {
178            JTabbedPane jtp = new JTabbedPane(tabPlacement);
179            for (Node node = children; node != null; node = node.getNext()) {
180                JComponent comp = node.getJComponent();
181                if (comp != null) {
182                    jtp.addTab(node.getDescription(), comp);
183                }
184            }
185            return jtp;
186        } else {
187            JPanel p = new JPanel();
188            p.setLayout(new BoxLayout(p,
189                                      horizontal
190                                      ? BoxLayout.X_AXIS
191                                      : BoxLayout.Y_AXIS));
192            p.setLayout(new CompactLayout(horizontal));
193            if (getDescription() != null && isBordered()) {
194                p.setBorder(new TitledBorder(getDescription()));
195                addEnableButtons(p);
196            }
197            for (Node node = children; node != null; node = node.getNext()) {
198                JComponent comp = node.getJComponent();
199                if (comp != null) {
200                    p.add(comp);
201                }
202            }
203            return new JScrollPane(p);
204        }
205    }
206
207    public void addEnableButtons(JPanel p) {
208        p.add(new EnableButton(this, EnableButton.DEFAULT));
209        p.add(new EnableButton(this, EnableButton.CLEAR));
210        p.add(new EnableButton(this, EnableButton.INVERT));
211        p.add(new EnableButton(this, EnableButton.SET));
212    }
213
214    public static void restoreAllDefaults() {
215        root.traverse(new Visitor() {
216            public void visit(Node node) {
217                node.restoreDefault();
218            }
219        });
220    }
221
222    public static void writeAll(final PrintWriter pw) {
223        root.traverse(new Visitor() {
224            public void visit(Node node) {
225                node.write(pw);
226            }
227        });
228        pw.flush();
229    }
230
231    public static String setOption(String s) {
232        int index = s.indexOf('=');
233        if (index < 0) {
234            return "No value specified";
235        }
236        String key = s.substring(0, index);
237        String value = s.substring(index+1);
238        return root.setOption(key, value);
239    }
240
241    public String toString() {
242        return "Group("+getTreeName()+")";
243    }
244
245    public class ChildIterator implements Node.Iterator {
246        protected Node cur = getFirstChild();
247
248        public boolean hasNext() {
249            return (cur != null);
250        }
251
252        public Node next() {
253            Node ret = cur;
254            if (ret == null) {
255                throw new NoSuchElementException();
256            }
257            cur = cur.getNext();
258            return ret;
259        }
260    }
261
262    public class RecursiveChildIterator extends ChildIterator {
263        Node.Iterator subiterator;
264
265        public boolean hasNext() {
266            while (true) {
267                if (subiterator != null && subiterator.hasNext()) {
268                    return true;
269                }
270                if (cur instanceof Group) {
271                    subiterator = ((Group) cur).getRecursiveChildIterator();
272                    cur = cur.getNext();
273                } else {
274                    subiterator = null;
275                    return super.hasNext();
276                }
277            }
278        }
279
280        public Node next() {
281            if (subiterator != null) {
282                return subiterator.next();
283            } else {
284                return super.next();
285            }
286        }
287    }
288
289    public static class EnableSet extends Group implements Modifier {
290        public EnableSet() {
291            super();
292        }
293
294        public EnableSet(Group parent, String nodeName, String description) {
295            super(parent, nodeName, description);
296        }
297
298        public Modifier.Iterator getIterator(TestEnvironment env) {
299            return new EnableIterator();
300        }
301
302        public void modifyTest(TestEnvironment env, Object val) {
303            ((Option.Enable) val).modifyTest(env);
304            env.setModifier(this, val);
305        }
306
307        public void restoreTest(TestEnvironment env, Object val) {
308            ((Option.Enable) val).restoreTest(env);
309            env.removeModifier(this);
310        }
311
312        public String getAbbreviatedModifierDescription(Object val) {
313            Option.Enable oe = (Option.Enable) val;
314            return oe.getAbbreviatedModifierDescription(Boolean.TRUE);
315        }
316
317        public String getModifierValueName(Object val) {
318            Option.Enable oe = (Option.Enable) val;
319            return oe.getModifierValueName(Boolean.TRUE);
320        }
321
322        public class EnableIterator implements Modifier.Iterator {
323            Node.Iterator childiterator = getRecursiveChildIterator();
324            Option.Enable curval;
325
326            public boolean hasNext() {
327                if (curval != null) {
328                    return true;
329                }
330                while (childiterator.hasNext()) {
331                    Node node = childiterator.next();
332                    if (node instanceof Option.Enable) {
333                        curval = (Option.Enable) node;
334                        if (curval.isEnabled()) {
335                            return true;
336                        }
337                        curval = null;
338                    }
339                }
340                return false;
341            }
342
343            public Object next() {
344                if (curval == null) {
345                    if (!hasNext()) {
346                        throw new NoSuchElementException();
347                    }
348                }
349                Object ret = curval;
350                curval = null;
351                return ret;
352            }
353        }
354    }
355}
356