diff options
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.java | 218 |
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); + } +} |