PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDevice.java

https://gitlab.com/Codeaurora/platform_sdk
Java | 389 lines | 220 code | 53 blank | 116 comment | 40 complexity | 388c509730cc7ad1fcd61e625e87d879 MD5 | raw file
  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. package com.android.ide.eclipse.adt.internal.sdk;
  17. import com.android.ide.common.resources.configuration.CountryCodeQualifier;
  18. import com.android.ide.common.resources.configuration.DensityQualifier;
  19. import com.android.ide.common.resources.configuration.FolderConfiguration;
  20. import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
  21. import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
  22. import com.android.ide.common.resources.configuration.NavigationStateQualifier;
  23. import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
  24. import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
  25. import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
  26. import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
  27. import com.android.ide.common.resources.configuration.ScreenSizeQualifier;
  28. import com.android.ide.common.resources.configuration.TextInputMethodQualifier;
  29. import com.android.ide.common.resources.configuration.TouchScreenQualifier;
  30. import org.w3c.dom.Document;
  31. import org.w3c.dom.Element;
  32. import java.util.ArrayList;
  33. import java.util.Collections;
  34. import java.util.List;
  35. /**
  36. * Class representing a layout device.
  37. *
  38. * A Layout device is a collection of {@link FolderConfiguration} that can be used to render Android
  39. * layout files.
  40. *
  41. * It also contains a single xdpi/ydpi that is independent of the {@link FolderConfiguration}.
  42. *
  43. * If the device is meant to represent a true device, then most of the FolderConfigurations' content
  44. * should be identical, with only a few qualifiers (orientation, keyboard state) that would differ.
  45. * However it is simpler to reuse the FolderConfiguration class (with the non changing qualifiers
  46. * duplicated in each configuration) as it's what's being used by the rendering library.
  47. *
  48. * To create, edit and delete LayoutDevice objects, see {@link LayoutDeviceManager}.
  49. * The class is not technically immutable but behaves as such outside of its package.
  50. */
  51. public class LayoutDevice {
  52. private final String mName;
  53. /**
  54. * Wrapper around a {@link FolderConfiguration}.
  55. * <p/>This adds a name, accessible through {@link #getName()}.
  56. * <p/>The folder config can be accessed through {@link #getConfig()}.
  57. *
  58. */
  59. public final static class DeviceConfig {
  60. private final String mName;
  61. private final FolderConfiguration mConfig;
  62. DeviceConfig(String name, FolderConfiguration config) {
  63. mName = name;
  64. mConfig = config;
  65. }
  66. public String getName() {
  67. return mName;
  68. }
  69. public FolderConfiguration getConfig() {
  70. return mConfig;
  71. }
  72. }
  73. /** editable list of the config */
  74. private final ArrayList<DeviceConfig> mConfigs = new ArrayList<DeviceConfig>();
  75. /** Read-only list */
  76. private List<DeviceConfig> mROList;
  77. private float mXDpi = Float.NaN;
  78. private float mYDpi = Float.NaN;
  79. LayoutDevice(String name) {
  80. mName = name;
  81. }
  82. /**
  83. * Saves the Layout Device into a document under a given node
  84. * @param doc the document.
  85. * @param parentNode the parent node.
  86. */
  87. void saveTo(Document doc, Element parentNode) {
  88. // create the device node
  89. Element deviceNode = createNode(doc, parentNode, LayoutDevicesXsd.NODE_DEVICE);
  90. // create the name attribute (no namespace on this one).
  91. deviceNode.setAttribute(LayoutDevicesXsd.ATTR_NAME, mName);
  92. // create a default with the x/y dpi
  93. Element defaultNode = createNode(doc, deviceNode, LayoutDevicesXsd.NODE_DEFAULT);
  94. if (Float.isNaN(mXDpi) == false) {
  95. Element xdpiNode = createNode(doc, defaultNode, LayoutDevicesXsd.NODE_XDPI);
  96. xdpiNode.setTextContent(Float.toString(mXDpi));
  97. }
  98. if (Float.isNaN(mYDpi) == false) {
  99. Element xdpiNode = createNode(doc, defaultNode, LayoutDevicesXsd.NODE_YDPI);
  100. xdpiNode.setTextContent(Float.toString(mYDpi));
  101. }
  102. // then save all the configs.
  103. synchronized (mConfigs) {
  104. for (DeviceConfig config : mConfigs) {
  105. saveConfigTo(doc, deviceNode, config.getName(), config.getConfig());
  106. }
  107. }
  108. }
  109. /**
  110. * Creates and returns a new NS-enabled node.
  111. * @param doc the {@link Document}
  112. * @param parentNode the parent node. The new node is appended to this one as a child.
  113. * @param name the name of the node.
  114. * @return the newly created node.
  115. */
  116. private Element createNode(Document doc, Element parentNode, String name) {
  117. Element newNode = doc.createElementNS(
  118. LayoutDevicesXsd.NS_LAYOUT_DEVICE_XSD, name);
  119. newNode.setPrefix(doc.lookupPrefix(LayoutDevicesXsd.NS_LAYOUT_DEVICE_XSD));
  120. parentNode.appendChild(newNode);
  121. return newNode;
  122. }
  123. /**
  124. * Saves a {@link FolderConfiguration} in a {@link Document}.
  125. * @param doc the Document in which to save
  126. * @param parent the parent node
  127. * @param configName the name of the config
  128. * @param config the config to save
  129. */
  130. private void saveConfigTo(Document doc, Element parent, String configName,
  131. FolderConfiguration config) {
  132. Element configNode = createNode(doc, parent, LayoutDevicesXsd.NODE_CONFIG);
  133. // create the name attribute (no namespace on this one).
  134. configNode.setAttribute(LayoutDevicesXsd.ATTR_NAME, configName);
  135. // now do the qualifiers
  136. CountryCodeQualifier ccq = config.getCountryCodeQualifier();
  137. if (ccq != null) {
  138. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_COUNTRY_CODE);
  139. node.setTextContent(Integer.toString(ccq.getCode()));
  140. }
  141. NetworkCodeQualifier ncq = config.getNetworkCodeQualifier();
  142. if (ncq != null) {
  143. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NETWORK_CODE);
  144. node.setTextContent(Integer.toString(ncq.getCode()));
  145. }
  146. ScreenSizeQualifier slsq = config.getScreenSizeQualifier();
  147. if (slsq != null) {
  148. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_SIZE);
  149. node.setTextContent(slsq.getFolderSegment());
  150. }
  151. ScreenRatioQualifier srq = config.getScreenRatioQualifier();
  152. if (srq != null) {
  153. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_RATIO);
  154. node.setTextContent(srq.getFolderSegment());
  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. DensityQualifier dq = config.getDensityQualifier();
  162. if (dq != null) {
  163. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_PIXEL_DENSITY);
  164. node.setTextContent(dq.getFolderSegment());
  165. }
  166. TouchScreenQualifier ttq = config.getTouchTypeQualifier();
  167. if (ttq != null) {
  168. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_TOUCH_TYPE);
  169. node.setTextContent(ttq.getFolderSegment());
  170. }
  171. KeyboardStateQualifier ksq = config.getKeyboardStateQualifier();
  172. if (ksq != null) {
  173. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_KEYBOARD_STATE);
  174. node.setTextContent(ksq.getFolderSegment());
  175. }
  176. TextInputMethodQualifier timq = config.getTextInputMethodQualifier();
  177. if (timq != null) {
  178. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_TEXT_INPUT_METHOD);
  179. node.setTextContent(timq.getFolderSegment());
  180. }
  181. NavigationStateQualifier nsq = config.getNavigationStateQualifier();
  182. if (nsq != null) {
  183. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NAV_STATE);
  184. node.setTextContent(nsq.getFolderSegment());
  185. }
  186. NavigationMethodQualifier nmq = config.getNavigationMethodQualifier();
  187. if (nmq != null) {
  188. Element node = createNode(doc, configNode, LayoutDevicesXsd.NODE_NAV_METHOD);
  189. node.setTextContent(nmq.getFolderSegment());
  190. }
  191. ScreenDimensionQualifier sdq = config.getScreenDimensionQualifier();
  192. if (sdq != null) {
  193. Element sizeNode = createNode(doc, configNode, LayoutDevicesXsd.NODE_SCREEN_DIMENSION);
  194. Element node = createNode(doc, sizeNode, LayoutDevicesXsd.NODE_SIZE);
  195. node.setTextContent(Integer.toString(sdq.getValue1()));
  196. node = createNode(doc, sizeNode, LayoutDevicesXsd.NODE_SIZE);
  197. node.setTextContent(Integer.toString(sdq.getValue2()));
  198. }
  199. }
  200. /**
  201. * Adds config to the LayoutDevice.
  202. * <p/>This ensures that no two configurations have the same. If a config already exists
  203. * with the same name, the new config replaces it.
  204. *
  205. * @param name the name of the config.
  206. * @param config the config.
  207. */
  208. void addConfig(String name, FolderConfiguration config) {
  209. synchronized (mConfigs) {
  210. doAddConfig(name, config);
  211. seal();
  212. }
  213. }
  214. /**
  215. * Adds a list of config to the LayoutDevice
  216. * <p/>This ensures that no two configurations have the same. If a config already exists
  217. * with the same name, the new config replaces it.
  218. * @param configs the configs to add.
  219. */
  220. void addConfigs(List<DeviceConfig> configs) {
  221. synchronized (mConfigs) {
  222. // add the configs manually one by one, to check for no duplicate.
  223. for (DeviceConfig config : configs) {
  224. String name = config.getName();
  225. for (DeviceConfig c : mConfigs) {
  226. if (c.getName().equals(name)) {
  227. mConfigs.remove(c);
  228. break;
  229. }
  230. }
  231. mConfigs.add(config);
  232. }
  233. seal();
  234. }
  235. }
  236. /**
  237. * Removes a config by its name.
  238. * @param name the name of the config to remove.
  239. */
  240. void removeConfig(String name) {
  241. synchronized (mConfigs) {
  242. for (DeviceConfig config : mConfigs) {
  243. if (config.getName().equals(name)) {
  244. mConfigs.remove(config);
  245. seal();
  246. return;
  247. }
  248. }
  249. }
  250. }
  251. /**
  252. * Adds config to the LayoutDevice. This is to be used to add plenty of
  253. * configurations. It must be followed by {@link #_seal()}.
  254. * <p/>This ensures that no two configurations have the same. If a config already exists
  255. * with the same name, the new config replaces it.
  256. * <p/><strong>This must be called inside a <code>synchronized(mConfigs)</code> block.</strong>
  257. *
  258. * @param name the name of the config
  259. * @param config the config.
  260. */
  261. private void doAddConfig(String name, FolderConfiguration config) {
  262. // remove config that would have the same name to ensure no duplicate
  263. for (DeviceConfig c : mConfigs) {
  264. if (c.getName().equals(name)) {
  265. mConfigs.remove(c);
  266. break;
  267. }
  268. }
  269. mConfigs.add(new DeviceConfig(name, config));
  270. }
  271. /**
  272. * Seals the layout device by setting up {@link #mROList}.
  273. * <p/><strong>This must be called inside a <code>synchronized(mConfigs)</code> block.</strong>
  274. */
  275. private void seal() {
  276. mROList = Collections.unmodifiableList(mConfigs);
  277. }
  278. void setXDpi(float xdpi) {
  279. mXDpi = xdpi;
  280. }
  281. void setYDpi(float ydpi) {
  282. mYDpi = ydpi;
  283. }
  284. public String getName() {
  285. return mName;
  286. }
  287. /**
  288. * Returns an unmodifiable list of all the {@link DeviceConfig}.
  289. */
  290. public List<DeviceConfig> getConfigs() {
  291. synchronized (mConfigs) {
  292. return mROList;
  293. }
  294. }
  295. /**
  296. * Returns a {@link DeviceConfig} by its name.
  297. */
  298. public DeviceConfig getDeviceConfigByName(String name) {
  299. synchronized (mConfigs) {
  300. for (DeviceConfig config : mConfigs) {
  301. if (config.getName().equals(name)) {
  302. return config;
  303. }
  304. }
  305. }
  306. return null;
  307. }
  308. /**
  309. * Returns a {@link FolderConfiguration} by its name.
  310. */
  311. public FolderConfiguration getFolderConfigByName(String name) {
  312. synchronized (mConfigs) {
  313. for (DeviceConfig config : mConfigs) {
  314. if (config.getName().equals(name)) {
  315. return config.getConfig();
  316. }
  317. }
  318. }
  319. return null;
  320. }
  321. /**
  322. * Returns the dpi of the Device screen in X.
  323. * @return the dpi of screen or {@link Float#NaN} if it's not set.
  324. */
  325. public float getXDpi() {
  326. return mXDpi;
  327. }
  328. /**
  329. * Returns the dpi of the Device screen in Y.
  330. * @return the dpi of screen or {@link Float#NaN} if it's not set.
  331. */
  332. public float getYDpi() {
  333. return mYDpi;
  334. }
  335. }