Home | History | Annotate | Download | only in layout
      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 
     17 package com.android.ide.common.layout;
     18 
     19 import static com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors.REQUEST_FOCUS;
     20 
     21 import com.android.ide.common.api.IMenuCallback;
     22 import com.android.ide.common.api.INode;
     23 import com.android.ide.common.api.INodeHandler;
     24 import com.android.ide.common.api.IViewRule;
     25 import com.android.ide.common.api.InsertType;
     26 import com.android.ide.common.api.RuleAction;
     27 
     28 import java.util.List;
     29 
     30 /**
     31  * An {@link IViewRule} for android.widget.EditText.
     32  */
     33 public class EditTextRule extends BaseViewRule {
     34 
     35     @Override
     36     public void onCreate(INode node, INode parent, InsertType insertType) {
     37         super.onCreate(node, parent, insertType);
     38 
     39         if (parent != null) {
     40             INode focus = findFocus(findRoot(parent));
     41             if (focus == null) {
     42                 // Add <requestFocus>
     43                 node.appendChild(REQUEST_FOCUS);
     44             }
     45         }
     46     }
     47 
     48     /**
     49      * {@inheritDoc}
     50      * <p>
     51      * Adds a "Request Focus" menu item.
     52      */
     53     @Override
     54     public void addContextMenuActions(List<RuleAction> actions, final INode selectedNode) {
     55         super.addContextMenuActions(actions, selectedNode);
     56 
     57         final boolean hasFocus = hasFocus(selectedNode);
     58         final String label = hasFocus ? "Clear Focus" : "Request Focus";
     59 
     60         IMenuCallback onChange = new IMenuCallback() {
     61             public void action(RuleAction menuAction, List<? extends INode> selectedNodes,
     62                     String valueId, Boolean newValue) {
     63                 selectedNode.editXml(label, new INodeHandler() {
     64                     public void handle(INode node) {
     65                         INode focus = findFocus(findRoot(node));
     66                         if (focus != null && focus.getParent() != null) {
     67                             focus.getParent().removeChild(focus);
     68                         }
     69                         if (!hasFocus) {
     70                             node.appendChild(REQUEST_FOCUS);
     71                         }
     72                     }
     73                 });
     74             }
     75         };
     76 
     77         actions.add(RuleAction.createAction("_setfocus", label, onChange, //$NON-NLS-1$
     78                 null, 5, false /*supportsMultipleNodes*/));
     79         actions.add(RuleAction.createSeparator(7));
     80     }
     81 
     82     /** Returns true if the given node currently has focus */
     83     private static boolean hasFocus(INode node) {
     84         INode focus = findFocus(node);
     85         if (focus != null) {
     86             return focus.getParent() == node;
     87         }
     88 
     89         return false;
     90     }
     91 
     92     /** Returns the root/top level node in the view hierarchy that contains the given node */
     93     private static INode findRoot(INode node) {
     94         // First find the parent
     95         INode root = node;
     96         while (root != null) {
     97             INode parent = root.getParent();
     98             if (parent == null) {
     99                 break;
    100             } else {
    101                 root = parent;
    102             }
    103         }
    104 
    105         return root;
    106     }
    107 
    108     /** Finds the focus node (not the node containing focus, but the actual request focus node
    109      * under a given node */
    110     private static INode findFocus(INode node) {
    111         if (node.getFqcn().equals(REQUEST_FOCUS)) {
    112             return node;
    113         }
    114 
    115         for (INode child : node.getChildren()) {
    116             INode focus = findFocus(child);
    117             if (focus != null) {
    118                 return focus;
    119             }
    120         }
    121         return null;
    122     }
    123 
    124 }
    125