public final void testEqualsObject() { Rect r = new Rect(3, 4, 20, 30); assertFalse(r.equals(null)); assertFalse(r.equals(new Object())); assertTrue(r.equals(new Rect(3, 4, 20, 30))); }
public final void testGetBottomRight() { Rect r = new Rect(3, 4, 20, 30); Point p = r.getBottomRight(); assertEquals(3 + 20, p.x); assertEquals(4 + 30, p.y); }
public final void testGetCenter() { Rect r = new Rect(3, 4, 20, 30); Point p = r.getCenter(); assertEquals(3 + 20 / 2, p.x); assertEquals(4 + 30 / 2, p.y); }
public final void testCopy() { Rect r = new Rect(1, 2, 3, 4); Rect r2 = r.copy(); assertNotSame(r2, r); assertEquals(r2, r); }
public final void testGetTopLeft() { Rect r = new Rect(3, 4, 20, 30); Point p = r.getTopLeft(); assertEquals(3, p.x); assertEquals(4, p.y); }
public final void testCenter() { Rect r = new Rect(10, 20, 30, 40); Point center = r.center(); assertEquals(25, center.x); assertEquals(40, center.y); assertEquals(25, r.centerX()); assertEquals(40, r.centerY()); }
/** * Computes a horizontal "gap" match - a preferred distance from the nearest edge, including * margin edges */ private void addColumnGapMatch( Rect bounds, int x1, int x2, List<GridMatch> columnMatches, int max) { if (x1 < bounds.x + MARGIN_SIZE + max) { int matchedLine = bounds.x + MARGIN_SIZE; int distance = abs(matchedLine - x1); if (distance <= max) { boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine; columnMatches.add( new GridMatch(SegmentType.LEFT, distance, matchedLine, 0, createCell, MARGIN_SIZE)); } } else if (x2 > bounds.x2() - MARGIN_SIZE - max) { int matchedLine = bounds.x2() - MARGIN_SIZE; int distance = abs(matchedLine - x2); if (distance <= max) { // This does not yet work properly; we need to use columnWeights to achieve this // boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine; // columnMatches.add(new GridMatch(SegmentType.RIGHT, distance, matchedLine, // mGrid.actualColumnCount - 1, createCell, MARGIN_SIZE)); } } else { int columnRight = mGrid.getColumn(x1 - SHORT_GAP_DP); int columnX = mGrid.getColumnMaxX(columnRight); int matchedLine = columnX + SHORT_GAP_DP; int distance = abs(matchedLine - x1); if (distance <= max) { boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine; columnMatches.add( new GridMatch( SegmentType.LEFT, distance, matchedLine, columnRight, createCell, SHORT_GAP_DP)); } // Add a column directly adjacent (no gap) columnRight = mGrid.getColumn(x1); columnX = mGrid.getColumnMaxX(columnRight); matchedLine = columnX; distance = abs(matchedLine - x1); // Let's say you have this arrangement: // [button1][button2] // This is two columns, where the right hand side edge of column 1 is // flush with the left side edge of column 2, because in fact the width of // button1 is what defines the width of column 1, and that in turn is what // defines the left side position of column 2. // // In this case we don't want to consider inserting a new column at the // right hand side of button1 a better match than matching left on column 2. // Therefore, to ensure that this doesn't happen, we "penalize" right column // matches such that they don't get preferential treatment when the matching // line is on the left side of the column. distance += 2; if (distance <= max) { boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine; columnMatches.add( new GridMatch(SegmentType.LEFT, distance, matchedLine, columnRight, createCell, 0)); } } }
public final void testOffsetBy() { Rect r = new Rect(3, 4, 20, 30); Rect r2 = r.offsetBy(100, 200); assertSame(r2, r); assertEquals(103, r.x); assertEquals(204, r.y); assertEquals(20, r.w); assertEquals(30, r.h); }
public final void testMoveTo() { Rect r = new Rect(3, 4, 20, 30); Rect r2 = r.moveTo(100, 200); assertSame(r2, r); assertEquals(100, r.x); assertEquals(200, r.y); assertEquals(20, r.w); assertEquals(30, r.h); }
public final void testSetIntIntIntInt() { Rect r = new Rect(1, 2, 3, 4); Rect r2 = r.set(3, 4, 20, 30); assertSame(r2, r); assertEquals(3, r2.x); assertEquals(4, r2.y); assertEquals(20, r2.w); assertEquals(30, r2.h); }
public final void testSetRect() { Rect r = new Rect(1, 2, 3, 4); Rect r2 = new Rect(3, 4, 20, 30); Rect r3 = r.set(r2); assertSame(r3, r); assertNotSame(r3, r2); assertEquals(3, r.x); assertEquals(4, r.y); assertEquals(20, r.w); assertEquals(30, r.h); }
public final void testContainsPoint() { Rect r = new Rect(3, 4, 20, 30); assertTrue(r.contains(new Point(3, 4))); assertTrue(r.contains(new Point(3 + 19, 4))); assertTrue(r.contains(new Point(3 + 19, 4 + 29))); assertTrue(r.contains(new Point(3, 4 + 29))); assertFalse(r.contains(new Point(3 - 1, 4))); assertFalse(r.contains(new Point(3, 4 - 1))); assertFalse(r.contains(new Point(3 - 1, 4 - 1))); assertFalse(r.contains(new Point(3 + 20, 4))); assertFalse(r.contains(new Point(3 + 20, 4 + 30))); assertFalse(r.contains(new Point(3, 4 + 30))); }
public final void testHashCode() { Rect r = new Rect(1, 2, 3, 4); Rect r1 = new Rect(3, 4, 20, 30); Rect r2 = new Rect(3, 4, 20, 30); assertFalse(r1.hashCode() == r.hashCode()); assertEquals(r2.hashCode(), r1.hashCode()); }
/** * Computes a vertical "gap" match - a preferred distance from the nearest edge, including margin * edges */ private void addRowGapMatch(Rect bounds, int y1, int y2, List<GridMatch> rowMatches, int max) { if (y1 < bounds.y + MARGIN_SIZE + max) { int matchedLine = bounds.y + MARGIN_SIZE; int distance = abs(matchedLine - y1); if (distance <= max) { boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine; rowMatches.add( new GridMatch(SegmentType.TOP, distance, matchedLine, 0, createCell, MARGIN_SIZE)); } } else if (y2 > bounds.y2() - MARGIN_SIZE - max) { int matchedLine = bounds.y2() - MARGIN_SIZE; int distance = abs(matchedLine - y2); if (distance <= max) { // This does not yet work properly; we need to use columnWeights to achieve this // boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine; // rowMatches.add(new GridMatch(SegmentType.BOTTOM, distance, matchedLine, // mGrid.actualRowCount - 1, createCell, MARGIN_SIZE)); } } else { int rowBottom = mGrid.getRow(y1 - SHORT_GAP_DP); int rowY = mGrid.getRowMaxY(rowBottom); int matchedLine = rowY + SHORT_GAP_DP; int distance = abs(matchedLine - y1); if (distance <= max) { boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine; rowMatches.add( new GridMatch( SegmentType.TOP, distance, matchedLine, rowBottom, createCell, SHORT_GAP_DP)); } // Add a row directly adjacent (no gap) rowBottom = mGrid.getRow(y1); rowY = mGrid.getRowMaxY(rowBottom); matchedLine = rowY; distance = abs(matchedLine - y1); distance += 2; // See explanation in addColumnGapMatch if (distance <= max) { boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine; rowMatches.add( new GridMatch(SegmentType.TOP, distance, matchedLine, rowBottom, createCell, 0)); } } }
public final void testIntersects() { Rect r1 = new Rect(0, 0, 10, 10); Rect r2 = new Rect(1, 1, 5, 5); Rect r3 = new Rect(10, 0, 1, 1); Rect r4 = new Rect(5, 5, 10, 10); Rect r5 = new Rect(-1, 0, 1, 1); Rect r6 = new Rect(0, 10, 1, 1); assertTrue(r1.intersects(r2)); assertTrue(r2.intersects(r1)); assertTrue(r1.intersects(r4)); assertFalse(r1.intersects(r3)); assertFalse(r1.intersects(r5)); assertFalse(r1.intersects(r6)); }
public final void testEqualsObject_Invalid() { Rect r = new Rect(3, 4, 20, 30); assertTrue(r.isValid()); Rect i1 = new Rect(3, 4, 0, 0); assertFalse(i1.isValid()); Rect i2 = new Rect(10, 20, 0, 0); assertFalse(i2.isValid()); // valid rects can't be equal to invalid rects assertFalse(r.equals(i1)); assertFalse(r.equals(i2)); // invalid rects are equal to each other whatever their content is assertEquals(i2, i1); }
public final void testIsValid() { Rect r = new Rect(); assertFalse(r.isValid()); r = new Rect(1, 2, 3, 4); assertTrue(r.isValid()); // Rectangles must have a width > 0 to be valid r = new Rect(1, 2, 0, 4); assertFalse(r.isValid()); r = new Rect(1, 2, -5, 4); assertFalse(r.isValid()); // Rectangles must have a height > 0 to be valid r = new Rect(1, 2, 3, 0); assertFalse(r.isValid()); r = new Rect(1, 2, 3, -5); assertFalse(r.isValid()); r = new Rect(1, 2, 0, 0); assertFalse(r.isValid()); r = new Rect(1, 2, -20, -5); assertFalse(r.isValid()); }
/** Adds a horizontal match with the center axis of the GridLayout */ private void addCenterColumnMatch( Rect bounds, int x1, int y1, int x2, int y2, List<GridMatch> columnMatches, int max) { Collection<INode> intersectsRow = mGrid.getIntersectsRow(y1, y2); if (intersectsRow.size() == 0) { // Offer centering on this row since there isn't anything there int matchedLine = bounds.centerX(); int distance = abs((x1 + x2) / 2 - matchedLine); if (distance <= 2 * max) { boolean createCell = false; // always just put in column 0 columnMatches.add( new GridMatch( SegmentType.CENTER_HORIZONTAL, distance, matchedLine, 0 /* column */, createCell, UNDEFINED)); } } }
/** * Computes the best horizontal and vertical matches for a drag to the given position. * * @param feedback a {@link DropFeedback} object containing drag state like the drag bounds and * the drag baseline * @param p the mouse position */ public void computeMatches(DropFeedback feedback, Point p) { mRowMatch = mColumnMatch = null; feedback.tooltip = null; Rect bounds = mGrid.layout.getBounds(); int x1 = p.x; int y1 = p.y; Rect dragBounds = feedback.dragBounds; int w = dragBounds != null ? dragBounds.w : 0; int h = dragBounds != null ? dragBounds.h : 0; if (!GridLayoutRule.sGridMode) { if (dragBounds != null) { // Sometimes the items are centered under the mouse so // offset by the top left corner distance x1 += dragBounds.x; y1 += dragBounds.y; } int x2 = x1 + w; int y2 = y1 + h; if (x2 < bounds.x || y2 < bounds.y || x1 > bounds.x2() || y1 > bounds.y2()) { return; } List<GridMatch> columnMatches = new ArrayList<GridMatch>(); List<GridMatch> rowMatches = new ArrayList<GridMatch>(); int max = BaseLayoutRule.getMaxMatchDistance(); // Column matches: addLeftSideMatch(x1, columnMatches, max); addRightSideMatch(x2, columnMatches, max); addCenterColumnMatch(bounds, x1, y1, x2, y2, columnMatches, max); // Row matches: int row = (mGrid.getViewCount() == 0) ? 0 : mGrid.getClosestRow(y1); int rowY = mGrid.getRowY(row); addTopMatch(y1, rowMatches, max, row, rowY); addBaselineMatch(feedback.dragBaseline, y1, rowMatches, max, row, rowY); addBottomMatch(y2, rowMatches, max); // Look for gap-matches: Predefined spacing between widgets. // TODO: Make this use metadata for predefined spacing between // pairs of types of components. For example, buttons have certain // inserts in their 9-patch files (depending on the theme) that should // be considered and subtracted from the overall proposed distance! addColumnGapMatch(bounds, x1, x2, columnMatches, max); addRowGapMatch(bounds, y1, y2, rowMatches, max); // Fallback: Split existing cell. Also do snap-to-grid. if (GridLayoutRule.sSnapToGrid) { x1 = ((x1 - MARGIN_SIZE - bounds.x) / GRID_SIZE) * GRID_SIZE + MARGIN_SIZE + bounds.x; y1 = ((y1 - MARGIN_SIZE - bounds.y) / GRID_SIZE) * GRID_SIZE + MARGIN_SIZE + bounds.y; x2 = x1 + w; y2 = y1 + h; } if (columnMatches.size() == 0 && x1 >= bounds.x) { // Split the current cell since we have no matches // TODO: Decide whether it should be gravity left or right... columnMatches.add( new GridMatch( SegmentType.LEFT, 0, x1, mGrid.getColumn(x1), true /* createCell */, UNDEFINED)); } if (rowMatches.size() == 0 && y1 >= bounds.y) { rowMatches.add( new GridMatch( SegmentType.TOP, 0, y1, mGrid.getRow(y1), true /* createCell */, UNDEFINED)); } // Pick best matches Collections.sort(rowMatches); Collections.sort(columnMatches); mColumnMatch = null; mRowMatch = null; String columnDescription = null; String rowDescription = null; if (columnMatches.size() > 0) { mColumnMatch = columnMatches.get(0); columnDescription = mColumnMatch.getDisplayName(mGrid.layout); } if (rowMatches.size() > 0) { mRowMatch = rowMatches.get(0); rowDescription = mRowMatch.getDisplayName(mGrid.layout); } if (columnDescription != null && rowDescription != null) { feedback.tooltip = columnDescription + '\n' + rowDescription; } feedback.invalidTarget = mColumnMatch == null || mRowMatch == null; } else { // Find which cell we're inside. // TODO: Find out where within the cell we are, and offer to tweak the gravity // based on the position. int column = mGrid.getColumn(x1); int row = mGrid.getRow(y1); int leftDistance = mGrid.getColumnDistance(column, x1); int rightDistance = mGrid.getColumnDistance(column + 1, x1); int topDistance = mGrid.getRowDistance(row, y1); int bottomDistance = mGrid.getRowDistance(row + 1, y1); int SLOP = 2; int radius = mRule.getNewCellSize(); if (rightDistance < radius + SLOP) { column = Math.min(column + 1, mGrid.actualColumnCount); leftDistance = rightDistance; } if (bottomDistance < radius + SLOP) { row = Math.min(row + 1, mGrid.actualRowCount); topDistance = bottomDistance; } boolean createColumn = leftDistance < radius + SLOP; boolean createRow = topDistance < radius + SLOP; if (x1 >= bounds.x2()) { createColumn = true; } if (y1 >= bounds.y2()) { createRow = true; } int cellWidth = leftDistance + rightDistance; int cellHeight = topDistance + bottomDistance; SegmentType horizontalType = SegmentType.LEFT; SegmentType verticalType = SegmentType.TOP; int minDistance = 10; // Don't center or right/bottom align in tiny cells if (!createColumn && leftDistance > minDistance && dragBounds != null && dragBounds.w < cellWidth - 10) { if (rightDistance < leftDistance) { horizontalType = SegmentType.RIGHT; } int centerDistance = Math.abs(cellWidth / 2 - leftDistance); if (centerDistance < leftDistance / 2 && centerDistance < rightDistance / 2) { horizontalType = SegmentType.CENTER_HORIZONTAL; } } if (!createRow && topDistance > minDistance && dragBounds != null && dragBounds.h < cellHeight - 10) { if (bottomDistance < topDistance) { verticalType = SegmentType.BOTTOM; } int centerDistance = Math.abs(cellHeight / 2 - topDistance); if (centerDistance < topDistance / 2 && centerDistance < bottomDistance / 2) { verticalType = SegmentType.CENTER_VERTICAL; } } mColumnMatch = new GridMatch(horizontalType, 0, x1, column, createColumn, 0); mRowMatch = new GridMatch(verticalType, 0, y1, row, createRow, 0); StringBuilder description = new StringBuilder(50); String rowString = Integer.toString(mColumnMatch.cellIndex + 1); String columnString = Integer.toString(mRowMatch.cellIndex + 1); if (mRowMatch.createCell && mRowMatch.cellIndex < mGrid.actualRowCount) { description.append(String.format("Shift row %1$d down", mRowMatch.cellIndex + 1)); description.append('\n'); } if (mColumnMatch.createCell && mColumnMatch.cellIndex < mGrid.actualColumnCount) { description.append(String.format("Shift column %1$d right", mColumnMatch.cellIndex + 1)); description.append('\n'); } description.append(String.format("Insert into cell (%1$s,%2$s)", rowString, columnString)); description.append('\n'); description.append( String.format( "Align %1$s, %2$s", horizontalType.name().toLowerCase(Locale.US), verticalType.name().toLowerCase(Locale.US))); feedback.tooltip = description.toString(); } }
public final void testContainsIntInt_Invalid() { // Invalid rects always return false Rect r = new Rect(3, 4, -20, -30); assertFalse(r.contains(3, 4)); }
public final void testContainsRect_Null() { // contains(null) returns false rather than an NPE Rect r = new Rect(3, 4, -20, -30); assertFalse(r.contains((Rect) null)); }
public final void testX2Y2() { Rect r = new Rect(1, 2, 3, 4); assertEquals(4, r.x2()); assertEquals(6, r.y2()); }
public final void testContainsRect() { Rect r = new Rect(3, 4, 20, 30); assertTrue(r.contains(new Rect(3, 4, 5, 10))); assertFalse(r.contains(new Rect(3 - 1, 4, 5, 10))); }
public final void testToString() { Rect r = new Rect(3, 4, 20, 30); assertEquals("Rect [(3,4)-(23,34): 20x30]", r.toString()); }