1aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez/* 2aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * Copyright (C) 2015 The Android Open Source Project 3aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * 4aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * Licensed under the Apache License, Version 2.0 (the "License"); 5aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * you may not use this file except in compliance with the License. 6aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * You may obtain a copy of the License at 7aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * 8aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * http://www.apache.org/licenses/LICENSE-2.0 9aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * 10aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * Unless required by applicable law or agreed to in writing, software 11aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * distributed under the License is distributed on an "AS IS" BASIS, 12aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * See the License for the specific language governing permissions and 14aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * limitations under the License. 15aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez */ 16aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 17aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezpackage com.android.tools.idea.editors.theme.widgets; 18aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 19aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport com.android.ide.common.rendering.api.LayoutLog; 20aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport com.android.layoutlib.bridge.Bridge; 21aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 22aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport android.content.Context; 23aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport android.graphics.Canvas; 24aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport android.util.AttributeSet; 25aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport android.view.View; 26aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezimport android.view.ViewGroup; 27aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 28aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez/** 29aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * {@link ViewGroup} that wraps another view and catches any possible exceptions that the child view 30aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * might generate. 31aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez * This is used by the theme editor to stop custom views from breaking the preview. 32aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez */ 33aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez// TODO: This view is just a temporary solution that will be replaced by adding a try / catch 34aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez// for custom views in the ClassConverter 35aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perezpublic class ErrorCatcher extends ViewGroup { 36aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez public ErrorCatcher(Context context) { 37aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez super(context); 38aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 39aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 40aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez public ErrorCatcher(Context context, AttributeSet attrs) { 41aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez super(context, attrs); 42aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 43aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 44aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr) { 45aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez super(context, attrs, defStyleAttr); 46aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 47aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 48aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 49aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez super(context, attrs, defStyleAttr, defStyleRes); 50aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 51aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 52aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez @Override 53aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 54aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez assert getChildCount() == 1 : "ErrorCatcher can only have one child"; 55aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 56aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez View child = getChildAt(0); 57aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez try { 58aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez measureChild(child, widthMeasureSpec, heightMeasureSpec); 59aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 60aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez setMeasuredDimension(resolveSize(child.getMeasuredWidth(), widthMeasureSpec), 61aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez resolveSize(child.getMeasuredHeight(), heightMeasureSpec)); 62aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } catch (Throwable t) { 63aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onMeasure for view " + 64aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez child.getClass().getCanonicalName(), t); 65aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez setMeasuredDimension(resolveSize(0, widthMeasureSpec), 66aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez resolveSize(0, heightMeasureSpec)); 67aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 68aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 69aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 70aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez @Override 71aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 72aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez try { 73aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez return super.drawChild(canvas, child, drawingTime); 74aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } catch (Throwable t) { 75aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to draw for view " + 76aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez child.getClass().getCanonicalName(), t); 77aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 78aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 79aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez return false; 80aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 81aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 82aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez @Override 83aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez protected void onLayout(boolean changed, int l, int t, int r, int b) { 84aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez assert getChildCount() == 1 : "ErrorCatcher can only have one child"; 85aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez 86aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez View child = getChildAt(0); 87aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez try { 88aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); 89aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } catch (Throwable e) { 90aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onLayout for view " + 91aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez child.getClass().getCanonicalName(), e); 92aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 93aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez } 94aa3b2043f0403d064afcf0977f6e713662aceaffDiego Perez} 95