/* * Copyright (C) 2010 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.adt.gscripts; /** * An {@link IViewRule} for android.widget.LinearLayout and all its derived classes. */ public class AndroidWidgetLinearLayoutRule extends BaseLayout { // ==== Drag'n'drop support ==== DropFeedback onDropEnter(INode targetNode, String fqcn) { def bn = targetNode.getBounds(); if (!bn.isValid()) { return; } boolean isVertical = targetNode.getStringAttr("orientation") == "vertical"; // Prepare a list of insertion points: X coords for horizontal, Y for vertical. // Each list is a tuple: 0=pixel coordinate, 1=index of children or -1 for "at end". def indexes = [ ] ; int last = isVertical ? bn.y : bn.x; int pos = 0; targetNode.getChildren().each { def bc = it.getBounds(); if (bc.isValid()) { // add an insertion point between the last point and the start of this child int v = isVertical ? bc.y : bc.x; v = (last + v) / 2; indexes.add( [v, pos++] ); last = isVertical ? (bc.y + bc.h) : (bc.x + bc.w); } } int v = isVertical ? (bn.y + bn.h) : (bn.x + bn.w); v = (last + v) / 2; indexes.add( [v, -1] ); return new DropFeedback( [ "isVertical": isVertical, // boolean: True if vertical linear layout "indexes": indexes, // list(tuple(0:int, 1:int)): insert points (pixels + index) "curr_x": null, // int: Current marker X position "curr_y": null, // int: Current marker Y position "insert_pos": -1 // int: Current drop insert index (-1 for "at the end") ], { gc, node, feedback -> // Paint closure for the LinearLayout. Rect b = node.getBounds(); if (!b.isValid()) { return; } gc.setForeground(gc.registerColor(0x00FFFF00)); gc.setLineStyle(IGraphics.LineStyle.LINE_SOLID); gc.setLineWidth(2); gc.drawRect(b); gc.setLineStyle(IGraphics.LineStyle.LINE_DOT); gc.setLineWidth(1); indexes.each { int i = it[0]; if (isVertical) { // draw horizontal lines gc.drawLine(b.x, i, b.x + b.w, i); } else { // draw vertical lines gc.drawLine(i, b.y, i, b.y + b.h); } } def curr_x = feedback.userData.curr_x; def curr_y = feedback.userData.curr_y; if (curr_x != null && curr_y != null) { gc.setLineStyle(IGraphics.LineStyle.LINE_SOLID); gc.setLineWidth(2); int x = curr_x; int y = curr_y; gc.drawLine(x - 10, y - 10, x + 10, y + 10); gc.drawLine(x + 10, y - 10, x - 10, y + 10); gc.drawRect(x - 10, y - 10, x + 10, y + 10); } }) } DropFeedback onDropMove(INode targetNode, String fqcn, DropFeedback feedback, Point p) { def data = feedback.userData; Rect b = targetNode.getBounds(); if (!b.isValid()) { return feedback; } boolean isVertical = data.isVertical; int bestDist = Integer.MAX_VALUE; int bestIndex = Integer.MIN_VALUE; int bestPos = null; for(index in data.indexes) { int i = index[0]; int pos = index[1]; int dist = (isVertical ? p.y : p.x) - i; if (dist < 0) dist = - dist; if (dist < bestDist) { bestDist = dist; bestIndex = i; bestPos = pos; if (bestDist <= 0) break; } } if (bestIndex != Integer.MIN_VALUE) { def old_x = data.curr_x; def old_y = data.curr_y; if (isVertical) { data.curr_x = b.x + b.w / 2; data.curr_y = bestIndex; } else { data.curr_x = bestIndex; data.curr_y = b.y + b.h / 2; } data.insert_pos = bestPos; feedback.requestPaint = (old_x != data.curr_x) || (old_y != data.curr_y); } return feedback; } void onDropLeave(INode targetNode, String fqcn, DropFeedback feedback) { // ignore } void onDropped(INode targetNode, String fqcn, DropFeedback feedback, Point p) { int insert_pos = feedback.userData.insert_pos; targetNode.debugPrintf("Linear.drop: add ${fqcn} at position ${insert_pos}"); // Get the last component of the FQCN (e.g. "android.view.Button" => "Button") String name = fqcn; name = name[name.lastIndexOf(".")+1 .. name.length()-1]; targetNode.editXml("Add ${name} to LinearLayout") { INode e = targetNode.insertChildAt(fqcn, insert_pos); } } }