aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java218
1 files changed, 218 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java
new file mode 100644
index 000000000..b6aeeb486
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/TableLayoutRule.java
@@ -0,0 +1,218 @@
+/*
+ * 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.ide.common.layout;
+
+import static com.android.SdkConstants.FQCN_TABLE_ROW;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.api.DropFeedback;
+import com.android.ide.common.api.IClientRulesEngine;
+import com.android.ide.common.api.IMenuCallback;
+import com.android.ide.common.api.INode;
+import com.android.ide.common.api.INodeHandler;
+import com.android.ide.common.api.IViewRule;
+import com.android.ide.common.api.InsertType;
+import com.android.ide.common.api.RuleAction;
+import com.android.ide.common.api.SegmentType;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An {@link IViewRule} for android.widget.TableLayout.
+ */
+public class TableLayoutRule extends LinearLayoutRule {
+ // A table is a linear layout, but with a few differences:
+ // the default is vertical, not horizontal
+ // The fill of all children should be wrap_content
+
+ private static final String ACTION_ADD_ROW = "_addrow"; //$NON-NLS-1$
+ private static final String ACTION_REMOVE_ROW = "_removerow"; //$NON-NLS-1$
+ private static final URL ICON_ADD_ROW =
+ TableLayoutRule.class.getResource("addrow.png"); //$NON-NLS-1$
+ private static final URL ICON_REMOVE_ROW =
+ TableLayoutRule.class.getResource("removerow.png"); //$NON-NLS-1$
+
+ @Override
+ protected boolean isVertical(INode node) {
+ // Tables are always vertical
+ return true;
+ }
+
+ @Override
+ protected boolean supportsOrientation() {
+ return false;
+ }
+
+ @Override
+ public void onChildInserted(@NonNull INode child, @NonNull INode parent,
+ @NonNull InsertType insertType) {
+ // Overridden to inhibit the setting of layout_width/layout_height since
+ // it should always be match_parent
+ }
+
+ /**
+ * Add an explicit "Add Row" action to the context menu
+ */
+ @Override
+ public void addContextMenuActions(@NonNull List<RuleAction> actions,
+ final @NonNull INode selectedNode) {
+ super.addContextMenuActions(actions, selectedNode);
+
+ IMenuCallback addTab = new IMenuCallback() {
+ @Override
+ public void action(
+ @NonNull RuleAction action,
+ @NonNull List<? extends INode> selectedNodes,
+ final @Nullable String valueId,
+ @Nullable Boolean newValue) {
+ final INode node = selectedNode;
+ INode newRow = node.appendChild(FQCN_TABLE_ROW);
+ mRulesEngine.select(Collections.singletonList(newRow));
+ }
+ };
+ actions.add(RuleAction.createAction("_addrow", "Add Row", addTab, null, 5, false)); //$NON-NLS-1$
+ }
+
+ @Override
+ public void addLayoutActions(
+ @NonNull List<RuleAction> actions,
+ final @NonNull INode parentNode,
+ final @NonNull List<? extends INode> children) {
+ super.addLayoutActions(actions, parentNode, children);
+ addTableLayoutActions(mRulesEngine, actions, parentNode, children);
+ }
+
+ /**
+ * Adds layout actions to add and remove toolbar items
+ */
+ static void addTableLayoutActions(final IClientRulesEngine rulesEngine,
+ List<RuleAction> actions, final INode parentNode,
+ final List<? extends INode> children) {
+ IMenuCallback actionCallback = new IMenuCallback() {
+ @Override
+ public void action(
+ final @NonNull RuleAction action,
+ @NonNull List<? extends INode> selectedNodes,
+ final @Nullable String valueId,
+ final @Nullable Boolean newValue) {
+ parentNode.editXml("Add/Remove Table Row", new INodeHandler() {
+ @Override
+ public void handle(@NonNull INode n) {
+ if (action.getId().equals(ACTION_ADD_ROW)) {
+ // Determine the index of the selection, if any; if there is
+ // a selection, insert the row before the current row, otherwise
+ // append it to the table.
+ int index = -1;
+ INode[] rows = parentNode.getChildren();
+ if (children != null) {
+ findTableIndex:
+ for (INode child : children) {
+ // Find direct child of table layout
+ while (child != null && child.getParent() != parentNode) {
+ child = child.getParent();
+ }
+ if (child != null) {
+ // Compute index of direct child of table layout
+ for (int i = 0; i < rows.length; i++) {
+ if (rows[i] == child) {
+ index = i;
+ break findTableIndex;
+ }
+ }
+ }
+ }
+ }
+ INode newRow;
+ if (index == -1) {
+ newRow = parentNode.appendChild(FQCN_TABLE_ROW);
+ } else {
+ newRow = parentNode.insertChildAt(FQCN_TABLE_ROW, index);
+ }
+ rulesEngine.select(Collections.singletonList(newRow));
+ } else if (action.getId().equals(ACTION_REMOVE_ROW)) {
+ // Find the direct children of the TableLayout to delete;
+ // this is necessary since TableRow might also use
+ // this implementation, so the parentNode is the true
+ // TableLayout but the children might be grand children.
+ Set<INode> targets = new HashSet<INode>();
+ for (INode child : children) {
+ while (child != null && child.getParent() != parentNode) {
+ child = child.getParent();
+ }
+ if (child != null) {
+ targets.add(child);
+ }
+ }
+ for (INode target : targets) {
+ parentNode.removeChild(target);
+ }
+ }
+ }
+ });
+ }
+ };
+
+ // Add Row
+ actions.add(RuleAction.createSeparator(150));
+ actions.add(RuleAction.createAction(ACTION_ADD_ROW, "Add Table Row", actionCallback,
+ ICON_ADD_ROW, 160, false));
+
+ // Remove Row (if something is selected)
+ if (children != null && children.size() > 0) {
+ actions.add(RuleAction.createAction(ACTION_REMOVE_ROW, "Remove Table Row",
+ actionCallback, ICON_REMOVE_ROW, 170, false));
+ }
+ }
+
+ @Override
+ public void onCreate(@NonNull INode node, @NonNull INode parent,
+ @NonNull InsertType insertType) {
+ super.onCreate(node, parent, insertType);
+
+ if (insertType.isCreate()) {
+ // Start the table with 4 rows
+ for (int i = 0; i < 4; i++) {
+ node.appendChild(FQCN_TABLE_ROW);
+ }
+ }
+ }
+
+ @Override
+ public DropFeedback onResizeBegin(@NonNull INode child, @NonNull INode parent,
+ @Nullable SegmentType horizontalEdge, @Nullable SegmentType verticalEdge,
+ @Nullable Object childView, @Nullable Object parentView) {
+ // Children of a table layout cannot set their widths (it is controlled by column
+ // settings on the table). They can set their heights (though for TableRow, the
+ // height is always wrap_content).
+ if (horizontalEdge == null) { // Widths are edited by vertical edges.
+ // The user is not editing a vertical height so don't allow resizing at all
+ return null;
+ }
+ if (child.getFqcn().equals(FQCN_TABLE_ROW)) {
+ // TableRows are always WRAP_CONTENT
+ return null;
+ }
+
+ // Allow resizing heights only
+ return super.onResizeBegin(child, parent, horizontalEdge, null /*verticalEdge*/,
+ childView, parentView);
+ }
+}