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