diff options
3 files changed, 206 insertions, 15 deletions
diff --git a/designer/src/com/android/tools/idea/uibuilder/handlers/GridInfo.java b/designer/src/com/android/tools/idea/uibuilder/handlers/GridInfo.java new file mode 100644 index 00000000000..645d4b0effb --- /dev/null +++ b/designer/src/com/android/tools/idea/uibuilder/handlers/GridInfo.java @@ -0,0 +1,113 @@ +/* + * 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.uibuilder.handlers; + +import com.android.tools.idea.uibuilder.model.Insets; +import com.android.tools.idea.uibuilder.model.NlComponent; + +import java.awt.*; +import java.lang.reflect.Field; +import java.util.Arrays; + +final class GridInfo { + private static final int NEW_CELL_SIZE = 32; + + private final NlComponent layout; + final int[] verticalLineLocations; + final int[] horizontalLineLocations; + + GridInfo(NlComponent layout) { + this.layout = layout; + + try { + Insets padding = layout.getPadding(); + Dimension size = getSize(); + + int[] horizontalAxisLocations = getAxisLocations("mHorizontalAxis", "horizontalAxis"); + verticalLineLocations = initLineLocations(layout.w - padding.width(), size.width, horizontalAxisLocations); + + int[] verticalAxisLocations = getAxisLocations("mVerticalAxis", "verticalAxis"); + horizontalLineLocations = initLineLocations(layout.h - padding.height(), size.height, verticalAxisLocations); + } + catch (NoSuchFieldException exception) { + throw new IllegalArgumentException(exception); + } + catch (IllegalAccessException exception) { + throw new IllegalArgumentException(exception); + } + } + + private Dimension getSize() { + Dimension size = new Dimension(); + + if (layout.children != null) { + Insets padding = layout.getPadding(); + + for (NlComponent child : layout.children) { + size.width = Math.max(child.x - layout.x - padding.left + child.w, size.width); + size.height = Math.max(child.y - layout.y - padding.top + child.h, size.height); + } + } + + return size; + } + + private int[] getAxisLocations(String name1, String name2) throws NoSuchFieldException, IllegalAccessException { + assert layout.viewInfo != null; + Object view = layout.viewInfo.getViewObject(); + + Field axisField = getDeclaredField(view.getClass(), name1, name2); + axisField.setAccessible(true); + + Object axis = axisField.get(view); + + Field locationsField = axis.getClass().getDeclaredField("locations"); + locationsField.setAccessible(true); + + return (int[])locationsField.get(axis); + } + + private static Field getDeclaredField(Class<?> c, String name1, String name2) throws NoSuchFieldException { + try { + return c.getDeclaredField(name1); + } + catch (NoSuchFieldException exception) { + return c.getDeclaredField(name2); + } + } + + private static int[] initLineLocations(int layoutSize, int gridInfoSize, int[] axisLocations) { + int difference = layoutSize - gridInfoSize; + int lineLocationsLength = difference > 0 ? axisLocations.length + difference / NEW_CELL_SIZE : axisLocations.length; + + int startIndex; + int[] lineLocations = Arrays.copyOf(axisLocations, lineLocationsLength); + + if (axisLocations.length == 0) { + startIndex = 1; + } + else { + lineLocations[axisLocations.length - 1] = gridInfoSize; + startIndex = axisLocations.length; + } + + for (int i = startIndex; i < lineLocationsLength; i++) { + lineLocations[i] = lineLocations[i - 1] + NEW_CELL_SIZE; + } + + return lineLocations; + } +} diff --git a/designer/src/com/android/tools/idea/uibuilder/handlers/GridLayoutHandler.java b/designer/src/com/android/tools/idea/uibuilder/handlers/GridLayoutHandler.java new file mode 100644 index 00000000000..9a6c3770424 --- /dev/null +++ b/designer/src/com/android/tools/idea/uibuilder/handlers/GridLayoutHandler.java @@ -0,0 +1,74 @@ +/* + * 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.uibuilder.handlers; + +import com.android.annotations.NonNull; +import com.android.tools.idea.uibuilder.api.DragHandler; +import com.android.tools.idea.uibuilder.api.DragType; +import com.android.tools.idea.uibuilder.api.ViewEditor; +import com.android.tools.idea.uibuilder.api.ViewGroupHandler; +import com.android.tools.idea.uibuilder.graphics.NlDrawingStyle; +import com.android.tools.idea.uibuilder.graphics.NlGraphics; +import com.android.tools.idea.uibuilder.model.Insets; +import com.android.tools.idea.uibuilder.model.NlComponent; + +import java.util.List; + +final class GridLayoutHandler extends ViewGroupHandler { + @Override + public DragHandler createDragHandler(@NonNull ViewEditor editor, @NonNull NlComponent layout, @NonNull List<NlComponent> components, + @NonNull DragType type) { + return new GridDragHandler(editor, this, layout, components, type); + } + + private static final class GridDragHandler extends DragHandler { + private final GridInfo info; + + private GridDragHandler(ViewEditor editor, ViewGroupHandler handler, NlComponent layout, List<NlComponent> components, DragType type) { + super(editor, handler, layout, components, type); + info = new GridInfo(layout); + } + + @Override + public void commit(int x, int y, int modifiers) { + } + + @Override + public void paint(@NonNull NlGraphics graphics) { + Insets padding = layout.getPadding(); + + int layoutX1 = layout.x + padding.left; + int layoutY1 = layout.y + padding.top; + int layoutX2 = layout.x + padding.left + layout.w - padding.width() - 1; + int layoutY2 = layout.y + padding.top + layout.h - padding.height() - 1; + + graphics.useStyle(NlDrawingStyle.DROP_ZONE); + + for (int x : info.verticalLineLocations) { + x += layoutX1; + graphics.drawLine(x, layoutY1, x, layoutY2); + } + + for (int y : info.horizontalLineLocations) { + y += layoutY1; + graphics.drawLine(layoutX1, y, layoutX2, y); + } + + graphics.useStyle(NlDrawingStyle.DROP_RECIPIENT); + graphics.drawRect(layoutX1, layoutY1, layout.w - padding.width(), layout.h - padding.height()); + } + } +} diff --git a/designer/src/com/android/tools/idea/uibuilder/handlers/ViewHandlerManager.java b/designer/src/com/android/tools/idea/uibuilder/handlers/ViewHandlerManager.java index 005f78ca806..bfb4df0fcc6 100644 --- a/designer/src/com/android/tools/idea/uibuilder/handlers/ViewHandlerManager.java +++ b/designer/src/com/android/tools/idea/uibuilder/handlers/ViewHandlerManager.java @@ -127,15 +127,30 @@ public class ViewHandlerManager implements ProjectComponent { private ViewHandler createHandler(@NonNull String viewTag) { // Builtin view. Don't bother with reflection for the common cases. + if (FRAME_LAYOUT.equals(viewTag)) { + return new FrameLayoutHandler(); + } + if (COORDINATOR_LAYOUT.equals(viewTag)) { + return new CoordinatorLayoutHandler(); + } + if (APP_BAR_LAYOUT.equals(viewTag)) { + return new AppBarLayoutHandler(); + } if (LINEAR_LAYOUT.equals(viewTag) || FQCN_LINEAR_LAYOUT.equals(viewTag)) { return new LinearLayoutHandler(); } + if (TABLE_LAYOUT.equals(viewTag)) { + return new TableLayoutHandler(); + } + if (TABLE_ROW.equals(viewTag)) { + return new TableRowHandler(); + } + if (GRID_LAYOUT.equals(viewTag)) { + return new GridLayoutHandler(); + } if (RELATIVE_LAYOUT.equals(viewTag) || FQCN_RELATIVE_LAYOUT.equals(viewTag)) { return new RelativeLayoutHandler(); } - if (FRAME_LAYOUT.equals(viewTag)) { - return new FrameLayoutHandler(); - } if (SCROLL_VIEW.equals(viewTag)) { return new ScrollViewHandler(); } @@ -163,18 +178,6 @@ public class ViewHandlerManager implements ProjectComponent { if (ABSOLUTE_LAYOUT.equals(viewTag)) { return new AbsoluteLayoutHandler(); } - if (TABLE_LAYOUT.equals(viewTag)) { - return new TableLayoutHandler(); - } - if (TABLE_ROW.equals(viewTag)) { - return new TableRowHandler(); - } - if (COORDINATOR_LAYOUT.equals(viewTag)) { - return new CoordinatorLayoutHandler(); - } - if (APP_BAR_LAYOUT.equals(viewTag)) { - return new AppBarLayoutHandler(); - } if (FLOATING_ACTION_BUTTON.equals(viewTag)) { return new FloatingActionButtonHandler(); } @@ -213,6 +216,7 @@ public class ViewHandlerManager implements ProjectComponent { for (PsiClass cls : classes) { // Look for bytecode and instantiate if possible, then return // TODO: Instantiate + // noinspection UseOfSystemOutOrSystemErr System.out.println("Find view handler " + cls.getQualifiedName() + " of type " + cls.getClass().getName()); } } |