Home | History | Annotate | Download | only in sdk
      1 /*
      2  * Copyright (C) 2009 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.eclipse.adt.internal.sdk;
     18 
     19 import com.android.ide.eclipse.adt.internal.resources.configurations.CountryCodeQualifier;
     20 import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
     21 import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
     22 import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
     23 import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationStateQualifier;
     24 import com.android.ide.eclipse.adt.internal.resources.configurations.NetworkCodeQualifier;
     25 import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
     26 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
     27 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
     28 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
     29 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
     30 import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
     31 import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
     32 
     33 import org.w3c.dom.Document;
     34 import org.w3c.dom.Element;
     35 
     36 import java.util.Collections;
     37 import java.util.HashMap;
     38 import java.util.Map;
     39 import java.util.Map.Entry;
     40 
     41 /**
     42  * Class representing a layout device.
     43  *
     44  * A Layout device is a collection of {@link FolderConfiguration} that can be used to render Android
     45  * layout files.
     46  *
     47  * It also contains a single xdpi/ydpi that is independent of the {@link FolderConfiguration}.
     48  *
     49  * If the device is meant to represent a true device, then most of the FolderConfigurations' content
     50  * should be identical, with only a few qualifiers (orientation, keyboard state) that would differ.
     51  * However it is simpler to reuse the FolderConfiguration class (with the non changing qualifiers
     52  * duplicated in each configuration) as it's what's being used by the rendering library.
     53  *
     54  * To create, edit and delete LayoutDevice objects, see {@link LayoutDeviceManager}.
     55  * The class is not technically immutable but behaves as such outside of its package.
     56  */
     57 public class LayoutDevice {
     58 
     59     private final String mName;
     60 
     61     /** editable map of the config */
     62     private Map<String, FolderConfiguration> mEditMap = new HashMap<String, FolderConfiguration>();
     63     /** unmodifiable map returned by {@link #getConfigs()}. */
     64     private Map<String, FolderConfiguration> mMap;
     65     private float mXDpi = Float.NaN;
     66     private float mYDpi = Float.NaN;
     67 
     68     LayoutDevice(String name) {
     69         mName = name;
     70     }
     71 
     72     /**
     73      * Saves the Layout Device into a document under a given node
     74      * @param doc the document.
     75      * @param parentNode the parent node.
     76      */
     77     void saveTo(Document doc, Element parentNode) {
     78         // create the device node
     79         Element deviceNode = createNode(doc, parentNode, LayoutDevicesXsd.NODE_DEVICE);
     80 
     81         // create the name attribute (no namespace on this one).
     82         deviceNode.setAttribute(LayoutDevicesXsd.ATTR_NAME, mName);
     83 
     84         // create a default with the x/y dpi
     85         Element defaultNode = createNode(doc, deviceNode, LayoutDevicesXsd.NODE_DEFAULT);
     86         if (Float.isNaN(mXDpi) == false) {
     87             Element xdpiNode = createNode(doc, defaultNode, LayoutDevicesXsd.NODE_XDPI);
     88             xdpiNode.setTextContent(Float.toString(mXDpi));
     89         }
     90         if (Float.isNaN(mYDpi) == false) {
     91             Element xdpiNode = createNode(doc, defaultNode, LayoutDevicesXsd.NODE_YDPI);
     92             xdpiNode.setTextContent(Float.toString(mYDpi));
     93         }
     94 
     95         // then save all the configs.
     96         for (Entry<String, FolderConfiguration> entry : mEditMap.entrySet()) {
     97             saveConfigTo(doc, deviceNode, entry.getKey(), entry.getValue());
     98         }
     99     }
    100 
    101     /**
    102      * Creates and returns a new NS-enabled node.
    103      * @param doc the {@link Document}
    104      * @param parentNode the parent node. The new node is appended to this one as a child.
    105      * @param name the name of the node.
    106      * @return the newly created node.
    107      */
    108     private Element createNode(Document doc, Element parentNode, String name) {
    109         Element newNode = doc.createElementNS(
    110                 LayoutDevicesXsd.NS_LAYOUT_DEVICE_XSD, name);
    111         newNode.setPrefix(doc.lookupPrefix(LayoutDevicesXsd.NS_LAYOUT_DEVICE_XSD));
    112         parentNode.appendChild(newNode);
    113 
    114         return newNode;
    115     }
    116 
    117     /**
    118      * Saves a {@link FolderConfiguration} in a {@link Document}.
    119      * @param doc the Document in which to save
    120      * @param parent the parent node
    121      * @param configName the name of the config
    122      * @param config the config to save
    123      */
    124     private void saveConfigTo(Document doc, Element parent, String configName,
    125             FolderConfiguration config) {
    126         Element configNode = createNode(doc, parent, LayoutDevicesXsd.NODE_CONFIG);
    127 
    128         // create the name attribute (no namespace on this one).
    129         configNode.setAttribute(LayoutDevicesXsd.ATTR_NAME, configName);
    130 
    131         // now do the qualifiers
    132         CountryCodeQualifier ccq = config.getCountryCodeQualifier();
    133         if (ccq != null) {
    134             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_COUNTRY_CODE);
    135             node.setTextContent(Integer.toString(ccq.getCode()));
    136         }
    137 
    138         NetworkCodeQualifier ncq = config.getNetworkCodeQualifier();
    139         if (ncq != null) {
    140             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NETWORK_CODE);
    141             node.setTextContent(Integer.toString(ncq.getCode()));
    142         }
    143 
    144         ScreenSizeQualifier ssq = config.getScreenSizeQualifier();
    145         if (ssq != null) {
    146             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_SIZE);
    147             node.setTextContent(ssq.getFolderSegment());
    148         }
    149 
    150         ScreenRatioQualifier srq = config.getScreenRatioQualifier();
    151         if (srq != null) {
    152             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_RATIO);
    153             node.setTextContent(srq.getFolderSegment());
    154         }
    155 
    156         ScreenOrientationQualifier soq = config.getScreenOrientationQualifier();
    157         if (soq != null) {
    158             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_ORIENTATION);
    159             node.setTextContent(soq.getFolderSegment());
    160         }
    161 
    162         PixelDensityQualifier pdq = config.getPixelDensityQualifier();
    163         if (pdq != null) {
    164             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_PIXEL_DENSITY);
    165             node.setTextContent(pdq.getFolderSegment());
    166         }
    167 
    168         TouchScreenQualifier ttq = config.getTouchTypeQualifier();
    169         if (ttq != null) {
    170             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_TOUCH_TYPE);
    171             node.setTextContent(ttq.getFolderSegment());
    172         }
    173 
    174         KeyboardStateQualifier ksq = config.getKeyboardStateQualifier();
    175         if (ksq != null) {
    176             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_KEYBOARD_STATE);
    177             node.setTextContent(ksq.getFolderSegment());
    178         }
    179 
    180         TextInputMethodQualifier timq = config.getTextInputMethodQualifier();
    181         if (timq != null) {
    182             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_TEXT_INPUT_METHOD);
    183             node.setTextContent(timq.getFolderSegment());
    184         }
    185 
    186         NavigationStateQualifier nsq = config.getNavigationStateQualifier();
    187         if (nsq != null) {
    188             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NAV_STATE);
    189             node.setTextContent(nsq.getFolderSegment());
    190         }
    191 
    192         NavigationMethodQualifier nmq = config.getNavigationMethodQualifier();
    193         if (nmq != null) {
    194             Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NAV_METHOD);
    195             node.setTextContent(nmq.getFolderSegment());
    196         }
    197 
    198         ScreenDimensionQualifier sdq = config.getScreenDimensionQualifier();
    199         if (sdq != null) {
    200             Element sizeNode = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_DIMENSION);
    201 
    202             Element node = createNode(doc, sizeNode, LayoutDevicesXsd.NODE_SIZE);
    203             node.setTextContent(Integer.toString(sdq.getValue1()));
    204 
    205             node = createNode(doc, sizeNode, LayoutDevicesXsd.NODE_SIZE);
    206             node.setTextContent(Integer.toString(sdq.getValue2()));
    207         }
    208     }
    209 
    210     void addConfig(String name, FolderConfiguration config) {
    211         mEditMap.put(name, config);
    212         _seal();
    213     }
    214 
    215     void addConfigs(Map<String, FolderConfiguration> configs) {
    216         mEditMap.putAll(configs);
    217         _seal();
    218     }
    219 
    220     void removeConfig(String name) {
    221         mEditMap.remove(name);
    222         _seal();
    223     }
    224 
    225     /**
    226      * Adds config to the LayoutDevice. This is to be used to add plenty of configurations.
    227      * It must be followed by {@link #_seal()}.
    228      * @param name the name of the config
    229      * @param config the config.
    230      */
    231     void _addConfig(String name, FolderConfiguration config) {
    232         mEditMap.put(name, config);
    233     }
    234 
    235     void _seal() {
    236         mMap = Collections.unmodifiableMap(mEditMap);
    237     }
    238 
    239     void setXDpi(float xdpi) {
    240         mXDpi = xdpi;
    241     }
    242 
    243     void setYDpi(float ydpi) {
    244         mYDpi = ydpi;
    245     }
    246 
    247     public String getName() {
    248         return mName;
    249     }
    250 
    251     public Map<String, FolderConfiguration> getConfigs() {
    252         return mMap;
    253     }
    254 
    255     /**
    256      * Returns the dpi of the Device screen in X.
    257      * @return the dpi of screen or {@link Float#NaN} if it's not set.
    258      */
    259     public float getXDpi() {
    260         return mXDpi;
    261     }
    262 
    263     /**
    264      * Returns the dpi of the Device screen in Y.
    265      * @return the dpi of screen or {@link Float#NaN} if it's not set.
    266      */
    267     public float getYDpi() {
    268         return mYDpi;
    269     }
    270  }
    271