aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionHandles.java
blob: 6d7f34a66d82019f7ceb07ee4e936ff35cb33452 (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
/*
 * 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.eclipse.adt.internal.editors.layout.gle2;

import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.ResizePolicy;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionHandle.Position;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * The {@link SelectionHandles} of a {@link SelectionItem} are the set of
 * {@link SelectionHandle} objects (possibly empty, for non-resizable objects) the user
 * can manipulate to resize a widget.
 */
public class SelectionHandles implements Iterable<SelectionHandle> {
    private final SelectionItem mItem;
    private List<SelectionHandle> mHandles;

    /**
     * Constructs a new {@link SelectionHandles} object for the given {link
     * {@link SelectionItem}
     * @param item the item to create {@link SelectionHandles} for
     */
    public SelectionHandles(SelectionItem item) {
        mItem = item;

        createHandles(item.getCanvas());
    }

    /**
     * Find a specific {@link SelectionHandle} from this set of {@link SelectionHandles},
     * which is within the given distance (in layout coordinates) from the center of the
     * {@link SelectionHandle}.
     *
     * @param point the mouse position (in layout coordinates) to test
     * @param distance the maximum distance from the handle center to accept
     * @return a {@link SelectionHandle} under the point, or null if not found
     */
    public SelectionHandle findHandle(LayoutPoint point, int distance) {
        for (SelectionHandle handle : mHandles) {
            if (handle.contains(point, distance)) {
                return handle;
            }
        }

        return null;
    }

    /**
     * Create the {@link SelectionHandle} objects for the selection item, according to its
     * {@link ResizePolicy}.
     */
    private void createHandles(LayoutCanvas canvas) {
        NodeProxy selectedNode = mItem.getNode();
        Rect r = selectedNode.getBounds();
        if (!r.isValid()) {
            mHandles = Collections.emptyList();
            return;
        }

        ResizePolicy resizability = mItem.getResizePolicy();
        if (resizability.isResizable()) {
            mHandles = new ArrayList<SelectionHandle>(8);
            boolean left = resizability.leftAllowed();
            boolean right = resizability.rightAllowed();
            boolean top = resizability.topAllowed();
            boolean bottom = resizability.bottomAllowed();
            int x1 = r.x;
            int y1 = r.y;
            int w = r.w;
            int h = r.h;
            int x2 = x1 + w;
            int y2 = y1 + h;

            Margins insets = canvas.getInsets(mItem.getNode().getFqcn());
            if (insets != null) {
                x1 += insets.left;
                x2 -= insets.right;
                y1 += insets.top;
                y2 -= insets.bottom;
            }

            int mx = (x1 + x2) / 2;
            int my = (y1 + y2) / 2;

            if (left) {
                mHandles.add(new SelectionHandle(x1, my, Position.LEFT_MIDDLE));
                if (top) {
                    mHandles.add(new SelectionHandle(x1, y1, Position.TOP_LEFT));
                }
                if (bottom) {
                    mHandles.add(new SelectionHandle(x1, y2, Position.BOTTOM_LEFT));
                }
            }
            if (right) {
                mHandles.add(new SelectionHandle(x2, my, Position.RIGHT_MIDDLE));
                if (top) {
                    mHandles.add(new SelectionHandle(x2, y1, Position.TOP_RIGHT));
                }
                if (bottom) {
                    mHandles.add(new SelectionHandle(x2, y2, Position.BOTTOM_RIGHT));
                }
            }
            if (top) {
                mHandles.add(new SelectionHandle(mx, y1, Position.TOP_MIDDLE));
            }
            if (bottom) {
                mHandles.add(new SelectionHandle(mx, y2, Position.BOTTOM_MIDDLE));
            }
        } else {
            mHandles = Collections.emptyList();
        }
    }

    // Implements Iterable<SelectionHandle>
    @Override
    public Iterator<SelectionHandle> iterator() {
        return mHandles.iterator();
    }
}