aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java
blob: 9bee34345b59672e4e8c77913b185716fdc15f6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * 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.grid.GridModel.UNDEFINED;

import com.android.ide.common.api.INode;
import com.android.ide.common.api.SegmentType;

/**
 * A match for a drag within a GridLayout, corresponding to an alignment with another
 * edge, or a margin, or centering, or a gap distance from another edge and so on.
 */
class GridMatch implements Comparable<GridMatch> {
    /** The distance to the matched edge - used to pick best matches */
    public final int distance;

    /** Type of edge that was matched (this refers to the edge on the dragged node,
     * not on the matched node/row/cell etc) */
    public final SegmentType type;

    /** Row or column for the match */
    public int cellIndex;

    /** If true, create a new row/column */
    public boolean createCell;

    /** The actual x or y position of the matched segment */
    public int matchedLine;

    /** Amount of margin between the matched edges */
    public int margin;

    /**
     * Constructs a match.
     *
     * @param type the edge of the dragged element that was matched
     * @param distance the absolute distance from the ideal match - used to find the best
     *            match
     * @param matchedLine the actual X or Y location of the ideal match
     * @param cellIndex the index of the row or column we matched with
     * @param createCell if true, create a new cell by splitting the existing cell at the
     *            matchedLine position
     * @param margin a margin distance to add to the actual location from the matched line
     */
    GridMatch(SegmentType type, int distance, int matchedLine, int cellIndex,
            boolean createCell, int margin) {
        super();
        this.type = type;
        this.distance = distance;
        this.matchedLine = matchedLine;
        this.cellIndex = cellIndex;
        this.createCell = createCell;
        this.margin = margin;
    }

    // Implements Comparable<GridMatch>
    @Override
    public int compareTo(GridMatch o) {
        // Pick closest matches first
        if (distance != o.distance) {
            return distance - o.distance;
        }

        // Prefer some types of matches over other matches
        return getPriority() - o.getPriority();
    }

    /**
     * Describes the match for the user
     *
     * @param layout the GridLayout containing the match
     * @return a short description for the user of the match
     */
    public String getDisplayName(INode layout) {
        switch (type) {
            case BASELINE:
                return String.format("Align baseline in row %1$d", cellIndex + 1);
            case CENTER_HORIZONTAL:
                return "Center horizontally";
            case LEFT:
                if (!createCell) {
                    return String.format("Insert into column %1$d", cellIndex + 1);
                }
                if (margin != UNDEFINED) {
                    if (cellIndex == 0 && margin != 0) {
                        return "Add one margin distance from the left";
                    }
                    return String.format("Add next to column %1$d", cellIndex + 1);
                }
                return String.format("Align left at x=%1$d", matchedLine - layout.getBounds().x);
            case RIGHT:
                if (!createCell) {
                    return String.format("Insert right-aligned into column %1$d", cellIndex + 1);
                }
                return String.format("Align right at x=%1$d", matchedLine - layout.getBounds().x);
            case TOP:
                if (!createCell) {
                    return String.format("Insert into row %1$d", cellIndex + 1);
                }
                if (margin != UNDEFINED) {
                    if (cellIndex == 0 && margin != 0) {
                        return "Add one margin distance from the top";
                    }
                    return String.format("Add below row %1$d", cellIndex + 1);
                }
                return String.format("Align top at y=%1d", matchedLine - layout.getBounds().y);
            case BOTTOM:
                if (!createCell) {
                    return String.format("Insert into bottom of row %1$d", cellIndex + 1);
                }
                return String.format("Align bottom at y=%1d", matchedLine - layout.getBounds().y);
            case CENTER_VERTICAL:
                return "Center vertically";
            case UNKNOWN:
            default:
                return null;
        }
    }

    /**
     * Computes the sorting priority of this match, giving baseline matches higher
     * precedence than centering which in turn is ordered before external edge matches
     */
    private int getPriority() {
        switch (type) {
            case BASELINE:
                return 0;
            case CENTER_HORIZONTAL:
            case CENTER_VERTICAL:
                return 1;
            case BOTTOM:
            case LEFT:
            case RIGHT:
            case TOP:
                return 2;
        }

        return 3;
    }
}