001 /* 002 * Created on Dec 22, 2007 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2007-2010 the original author or authors. 014 */ 015 package org.fest.swing.core; 016 017 import static org.fest.swing.edt.GuiActionRunner.execute; 018 import static org.fest.swing.format.Formatting.format; 019 import static org.fest.swing.hierarchy.NewHierarchy.ignoreExistingComponents; 020 021 import java.awt.Component; 022 import java.awt.Container; 023 import java.io.PrintStream; 024 025 import org.fest.swing.annotation.RunsInCurrentThread; 026 import org.fest.swing.annotation.RunsInEDT; 027 import org.fest.swing.edt.GuiTask; 028 import org.fest.swing.hierarchy.*; 029 030 /** 031 * Understands printing the <code>String</code> representation of <code>{@link java.awt.Component}</code>s to 032 * facilitate debugging. 033 * 034 * @author Alex Ruiz 035 */ 036 public final class BasicComponentPrinter implements ComponentPrinter { 037 038 private static final String INDENTATION = " "; 039 040 private static final ComponentMatcher ALWAYS_MATCHES = alwaysMatches(); 041 042 private static ComponentMatcher alwaysMatches() { 043 return new ComponentMatcher() { 044 public boolean matches(Component c) { 045 return true; 046 } 047 }; 048 } 049 050 private final ComponentHierarchy hierarchy; 051 052 /** 053 * Creates a new <code>{@link BasicComponentPrinter}</code> with a new AWT hierarchy. <code>{@link Component}</code>s 054 * created before the created <code>{@link BasicComponentPrinter}</code> cannot be accessed by the created 055 * <code>{@link BasicComponentPrinter}</code>. 056 * @return the created finder. 057 */ 058 public static ComponentPrinter printerWithNewAwtHierarchy() { 059 return new BasicComponentPrinter(ignoreExistingComponents()); 060 } 061 062 /** 063 * Creates a new <code>{@link BasicComponentPrinter}</code> that has access to all the GUI components in the AWT 064 * hierarchy. 065 * @return the created printer. 066 */ 067 public static ComponentPrinter printerWithCurrentAwtHierarchy() { 068 return new BasicComponentPrinter(new ExistingHierarchy()); 069 } 070 071 /** 072 * Creates a new <code>{@link BasicComponentPrinter}</code>. 073 * @param hierarchy the component hierarchy to use. 074 */ 075 protected BasicComponentPrinter(ComponentHierarchy hierarchy) { 076 this.hierarchy = hierarchy; 077 } 078 079 /** 080 * Returns the component hierarchy used by this printer. 081 * @return the component hierarchy used by this printer. 082 */ 083 protected final ComponentHierarchy hierarchy() { return hierarchy; } 084 085 /** {@inheritDoc} */ 086 @RunsInEDT 087 public void printComponents(PrintStream out) { 088 printComponents(out, ALWAYS_MATCHES); 089 } 090 091 /** {@inheritDoc} */ 092 @RunsInEDT 093 public void printComponents(PrintStream out, Container root) { 094 printComponents(out, ALWAYS_MATCHES, root); 095 } 096 097 /** {@inheritDoc} */ 098 @RunsInEDT 099 public void printComponents(PrintStream out, Class<? extends Component> type) { 100 printComponents(out, type, null); 101 } 102 103 /** {@inheritDoc} */ 104 @RunsInEDT 105 public void printComponents(PrintStream out, Class<? extends Component> type, Container root) { 106 validateNotNull(out); 107 if (type == null) throw new NullPointerException("The type to match should not be null"); 108 print(hierarchy(root), new TypeMatcher(type), out); 109 } 110 111 /** ${@inheritDoc} */ 112 public void printComponents(PrintStream out, ComponentMatcher matcher) { 113 printComponents(out, matcher, null); 114 } 115 116 /** ${@inheritDoc} */ 117 public void printComponents(PrintStream out, ComponentMatcher matcher, Container root) { 118 validateNotNull(out); 119 if (matcher == null) throw new NullPointerException("The matcher to use as filter should not be null"); 120 print(hierarchy(root), matcher, out); 121 } 122 123 private void validateNotNull(PrintStream out) { 124 if (out == null) throw new NullPointerException("The output stream should not be null"); 125 } 126 127 private ComponentHierarchy hierarchy(Container root) { 128 return root != null ? new SingleComponentHierarchy(root, hierarchy) : hierarchy; 129 } 130 131 @RunsInEDT 132 private static void print(final ComponentHierarchy hierarchy, final ComponentMatcher matcher, final PrintStream out) { 133 execute(new GuiTask() { 134 protected void executeInEDT() { 135 for (Component c : hierarchy.roots()) print(c, hierarchy, matcher, 0, out); 136 } 137 }); 138 } 139 140 @RunsInCurrentThread 141 private static void print(Component c, ComponentHierarchy h, ComponentMatcher matcher, int level, 142 PrintStream out) { 143 if (matcher.matches(c)) print(c, level, out); 144 for (Component child : h.childrenOf(c)) 145 print(child, h, matcher, level + 1, out); 146 } 147 148 @RunsInCurrentThread 149 private static void print(Component c, int level, PrintStream out) { 150 for (int i = 0; i < level; i++) out.print(INDENTATION); 151 out.println(format(c)); 152 } 153 }