• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 
17 package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
18 
19 import com.android.ide.common.rendering.api.LayoutLog;
20 import com.android.ide.eclipse.adt.AdtPlugin;
21 
22 import org.eclipse.core.runtime.IStatus;
23 
24 import java.util.ArrayList;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 
29 /**
30  * A {@link LayoutLog} which records the problems it encounters and offers them as a
31  * single summary at the end
32  */
33 class RenderLogger extends LayoutLog {
34     static final String TAG_MISSING_DIMENSION = "missing.dimension";     //$NON-NLS-1$
35 
36     private final String mName;
37     private List<String> mFidelityWarnings;
38     private List<String> mWarnings;
39     private List<String> mErrors;
40     private boolean mHaveExceptions;
41     private List<String> mTags;
42     private static Set<String> sIgnoredFidelityWarnings;
43 
44     /** Construct a logger for the given named layout */
RenderLogger(String name)45     RenderLogger(String name) {
46         mName = name;
47     }
48 
49     /**
50      * Are there any logged errors or warnings during the render?
51      *
52      * @return true if there were problems during the render
53      */
hasProblems()54     public boolean hasProblems() {
55         return mFidelityWarnings != null || mErrors != null || mWarnings != null ||
56             mHaveExceptions;
57     }
58 
59     /**
60      * Returns a (possibly multi-line) description of all the problems
61      *
62      * @param includeFidelityWarnings if true, include fidelity warnings in the problem
63      *            summary
64      * @return a string describing the rendering problems
65      */
getProblems(boolean includeFidelityWarnings)66     public String getProblems(boolean includeFidelityWarnings) {
67         StringBuilder sb = new StringBuilder();
68 
69         if (mErrors != null) {
70             for (String error : mErrors) {
71                 sb.append(error).append('\n');
72             }
73         }
74 
75         if (mWarnings != null) {
76             for (String warning : mWarnings) {
77                 sb.append(warning).append('\n');
78             }
79         }
80 
81         if (includeFidelityWarnings && mFidelityWarnings != null) {
82             sb.append("The graphics preview in the layout editor may not be accurate:\n");
83             for (String warning : mFidelityWarnings) {
84                 sb.append("* ");
85                 sb.append(warning).append('\n');
86             }
87         }
88 
89         if (mHaveExceptions) {
90             sb.append("Exception details are logged in Window > Show View > Error Log");
91         }
92 
93         return sb.toString();
94     }
95 
96     /**
97      * Returns the fidelity warnings
98      *
99      * @return the fidelity warnings
100      */
getFidelityWarnings()101     public List<String> getFidelityWarnings() {
102         return mFidelityWarnings;
103     }
104 
105     // ---- extends LayoutLog ----
106 
107     @Override
error(String tag, String message, Object data)108     public void error(String tag, String message, Object data) {
109         String description = describe(message);
110 
111         AdtPlugin.log(IStatus.ERROR, "%1$s: %2$s", mName, description);
112 
113         // Workaround: older layout libraries don't provide a tag for this error
114         if (tag == null && message != null
115                 && message.startsWith("Failed to find style ")) { //$NON-NLS-1$
116             tag = LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR;
117         }
118 
119         addError(tag, description);
120     }
121 
122     @Override
error(String tag, String message, Throwable throwable, Object data)123     public void error(String tag, String message, Throwable throwable, Object data) {
124         String description = describe(message);
125         AdtPlugin.log(throwable, "%1$s: %2$s", mName, description);
126         if (throwable != null) {
127             if (throwable instanceof ClassNotFoundException) {
128                 // The project callback is given a chance to resolve classes,
129                 // and when it fails, it will record it in its own list which
130                 // is displayed in a special way (with action hyperlinks etc).
131                 // Therefore, include these messages in the visible render log,
132                 // especially since the user message from a ClassNotFoundException
133                 // is really not helpful (it just lists the class name without
134                 // even mentioning that it is a class-not-found exception.)
135                 return;
136             }
137 
138             mHaveExceptions = true;
139         }
140 
141         addError(tag, description);
142     }
143 
144     @Override
warning(String tag, String message, Object data)145     public void warning(String tag, String message, Object data) {
146         String description = describe(message);
147         AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description);
148 
149         if (TAG_RESOURCES_FORMAT.equals(tag)) {
150             if (description.equals("You must supply a layout_width attribute.")       //$NON-NLS-1$
151                 || description.equals("You must supply a layout_height attribute.")) {//$NON-NLS-1$
152                 tag = TAG_MISSING_DIMENSION;
153             }
154         }
155 
156         addWarning(tag, description);
157     }
158 
159     @Override
fidelityWarning(String tag, String message, Throwable throwable, Object data)160     public void fidelityWarning(String tag, String message, Throwable throwable, Object data) {
161         if (sIgnoredFidelityWarnings != null && sIgnoredFidelityWarnings.contains(message)) {
162             return;
163         }
164 
165         String description = describe(message);
166         AdtPlugin.log(throwable, "%1$s: %2$s", mName, description);
167         if (throwable != null) {
168             mHaveExceptions = true;
169         }
170 
171         addFidelityWarning(tag, description);
172     }
173 
174     /**
175      * Ignore the given render fidelity warning for the current session
176      *
177      * @param message the message to be ignored for this session
178      */
ignoreFidelityWarning(String message)179     public static void ignoreFidelityWarning(String message) {
180         if (sIgnoredFidelityWarnings == null) {
181             sIgnoredFidelityWarnings = new HashSet<String>();
182         }
183         sIgnoredFidelityWarnings.add(message);
184     }
185 
describe(String message)186     private String describe(String message) {
187         StringBuilder sb = new StringBuilder();
188         if (message != null) {
189             if (sb.length() > 0) {
190                 sb.append(": ");
191             }
192             sb.append(message);
193         }
194         return sb.toString();
195     }
196 
addWarning(String tag, String description)197     private void addWarning(String tag, String description) {
198         if (mWarnings == null) {
199             mWarnings = new ArrayList<String>();
200         } else if (mWarnings.contains(description)) {
201             // Avoid duplicates
202             return;
203         }
204         mWarnings.add(description);
205         addTag(tag);
206     }
207 
addError(String tag, String description)208     private void addError(String tag, String description) {
209         if (mErrors == null) {
210             mErrors = new ArrayList<String>();
211         } else if (mErrors.contains(description)) {
212             // Avoid duplicates
213             return;
214         }
215         mErrors.add(description);
216         addTag(tag);
217     }
218 
addFidelityWarning(String tag, String description)219     private void addFidelityWarning(String tag, String description) {
220         if (mFidelityWarnings == null) {
221             mFidelityWarnings = new ArrayList<String>();
222         } else if (mFidelityWarnings.contains(description)) {
223             // Avoid duplicates
224             return;
225         }
226         mFidelityWarnings.add(description);
227         addTag(tag);
228     }
229 
230     // ---- Tags ----
231 
addTag(String tag)232     private void addTag(String tag) {
233         if (tag != null) {
234             if (mTags == null) {
235                 mTags = new ArrayList<String>();
236             }
237             mTags.add(tag);
238         }
239     }
240 
241     /**
242      * Returns true if the given tag prefix has been seen
243      *
244      * @param prefix the tag prefix to look for
245      * @return true iff any tags with the given prefix was seen during the render
246      */
seenTagPrefix(String prefix)247     public boolean seenTagPrefix(String prefix) {
248         if (mTags != null) {
249             for (String tag : mTags) {
250                 if (tag.startsWith(prefix)) {
251                     return true;
252                 }
253             }
254         }
255 
256         return false;
257     }
258 
259     /**
260      * Returns true if the given tag has been seen
261      *
262      * @param tag the tag to look for
263      * @return true iff the tag was seen during the render
264      */
seenTag(String tag)265     public boolean seenTag(String tag) {
266         if (mTags != null) {
267             return mTags.contains(tag);
268         } else {
269             return false;
270         }
271     }
272 }
273