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 
17 package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
18 
19 import com.android.ide.common.api.Margins;
20 import com.android.ide.common.api.Rect;
21 import com.android.ide.common.api.ResizePolicy;
22 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionHandle.Position;
23 import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
24 
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import 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  */
35 public 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      */
SelectionHandles(SelectionItem item)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      */
findHandle(LayoutPoint point, int distance)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      */
createHandles(LayoutCanvas canvas)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
iterator()137     public Iterator<SelectionHandle> iterator() {
138         return mHandles.iterator();
139     }
140 }
141