diff options
author | Bob Badour <bbadour@google.com> | 2020-05-06 15:09:12 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-05-06 15:09:12 +0000 |
commit | f1a59c98333d28b04b74772f204bcc1df6e83634 (patch) | |
tree | fd845444b59dfc72656b7781596e0b1a0662c4c7 /eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java | |
parent | 14a008655dafe4ca1fc7d014a16a1c401761675c (diff) | |
parent | d58f8ba3b1869530926bd5f167103dfa161787a1 (diff) | |
download | sdk-f1a59c98333d28b04b74772f204bcc1df6e83634.tar.gz |
Merge "Revert "Remove unused project."" am: fc7cda06f5 am: d3c69fa48e am: d58f8ba3b1
Change-Id: I297730ce4f9da2bf30dde696439ab825cd642b00
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java new file mode 100644 index 000000000..7e2d3a799 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.ide.common.layout.grid; + +import static com.android.ide.common.layout.GridLayoutRule.GRID_SIZE; +import static com.android.ide.common.layout.GridLayoutRule.MARGIN_SIZE; +import static com.android.ide.common.layout.grid.GridModel.UNDEFINED; + +import com.android.annotations.NonNull; +import com.android.ide.common.api.DrawingStyle; +import com.android.ide.common.api.DropFeedback; +import com.android.ide.common.api.IDragElement; +import com.android.ide.common.api.IFeedbackPainter; +import com.android.ide.common.api.IGraphics; +import com.android.ide.common.api.INode; +import com.android.ide.common.api.Rect; +import com.android.ide.common.api.SegmentType; +import com.android.ide.common.layout.GridLayoutRule; +import com.android.utils.Pair; + +/** + * Painter which paints feedback during drag, drop and resizing operations, as well as + * static selection feedback + */ +public class GridLayoutPainter { + + /** + * Creates a painter for drop feedback + * + * @param rule the corresponding {@link GridLayoutRule} + * @param elements the dragged elements + * @return a {@link IFeedbackPainter} which can paint the drop feedback + */ + public static IFeedbackPainter createDropFeedbackPainter(GridLayoutRule rule, + IDragElement[] elements) { + return new DropFeedbackPainter(rule, elements); + } + + /** + * Paints the structure (the grid model) of the given GridLayout. + * + * @param style the drawing style to use to paint the structure lines + * @param layout the grid layout node + * @param gc the graphics context to paint into + * @param grid the grid model to be visualized + */ + public static void paintStructure(DrawingStyle style, INode layout, IGraphics gc, + GridModel grid) { + Rect b = layout.getBounds(); + + gc.useStyle(style); + for (int row = 0; row < grid.actualRowCount; row++) { + int y = grid.getRowY(row); + gc.drawLine(b.x, y, b.x2(), y); + } + for (int column = 0; column < grid.actualColumnCount; column++) { + int x = grid.getColumnX(column); + gc.drawLine(x, b.y, x, b.y2()); + } + } + + /** + * Paints a regular grid according to the {@link GridLayoutRule#GRID_SIZE} and + * {@link GridLayoutRule#MARGIN_SIZE} dimensions. These are the same lines that + * snap-to-grid will align with. + * + * @param layout the GridLayout node + * @param gc the graphics context to paint the grid into + */ + public static void paintGrid(INode layout, IGraphics gc) { + Rect b = layout.getBounds(); + + int oldAlpha = gc.getAlpha(); + gc.useStyle(DrawingStyle.GUIDELINE); + gc.setAlpha(128); + + int y1 = b.y + MARGIN_SIZE; + int y2 = b.y2() - MARGIN_SIZE; + for (int y = y1; y < y2; y += GRID_SIZE) { + int x1 = b.x + MARGIN_SIZE; + int x2 = b.x2() - MARGIN_SIZE; + for (int x = x1; x < x2; x += GRID_SIZE) { + gc.drawPoint(x, y); + } + } + gc.setAlpha(oldAlpha); + } + + /** + * Paint resizing feedback (which currently paints the grid model faintly.) + * + * @param gc the graphics context + * @param layout the GridLayout + * @param grid the grid model + */ + public static void paintResizeFeedback(IGraphics gc, INode layout, GridModel grid) { + paintStructure(DrawingStyle.GRID, layout, gc, grid); + } + + /** + * A painter which can paint the drop feedback for elements being dragged into or + * within a GridLayout. + */ + private static class DropFeedbackPainter implements IFeedbackPainter { + private final GridLayoutRule mRule; + private final IDragElement[] mElements; + + /** Constructs a new {@link GridLayoutPainter} bound to the given {@link GridLayoutRule} + * @param rule the corresponding rule + * @param elements the elements to draw */ + public DropFeedbackPainter(GridLayoutRule rule, IDragElement[] elements) { + mRule = rule; + mElements = elements; + } + + // Implements IFeedbackPainter + @Override + public void paint(@NonNull IGraphics gc, @NonNull INode node, + @NonNull DropFeedback feedback) { + Rect b = node.getBounds(); + if (!b.isValid()) { + return; + } + + // Highlight the receiver + gc.useStyle(DrawingStyle.DROP_RECIPIENT); + gc.drawRect(b); + GridDropHandler data = (GridDropHandler) feedback.userData; + + if (!GridLayoutRule.sGridMode) { + paintFreeFormDropFeedback(gc, node, feedback, b, data); + } else { + paintGridModeDropFeedback(gc, b, data); + } + } + + /** + * Paints the drag feedback for a free-form mode drag + */ + private void paintFreeFormDropFeedback(IGraphics gc, INode node, DropFeedback feedback, + Rect b, GridDropHandler data) { + GridModel grid = data.getGrid(); + if (GridLayoutRule.sSnapToGrid) { + GridLayoutPainter.paintGrid(node, gc); + } + GridLayoutPainter.paintStructure(DrawingStyle.GRID, node, gc, grid); + + GridMatch rowMatch = data.getRowMatch(); + GridMatch columnMatch = data.getColumnMatch(); + + if (rowMatch == null || columnMatch == null) { + return; + } + + IDragElement first = mElements[0]; + Rect dragBounds = first.getBounds(); + int offsetX = 0; + int offsetY = 0; + if (rowMatch.type == SegmentType.BOTTOM) { + offsetY -= dragBounds.h; + } else if (rowMatch.type == SegmentType.BASELINE) { + offsetY -= feedback.dragBaseline; + } + if (columnMatch.type == SegmentType.RIGHT) { + offsetX -= dragBounds.w; + } else if (columnMatch.type == SegmentType.CENTER_HORIZONTAL) { + offsetX -= dragBounds.w / 2; + } + + // Draw guidelines for matches + int y = rowMatch.matchedLine; + int x = columnMatch.matchedLine; + Rect bounds = first.getBounds(); + + // Draw margin + if (rowMatch.margin != UNDEFINED && rowMatch.margin > 0) { + gc.useStyle(DrawingStyle.DISTANCE); + int centerX = bounds.w / 2 + offsetX + x; + int y1; + int y2; + if (rowMatch.type == SegmentType.TOP) { + y1 = offsetY + y - 1; + y2 = rowMatch.matchedLine - rowMatch.margin; + } else { + assert rowMatch.type == SegmentType.BOTTOM; + y1 = bounds.h + offsetY + y - 1; + y2 = rowMatch.matchedLine + rowMatch.margin; + } + gc.drawLine(b.x, y1, b.x2(), y1); + gc.drawLine(b.x, y2, b.x2(), y2); + gc.drawString(Integer.toString(rowMatch.margin), + centerX - 3, y1 + (y2 - y1 - 16) / 2); + } else { + gc.useStyle(rowMatch.margin == 0 ? DrawingStyle.DISTANCE + : rowMatch.createCell ? DrawingStyle.GUIDELINE_DASHED + : DrawingStyle.GUIDELINE); + gc.drawLine(b.x, y, b.x2(), y ); + } + + if (columnMatch.margin != UNDEFINED && columnMatch.margin > 0) { + gc.useStyle(DrawingStyle.DISTANCE); + int centerY = bounds.h / 2 + offsetY + y; + int x1; + int x2; + if (columnMatch.type == SegmentType.LEFT) { + x1 = offsetX + x - 1; + x2 = columnMatch.matchedLine - columnMatch.margin; + } else { + assert columnMatch.type == SegmentType.RIGHT; + x1 = bounds.w + offsetX + x - 1; + x2 = columnMatch.matchedLine + columnMatch.margin; + } + gc.drawLine(x1, b.y, x1, b.y2()); + gc.drawLine(x2, b.y, x2, b.y2()); + gc.drawString(Integer.toString(columnMatch.margin), + x1 + (x2 - x1 - 16) / 2, centerY - 3); + } else { + gc.useStyle(columnMatch.margin == 0 ? DrawingStyle.DISTANCE + : columnMatch.createCell ? DrawingStyle.GUIDELINE_DASHED + : DrawingStyle.GUIDELINE); + gc.drawLine(x, b.y, x, b.y2()); + } + + // Draw preview rectangles for all the dragged elements + gc.useStyle(DrawingStyle.DROP_PREVIEW); + offsetX += x - bounds.x; + offsetY += y - bounds.y; + + for (IDragElement element : mElements) { + if (element == first) { + mRule.drawElement(gc, first, offsetX, offsetY); + // Preview baseline as well + if (feedback.dragBaseline != -1) { + int x1 = dragBounds.x + offsetX; + int y1 = dragBounds.y + offsetY + feedback.dragBaseline; + gc.drawLine(x1, y1, x1 + dragBounds.w, y1); + } + } else { + b = element.getBounds(); + if (b.isValid()) { + gc.drawRect(b.x + offsetX, b.y + offsetY, + b.x + offsetX + b.w, b.y + offsetY + b.h); + } + } + } + } + + /** + * Paints the drag feedback for a grid-mode drag + */ + private void paintGridModeDropFeedback(IGraphics gc, Rect b, GridDropHandler data) { + int radius = mRule.getNewCellSize(); + GridModel grid = data.getGrid(); + + gc.useStyle(DrawingStyle.GUIDELINE); + // Paint grid + for (int row = 1; row < grid.actualRowCount; row++) { + int y = grid.getRowY(row); + gc.drawLine(b.x, y - radius, b.x2(), y - radius); + gc.drawLine(b.x, y + radius, b.x2(), y + radius); + + } + for (int column = 1; column < grid.actualColumnCount; column++) { + int x = grid.getColumnX(column); + gc.drawLine(x - radius, b.y, x - radius, b.y2()); + gc.drawLine(x + radius, b.y, x + radius, b.y2()); + } + gc.drawRect(b.x, b.y, b.x2(), b.y2()); + gc.drawRect(b.x + 2 * radius, b.y + 2 * radius, + b.x2() - 2 * radius, b.y2() - 2 * radius); + + GridMatch columnMatch = data.getColumnMatch(); + GridMatch rowMatch = data.getRowMatch(); + int column = columnMatch.cellIndex; + int row = rowMatch.cellIndex; + boolean createColumn = columnMatch.createCell; + boolean createRow = rowMatch.createCell; + + Rect cellBounds = grid.getCellBounds(row, column, 1, 1); + + IDragElement first = mElements[0]; + Rect dragBounds = first.getBounds(); + int offsetX = cellBounds.x - dragBounds.x; + int offsetY = cellBounds.y - dragBounds.y; + + gc.useStyle(DrawingStyle.DROP_ZONE_ACTIVE); + if (createColumn) { + gc.fillRect(new Rect(cellBounds.x - radius, + cellBounds.y + (createRow ? -radius : radius), + 2 * radius + 1, cellBounds.h - (createRow ? 0 : 2 * radius))); + offsetX -= radius + dragBounds.w / 2; + } + if (createRow) { + gc.fillRect(new Rect(cellBounds.x + radius, cellBounds.y - radius, + cellBounds.w - 2 * radius, 2 * radius + 1)); + offsetY -= radius + dragBounds.h / 2; + } else if (!createColumn) { + // Choose this cell + gc.fillRect(new Rect(cellBounds.x + radius, cellBounds.y + radius, + cellBounds.w - 2 * radius, cellBounds.h - 2 * radius)); + } + + gc.useStyle(DrawingStyle.DROP_PREVIEW); + + Rect bounds = first.getBounds(); + int x = offsetX; + int y = offsetY; + if (columnMatch.type == SegmentType.RIGHT) { + x += cellBounds.w - bounds.w; + } else if (columnMatch.type == SegmentType.CENTER_HORIZONTAL) { + x += cellBounds.w / 2 - bounds.w / 2; + } + if (rowMatch.type == SegmentType.BOTTOM) { + y += cellBounds.h - bounds.h; + } else if (rowMatch.type == SegmentType.CENTER_VERTICAL) { + y += cellBounds.h / 2 - bounds.h / 2; + } + + mRule.drawElement(gc, first, x, y); + } + } + + /** + * Paints the structure (the row and column boundaries) of the given + * GridLayout + * + * @param view the instance of the GridLayout whose structure should be + * painted + * @param style the drawing style to use for the cell boundaries + * @param layout the layout element + * @param gc the graphics context + * @return true if the structure was successfully inferred from the view and + * painted + */ + public static boolean paintStructure(Object view, DrawingStyle style, INode layout, + IGraphics gc) { + Pair<int[],int[]> cellBounds = GridModel.getAxisBounds(view); + if (cellBounds != null) { + int[] xs = cellBounds.getFirst(); + int[] ys = cellBounds.getSecond(); + Rect b = layout.getBounds(); + gc.useStyle(style); + for (int row = 0; row < ys.length; row++) { + int y = ys[row] + b.y; + gc.drawLine(b.x, y, b.x2(), y); + } + for (int column = 0; column < xs.length; column++) { + int x = xs[column] + b.x; + gc.drawLine(x, b.y, x, b.y2()); + } + + return true; + } else { + return false; + } + } +} |