1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.eclipse.org/org/documents/epl-v10.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
18
19import com.android.ide.common.api.Margins;
20import com.android.ide.common.api.Rect;
21import com.android.ide.common.api.ResizePolicy;
22import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionHandle.Position;
23import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
24
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.Iterator;
28import java.util.List;
29
30/**
31 * The {@link SelectionHandles} of a {@link SelectionItem} are the set of
32 * {@link SelectionHandle} objects (possibly empty, for non-resizable objects) the user
33 * can manipulate to resize a widget.
34 */
35public class SelectionHandles implements Iterable<SelectionHandle> {
36    private final SelectionItem mItem;
37    private List<SelectionHandle> mHandles;
38
39    /**
40     * Constructs a new {@link SelectionHandles} object for the given {link
41     * {@link SelectionItem}
42     * @param item the item to create {@link SelectionHandles} for
43     */
44    public SelectionHandles(SelectionItem item) {
45        mItem = item;
46
47        createHandles(item.getCanvas());
48    }
49
50    /**
51     * Find a specific {@link SelectionHandle} from this set of {@link SelectionHandles},
52     * which is within the given distance (in layout coordinates) from the center of the
53     * {@link SelectionHandle}.
54     *
55     * @param point the mouse position (in layout coordinates) to test
56     * @param distance the maximum distance from the handle center to accept
57     * @return a {@link SelectionHandle} under the point, or null if not found
58     */
59    public SelectionHandle findHandle(LayoutPoint point, int distance) {
60        for (SelectionHandle handle : mHandles) {
61            if (handle.contains(point, distance)) {
62                return handle;
63            }
64        }
65
66        return null;
67    }
68
69    /**
70     * Create the {@link SelectionHandle} objects for the selection item, according to its
71     * {@link ResizePolicy}.
72     */
73    private void createHandles(LayoutCanvas canvas) {
74        NodeProxy selectedNode = mItem.getNode();
75        Rect r = selectedNode.getBounds();
76        if (!r.isValid()) {
77            mHandles = Collections.emptyList();
78            return;
79        }
80
81        ResizePolicy resizability = mItem.getResizePolicy();
82        if (resizability.isResizable()) {
83            mHandles = new ArrayList<SelectionHandle>(8);
84            boolean left = resizability.leftAllowed();
85            boolean right = resizability.rightAllowed();
86            boolean top = resizability.topAllowed();
87            boolean bottom = resizability.bottomAllowed();
88            int x1 = r.x;
89            int y1 = r.y;
90            int w = r.w;
91            int h = r.h;
92            int x2 = x1 + w;
93            int y2 = y1 + h;
94
95            Margins insets = canvas.getInsets(mItem.getNode().getFqcn());
96            if (insets != null) {
97                x1 += insets.left;
98                x2 -= insets.right;
99                y1 += insets.top;
100                y2 -= insets.bottom;
101            }
102
103            int mx = (x1 + x2) / 2;
104            int my = (y1 + y2) / 2;
105
106            if (left) {
107                mHandles.add(new SelectionHandle(x1, my, Position.LEFT_MIDDLE));
108                if (top) {
109                    mHandles.add(new SelectionHandle(x1, y1, Position.TOP_LEFT));
110                }
111                if (bottom) {
112                    mHandles.add(new SelectionHandle(x1, y2, Position.BOTTOM_LEFT));
113                }
114            }
115            if (right) {
116                mHandles.add(new SelectionHandle(x2, my, Position.RIGHT_MIDDLE));
117                if (top) {
118                    mHandles.add(new SelectionHandle(x2, y1, Position.TOP_RIGHT));
119                }
120                if (bottom) {
121                    mHandles.add(new SelectionHandle(x2, y2, Position.BOTTOM_RIGHT));
122                }
123            }
124            if (top) {
125                mHandles.add(new SelectionHandle(mx, y1, Position.TOP_MIDDLE));
126            }
127            if (bottom) {
128                mHandles.add(new SelectionHandle(mx, y2, Position.BOTTOM_MIDDLE));
129            }
130        } else {
131            mHandles = Collections.emptyList();
132        }
133    }
134
135    // Implements Iterable<SelectionHandle>
136    @Override
137    public Iterator<SelectionHandle> iterator() {
138        return mHandles.iterator();
139    }
140}
141