Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa3b2043 authored by Diego Perez's avatar Diego Perez
Browse files

New custom widgets library

Adds the widgets needed by the theme editor as a jar file that will be
linked from AS. The controls currently are:
- ThemePreviewLayout: A custom layout that allows to dynamically reflow
  cards that display the theme preview.
- PressedButton: Custom button to display in a pressed state (currently
  we can only do it programatically).
- ErrorCatcher: View that can wrap other view and stops a view throwing
  exceptions that will break the theme editor rendering. This is
  currently used to wrap the custom controls loaded from the source
  code.

The new library currently depends on bridge to be able to use the logger
for the ErrorCatcher view. The ErrorCatcher view is a temporary solution
that will be replaced in a future CL and the dependency will be removed.

Change-Id: I832c447e22e1381abff74c46c4282921b3f6fa23
parent afd883f8
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
<component name="ArtifactManager">
  <artifact type="jar" name="studio-android-widgets:jar">
    <output-path>$PROJECT_DIR$/out/artifacts/studio_android_widgets_jar</output-path>
    <root id="archive" name="studio-android-widgets.jar">
      <element id="module-output" name="studio-android-widgets" />
    </root>
  </artifact>
</component>
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
<component name="ArtifactManager">
  <artifact type="jar" name="studio-android-widgets-src:jar">
    <output-path>$PROJECT_DIR$/out/artifacts/studio_android_widgets_src_jar</output-path>
    <root id="archive" name="studio-android-widgets-src.jar">
      <element id="dir-copy" path="$PROJECT_DIR$/studio-custom-widgets/src" />
    </root>
  </artifact>
</component>
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
    <modules>
      <module fileurl="file://$PROJECT_DIR$/bridge/bridge.iml" filepath="$PROJECT_DIR$/bridge/bridge.iml" />
      <module fileurl="file://$PROJECT_DIR$/create/create.iml" filepath="$PROJECT_DIR$/create/create.iml" />
      <module fileurl="file://$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" filepath="$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" />
    </modules>
  </component>
</project>
 No newline at end of file
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tools.idea.editors.theme.widgets;

import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * {@link ViewGroup} that wraps another view and catches any possible exceptions that the child view
 * might generate.
 * This is used by the theme editor to stop custom views from breaking the preview.
 */
// TODO: This view is just a temporary solution that will be replaced by adding a try / catch
// for custom views in the ClassConverter
public class ErrorCatcher extends ViewGroup {
    public ErrorCatcher(Context context) {
        super(context);
    }

    public ErrorCatcher(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        assert getChildCount() == 1 : "ErrorCatcher can only have one child";

        View child = getChildAt(0);
        try {
            measureChild(child, widthMeasureSpec, heightMeasureSpec);

            setMeasuredDimension(resolveSize(child.getMeasuredWidth(), widthMeasureSpec),
                    resolveSize(child.getMeasuredHeight(), heightMeasureSpec));
        } catch (Throwable t) {
            Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onMeasure for view " +
                    child.getClass().getCanonicalName(), t);
            setMeasuredDimension(resolveSize(0, widthMeasureSpec),
                    resolveSize(0, heightMeasureSpec));
        }
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        try {
            return super.drawChild(canvas, child, drawingTime);
        } catch (Throwable t) {
            Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to draw for view " +
                    child.getClass().getCanonicalName(), t);
        }

        return false;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        assert getChildCount() == 1 : "ErrorCatcher can only have one child";

        View child = getChildAt(0);
        try {
            child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
        } catch (Throwable e) {
            Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onLayout for view " +
                    child.getClass().getCanonicalName(), e);
        }
    }
}
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tools.idea.editors.theme.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;

@SuppressWarnings("unused")
public class PressedButton extends Button {
    public PressedButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        setPressed(true);
        jumpDrawablesToCurrentState();
    }
}
Loading