1/* 2 * Copyright (C) 2010 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.adt.gscripts; 18 19/** 20 * An {@link IViewRule} for android.widget.FrameLayout and all its derived classes. 21 */ 22public class AndroidWidgetFrameLayoutRule extends BaseLayout { 23 24 // ==== Drag'n'drop support ==== 25 // The FrameLayout accepts any drag'n'drop anywhere on its surface. 26 27 DropFeedback onDropEnter(INode targetNode, IDragElement[] elements) { 28 if (elements.length == 0) { 29 return null; 30 } 31 32 return new DropFeedback( 33 [ "p": null ], // Point: last cursor position 34 { 35 gc, node, feedback -> 36 // Paint closure for the FrameLayout. 37 38 drawFeedback(gc, node, elements, feedback); 39 }); 40 } 41 42 void drawFeedback(IGraphics gc, 43 INode targetNode, 44 IDragElement[] elements, 45 DropFeedback feedback) { 46 Rect b = targetNode.getBounds(); 47 if (!b.isValid()) { 48 return; 49 } 50 51 gc.setForeground(gc.registerColor(0x00FFFF00)); 52 gc.setLineStyle(IGraphics.LineStyle.LINE_SOLID); 53 gc.setLineWidth(2); 54 gc.drawRect(b); 55 56 // Get the drop point 57 Point p = feedback.userData.p; 58 59 if (p == null) { 60 return; 61 } 62 63 int x = p.x; 64 int y = p.y; 65 66 Rect be = elements[0].getBounds(); 67 68 if (be.isValid()) { 69 // At least the first element has a bound. Draw rectangles 70 // for all dropped elements with valid bounds, offset at 71 // the drop point. 72 int offsetX = x - be.x; 73 int offsetY = y - be.y; 74 elements.each { 75 drawElement(gc, it, offsetX, offsetY); 76 } 77 } else { 78 // We don't have bounds for new elements. In this case 79 // just draw a mark at the drop point. 80 gc.drawLine(x - 10, y - 10, x + 10, y + 10); 81 gc.drawLine(x + 10, y - 10, x - 10, y + 10); 82 gc.drawOval(x - 10, y - 10, x + 10, y + 10); 83 } 84 } 85 86 DropFeedback onDropMove(INode targetNode, 87 IDragElement[] elements, 88 DropFeedback feedback, 89 Point p) { 90 feedback.userData.p = p; 91 feedback.requestPaint = true; 92 return feedback; 93 } 94 95 void onDropLeave(INode targetNode, IDragElement[] elements, DropFeedback feedback) { 96 // ignore 97 } 98 99 void onDropped(INode targetNode, 100 IDragElement[] elements, 101 DropFeedback feedback, 102 Point p) { 103 Rect b = targetNode.getBounds(); 104 if (!b.isValid()) { 105 return; 106 } 107 108 // Collect IDs from dropped elements and remap them to new IDs 109 // if this is a copy or from a different canvas. 110 def idMap = getDropIdMap(targetNode, elements, feedback.isCopy || !feedback.sameCanvas); 111 112 targetNode.editXml("Add elements to FrameLayout") { 113 114 // Now write the new elements. 115 for (element in elements) { 116 String fqcn = element.getFqcn(); 117 Rect be = element.getBounds(); 118 119 INode newChild = targetNode.appendChild(fqcn); 120 121 // Copy all the attributes, modifying them as needed. 122 def attrFilter = getLayoutAttrFilter(); 123 addAttributes(newChild, element, idMap) { 124 uri, name, value -> 125 // TODO need a better way to exclude other layout attributes dynamically 126 if (uri == ANDROID_URI && name in attrFilter) { 127 return false; // don't set these attributes 128 } else { 129 return value; 130 } 131 }; 132 133 addInnerElements(newChild, element, idMap); 134 } 135 } 136 } 137} 138