diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.editors')
192 files changed, 0 insertions, 32702 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/.classpath b/eclipse/plugins/com.android.ide.eclipse.editors/.classpath deleted file mode 100644 index 66dbeb3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/.classpath +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"> - <accessrules> - <accessrule kind="accessible" pattern="org/eclipse/wst/**/internal/**"/> - </accessrules> - </classpathentry> - <classpathentry kind="lib" path="kxml2-2.3.0.jar"/> - <classpathentry kind="lib" path="layoutlib_api.jar"/> - <classpathentry kind="lib" path="ninepatch.jar"/> - <classpathentry kind="lib" path="layoutlib_utils.jar"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/.project b/eclipse/plugins/com.android.ide.eclipse.editors/.project deleted file mode 100644 index 292c698..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/.project +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>editors</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.pde.ManifestBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.pde.SchemaBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.pde.PluginNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF deleted file mode 100644 index 0bfaff9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF +++ /dev/null @@ -1,56 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Android Editors -Bundle-SymbolicName: com.android.ide.eclipse.editors;singleton:=true -Bundle-Version: 0.8.1.qualifier -Bundle-Activator: com.android.ide.eclipse.editors.EditorsPlugin -Bundle-Vendor: The Android Open Source Project -Require-Bundle: com.android.ide.eclipse.common, - org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.ui.editors, - org.eclipse.jface.text, - org.eclipse.ui.ide, - org.eclipse.wst.sse.ui, - org.eclipse.wst.xml.ui, - org.eclipse.wst.xml.core, - org.eclipse.wst.sse.core, - org.eclipse.ui.forms, - org.eclipse.jdt.core, - org.eclipse.ui.browser, - org.eclipse.jdt.ui, - org.eclipse.gef, - org.eclipse.ui.views, - org.eclipse.ui.console -Eclipse-LazyStart: true -Export-Package: com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests" -Bundle-ClassPath: kxml2-2.3.0.jar, - ., - layoutlib_api.jar, - ninepatch.jar, - layoutlib_utils.jar diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL b/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL deleted file mode 100644 index e69de29..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE b/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE deleted file mode 100644 index 49c101d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE +++ /dev/null @@ -1,224 +0,0 @@ -*Eclipse Public License - v 1.0* - -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE -PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF -THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -*1. DEFINITIONS* - -"Contribution" means: - -a) in the case of the initial Contributor, the initial code and -documentation distributed under this Agreement, and -b) in the case of each subsequent Contributor: - -i) changes to the Program, and - -ii) additions to the Program; - -where such changes and/or additions to the Program originate from and -are distributed by that particular Contributor. A Contribution -'originates' from a Contributor if it was added to the Program by such -Contributor itself or anyone acting on such Contributor's behalf. -Contributions do not include additions to the Program which: (i) are -separate modules of software distributed in conjunction with the Program -under their own license agreement, and (ii) are not derivative works of -the Program. - -"Contributor" means any person or entity that distributes the Program. - -"Licensed Patents " mean patent claims licensable by a Contributor which -are necessarily infringed by the use or sale of its Contribution alone -or when combined with the Program. - -"Program" means the Contributions distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors. - -*2. GRANT OF RIGHTS* - -a) Subject to the terms of this Agreement, each Contributor hereby -grants Recipient a non-exclusive, worldwide, royalty-free copyright -license to reproduce, prepare derivative works of, publicly display, -publicly perform, distribute and sublicense the Contribution of such -Contributor, if any, and such derivative works, in source code and -object code form. - -b) Subject to the terms of this Agreement, each Contributor hereby -grants Recipient a non-exclusive, worldwide, royalty-free patent license -under Licensed Patents to make, use, sell, offer to sell, import and -otherwise transfer the Contribution of such Contributor, if any, in -source code and object code form. This patent license shall apply to the -combination of the Contribution and the Program if, at the time the -Contribution is added by the Contributor, such addition of the -Contribution causes such combination to be covered by the Licensed -Patents. The patent license shall not apply to any other combinations -which include the Contribution. No hardware per se is licensed hereunder. - -c) Recipient understands that although each Contributor grants the -licenses to its Contributions set forth herein, no assurances are -provided by any Contributor that the Program does not infringe the -patent or other intellectual property rights of any other entity. Each -Contributor disclaims any liability to Recipient for claims brought by -any other entity based on infringement of intellectual property rights -or otherwise. As a condition to exercising the rights and licenses -granted hereunder, each Recipient hereby assumes sole responsibility to -secure any other intellectual property rights needed, if any. For -example, if a third party patent license is required to allow Recipient -to distribute the Program, it is Recipient's responsibility to acquire -that license before distributing the Program. - -d) Each Contributor represents that to its knowledge it has sufficient -copyright rights in its Contribution, if any, to grant the copyright -license set forth in this Agreement. - -*3. REQUIREMENTS* - -A Contributor may choose to distribute the Program in object code form -under its own license agreement, provided that: - -a) it complies with the terms and conditions of this Agreement; and - -b) its license agreement: - -i) effectively disclaims on behalf of all Contributors all warranties -and conditions, express and implied, including warranties or conditions -of title and non-infringement, and implied warranties or conditions of -merchantability and fitness for a particular purpose; - -ii) effectively excludes on behalf of all Contributors all liability for -damages, including direct, indirect, special, incidental and -consequential damages, such as lost profits; - -iii) states that any provisions which differ from this Agreement are -offered by that Contributor alone and not by any other party; and - -iv) states that source code for the Program is available from such -Contributor, and informs licensees how to obtain it in a reasonable -manner on or through a medium customarily used for software exchange. - -When the Program is made available in source code form: - -a) it must be made available under this Agreement; and - -b) a copy of this Agreement must be included with each copy of the Program. - -Contributors may not remove or alter any copyright notices contained -within the Program. - -Each Contributor must identify itself as the originator of its -Contribution, if any, in a manner that reasonably allows subsequent -Recipients to identify the originator of the Contribution. - -*4. COMMERCIAL DISTRIBUTION* - -Commercial distributors of software may accept certain responsibilities -with respect to end users, business partners and the like. While this -license is intended to facilitate the commercial use of the Program, the -Contributor who includes the Program in a commercial product offering -should do so in a manner which does not create potential liability for -other Contributors. Therefore, if a Contributor includes the Program in -a commercial product offering, such Contributor ("Commercial -Contributor") hereby agrees to defend and indemnify every other -Contributor ("Indemnified Contributor") against any losses, damages and -costs (collectively "Losses") arising from claims, lawsuits and other -legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the -Program in a commercial product offering. The obligations in this -section do not apply to any claims or Losses relating to any actual or -alleged intellectual property infringement. In order to qualify, an -Indemnified Contributor must: a) promptly notify the Commercial -Contributor in writing of such claim, and b) allow the Commercial -Contributor to control, and cooperate with the Commercial Contributor -in, the defense and any related settlement negotiations. The Indemnified -Contributor may participate in any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial -product offering, Product X. That Contributor is then a Commercial -Contributor. If that Commercial Contributor then makes performance -claims, or offers warranties related to Product X, those performance -claims and warranties are such Commercial Contributor's responsibility -alone. Under this section, the Commercial Contributor would have to -defend claims against the other Contributors related to those -performance claims and warranties, and if a court requires any other -Contributor to pay any damages as a result, the Commercial Contributor -must pay those damages. - -*5. NO WARRANTY* - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED -ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES -OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR -A PARTICULAR PURPOSE. Each Recipient is solely responsible for -determining the appropriateness of using and distributing the Program -and assumes all risks associated with its exercise of rights under this -Agreement , including but not limited to the risks and costs of program -errors, compliance with applicable laws, damage to or loss of data, -programs or equipment, and unavailability or interruption of operations. - -*6. DISCLAIMER OF LIABILITY* - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR -ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING -WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR -DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED -HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -*7. GENERAL* - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of -the remainder of the terms of this Agreement, and without further action -by the parties hereto, such provision shall be reformed to the minimum -extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity (including -a cross-claim or counterclaim in a lawsuit) alleging that the Program -itself (excluding combinations of the Program with other software or -hardware) infringes such Recipient's patent(s), then such Recipient's -rights granted under Section 2(b) shall terminate as of the date such -litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it fails -to comply with any of the material terms or conditions of this Agreement -and does not cure such failure in a reasonable period of time after -becoming aware of such noncompliance. If all Recipient's rights under -this Agreement terminate, Recipient agrees to cease use and distribution -of the Program as soon as reasonably practicable. However, Recipient's -obligations under this Agreement and any licenses granted by Recipient -relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, -but in order to avoid inconsistency the Agreement is copyrighted and may -only be modified in the following manner. The Agreement Steward reserves -the right to publish new versions (including revisions) of this -Agreement from time to time. No one other than the Agreement Steward has -the right to modify this Agreement. The Eclipse Foundation is the -initial Agreement Steward. The Eclipse Foundation may assign the -responsibility to serve as the Agreement Steward to a suitable separate -entity. Each new version of the Agreement will be given a distinguishing -version number. The Program (including Contributions) may always be -distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is -published, Contributor may elect to distribute the Program (including -its Contributions) under the new version. Except as expressly stated in -Sections 2(a) and 2(b) above, Recipient receives no rights or licenses -to the intellectual property of any Contributor under this Agreement, -whether expressly, by implication, estoppel or otherwise. All rights in -the Program not expressly granted under this Agreement are reserved. - -This Agreement is governed by the laws of the State of New York and the -intellectual property laws of the United States of America. No party to -this Agreement will bring a legal action under this Agreement more than -one year after the cause of action arose. Each party waives its rights -to a jury trial in any resulting litigation. - - - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/build.properties b/eclipse/plugins/com.android.ide.eclipse.editors/build.properties deleted file mode 100644 index 0a7bc7d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/build.properties +++ /dev/null @@ -1,10 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - plugin.xml,\ - icons/,\ - layoutlib_api.jar,\ - kxml2-2.3.0.jar,\ - ninepatch.jar,\ - layoutlib_utils.jar diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png Binary files differdeleted file mode 100644 index eefc2ca..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png Binary files differdeleted file mode 100644 index 3779d4d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png Binary files differdeleted file mode 100644 index 64e3601..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png Binary files differdeleted file mode 100644 index 5d92f76..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png Binary files differdeleted file mode 100644 index db5fab8..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png Binary files differdeleted file mode 100644 index 10057c8..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png Binary files differdeleted file mode 100644 index 36cd223..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png Binary files differdeleted file mode 100644 index fae5e96..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png Binary files differdeleted file mode 100644 index 1eecf2c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png Binary files differdeleted file mode 100644 index 7911a85..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png Binary files differdeleted file mode 100644 index a727dd5..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png Binary files differdeleted file mode 100644 index 7e939c2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png Binary files differdeleted file mode 100644 index aefffe4..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png Binary files differdeleted file mode 100644 index c2bb79a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png Binary files differdeleted file mode 100644 index 423c3cd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png Binary files differdeleted file mode 100644 index 9cfb53f..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png Binary files differdeleted file mode 100644 index b4ddc87..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png Binary files differdeleted file mode 100644 index 6536576..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png Binary files differdeleted file mode 100644 index 35b9a46..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png Binary files differdeleted file mode 100644 index ca3b6ed..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png Binary files differdeleted file mode 100644 index afdc16c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png +++ /dev/null diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml deleted file mode 100644 index 2678a5d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml +++ /dev/null @@ -1,107 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?eclipse version="3.2"?> -<plugin> - <extension - point="org.eclipse.ui.editors"> - <editor - class="com.android.ide.eclipse.editors.manifest.ManifestEditor" - default="true" - filenames="AndroidManifest.xml" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.manifest.ManifestEditor" - name="Android Manifest Editor"> - </editor> - <editor - class="com.android.ide.eclipse.editors.resources.ResourcesEditor" - default="false" - extensions="xml" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.resources.ResourcesEditor" - name="Android Resource Editor"> - </editor> - <editor - class="com.android.ide.eclipse.editors.layout.LayoutEditor" - default="false" - extensions="xml" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.layout.LayoutEditor" - matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy" - name="Android Layout Editor"> - </editor> - <editor - class="com.android.ide.eclipse.editors.menu.MenuEditor" - default="false" - extensions="xml" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.menu.MenuEditor" - name="Android Menu Editor"> - </editor> - <editor - class="com.android.ide.eclipse.editors.xml.XmlEditor" - default="false" - extensions="xml" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.xml.XmlEditor" - name="Android Xml Resources Editor"> - </editor> - </extension> - <extension - point="org.eclipse.wst.sse.ui.editorConfiguration"> - <sourceViewerConfiguration - class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig" - target="com.android.ide.eclipse.editors.manifest.ManifestEditor"> - </sourceViewerConfiguration> - <sourceViewerConfiguration - class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig" - target="com.android.ide.eclipse.editors.resources.ResourcesEditor"> - </sourceViewerConfiguration> - <sourceViewerConfiguration - class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig" - target="com.android.ide.eclipse.editors.layout.LayoutEditor"> - </sourceViewerConfiguration> - <sourceViewerConfiguration - class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig" - target="com.android.ide.eclipse.editors.menu.MenuEditor"> - </sourceViewerConfiguration> - <sourceViewerConfiguration - class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig" - target="com.android.ide.eclipse.editors.xml.XmlEditor"> - </sourceViewerConfiguration> - </extension> - <extension - point="org.eclipse.ui.views"> - <view - allowMultiple="false" - category="com.android.ide.eclipse.ddms.views.category" - class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView" - name="Resource Explorer"> - </view> - </extension> - <extension - point="org.eclipse.ui.newWizards"> - <wizard - canFinishEarly="false" - category="com.android.ide.eclipse.wizards.category" - class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard" - finalPerspective="org.eclipse.jdt.ui.JavaPerspective" - hasPages="true" - icon="icons/android.png" - id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard" - name="Android XML File" - preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective" - project="false"> - </wizard> - </extension> - <extension - point="org.eclipse.ui.perspectiveExtensions"> - <perspectiveExtension - targetID="org.eclipse.jdt.ui.JavaPerspective"> - <newWizardShortcut - id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"> - </newWizardShortcut> - </perspectiveExtension> - </extension> - -</plugin> diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java deleted file mode 100644 index 1dd0c27..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.TextSelection; -import org.eclipse.jface.text.contentassist.CompletionProposal; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.contentassist.IContentAssistProcessor; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.contentassist.IContextInformationValidator; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.regex.Pattern; - -/** - * Content Assist Processor for Android XML files - */ -public abstract class AndroidContentAssist implements IContentAssistProcessor { - - /** Regexp to detect a full attribute after an element tag. - * <pre>Syntax: - * name = "..." quoted string with all but < and " - * or: - * name = '...' quoted string with all but < and ' - * </pre> - */ - private static Pattern sFirstAttribute = Pattern.compile( - "^ *[a-zA-Z_:]+ *= *(?:\"[^<\"]*\"|'[^<']*')"); //$NON-NLS-1$ - - /** Regexp to detect an element tag name */ - private static Pattern sFirstElementWord = Pattern.compile("^[a-zA-Z0-9_:]+"); //$NON-NLS-1$ - - /** Regexp to detect whitespace */ - private static Pattern sWhitespace = Pattern.compile("\\s+"); //$NON-NLS-1$ - - protected final static String ROOT_ELEMENT = ""; - - /** Descriptor of the root of the XML hierarchy. This a "fake" ElementDescriptor which - * is used to list all the possible roots given by actual implementations. */ - private ElementDescriptor mRootDescriptor; - - /** - * Constructor for AndroidContentAssist - * @param rootElementDescriptors The valid root elements of the XML hierarchy - */ - public AndroidContentAssist(ElementDescriptor[] rootElementDescriptors) { - mRootDescriptor = new ElementDescriptor("", rootElementDescriptors); - } - - /** - * Returns a list of completion proposals based on the - * specified location within the document that corresponds - * to the current cursor position within the text viewer. - * - * @param viewer the viewer whose document is used to compute the proposals - * @param offset an offset within the document for which completions should be computed - * @return an array of completion proposals or <code>null</code> if no proposals are possible - * - * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int) - */ - public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { - - AndroidEditor editor = getAndroidEditor(viewer); - UiElementNode rootUiNode = editor.getUiRootNode(); - - Object[] choices = null; /* An array of ElementDescriptor, or AttributeDescriptor - or String or null */ - String parent = ""; //$NON-NLS-1$ - String wordPrefix = extractElementPrefix(viewer, offset); - char needTag = 0; - boolean isElement = false; - boolean isAttribute = false; - - Node currentNode = getNode(viewer, offset); - if (currentNode == null) - return null; - - // check to see if we can find a UiElementNode matching this XML node - UiElementNode currentUiNode = - rootUiNode == null ? null : rootUiNode.findXmlNode(currentNode); - - if (currentNode.getNodeType() == Node.ELEMENT_NODE) { - parent = currentNode.getNodeName(); - - if (wordPrefix.equals(parent)) { - // We are still editing the element's tag name, not the attributes - // (the element's tag name may not even be complete) - isElement = true; - choices = getChoicesForElement(parent, currentNode); - } else { - // We're not editing the current node name, so we might be editing its - // attributes instead... - isAttribute = true; - AttribInfo info = parseAttributeInfo(viewer, offset); - if (info != null) { - // We're editing attributes in an element node (either the attributes' names - // or their values). - choices = getChoicesForAttribute(parent, currentNode, currentUiNode, info); - - if (info.correctedPrefix != null) { - wordPrefix = info.correctedPrefix; - } - needTag = info.needTag; - } - } - } else if (currentNode.getNodeType() == Node.TEXT_NODE) { - isElement = true; - // Examine the parent of the text node. - choices = getChoicesForTextNode(currentNode); - } - - // Abort if we can't recognize the context or there are no completion choices - if (choices == null || choices.length == 0) return null; - - if (isElement) { - // If we found some suggestions, do we need to add an opening "<" bracket - // for the element? We don't if the cursor is right after "<" or "</". - // Per XML Spec, there's no whitespace between "<" or "</" and the tag name. - int offset2 = offset - wordPrefix.length() - 1; - int c1 = extractChar(viewer, offset2); - if (!((c1 == '<') || (c1 == '/' && extractChar(viewer, offset2 - 1) == '<'))) { - needTag = '<'; - } - } - - // get the selection length - int selectionLength = 0; - ISelection selection = viewer.getSelectionProvider().getSelection(); - if (selection instanceof TextSelection) { - TextSelection textSelection = (TextSelection)selection; - selectionLength = textSelection.getLength(); - } - - return computeProposals(offset, currentNode, choices, wordPrefix, needTag, - isAttribute, selectionLength); - } - - /** - * Returns the namespace prefix matching the Android Resource URI. - * If no such declaration is found, returns the default "android" prefix. - * - * @param node The current node. Must not be null. - * @param nsUri The namespace URI of which the prefix is to be found, - * e.g. AndroidConstants.NS_RESOURCES - * @return The first prefix declared or the default "android" prefix. - */ - private String lookupNamespacePrefix(Node node, String nsUri) { - // Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java - // The following emulates this: - // String prefix = node.lookupPrefix(AndroidConstants.NS_RESOURCES); - - if (XmlnsAttributeDescriptor.XMLNS_URI.equals(nsUri)) { - return "xmlns"; //$NON-NLS-1$ - } - - HashSet<String> visited = new HashSet<String>(); - - String prefix = null; - for (; prefix == null && - node != null && - node.getNodeType() == Node.ELEMENT_NODE; - node = node.getParentNode()) { - NamedNodeMap attrs = node.getAttributes(); - for (int n = attrs.getLength() - 1; n >= 0; --n) { - Node attr = attrs.item(n); - if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$ - String uri = attr.getNodeValue(); - if (AndroidConstants.NS_RESOURCES.equals(uri)) { - return attr.getLocalName(); - } - visited.add(uri); - } - } - } - - // Use a sensible default prefix if we can't find one. - // We need to make sure the prefix is not one that was declared in the scope - // visited above. - prefix = AndroidConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$ - String base = prefix; - for (int i = 1; visited.contains(prefix); i++) { - prefix = base + Integer.toString(i); - } - return prefix; - } - - /** - * Gets the choices when the user is editing the name of an XML element. - * <p/> - * The user is editing the name of an element (the "parent"). - * Find the grand-parent and if one is found, return its children element list. - * The name which is being edited should be one of those. - * <p/> - * Example: <manifest><applic*cursor* => returns the list of all elements that - * can be found under <manifest>, of which <application> is one of the choices. - * - * @return an ElementDescriptor[] or null if no valid element was found. - */ - private Object[] getChoicesForElement(String parent, Node current_node) { - ElementDescriptor grandparent = null; - if (current_node.getParentNode().getNodeType() == Node.ELEMENT_NODE) { - grandparent = getDescriptor(current_node.getParentNode().getNodeName()); - } else if (current_node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) { - grandparent = mRootDescriptor; - } - if (grandparent != null) { - for (ElementDescriptor e : grandparent.getChildren()) { - if (e.getXmlName().startsWith(parent)) { - return grandparent.getChildren(); - } - } - } - - return null; - } - - /** - * Gets the choices when the user is editing an XML attribute. - * <p/> - * In input, attrInfo contains details on the analyzed context, namely whether the - * user is editing an attribute value (isInValue) or an attribute name. - * <p/> - * In output, attrInfo also contains two possible new values (this is a hack to circumvent - * the lack of out-parameters in Java): - * - AttribInfo.correctedPrefix if the user has been editing an attribute value and it has - * been detected that what the user typed is different from what extractElementPrefix() - * predicted. This happens because extractElementPrefix() stops when a character that - * cannot be an element name appears whereas parseAttributeInfo() uses a grammar more - * lenient as suitable for attribute values. - * - AttribInfo.needTag will be non-zero if we find that the attribute completion proposal - * must be double-quoted. - * @param currentUiNode - * - * @return an AttributeDescriptor[] if the user is editing an attribute name. - * a String[] if the user is editing an attribute value with some known values, - * or null if nothing is known about the context. - */ - private Object[] getChoicesForAttribute(String parent, - Node currentNode, UiElementNode currentUiNode, AttribInfo attrInfo) { - Object[] choices = null; - if (attrInfo.isInValue) { - // Editing an attribute's value... Get the attribute name and then the - // possible choice for the tuple(parent,attribute) - String value = attrInfo.value; - if (value.startsWith("'") || value.startsWith("\"")) { //$NON-NLS-1$ //$NON-NLS-2$ - value = value.substring(1); - // The prefix that was found at the beginning only scan for characters - // valid of tag name. We now know the real prefix for this attribute's - // value, which is needed to generate the completion choices below. - attrInfo.correctedPrefix = value; - } else { - attrInfo.needTag = '"'; - } - - if (currentUiNode != null) { - // look for an UI attribute matching the current attribute name - String attrName = attrInfo.name; - - UiAttributeNode currAttrNode = null; - for (UiAttributeNode attrNode : currentUiNode.getUiAttributes()) { - if (attrNode.getDescriptor().getXmlLocalName().equals(attrName)) { - currAttrNode = attrNode; - break; - } - } - - if (currAttrNode != null) { - choices = currAttrNode.getPossibleValues(); - - if (currAttrNode instanceof UiFlagAttributeNode) { - // A "flag" can consist of several values separated by "or" (|). - // If the correct prefix contains such a pipe character, we change - // it so that only the currently edited value is completed. - int pos = value.indexOf('|'); - if (pos >= 0) { - attrInfo.correctedPrefix = value = value.substring(pos + 1); - attrInfo.needTag = 0; - } - } - } - } - - if (choices == null) { - // fallback on the older descriptor-only based lookup. - - // in order to properly handle the special case of the name attribute in - // the action tag, we need the grandparent of the action node, to know - // what type of actions we need. - // e.g. activity -> intent-filter -> action[@name] - String greatGrandParentName = null; - Node grandParent = currentNode.getParentNode(); - if (grandParent != null) { - Node greatGrandParent = grandParent.getParentNode(); - if (greatGrandParent != null) { - greatGrandParentName = greatGrandParent.getLocalName(); - } - } - choices = FrameworkResourceManager.getInstance().getValues( - parent, attrInfo.name, greatGrandParentName); - } - } else { - // Editing an attribute's name... Get attributes valid for the parent node. - if (currentUiNode != null) { - choices = currentUiNode.getAttributeDescriptors(); - } else { - ElementDescriptor parent_desc = getDescriptor(parent); - choices = parent_desc.getAttributes(); - } - } - return choices; - } - - /** - * Gets the choices when the user is editing an XML text node. - * <p/> - * This means the user is editing outside of any XML element or attribute. - * Simply return the list of XML elements that can be present there, based on the - * parent of the current node. - * - * @return An ElementDescriptor[] or null. - */ - private Object[] getChoicesForTextNode(Node currentNode) { - Object[] choices = null; - String parent; - Node parent_node = currentNode.getParentNode(); - if (parent_node.getNodeType() == Node.ELEMENT_NODE) { - // We're editing a text node which parent is an element node. Limit - // content assist to elements valid for the parent. - parent = parent_node.getNodeName(); - ElementDescriptor desc = getDescriptor(parent); - if (desc != null) { - choices = desc.getChildren(); - } - } else if (parent_node.getNodeType() == Node.DOCUMENT_NODE) { - // We're editing a text node at the first level (i.e. root node). - // Limit content assist to the only valid root elements. - choices = mRootDescriptor.getChildren(); - } - return choices; - } - - /** - * Given a list of choices found, generates the proposals to be displayed to the user. - * <p/> - * Choices is an object array. Items of the array can be: - * - ElementDescriptor: a possible element descriptor which XML name should be completed. - * - AttributeDescriptor: a possible attribute descriptor which XML name should be completed. - * - String: string values to display as-is to the user. Typically those are possible - * values for a given attribute. - * - * @return The ICompletionProposal[] to display to the user. - */ - private ICompletionProposal[] computeProposals(int offset, Node currentNode, - Object[] choices, String wordPrefix, char need_tag, - boolean is_attribute, int selectionLength) { - ArrayList<CompletionProposal> proposals = new ArrayList<CompletionProposal>(); - HashMap<String, String> nsUriMap = new HashMap<String, String>(); - - for (Object choice : choices) { - String keyword = null; - String nsPrefix = null; - Image icon = null; - String tooltip = null; - if (choice instanceof ElementDescriptor) { - keyword = ((ElementDescriptor)choice).getXmlName(); - icon = ((ElementDescriptor)choice).getIcon(); - tooltip = DescriptorsUtils.formatTooltip(((ElementDescriptor)choice).getTooltip()); - } else if (choice instanceof TextValueDescriptor) { - continue; // Value nodes are not part of the completion choices - } else if (choice instanceof SeparatorAttributeDescriptor) { - continue; // not real attribute descriptors - } else if (choice instanceof AttributeDescriptor) { - keyword = ((AttributeDescriptor)choice).getXmlLocalName(); - icon = ((AttributeDescriptor)choice).getIcon(); - if (choice instanceof TextAttributeDescriptor) { - tooltip = ((TextAttributeDescriptor) choice).getTooltip(); - } - - String nsUri = ((AttributeDescriptor)choice).getNamespaceUri(); - nsPrefix = nsUriMap.get(nsUri); - if (nsPrefix == null) { - nsPrefix = lookupNamespacePrefix(currentNode, nsUri); - nsUriMap.put(nsUri, nsPrefix); - } - if (nsPrefix != null) { - nsPrefix += ":"; //$NON-NLS-1$ - } - - } else if (choice instanceof String) { - keyword = (String) choice; - } else { - continue; // discard unknown choice - } - - if (keyword.startsWith(wordPrefix) || - (nsPrefix != null && keyword.startsWith(nsPrefix))) { - if (nsPrefix != null) { - keyword = nsPrefix + keyword; - } - String end_tag = ""; //$NON-NLS-1$ - if (need_tag != 0) { - if (need_tag == '"') { - keyword = need_tag + keyword; - end_tag = String.valueOf(need_tag); - } else if (need_tag == '<') { - if (elementCanHaveChildren(choice)) { - end_tag = String.format("></%1$s>", keyword); //$NON-NLS-1$ - keyword = need_tag + keyword; - } else { - keyword = need_tag + keyword; - end_tag = "/>"; //$NON-NLS-1$ - } - } - } - CompletionProposal proposal = new CompletionProposal( - keyword + end_tag, // String replacementString - offset - wordPrefix.length(), // int replacementOffset - wordPrefix.length() + selectionLength, // int replacementLength - keyword.length(), // int cursorPosition (rel. to rplcmntOffset) - icon, // Image image - null, // String displayString - null, // IContextInformation contextInformation - tooltip // String additionalProposalInfo - ); - - proposals.add(proposal); - } - } - - return proposals.toArray(new ICompletionProposal[proposals.size()]); - } - - /** - * Indicates whether this descriptor describes an element that can potentially - * have children (either sub-elements or text value). If an element can have children, - * we want to explicitly write an opening and a separate closing tag. - * <p/> - * Elements can have children if the descriptor has children element descriptors - * or if one of the attributes is a TextValueDescriptor. - * - * @param descriptor An ElementDescriptor or an AttributeDescriptor - * @return True if the descriptor is an ElementDescriptor that can have children or a text value - */ - private boolean elementCanHaveChildren(Object descriptor) { - if (descriptor instanceof ElementDescriptor) { - ElementDescriptor desc = (ElementDescriptor) descriptor; - if (desc.hasChildren()) { - return true; - } - for (AttributeDescriptor attr_desc : desc.getAttributes()) { - if (attr_desc instanceof TextValueDescriptor) { - return true; - } - } - } - return false; - } - - /** - * Returns the element descriptor matching a given XML node name or null if it can't be - * found. - * <p/> - * This is simplistic; ideally we should consider the parent's chain to make sure we - * can differentiate between different hierarchy trees. Right now the first match found - * is returned. - */ - private ElementDescriptor getDescriptor(String nodeName) { - return mRootDescriptor.findChildrenDescriptor(nodeName, true /* recursive */); - } - - public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { - return null; - } - - /** - * Returns the characters which when entered by the user should - * automatically trigger the presentation of possible completions. - * - * In our case, we auto-activate on opening tags and attributes namespace. - * - * @return the auto activation characters for completion proposal or <code>null</code> - * if no auto activation is desired - */ - public char[] getCompletionProposalAutoActivationCharacters() { - return new char[]{ '<', ':', '=' }; - } - - public char[] getContextInformationAutoActivationCharacters() { - return null; - } - - public IContextInformationValidator getContextInformationValidator() { - return null; - } - - public String getErrorMessage() { - return null; - } - - /** - * Heuristically extracts the prefix used for determining template relevance - * from the viewer's document. The default implementation returns the String from - * offset backwards that forms a potential XML element name. - * - * Code extracted from org.eclipse.jface.text.templatesTemplateCompletionProcessor - * and adapted to our needs. - * - * @param viewer the viewer - * @param offset offset into document - * @return the prefix to consider - */ - protected String extractElementPrefix(ITextViewer viewer, int offset) { - int i = offset; - IDocument document = viewer.getDocument(); - if (i > document.getLength()) return ""; //$NON-NLS-1$ - - try { - for (; i > 0; --i) { - char ch = document.getChar(i - 1); - // accepted characters are a-z and : (for attributes' namespace) - if (ch != ':' && (ch < 'a' || ch > 'z')) break; - } - - return document.get(i, offset - i); - } catch (BadLocationException e) { - return ""; //$NON-NLS-1$ - } - } - - /** - * Extracts the character at the given offset. - * Returns 0 if the offset is invalid. - */ - protected char extractChar(ITextViewer viewer, int offset) { - IDocument document = viewer.getDocument(); - if (offset > document.getLength()) return 0; - - try { - return document.getChar(offset); - } catch (BadLocationException e) { - return 0; - } - } - - /** - * Information about the current edit of an attribute as reported by parseAttributeInfo. - */ - private class AttribInfo { - /** True if the cursor is located in an attribute's value, false if in an attribute name */ - public boolean isInValue = false; - /** The attribute name. Null when not set. */ - public String name = null; - /** The attribute value. Null when not set. The value *may* start with a quote - * (' or "), in which case we know we don't need to quote the string for the user */ - public String value = null; - /** String typed by the user so far (i.e. right before requesting code completion), - * which will be corrected if we find a possible completion for an attribute value. - * See the long comment in getChoicesForAttribute(). */ - public String correctedPrefix = null; - /** Non-zero if an attribute value need a start/end tag (i.e. quotes or brackets) */ - public char needTag = 0; - } - - - /** - * Try to guess if the cursor is editing an element's name or an attribute following an - * element. If it's an attribute, try to find if an attribute name is being defined or - * its value. - * <br/> - * This is currently *only* called when we know the cursor is after a complete element - * tag name, so it should never return null. - * <br/> - * Reference for XML syntax: http://www.w3.org/TR/2006/REC-xml-20060816/#sec-starttags - * <br/> - * @return An AttribInfo describing which attribute is being edited or null if the cursor is - * not editing an attribute (in which case it must be an element's name). - */ - private AttribInfo parseAttributeInfo(ITextViewer viewer, int offset) { - AttribInfo info = new AttribInfo(); - - IDocument document = viewer.getDocument(); - int n = document.getLength(); - if (offset <= n) { - try { - n = offset; - for (;offset > 0; --offset) { - char ch = document.getChar(offset - 1); - if (ch == '<') break; - } - - // text will contain the full string of the current element, - // i.e. whatever is after the "<" to the current cursor - String text = document.get(offset, n - offset); - - // Normalize whitespace to single spaces - text = sWhitespace.matcher(text).replaceAll(" "); //$NON-NLS-1$ - - // Remove the leading element name. By spec, it must be after the < without - // any whitespace. If there's nothing left, no attribute has been defined yet. - // Be sure to keep any whitespace after the initial word if any, as it matters. - text = sFirstElementWord.matcher(text).replaceFirst(""); //$NON-NLS-1$ - - // There MUST be space after the element name. If not, the cursor is still - // defining the element name. - if (!text.startsWith(" ")) { //$NON-NLS-1$ - return null; - } - - // Remove full attributes: - // Syntax: - // name = "..." quoted string with all but < and " - // or: - // name = '...' quoted string with all but < and ' - String temp; - do { - temp = text; - text = sFirstAttribute.matcher(temp).replaceFirst(""); //$NON-NLS-1$ - } while(!temp.equals(text)); - - // Now we're left with 3 cases: - // - nothing: either there is no attribute definition or the cursor located after - // a completed attribute definition. - // - a string with no =: the user is writing an attribute name. This case can be - // merged with the previous one. - // - string with an = sign, optionally followed by a quote (' or "): the user is - // writing the value of the attribute. - int pos_equal = text.indexOf('='); - if (pos_equal == -1) { - info.isInValue = false; - info.name = text.trim(); - } else { - info.isInValue = true; - info.name = text.substring(0, pos_equal).trim(); - info.value = text.substring(pos_equal + 1).trim(); - } - return info; - } catch (BadLocationException e) { - // pass - } - } - - return null; - } - - - /** - * Returns the XML DOM node corresponding to the given offset of the given document. - */ - protected Node getNode(ITextViewer viewer, int offset) { - Node node = null; - try { - IModelManager mm = StructuredModelManager.getModelManager(); - if (mm != null) { - IStructuredModel model = mm.getExistingModelForRead(viewer.getDocument()); - if (model != null) { - for(; offset >= 0 && node == null; --offset) { - node = (Node) model.getIndexedRegion(offset); - } - } - } - } catch (Exception e) { - // Ignore exceptions. - } - - return node; - } - - /** - * Returns the active {@link AndroidEditor} matching this source viewer. - */ - private AndroidEditor getAndroidEditor(ITextViewer viewer) { - IWorkbenchWindow wwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (wwin != null) { - IWorkbenchPage page = wwin.getActivePage(); - if (page != null) { - IEditorPart editor = page.getActiveEditor(); - if (editor instanceof AndroidEditor) { - ISourceViewer ssviewer = ((AndroidEditor) editor).getStructuredSourceViewer(); - if (ssviewer == viewer) { - return (AndroidEditor) editor; - } - } - } - } - - return null; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java deleted file mode 100644 index 74eca96..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.browser.IWorkbenchBrowserSupport; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormEditor; -import org.eclipse.ui.forms.editor.IFormPage; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.events.IHyperlinkListener; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport; -import org.eclipse.ui.part.FileEditorInput; -import org.eclipse.ui.part.MultiPageEditorPart; -import org.eclipse.ui.part.WorkbenchPart; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.ui.StructuredTextEditor; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Document; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * Multi-page form editor for Android XML files. - * <p/> - * It is designed to work with a {@link StructuredTextEditor} that will display an XML file. - * <br/> - * Derived classes must implement createFormPages to create the forms before the - * source editor. This can be a no-op if desired. - */ -public abstract class AndroidEditor extends FormEditor implements IResourceChangeListener { - - /** Preference name for the current page of this file */ - private static final String PREF_CURRENT_PAGE = "_current_page"; - - /** Id string used to create the Android SDK browser */ - private static String BROWSER_ID = "android"; // $NON-NLS-1$ - - /** Page id of the XML source editor, used for switching tabs programmatically */ - public final static String TEXT_EDITOR_ID = "editor_part"; //$NON-NLS-1$ - - /** Width hint for text fields. Helps the grid layout resize properly on smaller screens */ - public static final int TEXT_WIDTH_HINT = 50; - - /** Page index of the text editor (always the last page) */ - private int mTextPageIndex; - /** The text editor */ - private StructuredTextEditor mEditor; - /** Listener for the XML model from the StructuredEditor */ - private XmlModelStateListener mXmlModelStateListener; - - /** - * Creates a form editor. - */ - public AndroidEditor() { - super(); - ResourcesPlugin.getWorkspace().addResourceChangeListener(this); - } - - // ---- Abstract Methods ---- - - /** - * Returns the root node of the UI element hierarchy manipulated by the current - * UI node editor. - */ - abstract public UiElementNode getUiRootNode(); - - /** - * Creates the various form pages. - * <p/> - * Derived classes must implement this to add their own specific tabs. - */ - abstract protected void createFormPages(); - - /** - * Subclasses should override this method to process the new XML Model, which XML - * root node is given. - * - * The base implementation is empty. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - protected void xmlModelChanged(Document xml_doc) { - // pass - } - - // ---- Base Class Overrides, Interfaces Implemented ---- - - /** - * Creates the pages of the multi-page editor. - */ - @Override - protected void addPages() { - createAndroidPages(); - selectDefaultPage(null /* defaultPageId */); - } - - /** - * Creates the page for the Android Editors - */ - protected void createAndroidPages() { - createFormPages(); - createTextEditor(); - } - - /** - * Selects the default active page. - * @param defaultPageId the id of the page to show. If <code>null</code> the editor attempts to - * find the default page in the properties of the {@link IResource} object being edited. - */ - protected void selectDefaultPage(String defaultPageId) { - if (defaultPageId == null) { - if (getEditorInput() instanceof IFileEditorInput) { - IFile file = ((IFileEditorInput) getEditorInput()).getFile(); - - QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID, - getClass().getSimpleName() + PREF_CURRENT_PAGE); - String pageId; - try { - pageId = file.getPersistentProperty(qname); - if (pageId != null) { - defaultPageId = pageId; - } - } catch (CoreException e) { - // ignored - } - } - } - - if (defaultPageId != null) { - try { - setActivePage(Integer.parseInt(defaultPageId)); - } catch (Exception e) { - // We can get NumberFormatException from parseInt but also - // AssertionError from setActivePage when the index is out of bounds. - // Generally speaking we just want to ignore any exception and fall back on the - // first page rather than crash the editor load. Logging the error is enough. - EditorsPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId); - } - } - } - - /** - * Removes all the pages from the editor. - */ - protected void removePages() { - int count = getPageCount(); - for (int i = count - 1 ; i >= 0 ; i--) { - removePage(i); - } - } - - /** - * Overrides the parent's setActivePage to be able to switch to the xml editor. - * - * If the special pageId TEXT_EDITOR_ID is given, switches to the mTextPageIndex page. - * This is needed because the editor doesn't actually derive from IFormPage and thus - * doesn't have the get-by-page-id method. In this case, the method returns null since - * IEditorPart does not implement IFormPage. - */ - @Override - public IFormPage setActivePage(String pageId) { - if (pageId.equals(TEXT_EDITOR_ID)) { - super.setActivePage(mTextPageIndex); - return null; - } else { - return super.setActivePage(pageId); - } - } - - - /** - * Notifies this multi-page editor that the page with the given id has been - * activated. This method is called when the user selects a different tab. - * - * @see MultiPageEditorPart#pageChange(int) - */ - @Override - protected void pageChange(int newPageIndex) { - super.pageChange(newPageIndex); - - if (getEditorInput() instanceof IFileEditorInput) { - IFile file = ((IFileEditorInput) getEditorInput()).getFile(); - - QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID, - getClass().getSimpleName() + PREF_CURRENT_PAGE); - try { - file.setPersistentProperty(qname, Integer.toString(newPageIndex)); - } catch (CoreException e) { - // ignore - } - } - } - - /** - * Notifies this listener that some resource changes - * are happening, or have already happened. - * - * Closes all project files on project close. - * @see IResourceChangeListener - */ - public void resourceChanged(final IResourceChangeEvent event) { - if (event.getType() == IResourceChangeEvent.PRE_CLOSE) { - Display.getDefault().asyncExec(new Runnable() { - public void run() { - IWorkbenchPage[] pages = getSite().getWorkbenchWindow() - .getPages(); - for (int i = 0; i < pages.length; i++) { - if (((FileEditorInput)mEditor.getEditorInput()) - .getFile().getProject().equals( - event.getResource())) { - IEditorPart editorPart = pages[i].findEditor(mEditor - .getEditorInput()); - pages[i].closeEditor(editorPart, true); - } - } - } - }); - } - } - - /** - * Initializes the editor part with a site and input. - * <p/> - * Checks that the input is an instance of {@link IFileEditorInput}. - * - * @see FormEditor - */ - @Override - public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException { - if (!(editorInput instanceof IFileEditorInput)) - throw new PartInitException("Invalid Input: Must be IFileEditorInput"); - super.init(site, editorInput); - } - - /** - * Removes attached listeners. - * - * @see WorkbenchPart - */ - @Override - public void dispose() { - IStructuredModel xml_model = getModelForRead(); - if (xml_model != null) { - try { - if (mXmlModelStateListener != null) { - xml_model.removeModelStateListener(mXmlModelStateListener); - } - - } finally { - xml_model.releaseFromRead(); - } - } - ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); - super.dispose(); - } - - /** - * Commit all dirty pages then saves the contents of the text editor. - * <p/> - * This works by committing all data to the XML model and then - * asking the Structured XML Editor to save the XML. - * - * @see IEditorPart - */ - @Override - public void doSave(IProgressMonitor monitor) { - commitPages(true /* onSave */); - - // The actual "save" operation is done by the Structured XML Editor - getEditor(mTextPageIndex).doSave(monitor); - } - - /* (non-Javadoc) - * Saves the contents of this editor to another object. - * <p> - * Subclasses must override this method to implement the open-save-close lifecycle - * for an editor. For greater details, see <code>IEditorPart</code> - * </p> - * - * @see IEditorPart - */ - @Override - public void doSaveAs() { - commitPages(true /* onSave */); - - IEditorPart editor = getEditor(mTextPageIndex); - editor.doSaveAs(); - setPageText(mTextPageIndex, editor.getTitle()); - setInput(editor.getEditorInput()); - } - - /** - * Commits all dirty pages in the editor. This method should - * be called as a first step of a 'save' operation. - * <p/> - * This is the same implementation as in {@link FormEditor} - * except it fixes two bugs: a cast to IFormPage is done - * from page.get(i) <em>before</em> being tested with instanceof. - * Another bug is that the last page might be a null pointer. - * <p/> - * The incorrect casting makes the original implementation crash due - * to our {@link StructuredTextEditor} not being an {@link IFormPage} - * so we have to override and duplicate to fix it. - * - * @param onSave <code>true</code> if commit is performed as part - * of the 'save' operation, <code>false</code> otherwise. - * @since 3.3 - */ - @Override - public void commitPages(boolean onSave) { - if (pages != null) { - for (int i = 0; i < pages.size(); i++) { - Object page = pages.get(i); - if (page != null && page instanceof IFormPage) { - IFormPage form_page = (IFormPage) page; - IManagedForm managed_form = form_page.getManagedForm(); - if (managed_form != null && managed_form.isDirty()) { - managed_form.commit(onSave); - } - } - } - } - } - - /* (non-Javadoc) - * Returns whether the "save as" operation is supported by this editor. - * <p> - * Subclasses must override this method to implement the open-save-close lifecycle - * for an editor. For greater details, see <code>IEditorPart</code> - * </p> - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return false; - } - - // ---- Local methods ---- - - - /** - * Helper method that creates a new hyper-link Listener. - * Used by derived classes which need active links in {@link FormText}. - * <p/> - * This link listener handles two kinds of URLs: - * <ul> - * <li> Links starting with "http" are simply sent to a local browser. - * <li> Links starting with "file:/" are simply sent to a local browser. - * <li> Links starting with "page:" are expected to be an editor page id to switch to. - * <li> Other links are ignored. - * </ul> - * - * @return A new hyper-link listener for FormText to use. - */ - public final IHyperlinkListener createHyperlinkListener() { - return new HyperlinkAdapter() { - /** - * Switch to the page corresponding to the link that has just been clicked. - * For this purpose, the HREF of the <a> tags above is the page ID to switch to. - */ - @Override - public void linkActivated(HyperlinkEvent e) { - super.linkActivated(e); - String link = e.data.toString(); - if (link.startsWith("http") || //$NON-NLS-1$ - link.startsWith("file:/")) { //$NON-NLS-1$ - openLinkInBrowser(link); - } else if (link.startsWith("page:")) { //$NON-NLS-1$ - // Switch to an internal page - setActivePage(link.substring(5 /* strlen("page:") */)); - } - } - }; - } - - /** - * Open the http link into a browser - * - * @param link The URL to open in a browser - */ - private void openLinkInBrowser(String link) { - try { - IWorkbenchBrowserSupport wbs = WorkbenchBrowserSupport.getInstance(); - wbs.createBrowser(BROWSER_ID).openURL(new URL(link)); - } catch (PartInitException e1) { - // pass - } catch (MalformedURLException e1) { - // pass - } - } - - /** - * Creates the XML source editor. - * <p/> - * Memorizes the index page of the source editor (it's always the last page, but the number - * of pages before can change.) - * <br/> - * Retrieves the underlying XML model from the StructuredEditor and attaches a listener to it. - * Finally triggers modelChanged() on the model listener -- derived classes can use this - * to initialize the model the first time. - * <p/> - * Called only once <em>after</em> createFormPages. - */ - private void createTextEditor() { - try { - mEditor = new StructuredTextEditor(); - int index = addPage(mEditor, getEditorInput()); - mTextPageIndex = index; - setPageText(index, mEditor.getTitle()); - - if (!(mEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) { - Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID, - "Error opening the Android XML editor. Is the document an XML file?"); - throw new RuntimeException("Android XML Editor Error", new CoreException(status)); - } - - IStructuredModel xml_model = getModelForRead(); - if (xml_model != null) { - try { - mXmlModelStateListener = new XmlModelStateListener(); - xml_model.addModelStateListener(mXmlModelStateListener); - mXmlModelStateListener.modelChanged(xml_model); - } finally { - xml_model.releaseFromRead(); - } - } - } catch (PartInitException e) { - ErrorDialog.openError(getSite().getShell(), - "Android XML Editor Error", null, e.getStatus()); - } - } - - /** - * Returns the ISourceViewer associated with the Structured Text editor. - */ - public final ISourceViewer getStructuredSourceViewer() { - if (mEditor != null) { - // We can't access mEditor.getSourceViewer() because it is protected, - // however getTextViewer simply returns the SourceViewer casted, so we - // can use it instead. - return mEditor.getTextViewer(); - } - return null; - } - - /** - * Returns the {@link IStructuredDocument} used by the StructuredTextEditor (aka Source - * Editor) or null if not available. - */ - public final IStructuredDocument getStructuredDocument() { - if (mEditor != null && mEditor.getTextViewer() != null) { - return (IStructuredDocument) mEditor.getTextViewer().getDocument(); - } - return null; - } - - /** - * Returns a version of the model that has been shared for read. - * <p/> - * Callers <em>must</em> call model.releaseFromRead() when done, typically - * in a try..finally clause. - * - * @return The model for the XML document or null if cannot be obtained from the editor - */ - public final IStructuredModel getModelForRead() { - IStructuredDocument document = getStructuredDocument(); - if (document != null) { - IModelManager mm = StructuredModelManager.getModelManager(); - if (mm != null) { - return mm.getModelForRead(document); - } - } - return null; - } - - /** - * Returns a version of the model that has been shared for edit. - * <p/> - * Callers <em>must</em> call model.releaseFromEdit() when done, typically - * in a try..finally clause. - * - * @return The model for the XML document or null if cannot be obtained from the editor - */ - public final IStructuredModel getModelForEdit() { - IStructuredDocument document = getStructuredDocument(); - if (document != null) { - IModelManager mm = StructuredModelManager.getModelManager(); - if (mm != null) { - return mm.getModelForEdit(document); - } - } - return null; - } - - /** - * Helper class to perform edits on the XML model whilst making sure the - * model has been prepared to be changed. - * - * It first gets a model for edition, then calls aboutToChangeModel, then performs the - * requested action and finally calls changedModel and releaseFromEdit. - * - * The method is synchronous. As soon as the changedModel method is called, XML model - * listeners will be triggered. - * - * @param edit_action Something that will change - */ - public final void editXmlModel(Runnable edit_action) { - IStructuredModel model = getModelForEdit(); - try { - model.aboutToChangeModel(); - edit_action.run(); - } finally { - // Notify the model we're done modifying it. This must *always* be executed. - model.changedModel(); - model.releaseFromEdit(); - } - } - - /** - * Returns the XML {@link Document} or null if we can't get it - */ - protected final Document getXmlDocument(IStructuredModel model) { - if (model == null) { - EditorsPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$ - return null; - } - - if (model instanceof IDOMModel) { - IDOMModel dom_model = (IDOMModel) model; - return dom_model.getDocument(); - } - return null; - } - - /** - * Listen to changes in the underlying XML model in the structured editor. - */ - private class XmlModelStateListener implements IModelStateListener { - - /** - * A model is about to be changed. This typically is initiated by one - * client of the model, to signal a large change and/or a change to the - * model's ID or base Location. A typical use might be if a client might - * want to suspend processing until all changes have been made. - * <p/> - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelAboutToBeChanged(IStructuredModel model) { - // pass - } - - /** - * Signals that the changes foretold by modelAboutToBeChanged have been - * made. A typical use might be to refresh, or to resume processing that - * was suspended as a result of modelAboutToBeChanged. - * <p/> - * This AndroidEditor implementation calls the xmlModelChanged callback. - */ - public void modelChanged(IStructuredModel model) { - xmlModelChanged(getXmlDocument(model)); - } - - /** - * Notifies that a model's dirty state has changed, and passes that state - * in isDirty. A model becomes dirty when any change is made, and becomes - * not-dirty when the model is saved. - * <p/> - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) { - // pass - } - - /** - * A modelDeleted means the underlying resource has been deleted. The - * model itself is not removed from model management until all have - * released it. Note: baseLocation is not (necessarily) changed in this - * event, but may not be accurate. - * <p/> - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelResourceDeleted(IStructuredModel model) { - // pass - } - - /** - * A model has been renamed or copied (as in saveAs..). In the renamed - * case, the two paramenters are the same instance, and only contain the - * new info for id and base location. - * <p/> - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) { - // pass - } - - /** - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelAboutToBeReinitialized(IStructuredModel structuredModel) { - // pass - } - - /** - * This AndroidEditor implementation of IModelChangedListener is empty. - */ - public void modelReinitialized(IStructuredModel structuredModel) { - // pass - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java deleted file mode 100644 index ab17bef..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors; - - -import org.eclipse.jface.text.IAutoEditStrategy; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextHover; -import org.eclipse.jface.text.contentassist.IContentAssistProcessor; -import org.eclipse.jface.text.contentassist.IContentAssistant; -import org.eclipse.jface.text.formatter.IContentFormatter; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.viewers.IInputProvider; -import org.eclipse.wst.sse.core.text.IStructuredPartitions; -import org.eclipse.wst.xml.core.text.IXMLPartitions; -import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML; - -import java.util.ArrayList; - -/** - * Base Source Viewer Configuration for Android resources. - */ -public class AndroidSourceViewerConfig extends StructuredTextViewerConfigurationXML { - - /** Content Assist Processor to use for all handled partitions. */ - private IContentAssistProcessor mProcessor; - - public AndroidSourceViewerConfig(IContentAssistProcessor processor) { - super(); - mProcessor = processor; - } - - @Override - public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { - return super.getContentAssistant(sourceViewer); - } - - /** - * Returns the content assist processors that will be used for content - * assist in the given source viewer and for the given partition type. - * - * @param sourceViewer the source viewer to be configured by this - * configuration - * @param partitionType the partition type for which the content assist - * processors are applicable - * @return IContentAssistProcessors or null if should not be supported - */ - @Override - protected IContentAssistProcessor[] getContentAssistProcessors( - ISourceViewer sourceViewer, String partitionType) { - ArrayList<IContentAssistProcessor> processors = new ArrayList<IContentAssistProcessor>(); - if (partitionType == IStructuredPartitions.UNKNOWN_PARTITION || - partitionType == IStructuredPartitions.DEFAULT_PARTITION || - partitionType == IXMLPartitions.XML_DEFAULT) { - if (sourceViewer instanceof IInputProvider) { - IInputProvider input = (IInputProvider) sourceViewer; - Object a = input.getInput(); - if (a != null) - a.toString(); - } - - IDocument doc = sourceViewer.getDocument(); - if (doc != null) - doc.toString(); - - processors.add(mProcessor); - } - - IContentAssistProcessor[] others = super.getContentAssistProcessors(sourceViewer, - partitionType); - if (others != null && others.length > 0) { - for (IContentAssistProcessor p : others) { - processors.add(p); - } - } - - if (processors.size() > 0) { - return processors.toArray(new IContentAssistProcessor[processors.size()]); - } else { - return null; - } - } - - @Override - public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { - // TODO text hover for android xml - return super.getTextHover(sourceViewer, contentType); - } - - @Override - public IAutoEditStrategy[] getAutoEditStrategies( - ISourceViewer sourceViewer, String contentType) { - // TODO auto edit strategies for android xml - return super.getAutoEditStrategies(sourceViewer, contentType); - } - - @Override - public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { - // TODO content formatter for android xml - return super.getContentFormatter(sourceViewer); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java deleted file mode 100644 index 354276a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.CommonPlugin; -import com.android.ide.eclipse.common.SdkStatsHelper; -import com.android.ide.eclipse.common.StreamHelper; -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge.LoadStatus; -import com.android.ide.eclipse.editors.layout.LayoutEditor; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.menu.MenuEditor; -import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors; -import com.android.ide.eclipse.editors.resources.ResourcesEditor; -import com.android.ide.eclipse.editors.resources.manager.ProjectResources; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; -import com.android.ide.eclipse.editors.xml.XmlEditor; -import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors; -import com.android.layoutlib.api.ILayoutBridge; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IEditorDescriptor; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.console.MessageConsole; -import org.eclipse.ui.console.MessageConsoleStream; -import org.eclipse.ui.ide.IDE; -import org.eclipse.ui.part.FileEditorInput; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.Version; - -import java.io.File; -import java.io.OutputStream; -import java.lang.reflect.Constructor; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; - -/** - * The activator class controls the plug-in life cycle - */ -public class EditorsPlugin extends AbstractUIPlugin { - // The shared instance - private static EditorsPlugin sPlugin; - - private static Image sAndroidLogo; - private static ImageDescriptor sAndroidLogoDesc; - - private ResourceMonitor mResourceMonitor; - private SdkPathChangedListener mSdkPathChangedListener; - private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>(); - - private MessageConsoleStream mAndroidConsoleStream; - /** Stream to write error messages to the android console */ - private MessageConsoleStream mAndroidConsoleErrorStream; - - public final static class LayoutBridge { - public enum LoadStatus { LOADING, LOADED, FAILED } - - /** Link to the layout bridge */ - public ILayoutBridge bridge; - - public LoadStatus status = LoadStatus.LOADING; - } - - private final LayoutBridge mLayoutBridge = new LayoutBridge(); - - private boolean mLayoutBridgeInit; - - private ClassLoader mBridgeClassLoader; - - private Color mRed; - - - /** - * The constructor - */ - public EditorsPlugin() { - } - - /** - * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code> - * method refreshes the plug-in actions. Subclasses may extend this method, - * but must send super <b>first</b>. - * {@inheritDoc} - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) - */ - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - sPlugin = this; - sAndroidLogoDesc = imageDescriptorFromPlugin(AndroidConstants.EDITORS_PLUGIN_ID, - "/icons/android.png"); //$NON-NLS-1$ - sAndroidLogo = sAndroidLogoDesc.createImage(); - - // get the stream to write in the android console. - MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole(); - mAndroidConsoleStream = androidConsole.newMessageStream(); - - mAndroidConsoleErrorStream = androidConsole.newMessageStream(); - mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00); - - // because this can be run, in some cases, by a non ui thread, and beccause - // changing the console properties update the ui, we need to make this change - // in the ui thread. - getDisplay().asyncExec(new Runnable() { - public void run() { - mAndroidConsoleErrorStream.setColor(mRed); - } - }); - - // Add a resource listener to handle compiled resources. - IWorkspace ws = ResourcesPlugin.getWorkspace(); - mResourceMonitor = ResourceMonitor.startMonitoring(ws); - - if (mResourceMonitor != null) { - setupDefaultEditor(mResourceMonitor); - ResourceManager.setup(mResourceMonitor); - } - - // Setup the sdk location changed listener and invoke it the first time - mSdkPathChangedListener = new SdkPathChangedListener(); - FrameworkResourceManager.getInstance().addFrameworkResourcesChangeListener( - mSdkPathChangedListener); - - // ping the usage server - pingUsageServer(); - } - - /** - * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code> - * method saves this plug-in's preference and dialog stores and shuts down - * its image registry (if they are in use). Subclasses may extend this - * method, but must send super <b>last</b>. A try-finally statement should - * be used where necessary to ensure that <code>super.shutdown()</code> is - * always done. - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) - */ - @Override - public void stop(BundleContext context) throws Exception { - sPlugin = null; - sAndroidLogo.dispose(); - - IconFactory.getInstance().Dispose(); - - // Remove the resource listener that handles compiled resources. - IWorkspace ws = ResourcesPlugin.getWorkspace(); - ResourceMonitor.stopMonitoring(ws); - - FrameworkResourceManager.getInstance().removeFrameworkResourcesChangeListener( - mSdkPathChangedListener); - mSdkPathChangedListener = null; - - mRed.dispose(); - - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static EditorsPlugin getDefault() { - return sPlugin; - } - - /** - * Returns an Image for the small Android logo. - * - * Callers should not dispose it. - */ - public static Image getAndroidLogo() { - return sAndroidLogo; - } - - /** - * Returns an {@link ImageDescriptor} for the small Android logo. - * - * Callers should not dispose it. - */ - public static ImageDescriptor getAndroidLogoDesc() { - return sAndroidLogoDesc; - } - - /** - * Logs a message to the default Eclipse log. - * - * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL. - * @param format The format string, like for String.format(). - * @param args The arguments for the format string, like for String.format(). - */ - public static void log(int severity, String format, Object ... args) { - String message = String.format(format, args); - Status status = new Status(severity, AndroidConstants.EDITORS_PLUGIN_ID, message); - getDefault().getLog().log(status); - } - - /** - * Logs an exception to the default Eclipse log. - * <p/> - * The status severity is always set to ERROR. - * - * @param exception The exception to log. Its call trace will be recorded. - * @param format The format string, like for String.format(). - * @param args The arguments for the format string, like for String.format(). - */ - public static void log(Throwable exception, String format, Object ... args) { - String message = String.format(format, args); - Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID, - message, exception); - getDefault().getLog().log(status); - } - - /** - * Returns the ResourceMonitor object. - */ - public ResourceMonitor getResourceMonitor() { - return mResourceMonitor; - } - - - /** - * Sets up the editor to register default editors for resource files when needed. - * - * This is called by the {@link EditorsPlugin} during initialization. - * - * @param monitor The main Resource Monitor object. - */ - public void setupDefaultEditor(ResourceMonitor monitor) { - monitor.addFileListener(new IFileListener() { - - private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$ - - /* (non-Javadoc) - * Sent when a file changed. - * @param file The file that changed. - * @param markerDeltas The marker deltas for the file. - * @param kind The change kind. This is equivalent to - * {@link IResourceDelta#accept(IResourceDeltaVisitor)} - * - * @see IFileListener#fileChanged - */ - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) { - if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) { - // The resources files must have a file path similar to - // project/res/.../*.xml - // There is no support for sub folders, so the segment count must be 4 - if (file.getFullPath().segmentCount() == 4) { - // check if we are inside the res folder. - String segment = file.getFullPath().segment(1); - if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) { - // we are inside a res/ folder, get the actual ResourceFolder - ProjectResources resources = ResourceManager.getInstance(). - getProjectResources(file.getProject()); - - // This happens when importing old Android projects in Eclipse - // that lack the container (probably because resources fail to build - // properly.) - if (resources == null) { - log(IStatus.INFO, - "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$ - file.getFullPath().toOSString(), - file.getProject().getName()); - return; - } - - ResourceFolder resFolder = resources.getResourceFolder( - (IFolder)file.getParent()); - - if (resFolder != null) { - if (kind == IResourceDelta.ADDED) { - resourceAdded(file, resFolder.getType()); - } else if (kind == IResourceDelta.CHANGED) { - resourceChanged(file, resFolder.getType()); - } - } else { - // if the res folder is null, this means the name is invalid, - // in this case we remove whatever android editors that was set - // as the default editor. - IEditorDescriptor desc = IDE.getDefaultEditor(file); - String editorId = desc.getId(); - if (editorId.startsWith(AndroidConstants.EDITORS_PLUGIN_ID)) { - // reset the default editor. - IDE.setDefaultEditor(file, null); - } - } - } - } - } - } - - private void resourceAdded(IFile file, ResourceFolderType type) { - // set the default editor based on the type. - if (type == ResourceFolderType.LAYOUT) { - IDE.setDefaultEditor(file, LayoutEditor.ID); - } else if (type == ResourceFolderType.DRAWABLE - || type == ResourceFolderType.VALUES) { - IDE.setDefaultEditor(file, ResourcesEditor.ID); - } else if (type == ResourceFolderType.MENU) { - IDE.setDefaultEditor(file, MenuEditor.ID); - } else if (type == ResourceFolderType.XML) { - if (XmlEditor.canHandleFile(file)) { - IDE.setDefaultEditor(file, XmlEditor.ID); - } else { - // set a property to determine later if the XML can be handled - QualifiedName qname = new QualifiedName( - AndroidConstants.EDITORS_PLUGIN_ID, - UNKNOWN_EDITOR); - try { - file.setPersistentProperty(qname, "1"); - } catch (CoreException e) { - // pass - } - } - } - } - - private void resourceChanged(IFile file, ResourceFolderType type) { - if (type == ResourceFolderType.XML) { - IEditorDescriptor ed = IDE.getDefaultEditor(file); - if (ed == null || ed.getId() != XmlEditor.ID) { - QualifiedName qname = new QualifiedName( - AndroidConstants.EDITORS_PLUGIN_ID, - UNKNOWN_EDITOR); - String prop = null; - try { - prop = file.getPersistentProperty(qname); - } catch (CoreException e) { - // pass - } - if (prop != null && XmlEditor.canHandleFile(file)) { - try { - // remove the property & set editor - file.setPersistentProperty(qname, null); - IWorkbenchPage page = PlatformUI.getWorkbench(). - getActiveWorkbenchWindow().getActivePage(); - - IEditorPart oldEditor = page.findEditor(new FileEditorInput(file)); - if (oldEditor != null && - CommonPlugin.displayPrompt("Android XML Editor", - String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?", - file.getFullPath()))) { - IDE.setDefaultEditor(file, XmlEditor.ID); - IEditorPart newEditor = page.openEditor( - new FileEditorInput(file), - XmlEditor.ID, - true, /* activate */ - IWorkbenchPage.MATCH_NONE); - - if (newEditor != null) { - page.closeEditor(oldEditor, true /* save */); - } - } - } catch (CoreException e) { - // setPersistentProperty or page.openEditor may have failed - } - } - } - } - } - - }, IResourceDelta.ADDED | IResourceDelta.CHANGED); - } - - /** - * Respond to notifications from the resource manager than the SDK resources have been updated. - * It gets the new resources from the {@link FrameworkResourceManager} and then try to update - * the layout descriptors from the new layout data. - */ - private class SdkPathChangedListener implements Runnable { - public void run() { - - // Perform the update in a thread (here an Eclipse runtime job) - // since this should never block the caller (especially the start method) - new Job("Editors: Load Framework Resource Parser") { - - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - SubMonitor progress = SubMonitor.convert(monitor, "Update Description", - 60); - - FrameworkResourceManager resourceManager = FrameworkResourceManager.getInstance(); - - AndroidManifestDescriptors.updateDescriptors( - resourceManager.getManifestDefinitions()); - progress.worked(10); - - if (progress.isCanceled()) { - return Status.CANCEL_STATUS; - } - - LayoutDescriptors.getInstance().updateDescriptors( - resourceManager.getLayoutViewsInfo(), - resourceManager.getLayoutGroupsInfo()); - progress.worked(10); - - if (progress.isCanceled()) { - return Status.CANCEL_STATUS; - } - - MenuDescriptors.getInstance().updateDescriptors( - resourceManager.getXmlMenuDefinitions()); - progress.worked(10); - - if (progress.isCanceled()) { - return Status.CANCEL_STATUS; - } - - XmlDescriptors.getInstance().updateDescriptors( - resourceManager.getXmlSearchableDefinitions(), - resourceManager.getPreferencesInfo(), - resourceManager.getPreferenceGroupsInfo()); - progress.worked(10); - - // load the layout lib bridge. - if (System.getenv("ANDROID_DISABLE_LAYOUT") == null) { - loadLayoutBridge(); - FrameworkResourceManager frMgr = FrameworkResourceManager.getInstance(); - ResourceManager rMgr = ResourceManager.getInstance(); - rMgr.loadFrameworkResources(frMgr.getFrameworkResourcesLocation()); - } - progress.worked(10); - - // Notify resource changed listeners - progress.subTask("Refresh UI"); - progress.setWorkRemaining(mResourceRefreshListener.size()); - - // Clone the list before iterating, to avoid Concurrent Modification - // exceptions - @SuppressWarnings("unchecked") - ArrayList<Runnable> listeners = (ArrayList<Runnable>) - mResourceRefreshListener.clone(); - for (Runnable listener : listeners) { - try { - getDisplay().syncExec(listener); - } catch (Exception e) { - log(e, "ResourceRefreshListener Failed"); //$NON-NLS-1$ - } finally { - progress.worked(1); - } - } - } catch (Throwable e) { - EditorsPlugin.log(e, "Load Framework Resource Parser failed"); //$NON-NLS-1$ - EditorsPlugin.printToConsole("Framework Resource Parser", - "Failed to parse"); - } finally { - if (monitor != null) { - monitor.done(); - } - } - return Status.OK_STATUS; - } - }.schedule(); - } - } - - public void addResourceChangedListener(Runnable resourceRefreshListener) { - mResourceRefreshListener.add(resourceRefreshListener); - } - - public void removeResourceChangedListener(Runnable resourceRefreshListener) { - mResourceRefreshListener.remove(resourceRefreshListener); - } - - public static Display getDisplay() { - IWorkbench bench = sPlugin.getWorkbench(); - if (bench != null) { - return bench.getDisplay(); - } - return null; - } - - /** - * Pings the usage start server. - */ - private void pingUsageServer() { - // In order to not block the plugin loading, so we spawn another thread. - new Thread("Ping!") { //$NON-NLS-1$ - @Override - public void run() { - // get the version of the plugin - String versionString = (String) getBundle().getHeaders().get( - Constants.BUNDLE_VERSION); - Version version = new Version(versionString); - - SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$ - } - }.start(); - - } - - /** - * Prints one or more message to the android console. - * @param tag The tag to be associated with the message. Can be null. - * @param objects the objects to print through their <code>toString</code> method. - */ - public static synchronized void printToConsole(String tag, Object... objects) { - StreamHelper.printToStream(sPlugin.mAndroidConsoleStream, tag, objects); - } - - /** - * Prints one or more error messages to the android console. - * @param tag The tag to be associated with the message. Can be null. - * @param objects the objects to print through their <code>toString</code> method. - */ - public static synchronized void printErrorToConsole(String tag, Object... objects) { - StreamHelper.printToStream(sPlugin.mAndroidConsoleErrorStream, tag, objects); - } - - public static synchronized OutputStream getErrorStream() { - return sPlugin.mAndroidConsoleErrorStream; - } - - /** - * Displays an error dialog box. This dialog box is ran asynchronously in the ui thread, - * therefore this method can be called from any thread. - * @param title The title of the dialog box - * @param message The error message - */ - public final static void displayError(final String title, final String message) { - // get the current Display - final Display display = getDisplay(); - - // dialog box only run in ui thread.. - display.asyncExec(new Runnable() { - public void run() { - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, title, message); - } - }); - } - - /** - * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread, - * therefore this message can be called from any thread. - * @param title The title of the dialog box - * @param message The error message - * @return true if OK was clicked. - */ - public final static boolean displayPrompt(final String title, final String message) { - // get the current Display and Shell - final Display display = getDisplay(); - - // we need to ask the user what he wants to do. - final boolean[] wrapper = new boolean[] { false }; - display.syncExec(new Runnable() { - public void run() { - Shell shell = display.getActiveShell(); - wrapper[0] = MessageDialog.openQuestion(shell, title, message); - } - }); - return wrapper[0]; - } - - /** - * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object. - * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will - * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}). - * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned. - */ - public synchronized LayoutBridge getLayoutBridge() { - if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) { - FrameworkResourceManager manager = FrameworkResourceManager.getInstance(); - mLayoutBridge.bridge.init( - manager.getFrameworkFontLocation() + AndroidConstants.FD_DEFAULT_RES, - manager.getEnumValueMap()); - mLayoutBridgeInit = true; - } - return mLayoutBridge; - } - - /** - * Loads the layout bridge from the dynamically loaded layoutlib.jar - */ - private void loadLayoutBridge() { - try { - // reset to be sure we won't be using an obsolete version if we - // get an exception somewhere. - mLayoutBridge.bridge = null; - mLayoutBridge.status = LayoutBridge.LoadStatus.LOADING; - - // get the URL for the file. - File f = new File( - FrameworkResourceManager.getInstance().getLayoutLibLocation()); - if (f.isFile() == false) { - log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$ - } else { - URL url = f.toURL(); - - // create a class loader. Because this jar reference interfaces - // that are in the editors plugin, it's important to provide - // a parent class loader. - mBridgeClassLoader = new URLClassLoader(new URL[] { url }, - this.getClass().getClassLoader()); - - // load the class - Class<?> clazz = mBridgeClassLoader.loadClass(AndroidConstants.CLASS_BRIDGE); - if (clazz != null) { - // instantiate an object of the class. - Constructor<?> constructor = clazz.getConstructor(); - if (constructor != null) { - Object bridge = constructor.newInstance(); - if (bridge instanceof ILayoutBridge) { - mLayoutBridge.bridge = (ILayoutBridge)bridge; - } - } - } - - if (mLayoutBridge.bridge == null) { - mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED; - log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$ - } else { - mLayoutBridge.status = LayoutBridge.LoadStatus.LOADED; - } - } - } catch (Throwable t) { - mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED; - // log the error. - log(t, "Failed to load the LayoutLib"); - } - } - - public ClassLoader getLayoutlibBridgeClassLoader() { - return mBridgeClassLoader; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java deleted file mode 100644 index bb0996b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors; - -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Quickly parses a (potential) XML file to extract its first element (i.e. the root element) - * and namespace, if any. - * <p/> - * This is used to determine if a file is an XML document that the XmlEditor can process. - * <p/> - * TODO use this to remove the hardcoded "android" namespace prefix limitation. - */ -public final class FirstElementParser { - - private static SAXParserFactory sSaxfactory; - - /** - * Result from the XML parsing. <br/> - * Contains the name of the root XML element. <br/> - * If an XMLNS URI was specified and found, the XMLNS prefix is recorded. Otherwise it is null. - */ - public static final class Result { - private String mElement; - private String mXmlnsPrefix; - private String mXmlnsUri; - - public String getElement() { - return mElement; - } - - public String getXmlnsPrefix() { - return mXmlnsPrefix; - } - - public String getXmlnsUri() { - return mXmlnsUri; - } - - void setElement(String element) { - mElement = element; - } - - void setXmlnsPrefix(String xmlnsPrefix) { - mXmlnsPrefix = xmlnsPrefix; - } - - void setXmlnsUri(String xmlnsUri) { - mXmlnsUri = xmlnsUri; - } - } - - private static class ResultFoundException extends SAXException { } - - /** - * Parses the given filename. - * - * @param osFilename The file to parse. - * @param xmlnsUri An optional URL of which we want to know the prefix. - * @return The element details found or null if not found. - */ - public static Result parse(String osFilename, String xmlnsUri) { - if (sSaxfactory == null) { - // TODO just create a single factory in CommonPlugin and reuse it - sSaxfactory = SAXParserFactory.newInstance(); - sSaxfactory.setNamespaceAware(true); - } - - Result result = new Result(); - if (xmlnsUri != null && xmlnsUri.length() > 0) { - result.setXmlnsUri(xmlnsUri); - } - - try { - SAXParser parser = sSaxfactory.newSAXParser(); - XmlHandler handler = new XmlHandler(result); - parser.parse(new InputSource(new FileReader(osFilename)), handler); - - } catch(ResultFoundException e) { - // XML handling was aborted because the required element was found. - // Simply return the result. - return result; - } catch (ParserConfigurationException e) { - } catch (SAXException e) { - } catch (FileNotFoundException e) { - } catch (IOException e) { - } - - return null; - } - - /** - * Private constructor. Use the static parse() method instead. - */ - private FirstElementParser() { - // pass - } - - /** - * A specialized SAX handler that captures the arguments of the very first element - * (i.e. the root element) - */ - private static class XmlHandler extends DefaultHandler { - private final Result mResult; - - public XmlHandler(Result result) { - mResult = result; - } - - /** - * Processes a namespace prefix mapping. - * I.e. for xmlns:android="some-uri", this received prefix="android" and uri="some-uri". - * <p/> - * The prefix is recorded in the result structure if the URI is the one searched for. - * <p/> - * This event happens <em>before</em> the corresponding startElement event. - */ - @Override - public void startPrefixMapping(String prefix, String uri) { - if (uri.equals(mResult.getXmlnsUri())) { - mResult.setXmlnsPrefix(prefix); - } - } - - /** - * Processes a new element start. - * <p/> - * This simply records the element name and abort processing by throwing an exception. - */ - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) - throws SAXException { - mResult.setElement(localName); - throw new ResultFoundException(); - } - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java deleted file mode 100644 index 9e3b733..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.eclipse.editors; - -import com.android.ide.eclipse.common.AndroidConstants; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Display; - -import java.util.HashMap; - -/** - * Factory to generate icons for Android Editors. - * <p/> - * Icons are kept here and reused. - */ -public class IconFactory { - - public static final int COLOR_RED = SWT.COLOR_DARK_RED; - public static final int COLOR_GREEN = SWT.COLOR_DARK_GREEN; - public static final int COLOR_BLUE = SWT.COLOR_DARK_BLUE; - public static final int COLOR_DEFAULT = SWT.COLOR_BLACK; - - public static final int SHAPE_CIRCLE = 'C'; - public static final int SHAPE_RECT = 'R'; - public static final int SHAPE_DEFAULT = SHAPE_CIRCLE; - - private static IconFactory sInstance; - - private HashMap<String, Image> mIconMap = new HashMap<String, Image>(); - private HashMap<String, ImageDescriptor> mImageDescMap = new HashMap<String, ImageDescriptor>(); - - private IconFactory() { - } - - public static synchronized IconFactory getInstance() { - if (sInstance == null) { - sInstance = new IconFactory(); - } - return sInstance; - } - - public void Dispose() { - // Dispose icons - for (Image icon : mIconMap.values()) { - // The map can contain null values - if (icon != null) { - icon.dispose(); - } - } - mIconMap.clear(); - } - - /** - * Returns an Image for a given icon name. - * <p/> - * Callers should not dispose it. - * - * @param osName The leaf name, without the extension, of an existing icon in the - * editor's "icons" directory. If it doesn't exists, a default icon will be - * generated automatically based on the name. - */ - public Image getIcon(String osName) { - return getIcon(osName, COLOR_DEFAULT, SHAPE_DEFAULT); - } - - /** - * Returns an Image for a given icon name. - * <p/> - * Callers should not dispose it. - * - * @param osName The leaf name, without the extension, of an existing icon in the - * editor's "icons" directory. If it doesn't exists, a default icon will be - * generated automatically based on the name. - * @param color The color of the text in the automatically generated icons, - * one of COLOR_DEFAULT, COLOR_RED, COLOR_BLUE or COLOR_RED. - * @param shape The shape of the icon in the automatically generated icons, - * one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT. - */ - public Image getIcon(String osName, int color, int shape) { - EditorsPlugin plugin = EditorsPlugin.getDefault(); - - String key = Character.toString((char) shape) + Integer.toString(color) + osName; - Image icon = mIconMap.get(key); - if (icon == null && !mIconMap.containsKey(key)) { - ImageDescriptor id = getImageDescriptor(osName, color, shape); - if (id != null) { - icon = id.createImage(); - } - // Note that we store null references in the icon map, to avoid looking them - // up every time. If it didn't exist once, it will not exist later. - mIconMap.put(key, icon); - } - return icon; - } - - /** - * Returns an ImageDescriptor for a given icon name. - * <p/> - * Callers should not dispose it. - * - * @param osName The leaf name, without the extension, of an existing icon in the - * editor's "icons" directory. If it doesn't exists, a default icon will be - * generated automatically based on the name. - */ - public ImageDescriptor getImageDescriptor(String osName) { - return getImageDescriptor(osName, COLOR_DEFAULT, SHAPE_DEFAULT); - } - - /** - * Returns an ImageDescriptor for a given icon name. - * <p/> - * Callers should not dispose it. - * - * @param osName The leaf name, without the extension, of an existing icon in the - * editor's "icons" directory. If it doesn't exists, a default icon will be - * generated automatically based on the name. - * @param color The color of the text in the automatically generated icons. - * one of COLOR_DEFAULT, COLOR_RED, COLOR_BLUE or COLOR_RED. - * @param shape The shape of the icon in the automatically generated icons, - * one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT. - */ - public ImageDescriptor getImageDescriptor(String osName, int color, int shape) { - EditorsPlugin plugin = EditorsPlugin.getDefault(); - - String key = Character.toString((char) shape) + Integer.toString(color) + osName; - ImageDescriptor id = mImageDescMap.get(key); - if (id == null && !mImageDescMap.containsKey(key)) { - id = plugin.imageDescriptorFromPlugin( - AndroidConstants.EDITORS_PLUGIN_ID, - String.format("/icons/%1$s.png", osName)); //$NON-NLS-1$ - - if (id == null) { - id = new LetterImageDescriptor(osName.charAt(0), color, shape); - } - - // Note that we store null references in the icon map, to avoid looking them - // up every time. If it didn't exist once, it will not exist later. - mImageDescMap.put(key, id); - } - return id; - } - - /** - * A simple image description that generates a 16x16 image which consists - * of a colored letter inside a black & white circle. - */ - private static class LetterImageDescriptor extends ImageDescriptor { - - private final char mLetter; - private final int mColor; - private final int mShape; - - public LetterImageDescriptor(char letter, int color, int shape) { - mLetter = letter; - mColor = color; - mShape = shape; - } - - @Override - public ImageData getImageData() { - - final int SX = 15; - final int SY = 15; - final int RX = 4; - final int RY = 4; - - Display display = Display.getCurrent(); - if (display == null) { - return null; - } - - Image image = new Image(display, SX, SY); - - image.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); - - GC gc = new GC(image); - gc.setAdvanced(true); - gc.setAntialias(SWT.ON); - gc.setTextAntialias(SWT.ON); - - gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); - if (mShape == SHAPE_CIRCLE) { - gc.fillOval(0, 0, SX - 1, SY - 1); - } else if (mShape == SHAPE_RECT) { - gc.fillRoundRectangle(0, 0, SX - 1, SY - 1, RX, RY); - } - - gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); - gc.setLineWidth(1); - if (mShape == SHAPE_CIRCLE) { - gc.drawOval(0, 0, SX - 1, SY - 1); - } else if (mShape == SHAPE_RECT) { - gc.drawRoundRectangle(0, 0, SX - 1, SY - 1, RX, RY); - } - - // Get a bold version of the default system font, if possible. - Font font = display.getSystemFont(); - FontData[] fds = font.getFontData(); - fds[0].setStyle(SWT.BOLD); - // use 3/4th of the circle diameter for the font size (in pixels) - // and convert it to "font points" (font points in SWT are hardcoded in an - // arbitrary 72 dpi and then converted in real pixels using whatever is - // indicated by getDPI -- at least that's how it works under Win32). - fds[0].setHeight((int) ((SY + 1) * 3./4. * 72./display.getDPI().y)); - // Note: win32 implementation always uses fds[0] so we change just that one. - // getFontData indicates that the array of fd is really an unusual thing for X11. - font = new Font(display, fds); - gc.setFont(font); - gc.setForeground(display.getSystemColor(mColor)); - - // Text measurement varies so slightly depending on the platform - int ofx = 0; - int ofy = 0; - if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_WINDOWS) { - ofx = +1; - ofy = -1; - } - - String s = Character.toString(mLetter).toUpperCase(); - Point p = gc.textExtent(s); - int tx = (SX + ofx - p.x) / 2; - int ty = (SY + ofy - p.y) / 2; - gc.drawText(s, tx, ty, true /* isTransparent */); - - font.dispose(); - gc.dispose(); - - ImageData data = image.getImageData(); - image.dispose(); - return data; - } - - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java deleted file mode 100644 index 48fa903..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.swt.graphics.Image; - -/** - * {@link AttributeDescriptor} describes an XML attribute with its XML attribute name. - * <p/> - * An attribute descriptor also knows which UI node should be instantiated to represent - * this particular attribute (e.g. text field, icon chooser, class selector, etc.) - * Some attributes may be hidden and have no user interface at all. - * <p/> - * This is an abstract class. Derived classes must implement data description and return - * the correct UiAttributeNode-derived class. - */ -public abstract class AttributeDescriptor { - private String mXmlLocalName; - private ElementDescriptor mParent; - private final String mNsUri; - - /** - * Creates a new {@link AttributeDescriptor} - * - * @param xmlLocalName The XML name of the attribute (case sensitive) - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - */ - public AttributeDescriptor(String xmlLocalName, String nsUri) { - mXmlLocalName = xmlLocalName; - mNsUri = nsUri; - } - - /** - * Returns the XML local name of the attribute (case sensitive) - */ - public final String getXmlLocalName() { - return mXmlLocalName; - } - - public final String getNamespaceUri() { - return mNsUri; - } - - /** - * Returns the XML qualified name of the attribute (case sensitive, with namespace prefix - * if present) - * - * @deprecated - */ - private final String getXmlName() { - return mXmlLocalName; - } - - /** - * Returns the namespace of the attribute. - * - * @deprecated - */ - private final String getNamespace() { - // For now we hard-code the prefix as being "android" - if (mXmlLocalName.startsWith("android:")) { //$NON-NLs-1$ - return AndroidConstants.NS_RESOURCES; - } - - return ""; //$NON-NLs-1$ - } - - final void setParent(ElementDescriptor parent) { - mParent = parent; - } - - public final ElementDescriptor getParent() { - return mParent; - } - - /** - * Returns an optional icon for the attribute. - * <p/> - * By default this tries to return an icon based on the XML name of the attribute. - * If this fails, it tries to return the default Android logo as defined in the - * plugin. If all fails, it returns null. - * - * @return An icon for this element or null. - */ - public Image getIcon() { - IconFactory factory = IconFactory.getInstance(); - Image icon; - icon = factory.getIcon(getXmlLocalName(), IconFactory.COLOR_RED, IconFactory.SHAPE_CIRCLE); - return icon != null ? icon : EditorsPlugin.getAndroidLogo(); - } - - /** - * @param uiParent The {@link UiElementNode} parent of this UI attribute. - * @return A new {@link UiAttributeNode} linked to this descriptor or null if this - * attribute has no user interface. - */ - public abstract UiAttributeNode createUiNode(UiElementNode uiParent); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java deleted file mode 100644 index 05ae922..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiAbstractTextAttributeNode; - -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.swt.graphics.Image; - -/** - * Label provider for {@link UiAbstractTextAttributeNode}. - */ -public class AttributeDescriptorLabelProvider implements ILabelProvider { - - private final static AttributeDescriptorLabelProvider sThis = - new AttributeDescriptorLabelProvider(); - - public static ILabelProvider getProvider() { - return sThis; - } - - public Image getImage(Object element) { - return null; - } - - public String getText(Object element) { - if (element instanceof UiAbstractTextAttributeNode) { - return ((UiAbstractTextAttributeNode)element).getCurrentValue(); - } - - return null; - } - - public void addListener(ILabelProviderListener listener) { - // TODO Auto-generated method stub - - } - - public void dispose() { - // TODO Auto-generated method stub - - } - - public boolean isLabelProperty(Object element, String property) { - // TODO Auto-generated method stub - return false; - } - - public void removeListener(ILabelProviderListener listener) { - // TODO Auto-generated method stub - - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java deleted file mode 100644 index 9ebf5f1..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiListAttributeNode; - -/** - * Describes a text attribute that can only contain boolean values. - * It is displayed by a {@link UiListAttributeNode}. - */ -public class BooleanAttributeDescriptor extends ListAttributeDescriptor { - - public BooleanAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip, - new String[] { "true", "false" } ); - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java deleted file mode 100644 index f848d79..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.swt.graphics.Image; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Utility methods related to descriptors handling. - */ -public final class DescriptorsUtils { - - private static final int JAVADOC_BREAK_LENGTH = 60; - - /** - * The path in the online documentation for the manifest description. - * <p/> - * This is NOT a complete URL. To be used, it needs to be appended - * to {@link AndroidConstants#CODESITE_BASE_URL} or to the local SDK - * documentation. - */ - public static final String MANIFEST_SDK_URL = "/reference/android/R.styleable.html#"; //$NON-NLS-1$ - - public static final String IMAGE_KEY = "image"; //$NON-NLS-1$ - - private static final String CODE = "$code"; //$NON-NLS-1$ - private static final String LINK = "$link"; //$NON-NLS-1$ - private static final String ELEM = "$elem"; //$NON-NLS-1$ - private static final String BREAK = "$break"; //$NON-NLS-1$ - - /** - * The {@link ITextAttributeCreator} interface is used by the appendAttribute() method - * to provide a way for caller to override the kind of {@link TextAttributeDescriptor} - * created for a give XML attribute name. - */ - public interface ITextAttributeCreator { - /** - * Creates a new {@link TextAttributeDescriptor} instance for the given XML name, - * UI name and tooltip. - * - * @param xmlName The XML attribute name. - * @param uiName The UI attribute name. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip An optional tooltip. - * @return A new {@link TextAttributeDescriptor} (or derived) instance. - */ - public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri, - String tooltip); - } - - /** - * Add all {@link AttributeInfo} to the the array of {@link AttributeDescriptor}. - * - * @param attributes The list of {@link AttributeDescriptor} to append to - * @param elementXmlName Optional XML local name of the element to which attributes are - * being added. When not null, this is used to filter overrides. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param infos The array of {@link AttributeInfo} to read and append to attributes - * @param requiredAttributes An optional list of attributes to mark as "required" (i.e. append - * a "*" to their UI name as a hint for the user.) - * @param overrides A map [attribute name => TextAttributeDescriptor creator]. A creator - * can either by a Class<? extends TextAttributeDescriptor> or an instance of - * {@link ITextAttributeCreator} that instantiates the right TextAttributeDescriptor. - */ - public static void appendAttributes(ArrayList<AttributeDescriptor> attributes, - String elementXmlName, - String nsUri, AttributeInfo[] infos, - String[] requiredAttributes, - Map<String, Object> overrides) { - for (AttributeInfo info : infos) { - boolean required = false; - if (requiredAttributes != null) { - for(String attr_name : requiredAttributes) { - if (attr_name.equals(info.getName())) { - required = true; - break; - } - } - } - appendAttribute(attributes, elementXmlName, nsUri, info, required, overrides); - } - } - - /** - * Add an {@link AttributeInfo} to the the array of {@link AttributeDescriptor}. - * - * @param attributes The list of {@link AttributeDescriptor} to append to - * @param elementXmlName Optional XML local name of the element to which attributes are - * being added. When not null, this is used to filter overrides. - * @param info The {@link AttributeInfo} to append to attributes - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param required True if the attribute is to be marked as "required" (i.e. append - * a "*" to its UI name as a hint for the user.) - * @param overrides A map [attribute name => TextAttributeDescriptor creator]. A creator - * can either by a Class<? extends TextAttributeDescriptor> or an instance of - * {@link ITextAttributeCreator} that instantiates the right TextAttributeDescriptor. - */ - public static void appendAttribute(ArrayList<AttributeDescriptor> attributes, - String elementXmlName, - String nsUri, - AttributeInfo info, boolean required, - Map<String, Object> overrides) { - AttributeDescriptor attr = null; - - String xmlLocalName = info.getName(); - String uiName = prettyAttributeUiName(info.getName()); // ui_name - if (required) { - uiName += "*"; //$NON-NLS-1$ - } - String tooltip = formatTooltip(info.getJavaDoc()); // tooltip - - // Add the known types to the tooltip - Format[] formats_list = info.getFormats(); - int flen = formats_list.length; - if (flen > 0) { - // Fill the formats in a set for faster access - HashSet<Format> formats_set = new HashSet<Format>(); - - StringBuilder sb = new StringBuilder(); - if (tooltip != null) { - sb.append(tooltip); - sb.append(" "); //$NON-NLS-1$ - } - sb.append("["); //$NON-NLS-1$ - for (int i = 0; i < flen; i++) { - Format f = formats_list[i]; - formats_set.add(f); - - sb.append(f.toString().toLowerCase()); - if (i < flen - 1) { - sb.append(", "); //$NON-NLS-1$ - } - } - // The extra space at the end makes the tooltip more readable on Windows. - sb.append("]"); //$NON-NLS-1$ - - if (required) { - sb.append(". Required."); - } - - // The extra space at the end makes the tooltip more readable on Windows. - sb.append(" "); //$NON-NLS-1$ - - tooltip = sb.toString(); - - // Create a specialized attribute if we can - if (overrides != null) { - for (Entry<String, Object> entry: overrides.entrySet()) { - String key = entry.getKey(); - String elements[] = key.split("/"); - String overrideAttrLocalName = null; - if (elements.length < 1) { - continue; - } else if (elements.length == 1) { - overrideAttrLocalName = elements[0]; - elements = null; - } else { - overrideAttrLocalName = elements[elements.length - 1]; - elements = elements[0].split(","); - } - - if (overrideAttrLocalName == null || - !overrideAttrLocalName.equals(xmlLocalName)) { - continue; - } - - boolean ok_element = elements.length < 1; - if (!ok_element) { - for (String element : elements) { - if (element.equals("*") || element.equals(elementXmlName)) { - ok_element = true; - break; - } - } - } - - if (!ok_element) { - continue; - } - - Object override = entry.getValue(); - if (override instanceof Class) { - try { - // The override is instance of the class to create, which must - // have a constructor compatible with TextAttributeDescriptor. - @SuppressWarnings("unchecked") //$NON-NLS-1$ - Class<? extends TextAttributeDescriptor> clazz = - (Class<? extends TextAttributeDescriptor>) override; - Constructor<? extends TextAttributeDescriptor> cons; - cons = clazz.getConstructor(new Class<?>[] { - String.class, String.class, String.class, String.class } ); - attr = cons.newInstance( - new Object[] { xmlLocalName, uiName, nsUri, tooltip }); - } catch (SecurityException e) { - // ignore - } catch (NoSuchMethodException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } catch (InstantiationException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } catch (InvocationTargetException e) { - // ignore - } - } else if (override instanceof ITextAttributeCreator) { - attr = ((ITextAttributeCreator) override).create( - xmlLocalName, uiName, nsUri, tooltip); - } - } - } // if overrides - - // Create a specialized descriptor if we can, based on type - if (attr == null) { - if (formats_set.contains(Format.REFERENCE)) { - // This is either a multi-type reference or a generic reference. - attr = new ReferenceAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip); - } else if (formats_set.contains(Format.ENUM)) { - attr = new ListAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip, - info.getEnumValues()); - } else if (formats_set.contains(Format.FLAG)) { - attr = new FlagAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip, - info.getFlagValues()); - } else if (formats_set.contains(Format.BOOLEAN)) { - attr = new BooleanAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip); - } else if (formats_set.contains(Format.STRING)) { - attr = new ReferenceAttributeDescriptor(ResourceType.STRING, - xmlLocalName, uiName, nsUri, - tooltip); - } - } - } - - // By default a simple text field is used - if (attr == null) { - attr = new TextAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip); - } - attributes.add(attr); - } - - /** - * Indicates the the given {@link AttributeInfo} already exists in the ArrayList of - * {@link AttributeDescriptor}. This test for the presence of a descriptor with the same - * XML name. - * - * @param attributes The list of {@link AttributeDescriptor} to compare to. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param info The {@link AttributeInfo} to know whether it is included in the above list. - * @return True if this {@link AttributeInfo} is already present in - * the {@link AttributeDescriptor} list. - */ - public static boolean containsAttribute(ArrayList<AttributeDescriptor> attributes, - String nsUri, - AttributeInfo info) { - String xmlLocalName = info.getName(); - for (AttributeDescriptor desc : attributes) { - if (desc.getXmlLocalName().equals(xmlLocalName)) { - if (nsUri == desc.getNamespaceUri() || - (nsUri != null && nsUri.equals(desc.getNamespaceUri()))) { - return true; - } - } - } - return false; - } - - /** - * Create a pretty attribute UI name from an XML name. - * <p/> - * The original xml name starts with a lower case and is camel-case, - * e.g. "maxWidthForView". The pretty name starts with an upper case - * and has space separators, e.g. "Max width for view". - */ - public static String prettyAttributeUiName(String name) { - if (name.length() < 1) { - return name; - } - StringBuffer buf = new StringBuffer(); - - char c = name.charAt(0); - // Use upper case initial letter - buf.append((char)(c >= 'a' && c <= 'z' ? c + 'A' - 'a' : c)); - int len = name.length(); - for (int i = 1; i < len; i++) { - c = name.charAt(i); - if (c >= 'A' && c <= 'Z') { - // Break camel case into separate words - buf.append(' '); - // Use a lower case initial letter for the next word, except if the - // word is solely X, Y or Z. - if (c >= 'X' && c <= 'Z' && - (i == len-1 || - (i < len-1 && name.charAt(i+1) >= 'A' && name.charAt(i+1) <= 'Z'))) { - buf.append(c); - } else { - buf.append((char)(c - 'A' + 'a')); - } - } else if (c == '_') { - buf.append(' '); - } else { - buf.append(c); - } - } - - name = buf.toString(); - - // Replace these acronyms by upper-case versions - // - (?<=^| ) means "if preceded by a space or beginning of string" - // - (?=$| ) means "if followed by a space or end of string" - name = name.replaceAll("(?<=^| )sdk(?=$| )", "SDK"); - name = name.replaceAll("(?<=^| )uri(?=$| )", "URI"); - - return name; - } - - /** - * Capitalizes the string, i.e. transforms the initial [a-z] into [A-Z]. - * Returns the string unmodified if the first character is not [a-z]. - * - * @param str The string to capitalize. - * @return The capitalized string - */ - public static String capitalize(String str) { - if (str == null || str.length() < 1 || str.charAt(0) < 'a' || str.charAt(0) > 'z') { - return str; - } - - StringBuilder sb = new StringBuilder(); - sb.append((char)(str.charAt(0) + 'A' - 'a')); - sb.append(str.substring(1)); - return sb.toString(); - } - - /** - * Formats the javadoc tooltip to be usable in a tooltip. - */ - public static String formatTooltip(String javadoc) { - ArrayList<String> spans = scanJavadoc(javadoc); - - StringBuilder sb = new StringBuilder(); - boolean needBreak = false; - - for (int n = spans.size(), i = 0; i < n; ++i) { - String s = spans.get(i); - if (CODE.equals(s)) { - s = spans.get(++i); - if (s != null) { - sb.append('"').append(s).append('"'); - } - } else if (LINK.equals(s)) { - String base = spans.get(++i); - String anchor = spans.get(++i); - String text = spans.get(++i); - - if (base != null) { - base = base.trim(); - } - if (anchor != null) { - anchor = anchor.trim(); - } - if (text != null) { - text = text.trim(); - } - - // If there's no text, use the anchor if there's one - if (text == null || text.length() == 0) { - text = anchor; - } - - if (base != null && base.length() > 0) { - if (text == null || text.length() == 0) { - // If we still have no text, use the base as text - text = base; - } - } - - if (text != null) { - sb.append(text); - } - - } else if (ELEM.equals(s)) { - s = spans.get(++i); - if (s != null) { - sb.append(s); - } - } else if (BREAK.equals(s)) { - needBreak = true; - } else if (s != null) { - if (needBreak && s.trim().length() > 0) { - sb.append('\r'); - } - sb.append(s); - needBreak = false; - } - } - - return sb.toString(); - } - - /** - * Formats the javadoc tooltip to be usable in a FormText. - * <p/> - * If the descriptor can provide an icon, the caller should provide - * elementsDescriptor.getIcon() as "image" to FormText, e.g.: - * <code>formText.setImage(IMAGE_KEY, elementsDescriptor.getIcon());</code> - * - * @param javadoc The javadoc to format. Cannot be null. - * @param elementDescriptor The element descriptor parent of the javadoc. Cannot be null. - * @param androidDocBaseUrl The base URL for the documentation. Cannot be null. Should be - * <code>FrameworkResourceManager.getInstance().getDocumentationBaseUrl()</code> - */ - public static String formatFormText(String javadoc, - ElementDescriptor elementDescriptor, - String androidDocBaseUrl) { - ArrayList<String> spans = scanJavadoc(javadoc); - - String fullSdkUrl = androidDocBaseUrl + MANIFEST_SDK_URL; - String sdkUrl = elementDescriptor.getSdkUrl(); - if (sdkUrl != null && sdkUrl.startsWith(MANIFEST_SDK_URL)) { - fullSdkUrl = androidDocBaseUrl + sdkUrl; - } - - StringBuilder sb = new StringBuilder(); - - Image icon = elementDescriptor.getIcon(); - if (icon != null) { - sb.append("<form><li style=\"image\" value=\"" + IMAGE_KEY + "\">"); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - sb.append("<form><p>"); //$NON-NLS-1$ - } - - for (int n = spans.size(), i = 0; i < n; ++i) { - String s = spans.get(i); - if (CODE.equals(s)) { - s = spans.get(++i); - if (elementDescriptor.getXmlName().equals(s) && fullSdkUrl != null) { - sb.append("<a href=\""); //$NON-NLS-1$ - sb.append(fullSdkUrl); - sb.append("\">"); //$NON-NLS-1$ - sb.append(s); - sb.append("</a>"); //$NON-NLS-1$ - } else if (s != null) { - sb.append('"').append(s).append('"'); - } - } else if (LINK.equals(s)) { - String base = spans.get(++i); - String anchor = spans.get(++i); - String text = spans.get(++i); - - if (base != null) { - base = base.trim(); - } - if (anchor != null) { - anchor = anchor.trim(); - } - if (text != null) { - text = text.trim(); - } - - // If there's no text, use the anchor if there's one - if (text == null || text.length() == 0) { - text = anchor; - } - - // TODO specialize with a base URL for views, menus & other resources - // Base is empty for a local page anchor, in which case we'll replace it - // by the element SDK URL if it exists. - if ((base == null || base.length() == 0) && fullSdkUrl != null) { - base = fullSdkUrl; - } - - String url = null; - if (base != null && base.length() > 0) { - if (base.startsWith("http")) { //$NON-NLS-1$ - // If base looks an URL, use it, with the optional anchor - url = base; - if (anchor != null && anchor.length() > 0) { - // If the base URL already has an anchor, it needs to be - // removed first. If there's no anchor, we need to add "#" - int pos = url.lastIndexOf('#'); - if (pos < 0) { - url += "#"; //$NON-NLS-1$ - } else if (pos < url.length() - 1) { - url = url.substring(0, pos + 1); - } - - url += anchor; - } - } else if (text == null || text.length() == 0) { - // If we still have no text, use the base as text - text = base; - } - } - - if (url != null && text != null) { - sb.append("<a href=\""); //$NON-NLS-1$ - sb.append(url); - sb.append("\">"); //$NON-NLS-1$ - sb.append(text); - sb.append("</a>"); //$NON-NLS-1$ - } else if (text != null) { - sb.append("<b>").append(text).append("</b>"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - } else if (ELEM.equals(s)) { - s = spans.get(++i); - if (sdkUrl != null && s != null) { - sb.append("<a href=\""); //$NON-NLS-1$ - sb.append(sdkUrl); - sb.append("\">"); //$NON-NLS-1$ - sb.append(s); - sb.append("</a>"); //$NON-NLS-1$ - } else if (s != null) { - sb.append("<b>").append(s).append("</b>"); //$NON-NLS-1$ //$NON-NLS-2$ - } - } else if (BREAK.equals(s)) { - // ignore line breaks in pseudo-HTML rendering - } else if (s != null) { - sb.append(s); - } - } - - if (icon != null) { - sb.append("</li></form>"); //$NON-NLS-1$ - } else { - sb.append("</p></form>"); //$NON-NLS-1$ - } - return sb.toString(); - } - - private static ArrayList<String> scanJavadoc(String javadoc) { - ArrayList<String> spans = new ArrayList<String>(); - - // Standardize all whitespace in the javadoc to single spaces. - if (javadoc != null) { - javadoc = javadoc.replaceAll("[ \t\f\r\n]+", " "); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Detects {@link <base>#<name> <text>} where all 3 are optional - Pattern p_link = Pattern.compile("\\{@link\\s+([^#\\}\\s]*)(?:#([^\\s\\}]*))?(?:\\s*([^\\}]*))?\\}(.*)"); //$NON-NLS-1$ - // Detects <code>blah</code> - Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$ - // Detects @blah@, used in hard-coded tooltip descriptors - Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$ - // Detects a buffer that starts by @ < or { (one that was not matched above) - Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$ - // Detects everything till the next potential separator, i.e. @ < or { - Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$ - - int currentLength = 0; - String text = null; - - while(javadoc != null && javadoc.length() > 0) { - Matcher m; - String s = null; - if ((m = p_code.matcher(javadoc)).matches()) { - spans.add(CODE); - spans.add(text = cleanupJavadocHtml(m.group(1))); // <code> text - javadoc = m.group(2); - if (text != null) { - currentLength += text.length(); - } - } else if ((m = p_link.matcher(javadoc)).matches()) { - spans.add(LINK); - spans.add(m.group(1)); // @link base - spans.add(m.group(2)); // @link anchor - spans.add(text = cleanupJavadocHtml(m.group(3))); // @link text - javadoc = m.group(4); - if (text != null) { - currentLength += text.length(); - } - } else if ((m = p_elem.matcher(javadoc)).matches()) { - spans.add(ELEM); - spans.add(text = cleanupJavadocHtml(m.group(1))); // @text@ - javadoc = m.group(2); - if (text != null) { - currentLength += text.length() - 2; - } - } else if ((m = p_open.matcher(javadoc)).matches()) { - s = m.group(1); - javadoc = m.group(2); - } else if ((m = p_text.matcher(javadoc)).matches()) { - s = m.group(1); - javadoc = m.group(2); - } else { - // This is not supposed to happen. In case of, just use everything. - s = javadoc; - javadoc = null; - } - if (s != null && s.length() > 0) { - s = cleanupJavadocHtml(s); - - if (currentLength >= JAVADOC_BREAK_LENGTH) { - spans.add(BREAK); - currentLength = 0; - } - while (currentLength + s.length() > JAVADOC_BREAK_LENGTH) { - int pos = s.indexOf(' ', JAVADOC_BREAK_LENGTH - currentLength); - if (pos <= 0) { - break; - } - spans.add(s.substring(0, pos + 1)); - spans.add(BREAK); - currentLength = 0; - s = s.substring(pos + 1); - } - - spans.add(s); - currentLength += s.length(); - } - } - - return spans; - } - - /** - * Remove anything that looks like HTML from a javadoc snippet, as it is supported - * neither by FormText nor a standard text tooltip. - */ - private static String cleanupJavadocHtml(String s) { - if (s != null) { - s = s.replaceAll("<", "\""); //$NON-NLS-1$ $NON-NLS-2$ - s = s.replaceAll(">", "\""); //$NON-NLS-1$ $NON-NLS-2$ - s = s.replaceAll("<[^>]+>", ""); //$NON-NLS-1$ $NON-NLS-2$ - } - return s; - } - - /** - * Sets the default layout attributes for the a new UiElementNode. - * <p/> - * Note that ideally the node should already be part of a hierarchy so that its - * parent layout and previous sibling can be determined, if any. - * <p/> - * This does not override attributes which are not empty. - */ - public static void setDefaultLayoutAttributes(UiElementNode ui_node) { - ui_node.setAttributeValue("layout_width", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$ - ui_node.setAttributeValue("layout_height", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$ - - String widget_id = getFreeWidgetId(ui_node.getUiRoot(), - new Object[] {ui_node.getDescriptor().getXmlLocalName(), 1, null }); - if (widget_id != null) { - ui_node.setAttributeValue("id", "@+id/" + widget_id, false /* override */); //$NON-NLS-1$ $NON-NLS-2$ - } - - UiElementNode ui_parent = ui_node.getUiParent(); - if (ui_parent != null && ui_parent.getDescriptor().getXmlLocalName().equals("RelativeLayout")) { //$NON-NLS-1$ - UiElementNode ui_previous = ui_node.getUiPreviousSibling(); - if (ui_previous != null) { - String id = ui_previous.getAttributeValue("id"); //$NON-NLS-1$ - if (id != null && id.length() > 0) { - id = id.replace("@+", "@"); - ui_node.setAttributeValue("layout_below", id, false /* override */); - } - } - } - - } - - /** - * Given a UI root node, returns the first available id that matches the - * pattern "prefix%02d". - * - * For recursion purposes, a "context" is given. Since Java doesn't have in-out parameters - * in methods and we're not going to do a dedicated type, we just use an object array which - * must contain the following items: - * - prefix(String): The prefix of the generated id, i.e. "widget" - * - index(Integer): The minimum index of the generated id - * - generated(String) The generated widget currently being searched. Must start with null. - * - * @param uiRoot The Ui root node where to start searching recusrively. - * @param params An in-out context of parameters used during recursion, as explaine above. - * @return A suitable generated id - */ - private static String getFreeWidgetId(UiElementNode uiRoot, Object[] params) { - String generated = (String) params[2]; - if (generated == null) { - String prefix = (String) params[0]; - int pos = prefix.indexOf('.'); - if (pos >= 0) { - prefix = prefix.substring(pos + 1); - } - pos = prefix.indexOf('$'); - if (pos >= 0) { - prefix = prefix.substring(pos + 1); - } - prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$ - if (prefix.length() == 0) { - prefix = "widget"; - } - generated = String.format("%1$s%2$02d", prefix, ((Integer)params[1]).intValue()); - params[0] = prefix; - params[2] = generated; - } - - String id = uiRoot.getAttributeValue("id"); //$NON-NLS-1$ - if (id != null) { - id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$ - id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$ - if (id.equals(generated)) { - // switch to next value - int num = ((Integer)params[1]).intValue() + 1; - generated = String.format("%1$s%2$02d", params[0], num); - params[1] = num; - params[2] = generated; - } - } - - for (UiElementNode uiChild : uiRoot.getUiChildren()) { - getFreeWidgetId(uiChild, params); - } - - return (String) params[2]; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java deleted file mode 100644 index 7d296f7..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * {@link DocumentDescriptor} describes the properties expected for an XML document node. - * - * Compared to ElementDescriptor, {@link DocumentDescriptor} does not have XML name nor UI name, - * tooltip, SDK url and attributes list. - * <p/> - * It has a children list which represent all the possible roots of the document. - * <p/> - * The document nodes are "mandatory", meaning the UI node is never deleted and it may lack - * an actual XML node attached. - */ -public class DocumentDescriptor extends ElementDescriptor { - - /** - * Constructs a new {@link DocumentDescriptor} based on its XML name and children list. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * <p/> - * The XML name is never shown in the UI directly. It is however used when an icon - * needs to be found for the node. - * - * @param xml_name The XML element node name. Case sensitive. - * @param children The list of allowed children. Can be null or empty. - */ - public DocumentDescriptor(String xml_name, ElementDescriptor[] children) { - super(xml_name, children, true /* mandatory */); - } - - /** - * @return A new {@link UiElementNode} linked to this descriptor. - */ - @Override - public UiElementNode createUiNode() { - return new UiDocumentNode(this); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java deleted file mode 100644 index 12ebc38..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.graphics.Image; - -import java.util.HashSet; -import java.util.Set; - -/** - * {@link ElementDescriptor} describes the properties expected for a given XML element node. - * - * {@link ElementDescriptor} have an XML name, UI name, a tooltip, an SDK url, - * an attributes list and a children list. - * - * An UI node can be "mandatory", meaning the UI node is never deleted and it may lack - * an actual XML node attached. A non-mandatory UI node MUST have an XML node attached - * and it will cease to exist when the XML node ceases to exist. - */ -public class ElementDescriptor { - /** The XML element node name. Case sensitive. */ - private String mXmlName; - /** The XML element name for the user interface, typically capitalized. */ - private String mUiName; - /** The list of allowed attributes. */ - private AttributeDescriptor[] mAttributes; - /** The list of allowed children */ - private ElementDescriptor[] mChildren; - /* An optional tooltip. Can be empty. */ - private String mTooltip; - /** An optional SKD URL. Can be empty. */ - private String mSdkUrl; - /** Whether this UI node must always exist (even for empty models). */ - private boolean mMandatory; - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name, UI name, - * tooltip, SDK url, attributes list, children list and mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param ui_name The XML element name for the user interface, typically capitalized. - * @param tooltip An optional tooltip. Can be null or empty. - * @param sdk_url An optional SKD URL. Can be null or empty. - * @param attributes The list of allowed attributes. Can be null or empty. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). A mandatory - * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory - * UI node MUST have an XML node attached and it will cease to exist when the XML node - * ceases to exist. - */ - public ElementDescriptor(String xml_name, String ui_name, String tooltip, String sdk_url, - AttributeDescriptor[] attributes, - ElementDescriptor[] children, - boolean mandatory) { - mMandatory = mandatory; - mXmlName = xml_name; - mUiName = ui_name; - mTooltip = (tooltip != null && tooltip.length() > 0) ? tooltip : null; - mSdkUrl = (sdk_url != null && sdk_url.length() > 0) ? sdk_url : null; - setAttributes(attributes != null ? attributes : new AttributeDescriptor[]{}); - mChildren = children != null ? children : new ElementDescriptor[]{}; - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name and children list. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). A mandatory - * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory - * UI node MUST have an XML node attached and it will cease to exist when the XML node - * ceases to exist. - */ - public ElementDescriptor(String xml_name, ElementDescriptor[] children, boolean mandatory) { - this(xml_name, prettyName(xml_name), null, null, null, children, mandatory); - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name and children list. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param children The list of allowed children. Can be null or empty. - */ - public ElementDescriptor(String xml_name, ElementDescriptor[] children) { - this(xml_name, prettyName(xml_name), null, null, null, children, false); - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - */ - public ElementDescriptor(String xml_name) { - this(xml_name, prettyName(xml_name), null, null, null, null, false); - } - - /** Returns whether this node must always exist (even for empty models) */ - public boolean isMandatory() { - return mMandatory; - } - - /** - * Returns the XML element node local name (case sensitive) - */ - public final String getXmlLocalName() { - int pos = mXmlName.indexOf(':'); - if (pos != -1) { - return mXmlName.substring(pos+1); - } - return mXmlName; - } - - /** Returns the XML element node name. Case sensitive. */ - public String getXmlName() { - return mXmlName; - } - - /** - * Returns the namespace of the attribute. - */ - public final String getNamespace() { - // For now we hard-code the prefix as being "android" - if (mXmlName.startsWith("android:")) { //$NON-NLs-1$ - return AndroidConstants.NS_RESOURCES; - } - - return ""; //$NON-NLs-1$ - } - - - /** Returns the XML element name for the user interface, typically capitalized. */ - public String getUiName() { - return mUiName; - } - - /** - * Returns an optional icon for the element. - * <p/> - * By default this tries to return an icon based on the XML name of the element. - * If this fails, it tries to return the default Android logo as defined in the - * plugin. If all fails, it returns null. - * - * @return An icon for this element or null. - */ - public Image getIcon() { - IconFactory factory = IconFactory.getInstance(); - int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN; - int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE; - Image icon = factory.getIcon(mXmlName, color, shape); - return icon != null ? icon : EditorsPlugin.getAndroidLogo(); - } - - /** - * Returns an optional ImageDescriptor for the element. - * <p/> - * By default this tries to return an image based on the XML name of the element. - * If this fails, it tries to return the default Android logo as defined in the - * plugin. If all fails, it returns null. - * - * @return An ImageDescriptor for this element or null. - */ - public ImageDescriptor getImageDescriptor() { - IconFactory factory = IconFactory.getInstance(); - int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN; - int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE; - ImageDescriptor id = factory.getImageDescriptor(mXmlName, color, shape); - return id != null ? id : EditorsPlugin.getAndroidLogoDesc(); - } - - /* Returns the list of allowed attributes. */ - public AttributeDescriptor[] getAttributes() { - return mAttributes; - } - - /* Sets the list of allowed attributes. */ - public void setAttributes(AttributeDescriptor[] attributes) { - mAttributes = attributes; - for (AttributeDescriptor attribute : attributes) { - attribute.setParent(this); - } - } - - /** Returns the list of allowed children */ - public ElementDescriptor[] getChildren() { - return mChildren; - } - - /** @return True if this descriptor has children available */ - public boolean hasChildren() { - return mChildren.length > 0; - } - - /** Sets the list of allowed children. */ - public void setChildren(ElementDescriptor[] newChildren) { - mChildren = newChildren; - } - - /** - * Returns an optional tooltip. Will be null if not present. - * <p/> - * The tooltip is based on the Javadoc of the element and already processed via - * {@link DescriptorsUtils#formatTooltip(String)} to be displayed right away as - * a UI tooltip. - */ - public String getTooltip() { - return mTooltip; - } - - /** Returns an optional SKD URL. Will be null if not present. */ - public String getSdkUrl() { - return mSdkUrl; - } - - /** Sets the optional tooltip. Can be null or empty. */ - public void setTooltip(String tooltip) { - mTooltip = tooltip; - } - - /** Sets the optional SDK URL. Can be null or empty. */ - public void setSdkUrl(String sdkUrl) { - mSdkUrl = sdkUrl; - } - - /** - * @return A new {@link UiElementNode} linked to this descriptor. - */ - public UiElementNode createUiNode() { - return new UiElementNode(this); - } - - /** - * Returns the first children of this descriptor that describes the given XML element name. - * <p/> - * In recursive mode, searches the direct children first before descending in the hierarchy. - * - * @return The ElementDescriptor matching the requested XML node element name or null. - */ - public ElementDescriptor findChildrenDescriptor(String element_name, boolean recursive) { - return findChildrenDescriptorInternal(element_name, recursive, null); - } - - private ElementDescriptor findChildrenDescriptorInternal(String element_name, - boolean recursive, - Set<ElementDescriptor> visited) { - if (recursive && visited == null) { - visited = new HashSet<ElementDescriptor>(); - } - - for (ElementDescriptor e : getChildren()) { - if (e.getXmlName().equals(element_name)) { - return e; - } - } - - if (visited != null) { - visited.add(this); - } - - if (recursive) { - for (ElementDescriptor e : getChildren()) { - if (visited != null) { - if (!visited.add(e)) { // Set.add() returns false if element is already present - continue; - } - } - ElementDescriptor f = e.findChildrenDescriptorInternal(element_name, - recursive, visited); - if (f != null) { - return f; - } - } - } - - return null; - } - - /** - * Utility helper than pretty-formats an XML Name for the UI. - * This is used by the simplified constructor that takes only an XML element name. - * - * @param xml_name The XML name to convert. - * @return The XML name with dashes replaced by spaces and capitalized. - */ - private static String prettyName(String xml_name) { - char c[] = xml_name.toCharArray(); - if (c.length > 0) { - c[0] = Character.toUpperCase(c[0]); - } - return new String(c).replace("-", " "); //$NON-NLS-1$ //$NON-NLS-2$ - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java deleted file mode 100644 index cab9883..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiListAttributeNode; - -/** - * Describes a text attribute that can only contains some predefined values. - * It is displayed by a {@link UiListAttributeNode}. - */ -public class EnumAttributeDescriptor extends ListAttributeDescriptor { - - public EnumAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiListAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiListAttributeNode(this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java deleted file mode 100644 index 903417b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.ui.FlagValueCellEditor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiListAttributeNode; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.swt.widgets.Composite; - -/** - * Describes a text attribute that can only contains some predefined values. - * It is displayed by a {@link UiListAttributeNode}. - * - * Note: in Android resources, a "flag" is a list of fixed values where one or - * more values can be selected using an "or", e.g. "align='left|top'". - * By contrast, an "enum" is a list of fixed values of which only one can be - * selected at a given time, e.g. "gravity='right'". - * <p/> - * This class handles the "flag" case. - * The "enum" case is done using {@link ListAttributeDescriptor}. - */ -public class FlagAttributeDescriptor extends TextAttributeDescriptor { - - private String[] mNames; - - /** - * Creates a new {@link FlagAttributeDescriptor} which automatically gets its - * values from the FrameworkResourceManager. - */ - public FlagAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * Creates a new {@link FlagAttributeDescriptor} which uses the provided values. - */ - public FlagAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip, String[] names) { - super(xmlLocalName, uiName, nsUri, tooltip); - mNames = names; - } - - /** - * @return The initial names of the flags. Can be null, in which case the Framework - * resource parser should be checked. - */ - public String[] getNames() { - return mNames; - } - - /** - * @return A new {@link UiListAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiFlagAttributeNode(this, uiParent); - } - - // ------- IPropertyDescriptor Methods - - @Override - public CellEditor createPropertyEditor(Composite parent) { - return new FlagValueCellEditor(parent); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java deleted file mode 100644 index 93969e9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.ui.ListValueCellEditor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiListAttributeNode; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.swt.widgets.Composite; - -/** - * Describes a text attribute that can contains some predefined values. - * It is displayed by a {@link UiListAttributeNode}. - */ -public class ListAttributeDescriptor extends TextAttributeDescriptor { - - private String[] mValues = null; - - /** - * Creates a new {@link ListAttributeDescriptor} which automatically gets its - * values from the FrameworkResourceManager. - */ - public ListAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * Creates a new {@link ListAttributeDescriptor} which uses the provided values. - */ - public ListAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip, String[] values) { - super(xmlLocalName, uiName, nsUri, tooltip); - mValues = values; - } - - public String[] getValues() { - return mValues; - } - - /** - * @return A new {@link UiListAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiListAttributeNode(this, uiParent); - } - - // ------- IPropertyDescriptor Methods - - @Override - public CellEditor createPropertyEditor(Composite parent) { - return new ListValueCellEditor(parent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java deleted file mode 100644 index 3d3ff29..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.ui.ResourceValueCellEditor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.swt.widgets.Composite; - -/** - * Describes an XML attribute displayed containing a value or a reference to a resource. - * It is displayed by a {@link UiResourceAttributeNode}. - */ -public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor { - - private ResourceType mResourceType; - - /** - * Creates a reference attributes that can contain any type of resources. - * @param xmlLocalName The XML name of the attribute (case sensitive) - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip A non-empty tooltip string or null - */ - public ReferenceAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * Creates a reference attributes that can contain a reference to a specific - * {@link ResourceType}. - * @param resourceType The specific {@link ResourceType} that this reference attribute supports. - * It can be <code>null</code>, in which case, all resource types are supported. - * @param xmlLocalName The XML name of the attribute (case sensitive) - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip A non-empty tooltip string or null - */ - public ReferenceAttributeDescriptor(ResourceType resourceType, - String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - mResourceType = resourceType; - } - - - /** - * @return A new {@link UiResourceAttributeNode} linked to this reference descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiResourceAttributeNode(mResourceType, this, uiParent); - } - - // ------- IPropertyDescriptor Methods - - @Override - public CellEditor createPropertyEditor(Composite parent) { - return new ResourceValueCellEditor(parent); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java deleted file mode 100644 index 8fb1c7c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiSeparatorAttributeNode; - -/** - * {@link SeparatorAttributeDescriptor} does not represent any real attribute. - * <p/> - * It is used to separate groups of attributes visually. - */ -public class SeparatorAttributeDescriptor extends AttributeDescriptor { - - /** - * Creates a new {@link SeparatorAttributeDescriptor} - */ - public SeparatorAttributeDescriptor(String label) { - super(label /* xmlLocalName */, null /* nsUri */); - } - - /** - * @return A new {@link UiAttributeNode} linked to this descriptor or null if this - * attribute has no user interface. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiSeparatorAttributeNode(this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java deleted file mode 100644 index 632471d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.ui.TextValueCellEditor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.ui.views.properties.IPropertyDescriptor; - - -/** - * Describes a textual XML attribute. - * <p/> - * Such an attribute has a tooltip and would typically be displayed by - * {@link UiTextAttributeNode} using a label widget and text field. - * <p/> - * This is the "default" kind of attribute. If in doubt, use this. - */ -public class TextAttributeDescriptor extends AttributeDescriptor implements IPropertyDescriptor { - private String mUiName; - private String mTooltip; - - /** - * Creates a new {@link TextAttributeDescriptor} - * - * @param xmlLocalName The XML name of the attribute (case sensitive) - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip A non-empty tooltip string or null - */ - public TextAttributeDescriptor(String xmlLocalName, String uiName, - String nsUri, String tooltip) { - super(xmlLocalName, nsUri); - mUiName = uiName; - mTooltip = (tooltip != null && tooltip.length() > 0) ? tooltip : null; - } - - /** - * @return The UI name of the attribute. Cannot be an empty string and cannot be null. - */ - public final String getUiName() { - return mUiName; - } - - /** - * The tooltip string is either null or a non-empty string. - * <p/> - * The tooltip is based on the Javadoc of the attribute and already processed via - * {@link DescriptorsUtils#formatTooltip(String)} to be displayed right away as - * a UI tooltip. - * <p/> - * An empty string is converted to null, to match the behavior of setToolTipText() in - * {@link Control}. - * - * @return A non-empty tooltip string or null - */ - public final String getTooltip() { - return mTooltip; - } - - /** - * @return A new {@link UiTextAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiTextAttributeNode(this, uiParent); - } - - // ------- IPropertyDescriptor Methods - - public CellEditor createPropertyEditor(Composite parent) { - return new TextValueCellEditor(parent); - } - - public String getCategory() { - ElementDescriptor parent = getParent(); - if (parent != null) { - return parent.getUiName(); - } - - return null; - } - - public String getDescription() { - return mTooltip; - } - - public String getDisplayName() { - return mUiName; - } - - public String[] getFilterFlags() { - return null; - } - - public Object getHelpContextIds() { - return null; - } - - public Object getId() { - return this; - } - - public ILabelProvider getLabelProvider() { - return AttributeDescriptorLabelProvider.getProvider(); - } - - public boolean isCompatibleWith(IPropertyDescriptor anotherProperty) { - return anotherProperty == this; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java deleted file mode 100644 index 2015d71..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiTextValueNode; - - -/** - * Describes the value of an XML element. - * <p/> - * The value is a simple text string, displayed by an {@link UiTextValueNode}. - */ -public class TextValueDescriptor extends TextAttributeDescriptor { - - /** - * Creates a new {@link TextValueDescriptor} - * - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param tooltip A non-empty tooltip string or null - */ - public TextValueDescriptor(String uiName, String tooltip) { - super("#text" /* xmlLocalName */, uiName, null /* nsUri */, tooltip); - } - - /** - * @return A new {@link UiTextValueNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiTextValueNode(this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java deleted file mode 100644 index ed9c897..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.descriptors; - -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - - -/** - * Describes an XMLNS attribute that is hidden. - * <p/> - * Such an attribute has no user interface and no corresponding {@link UiAttributeNode}. - * It also has a single constant default value. - * <p/> - * When loading an XML, we'll ignore this attribute. - * However when writing a new XML, we should always write this attribute. - * <p/> - * Currently this is used for the xmlns:android attribute in the manifest element. - */ -public final class XmlnsAttributeDescriptor extends AttributeDescriptor { - - /** - * URI of the reserved "xmlns" prefix, as described in - * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#normalizeDocumentAlgo - */ - public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; //$NON-NLS-1$ - - private String mValue; - - - public XmlnsAttributeDescriptor(String defaultPrefix, String value) { - super(defaultPrefix, XMLNS_URI); - mValue = value; - } - - /** - * Returns the value of this specialized attribute descriptor, which is the URI associated - * to the declared namespace prefix. - */ - public String getValue() { - return mValue; - } - - /** - * Returns the "xmlns" prefix that is always used by this node for its namespace URI. - * This is defined by the XML specification. - */ - public String getXmlNsPrefix() { - return "xmlns"; //$NON-NLS-1$ - } - - /** - * Returns the fully-qualified attribute name, namely "xmlns:xxx" where xxx is - * the defaultPrefix passed in the constructor. - */ - public String getXmlNsName() { - return getXmlNsPrefix() + ":" + getXmlLocalName(); //$NON-NLS-1$ - } - - /** - * @return Always returns null. {@link XmlnsAttributeDescriptor} has no user interface. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java deleted file mode 100644 index 278b921..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java +++ /dev/null @@ -1,1963 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge; -import com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener; -import com.android.ide.eclipse.editors.layout.parts.UiElementsEditPartFactory; -import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier; -import com.android.ide.eclipse.editors.resources.configurations.LanguageQualifier; -import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier; -import com.android.ide.eclipse.editors.resources.configurations.NetworkCodeQualifier; -import com.android.ide.eclipse.editors.resources.configurations.PixelDensityQualifier; -import com.android.ide.eclipse.editors.resources.configurations.RegionQualifier; -import com.android.ide.eclipse.editors.resources.configurations.ScreenDimensionQualifier; -import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier; -import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier; -import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier; -import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier.KeyboardState; -import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier.NavigationMethod; -import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier.ScreenOrientation; -import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier.TextInputMethod; -import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier.TouchScreenType; -import com.android.ide.eclipse.editors.resources.manager.ProjectResources; -import com.android.ide.eclipse.editors.resources.manager.ResourceFile; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.DensityVerifier; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.DimensionVerifier; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.LanguageRegionVerifier; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.MobileCodeVerifier; -import com.android.layoutlib.api.ILayoutLog; -import com.android.layoutlib.api.ILayoutResult; -import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.api.IStyleResourceValue; -import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.draw2d.geometry.Rectangle; -import org.eclipse.gef.DefaultEditDomain; -import org.eclipse.gef.GraphicalViewer; -import org.eclipse.gef.SelectionManager; -import org.eclipse.gef.dnd.TemplateTransferDragSourceListener; -import org.eclipse.gef.dnd.TemplateTransferDropTargetListener; -import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; -import org.eclipse.gef.palette.PaletteRoot; -import org.eclipse.gef.ui.parts.GraphicalEditor; -import org.eclipse.gef.ui.parts.SelectionSynchronizer; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.ide.IDE; -import org.eclipse.ui.part.FileEditorInput; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Graphical layout editor, based on GEF. - */ -public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/ - implements ILayoutReloadListener { - - private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$ - - /** Reference to the layout editor */ - private final LayoutEditor mLayoutEditor; - - /** reference to the file being edited. */ - private IFile mEditedFile; - - private Clipboard mClipboard; - private Composite mParent; - - private Text mCountry; - private Text mNetwork; - private Combo mLanguage; - private Combo mRegion; - private Combo mOrientation; - private Text mDensity; - private Combo mTouch; - private Combo mKeyboard; - private Combo mTextInput; - private Combo mNavigation; - private Text mSize1; - private Text mSize2; - private Combo mThemeCombo; - private Button mCreateButton; - - private Label mCountryIcon; - private Label mNetworkIcon; - private Label mLanguageIcon; - private Label mRegionIcon; - private Label mOrientationIcon; - private Label mDensityIcon; - private Label mTouchIcon; - private Label mKeyboardIcon; - private Label mTextInputIcon; - private Label mNavigationIcon; - private Label mSizeIcon; - - private Label mCurrentLayoutLabel; - - private Image mWarningImage; - private Image mMatchImage; - private Image mErrorImage; - - /** The {@link FolderConfiguration} representing the state of the UI controls */ - private FolderConfiguration mCurrentConfig = new FolderConfiguration(); - /** The {@link FolderConfiguration} being edited. */ - private FolderConfiguration mEditedConfig; - - private Map<String, Map<String, IResourceValue>> mConfiguredFrameworkRes; - private Map<String, Map<String, IResourceValue>> mConfiguredProjectRes; - private ProjectCallback mProjectCallback; - private ILayoutLog mLogger; - - private boolean mNeedsRecompute = false; - private int mPlatformThemeCount = 0; - private boolean mDisableUpdates = false; - - private Runnable mFrameworkResourceChangeListener = new Runnable() { - public void run() { - // because the SDK changed we must reset the configured framework resource. - mConfiguredFrameworkRes = null; - - updateUIFromResources(); - mThemeCombo.getParent().layout(); - - // updateUiFromFramework will reset language/region combo, so we must call - // setConfiguration after, or the settext on language/region will be lost. - if (mEditedConfig != null) { - setConfiguration(mEditedConfig); - } - - // make sure we remove the custom view loader, since its parent class loader is the - // bridge class loader. - mProjectCallback = null; - - recomputeLayout(); - } - }; - - private final Runnable mConditionalRecomputeRunnable = new Runnable() { - public void run() { - if (mLayoutEditor.isGraphicalEditorActive()) { - recomputeLayout(); - } else { - mNeedsRecompute = true; - } - } - }; - - private final Runnable mUiUpdateFromResourcesRunnable = new Runnable() { - public void run() { - updateUIFromResources(); - mThemeCombo.getParent().layout(); - } - }; - - public GraphicalLayoutEditor(LayoutEditor layoutEditor) { - mLayoutEditor = layoutEditor; - setEditDomain(new DefaultEditDomain(this)); - setPartName("Layout"); - - IconFactory factory = IconFactory.getInstance(); - mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$ - mMatchImage = factory.getIcon("match"); //$NON-NLS-1$ - mErrorImage = factory.getIcon("error"); //$NON-NLS-1$ - - EditorsPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener); - } - - // ------------------------------------ - // Methods overridden from base classes - //------------------------------------ - - @Override - public void createPartControl(Composite parent) { - mParent = parent; - GridLayout gl; - GridData gd; - - mClipboard = new Clipboard(parent.getDisplay()); - - parent.setLayout(gl = new GridLayout(1, false)); - gl.marginHeight = gl.marginWidth = 0; - - // create the top part for the configuration control - int cols = 10; - - Composite topParent = new Composite(parent, SWT.NONE); - topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - topParent.setLayout(gl = new GridLayout(cols, false)); - - new Label(topParent, SWT.NONE).setText("MCC"); - mCountryIcon = createControlComposite(topParent, true /* grab_horizontal */); - mCountry = new Text(mCountryIcon.getParent(), SWT.BORDER); - mCountry.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mCountry.addVerifyListener(new MobileCodeVerifier()); - mCountry.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - onCountryCodeChange(); - } - }); - mCountry.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onCountryCodeChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("MNC"); - mNetworkIcon = createControlComposite(topParent, true /* grab_horizontal */); - mNetwork = new Text(mNetworkIcon.getParent(), SWT.BORDER); - mNetwork.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mNetwork.addVerifyListener(new MobileCodeVerifier()); - mNetwork.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - onNetworkCodeChange(); - } - }); - mNetwork.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onNetworkCodeChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Lang"); - mLanguageIcon = createControlComposite(topParent, true /* grab_horizontal */); - mLanguage = new Combo(mLanguageIcon.getParent(), SWT.DROP_DOWN); - mLanguage.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mLanguage.addVerifyListener(new LanguageRegionVerifier()); - mLanguage.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onLanguageChange(); - } - public void widgetSelected(SelectionEvent e) { - onLanguageChange(); - } - }); - mLanguage.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onLanguageChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Region"); - mRegionIcon = createControlComposite(topParent, true /* grab_horizontal */); - mRegion = new Combo(mRegionIcon.getParent(), SWT.DROP_DOWN); - mRegion.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mRegion.addVerifyListener(new LanguageRegionVerifier()); - mRegion.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onRegionChange(); - } - public void widgetSelected(SelectionEvent e) { - onRegionChange(); - } - }); - mRegion.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onRegionChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Orient"); - mOrientationIcon = createControlComposite(topParent, true /* grab_horizontal */); - mOrientation = new Combo(mOrientationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - ScreenOrientation[] soValues = ScreenOrientation.values(); - mOrientation.add("(Default)"); - for (ScreenOrientation value : soValues) { - mOrientation.add(value.getDisplayValue()); - } - mOrientation.select(0); - mOrientation.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mOrientation.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onOrientationChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Density"); - mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */); - mDensity = new Text(mDensityIcon.getParent(), SWT.BORDER); - mDensity.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mDensity.addVerifyListener(new DensityVerifier()); - mDensity.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - onDensityChange(); - } - }); - mDensity.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onDensityChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Touch"); - mTouchIcon = createControlComposite(topParent, true /* grab_horizontal */); - mTouch = new Combo(mTouchIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - TouchScreenType[] tstValues = TouchScreenType.values(); - mTouch.add("(Default)"); - for (TouchScreenType value : tstValues) { - mTouch.add(value.getDisplayValue()); - } - mTouch.select(0); - mTouch.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mTouch.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onTouchChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Keybrd"); - mKeyboardIcon = createControlComposite(topParent, true /* grab_horizontal */); - mKeyboard = new Combo(mKeyboardIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - KeyboardState[] ksValues = KeyboardState.values(); - mKeyboard.add("(Default)"); - for (KeyboardState value : ksValues) { - mKeyboard.add(value.getDisplayValue()); - } - mKeyboard.select(0); - mKeyboard.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mKeyboard.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onKeyboardChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Input"); - mTextInputIcon = createControlComposite(topParent, true /* grab_horizontal */); - mTextInput = new Combo(mTextInputIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - TextInputMethod[] timValues = TextInputMethod.values(); - mTextInput.add("(Default)"); - for (TextInputMethod value : timValues) { - mTextInput.add(value.getDisplayValue()); - } - mTextInput.select(0); - mTextInput.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mTextInput.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onTextInputChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Nav"); - mNavigationIcon = createControlComposite(topParent, true /* grab_horizontal */); - mNavigation = new Combo(mNavigationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - NavigationMethod[] nValues = NavigationMethod.values(); - mNavigation.add("(Default)"); - for (NavigationMethod value : nValues) { - mNavigation.add(value.getDisplayValue()); - } - mNavigation.select(0); - mNavigation.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mNavigation.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onNavigationChange(); - } - }); - - Composite labelParent = new Composite(topParent, SWT.NONE); - labelParent.setLayout(gl = new GridLayout(8, false)); - gl.marginWidth = gl.marginHeight = 0; - labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = cols; - - new Label(labelParent, SWT.NONE).setText("Editing config:"); - mCurrentLayoutLabel = new Label(labelParent, SWT.NONE); - mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.widthHint = 50; - - new Label(labelParent, SWT.NONE).setText("Size"); - mSizeIcon = createControlComposite(labelParent, false); - Composite sizeParent = new Composite(mSizeIcon.getParent(), SWT.NONE); - sizeParent.setLayout(gl = new GridLayout(3, false)); - gl.marginWidth = gl.marginHeight = 0; - gl.horizontalSpacing = 0; - - mSize1 = new Text(sizeParent, SWT.BORDER); - mSize1.setLayoutData(gd = new GridData()); - gd.widthHint = 30; - new Label(sizeParent, SWT.NONE).setText("x"); - mSize2 = new Text(sizeParent, SWT.BORDER); - mSize2.setLayoutData(gd = new GridData()); - gd.widthHint = 30; - - DimensionVerifier verifier = new DimensionVerifier(); - mSize1.addVerifyListener(verifier); - mSize2.addVerifyListener(verifier); - - SelectionListener sl = new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onSizeChange(); - } - public void widgetSelected(SelectionEvent e) { - onSizeChange(); - } - }; - - mSize1.addSelectionListener(sl); - mSize2.addSelectionListener(sl); - - ModifyListener sizeModifyListener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - onSizeChange(); - } - }; - - mSize1.addModifyListener(sizeModifyListener); - mSize2.addModifyListener(sizeModifyListener); - - // first separator - Label separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL); - separator.setLayoutData(gd = new GridData( - GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); - gd.heightHint = 0; - - mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN); - mThemeCombo.setEnabled(false); - updateUIFromResources(); - mThemeCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onThemeChange(); - } - }); - - // second separator - separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL); - separator.setLayoutData(gd = new GridData( - GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); - gd.heightHint = 0; - - mCreateButton = new Button(labelParent, SWT.PUSH | SWT.FLAT); - mCreateButton.setText("Create..."); - mCreateButton.setEnabled(false); - mCreateButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - LayoutCreatorDialog dialog = new LayoutCreatorDialog(mCreateButton.getShell(), - mEditedFile.getName(), mCurrentConfig); - if (dialog.open() == Dialog.OK) { - final FolderConfiguration config = new FolderConfiguration(); - dialog.getConfiguration(config); - - createAlternateLayout(config); - } - } - }); - - // create a new composite that will contain the standard editor controls. - Composite editorParent = new Composite(parent, SWT.NONE); - editorParent.setLayoutData(new GridData(GridData.FILL_BOTH)); - editorParent.setLayout(new FillLayout()); - super.createPartControl(editorParent); - } - - @Override - public void dispose() { - if (mFrameworkResourceChangeListener != null) { - EditorsPlugin.getDefault().removeResourceChangedListener( - mFrameworkResourceChangeListener); - mFrameworkResourceChangeListener = null; - } - - LayoutReloadMonitor.getMonitor().removeListener(mEditedFile.getProject(), this); - - if (mClipboard != null) { - mClipboard.dispose(); - mClipboard = null; - } - - super.dispose(); - } - - /* (non-Javadoc) - * Creates the palette root. - */ - protected PaletteRoot getPaletteRoot() { - return PaletteFactory.createPaletteRoot(); - } - - public Clipboard getClipboard() { - return mClipboard; - } - - /** - * Save operation in the Graphical Layout Editor. - * <p/> - * In our workflow, the model is owned by the Structured XML Editor. - * The graphical layout editor just displays it -- thus we don't really - * save anything here. - * <p/> - * This must NOT call the parent editor part. At the contrary, the parent editor - * part will call this *after* having done the actual save operation. - * <p/> - * The only action this editor must do is mark the undo command stack as - * being no longer dirty. - */ - @Override - public void doSave(IProgressMonitor monitor) { - getCommandStack().markSaveLocation(); - firePropertyChange(PROP_DIRTY); - } - - /* (non-javadoc) - * Configure the graphical viewer before it receives its contents. - */ - @Override - protected void configureGraphicalViewer() { - super.configureGraphicalViewer(); - - GraphicalViewer viewer = getGraphicalViewer(); - viewer.setEditPartFactory(new UiElementsEditPartFactory(mParent.getDisplay())); - viewer.setRootEditPart(new ScalableFreeformRootEditPart()); - - // TODO: viewer.setKeyHandler() - // TODO: custom ContextMenuProvider => viewer.setContextMenu & registerContextMenu - - viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer)); - viewer.addDropTargetListener(new TemplateTransferDropTargetListener(viewer)); - } - - /* (non-javadoc) - * Set the contents of the GraphicalViewer after it has been created. - */ - @Override - protected void initializeGraphicalViewer() { - GraphicalViewer viewer = getGraphicalViewer(); - viewer.setContents(getModel()); - - IEditorInput input = getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - mEditedFile = fileInput.getFile(); - - updateUIFromResources(); - - LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this); - } else { - // really this shouldn't happen! Log it in case it happens - mEditedFile = null; - EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s", - input.toString()); - } - } - - //-------------- - // Local methods - //-------------- - - public LayoutEditor getLayoutEditor() { - return mLayoutEditor; - } - - /** - * Sets the UI for the edition of a new file. - * @param configuration the configuration of the new file. - */ - public void editNewFile(FolderConfiguration configuration) { - // update the configuration UI - setConfiguration(configuration); - - // enable the create button if the current and edited config are not equals - mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false); - } - - public Rectangle getBounds() { - ScreenOrientation orientation = null; - if (mOrientation.getSelectionIndex() == 0) { - orientation = ScreenOrientation.PORTRAIT; - } else { - orientation = ScreenOrientation.getByIndex( - mOrientation.getSelectionIndex() - 1); - } - - int s1, s2; - - // get the size from the UI controls. If it fails, revert to default values. - try { - s1 = Integer.parseInt(mSize1.getText().trim()); - } catch (NumberFormatException e) { - s1 = 480; - } - - try { - s2 = Integer.parseInt(mSize2.getText().trim()); - } catch (NumberFormatException e) { - s2 = 320; - } - - // make sure s1 is bigger than s2 - if (s1 < s2) { - int tmp = s1; - s1 = s2; - s2 = tmp; - } - - switch (orientation) { - default: - case PORTRAIT: - return new Rectangle(0, 0, s2, s1); - case LANDSCAPE: - return new Rectangle(0, 0, s1, s2); - case SQUARE: - return new Rectangle(0, 0, s1, s1); - } - } - - /** - * Reloads this editor, by getting the new model from the {@link LayoutEditor}. - */ - void reloadEditor() { - GraphicalViewer viewer = getGraphicalViewer(); - viewer.setContents(getModel()); - - IEditorInput input = mLayoutEditor.getEditorInput(); - setInput(input); - - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - mEditedFile = fileInput.getFile(); - } else { - // really this shouldn't happen! Log it in case it happens - mEditedFile = null; - EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s", - input.toString()); - } - } - - /** - * Update the layout editor when the Xml model is changed. - */ - void onXmlModelChanged() { - GraphicalViewer viewer = getGraphicalViewer(); - - // try to preserve the selection before changing the content - SelectionManager selMan = viewer.getSelectionManager(); - ISelection selection = selMan.getSelection(); - - try { - viewer.setContents(getModel()); - } finally { - selMan.setSelection(selection); - } - - if (mLayoutEditor.isGraphicalEditorActive()) { - recomputeLayout(); - } else { - mNeedsRecompute = true; - } - } - - /** - * Update the UI controls state with a given {@link FolderConfiguration}. - * <p/>If a qualifier is not present in the {@link FolderConfiguration} object, the UI control - * is not modified. However if the value in the control is not the default value, a warning - * icon is showed. - */ - void setConfiguration(FolderConfiguration config) { - mDisableUpdates = true; // we do not want to trigger onXXXChange when setting new values in the widgets. - - mEditedConfig = config; - mConfiguredFrameworkRes = mConfiguredProjectRes = null; - - mCountryIcon.setImage(mMatchImage); - CountryCodeQualifier countryQualifier = config.getCountryCodeQualifier(); - if (countryQualifier != null) { - mCountry.setText(String.format("%1$d", countryQualifier.getCode())); - mCurrentConfig.setCountryCodeQualifier(countryQualifier); - } else if (mCountry.getText().length() > 0) { - mCountryIcon.setImage(mWarningImage); - } - - mNetworkIcon.setImage(mMatchImage); - NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier(); - if (networkQualifier != null) { - mNetwork.setText(String.format("%1$d", networkQualifier.getCode())); - mCurrentConfig.setNetworkCodeQualifier(networkQualifier); - } else if (mNetwork.getText().length() > 0) { - mNetworkIcon.setImage(mWarningImage); - } - - mLanguageIcon.setImage(mMatchImage); - LanguageQualifier languageQualifier = config.getLanguageQualifier(); - if (languageQualifier != null) { - mLanguage.setText(languageQualifier.getValue()); - mCurrentConfig.setLanguageQualifier(languageQualifier); - } else if (mLanguage.getText().length() > 0) { - mLanguageIcon.setImage(mWarningImage); - } - - mRegionIcon.setImage(mMatchImage); - RegionQualifier regionQualifier = config.getRegionQualifier(); - if (regionQualifier != null) { - mRegion.setText(regionQualifier.getValue()); - mCurrentConfig.setRegionQualifier(regionQualifier); - } else if (mRegion.getText().length() > 0) { - mRegionIcon.setImage(mWarningImage); - } - - mOrientationIcon.setImage(mMatchImage); - ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier(); - if (orientationQualifier != null) { - mOrientation.select( - ScreenOrientation.getIndex(orientationQualifier.getValue()) + 1); - mCurrentConfig.setScreenOrientationQualifier(orientationQualifier); - } else if (mOrientation.getSelectionIndex() != 0) { - mOrientationIcon.setImage(mWarningImage); - } - - mDensityIcon.setImage(mMatchImage); - PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier(); - if (densityQualifier != null) { - mDensity.setText(String.format("%1$d", densityQualifier.getValue())); - mCurrentConfig.setPixelDensityQualifier(densityQualifier); - } else if (mDensity.getText().length() > 0) { - mDensityIcon.setImage(mWarningImage); - } - - mTouchIcon.setImage(mMatchImage); - TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier(); - if (touchQualifier != null) { - mTouch.select(TouchScreenType.getIndex(touchQualifier.getValue()) + 1); - mCurrentConfig.setTouchTypeQualifier(touchQualifier); - } else if (mTouch.getSelectionIndex() != 0) { - mTouchIcon.setImage(mWarningImage); - } - - mKeyboardIcon.setImage(mMatchImage); - KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier(); - if (keyboardQualifier != null) { - mKeyboard.select(KeyboardState.getIndex(keyboardQualifier.getValue()) + 1); - mCurrentConfig.setKeyboardStateQualifier(keyboardQualifier); - } else if (mKeyboard.getSelectionIndex() != 0) { - mKeyboardIcon.setImage(mWarningImage); - } - - mTextInputIcon.setImage(mMatchImage); - TextInputMethodQualifier inputQualifier = config.getTextInputMethodQualifier(); - if (inputQualifier != null) { - mTextInput.select(TextInputMethod.getIndex(inputQualifier.getValue()) + 1); - mCurrentConfig.setTextInputMethodQualifier(inputQualifier); - } else if (mTextInput.getSelectionIndex() != 0) { - mTextInputIcon.setImage(mWarningImage); - } - - mNavigationIcon.setImage(mMatchImage); - NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier(); - if (navigationQualifiter != null) { - mNavigation.select( - NavigationMethod.getIndex(navigationQualifiter.getValue()) + 1); - mCurrentConfig.setNavigationMethodQualifier(navigationQualifiter); - } else if (mNavigation.getSelectionIndex() != 0) { - mNavigationIcon.setImage(mWarningImage); - } - - mSizeIcon.setImage(mMatchImage); - ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier(); - if (sizeQualifier != null) { - mSize1.setText(String.format("%1$d", sizeQualifier.getValue1())); - mSize2.setText(String.format("%1$d", sizeQualifier.getValue2())); - mCurrentConfig.setScreenDimensionQualifier(sizeQualifier); - } else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) { - mSizeIcon.setImage(mWarningImage); - } - - // update the string showing the folder name - String current = config.toDisplayString(); - mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); - - mDisableUpdates = false; - } - - /** - * Displays an error icon in front of all the non-null qualifiers. - */ - void displayConfigError() { - mCountryIcon.setImage(mMatchImage); - CountryCodeQualifier countryQualifier = mCurrentConfig.getCountryCodeQualifier(); - if (countryQualifier != null) { - mCountryIcon.setImage(mErrorImage); - } - - mNetworkIcon.setImage(mMatchImage); - NetworkCodeQualifier networkQualifier = mCurrentConfig.getNetworkCodeQualifier(); - if (networkQualifier != null) { - mNetworkIcon.setImage(mErrorImage); - } - - mLanguageIcon.setImage(mMatchImage); - LanguageQualifier languageQualifier = mCurrentConfig.getLanguageQualifier(); - if (languageQualifier != null) { - mLanguageIcon.setImage(mErrorImage); - } - - mRegionIcon.setImage(mMatchImage); - RegionQualifier regionQualifier = mCurrentConfig.getRegionQualifier(); - if (regionQualifier != null) { - mRegionIcon.setImage(mErrorImage); - } - - mOrientationIcon.setImage(mMatchImage); - ScreenOrientationQualifier orientationQualifier = - mCurrentConfig.getScreenOrientationQualifier(); - if (orientationQualifier != null) { - mOrientationIcon.setImage(mErrorImage); - } - - mDensityIcon.setImage(mMatchImage); - PixelDensityQualifier densityQualifier = mCurrentConfig.getPixelDensityQualifier(); - if (densityQualifier != null) { - mDensityIcon.setImage(mErrorImage); - } - - mTouchIcon.setImage(mMatchImage); - TouchScreenQualifier touchQualifier = mCurrentConfig.getTouchTypeQualifier(); - if (touchQualifier != null) { - mTouchIcon.setImage(mErrorImage); - } - - mKeyboardIcon.setImage(mMatchImage); - KeyboardStateQualifier keyboardQualifier = mCurrentConfig.getKeyboardStateQualifier(); - if (keyboardQualifier != null) { - mKeyboardIcon.setImage(mErrorImage); - } - - mTextInputIcon.setImage(mMatchImage); - TextInputMethodQualifier inputQualifier = mCurrentConfig.getTextInputMethodQualifier(); - if (inputQualifier != null) { - mTextInputIcon.setImage(mErrorImage); - } - - mNavigationIcon.setImage(mMatchImage); - NavigationMethodQualifier navigationQualifiter = - mCurrentConfig.getNavigationMethodQualifier(); - if (navigationQualifiter != null) { - mNavigationIcon.setImage(mErrorImage); - } - - mSizeIcon.setImage(mMatchImage); - ScreenDimensionQualifier sizeQualifier = mCurrentConfig.getScreenDimensionQualifier(); - if (sizeQualifier != null) { - mSizeIcon.setImage(mErrorImage); - } - - // update the string showing the folder name - String current = mCurrentConfig.toDisplayString(); - mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); - } - - UiDocumentNode getModel() { - return mLayoutEditor.getUiRootNode(); - } - - private void onCountryCodeChange() { - // because mCountry triggers onCountryCodeChange at each modification, calling setText() - // will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mCountry.getText(); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setCountryCodeQualifier(null); - } else { - try { - CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier( - CountryCodeQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mCurrentConfig.setCountryCodeQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - // We do nothing in this case. - mCountryIcon.setImage(mErrorImage); - return; - } - } catch (NumberFormatException e) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - mCurrentConfig.setCountryCodeQualifier(null); - mCountryIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onNetworkCodeChange() { - // because mNetwork triggers onNetworkCodeChange at each modification, calling setText() - // will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mNetwork.getText(); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setNetworkCodeQualifier(null); - } else { - try { - NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier( - NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mCurrentConfig.setNetworkCodeQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - // We do nothing in this case. - mNetworkIcon.setImage(mErrorImage); - return; - } - } catch (NumberFormatException e) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - mCurrentConfig.setNetworkCodeQualifier(null); - mNetworkIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - /** - * Call back for language combo selection - */ - private void onLanguageChange() { - // because mLanguage triggers onLanguageChange at each modification, the filling - // of the combo with data will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mLanguage.getText(); - - updateRegionUi(null /* projectResources */, null /* frameworkResources */); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setLanguageQualifier(null); - } else { - LanguageQualifier qualifier = null; - String segment = LanguageQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = LanguageQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mCurrentConfig.setLanguageQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mCurrentConfig.setLanguageQualifier(null); - mLanguageIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onRegionChange() { - // because mRegion triggers onRegionChange at each modification, the filling - // of the combo with data will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mRegion.getText(); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setRegionQualifier(null); - } else { - RegionQualifier qualifier = null; - String segment = RegionQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = RegionQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mCurrentConfig.setRegionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mCurrentConfig.setRegionQualifier(null); - mRegionIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onOrientationChange() { - // update the current config - int index = mOrientation.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setScreenOrientationQualifier(new ScreenOrientationQualifier( - ScreenOrientation.getByIndex(index-1))); - } else { - mCurrentConfig.setScreenOrientationQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onDensityChange() { - // because mDensity triggers onDensityChange at each modification, calling setText() - // will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mDensity.getText(); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setPixelDensityQualifier(null); - } else { - try { - PixelDensityQualifier qualifier = PixelDensityQualifier.getQualifier( - PixelDensityQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mCurrentConfig.setPixelDensityQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - // We do nothing in this case. - return; - } - } catch (NumberFormatException e) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - // We do nothing in this case. - mDensityIcon.setImage(mErrorImage); - return; - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onTouchChange() { - // update the current config - int index = mTouch.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setTouchTypeQualifier(new TouchScreenQualifier( - TouchScreenType.getByIndex(index-1))); - } else { - mCurrentConfig.setTouchTypeQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onKeyboardChange() { - // update the current config - int index = mKeyboard.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setKeyboardStateQualifier(new KeyboardStateQualifier( - KeyboardState.getByIndex(index-1))); - } else { - mCurrentConfig.setKeyboardStateQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onTextInputChange() { - // update the current config - int index = mTextInput.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setTextInputMethodQualifier(new TextInputMethodQualifier( - TextInputMethod.getByIndex(index-1))); - } else { - mCurrentConfig.setTextInputMethodQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onNavigationChange() { - // update the current config - int index = mNavigation.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setNavigationMethodQualifier(new NavigationMethodQualifier( - NavigationMethod.getByIndex(index-1))); - } else { - mCurrentConfig.setNavigationMethodQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onSizeChange() { - // because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText() - // will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String size1 = mSize1.getText(); - String size2 = mSize2.getText(); - - // if only one of the strings is empty, do nothing - if ((size1.length() == 0) ^ (size2.length() == 0)) { - mSizeIcon.setImage(mErrorImage); - return; - } else if (size1.length() == 0 && size2.length() == 0) { - // both sizes are empty: remove the qualifier. - mCurrentConfig.setScreenDimensionQualifier(null); - } else { - ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1, - size2); - - if (qualifier != null) { - mCurrentConfig.setScreenDimensionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong. - // we do nothing in this case. - return; - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - - /** - * Looks for a file matching the new {@link FolderConfiguration} and attempts to open it. - * <p/>If there is no match, notify the user. - */ - private void onConfigurationChange() { - mConfiguredFrameworkRes = mConfiguredProjectRes = null; - - if (mEditedFile == null || mEditedConfig == null) { - return; - } - - // get the resources of the file's project. - ProjectResources resources = ResourceManager.getInstance().getProjectResources( - mEditedFile.getProject()); - - // from the resources, look for a matching file - ResourceFile match = null; - if (resources != null) { - match = resources.getMatchingFile(mEditedFile.getName(), - ResourceFolderType.LAYOUT, - mCurrentConfig); - } - - if (match != null) { - if (match.getFile().equals(mEditedFile) == false) { - try { - IDE.openEditor( - getSite().getWorkbenchWindow().getActivePage(), - match.getFile().getIFile()); - - // we're done! - return; - } catch (PartInitException e) { - // FIXME: do something! - } - } - - // at this point, we have not opened a new file. - - // update the configuration icons with the new edited config. - setConfiguration(mEditedConfig); - - // enable the create button if the current and edited config are not equals - mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false); - - // Even though the layout doesn't change, the config changed, and referenced - // resources need to be updated. - recomputeLayout(); - } else { - // update the configuration icons with the new edited config. - displayConfigError(); - - // enable the Create button - mCreateButton.setEnabled(true); - - // display the error. - String message = String.format( - "No resources match the configuration\n \n\t%1$s\n \nChange the configuration or create:\n \n\tres/%2$s/%3$s\n \nYou can also click the 'Create' button above.", - mCurrentConfig.toDisplayString(), - mCurrentConfig.getFolderName(ResourceFolderType.LAYOUT), - mEditedFile.getName()); - showErrorInEditor(message); - } - } - - private void onThemeChange() { - int themeIndex = mThemeCombo.getSelectionIndex(); - if (themeIndex != -1) { - String theme = mThemeCombo.getItem(themeIndex); - - if (theme.equals(THEME_SEPARATOR)) { - mThemeCombo.select(0); - } - - recomputeLayout(); - } - } - - /** - * Creates a composite with no margin/spacing, and puts a {@link Label} in it with the matching - * icon. - * @param parent the parent to receive the composite - * @return the created {@link Label} object. - */ - private Label createControlComposite(Composite parent, boolean grab) { - GridLayout gl; - - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - gl.horizontalSpacing = 0; - if (grab) { - composite.setLayoutData( - new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - } - - // create the label - Label icon = new Label(composite, SWT.NONE); - icon.setImage(mMatchImage); - - return icon; - } - - /** - * Recomputes the layout with the help of layoutlib. - */ - void recomputeLayout() { - try { - // check that the resource exists. If the file is opened but the project is closed - // or deleted for some reason (changed from outside of eclipse), then this will - // return false; - if (mEditedFile.exists() == false) { - String message = String.format("Resource '%1$s' does not exist.", - mEditedFile.getFullPath().toString()); - - showErrorInEditor(message); - - return; - } - - IProject iProject = mEditedFile.getProject(); - - if (mEditedFile.isSynchronized(IResource.DEPTH_ZERO) == false) { - String message = String.format("%1$s is out of sync. Please refresh.", - mEditedFile.getName()); - - showErrorInEditor(message); - - // also print it in the error console. - EditorsPlugin.printErrorToConsole(iProject.getName(), message); - return; - } - - // check there is actually a model (maybe the file is empty). - UiDocumentNode model = getModel(); - - if (model.getUiChildren().size() == 0) { - showErrorInEditor("No Xml content. Go to the Outline view and add nodes."); - return; - } - - EditorsPlugin plugin = EditorsPlugin.getDefault(); - LayoutBridge bridge = plugin.getLayoutBridge(); - - if (bridge.bridge != null) { // bridge can never be null. - ResourceManager resManager = ResourceManager.getInstance(); - - ProjectResources projectRes = resManager.getProjectResources(iProject); - if (projectRes == null) { - return; - } - - // get the resources of the file's project. - if (mConfiguredProjectRes == null) { - // make sure they are loaded - projectRes.loadAll(); - - // get the project resource values based on the current config - mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig); - } - - // get the framework resources - Map<String, Map<String, IResourceValue>> frameworkResources = - getConfiguredFrameworkResources(); - - if (mConfiguredProjectRes != null && frameworkResources != null) { - if (mProjectCallback == null) { - mProjectCallback = new ProjectCallback( - plugin.getLayoutlibBridgeClassLoader(), projectRes, iProject); - } - - if (mLogger == null) { - mLogger = new ILayoutLog() { - public void error(String message) { - EditorsPlugin.printErrorToConsole(mEditedFile.getName(), message); - } - - public void error(Throwable error) { - String message = error.getMessage(); - if (message == null) { - message = error.getClass().getName(); - } - - PrintStream ps = new PrintStream(EditorsPlugin.getErrorStream()); - error.printStackTrace(ps); - } - - public void warning(String message) { - EditorsPlugin.printToConsole(mEditedFile.getName(), message); - } - }; - } - - // get the selected theme - int themeIndex = mThemeCombo.getSelectionIndex(); - if (themeIndex != -1) { - String theme = mThemeCombo.getItem(themeIndex); - - // change the string if it's a custom theme to make sure we can - // differentiate them - if (themeIndex >= mPlatformThemeCount) { - theme = "*" + theme; //$NON-NLS-1$ - } - - // Compute the layout - UiElementPullParser parser = new UiElementPullParser(getModel()); - Rectangle rect = getBounds(); - ILayoutResult result = bridge.bridge.computeLayout(parser, iProject, - rect.width, rect.height, theme, - mConfiguredProjectRes, frameworkResources, mProjectCallback, - mLogger); - - // update the UiElementNode with the layout info. - if (result.getSuccess() == ILayoutResult.SUCCESS) { - model.setEditData(result.getImage()); - - updateNodeWithBounds(result.getRootView()); - } else { - String message = result.getErrorMessage(); - - // Reset the edit data for all the nodes. - resetNodeBounds(model); - - if (message != null) { - // set the error in the top element. - model.setEditData(message); - } - } - - model.refreshUi(); - } - } - } else { - String message = null; - - // check whether the bridge managed to load, or not - if (bridge.status == LayoutBridge.LoadStatus.LOADING) { - message = String.format( - "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.", - mEditedFile.getName()); - } else { - message = String.format("Eclipse failed to load the framework information and the Layout library!"); - } - - showErrorInEditor(message); - } - } finally { - // no matter the result, we are done doing the recompute based on the latest - // resource/code change. - mNeedsRecompute = false; - } - } - - private void showErrorInEditor(String message) { - // get the model to display the error directly in the editor - UiDocumentNode model = getModel(); - - // Reset the edit data for all the nodes. - resetNodeBounds(model); - - if (message != null) { - // set the error in the top element. - model.setEditData(message); - } - - model.refreshUi(); - } - - private void resetNodeBounds(UiElementNode node) { - node.setEditData(null); - - List<UiElementNode> children = node.getUiChildren(); - for (UiElementNode child : children) { - resetNodeBounds(child); - } - } - - private void updateNodeWithBounds(ILayoutViewInfo r) { - if (r != null) { - // update the node itself, as the viewKey is the XML node in this implementation. - Object viewKey = r.getViewKey(); - if (viewKey instanceof UiElementNode) { - Rectangle bounds = new Rectangle(r.getLeft(), r.getTop(), - r.getRight()-r.getLeft(), r.getBottom() - r.getTop()); - - ((UiElementNode)viewKey).setEditData(bounds); - } - - // and then its children. - ILayoutViewInfo[] children = r.getChildren(); - if (children != null) { - for (ILayoutViewInfo child : children) { - updateNodeWithBounds(child); - } - } - } - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener#reloadLayout(boolean, boolean, boolean) - * - * Called when the file changes triggered a redraw of the layout - */ - public void reloadLayout(boolean codeChange, boolean rChange, boolean resChange) { - boolean recompute = rChange; - - if (resChange) { - recompute = true; - - // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache. - - // force a reparse in case a value XML file changed. - mConfiguredProjectRes = null; - - // clear the cache in the bridge in case a bitmap/9-patch changed. - EditorsPlugin plugin = EditorsPlugin.getDefault(); - LayoutBridge bridge = plugin.getLayoutBridge(); - - if (bridge.bridge != null) { - bridge.bridge.clearCaches(mEditedFile.getProject()); - } - - mParent.getDisplay().asyncExec(mUiUpdateFromResourcesRunnable); - } - - if (codeChange) { - // only recompute if the custom view loader was used to load some code. - if (mProjectCallback != null && mProjectCallback.isUsed()) { - mProjectCallback = null; - recompute = true; - } - } - - if (recompute) { - mParent.getDisplay().asyncExec(mConditionalRecomputeRunnable); - } - } - - /** - * Responds to a page change that made the Graphical editor page the activated page. - */ - void activated() { - if (mNeedsRecompute) { - recomputeLayout(); - } - } - - /** - * Updates the UI from values in the resources, such as languages, regions, themes, etc... - * This must be called from the UI thread. - */ - private void updateUIFromResources() { - - ResourceManager manager = ResourceManager.getInstance(); - - ProjectResources frameworkProject = manager.getFrameworkResources(); - - mDisableUpdates = true; - - // Reset stuff - int selection = mThemeCombo.getSelectionIndex(); - mThemeCombo.removeAll(); - mPlatformThemeCount = 0; - mLanguage.removeAll(); - - Set<String> languages = new HashSet<String>(); - ArrayList<String> themes = new ArrayList<String>(); - - // get the themes, and languages from the Framework. - if (frameworkProject != null) { - // get the configured resources for the framework - Map<String, Map<String, IResourceValue>> frameworResources = - getConfiguredFrameworkResources(); - - if (frameworResources != null) { - // get the styles. - Map<String, IResourceValue> styles = frameworResources.get( - ResourceType.STYLE.getName()); - - - // collect the themes out of all the styles. - for (IResourceValue value : styles.values()) { - String name = value.getName(); - if (name.startsWith("Theme.") || name.equals("Theme")) { - themes.add(value.getName()); - mPlatformThemeCount++; - } - } - - // sort them and add them to the combo - Collections.sort(themes); - - for (String theme : themes) { - mThemeCombo.add(theme); - } - - mPlatformThemeCount = themes.size(); - themes.clear(); - } - - // now get the languages from the framework. - Set<String> frameworkLanguages = frameworkProject.getLanguages(); - if (frameworkLanguages != null) { - languages.addAll(frameworkLanguages); - } - } - - // now get the themes and languages from the project. - ProjectResources project = null; - if (mEditedFile != null) { - project = manager.getProjectResources(mEditedFile.getProject()); - - // in cases where the opened file is not linked to a project, this could be null. - if (project != null) { - // get the configured resources for the project - if (mConfiguredProjectRes == null) { - // make sure they are loaded - project.loadAll(); - - // get the project resource values based on the current config - mConfiguredProjectRes = project.getConfiguredResources(mCurrentConfig); - } - - if (mConfiguredProjectRes != null) { - // get the styles. - Map<String, IResourceValue> styleMap = mConfiguredProjectRes.get( - ResourceType.STYLE.getName()); - - if (styleMap != null) { - // collect the themes out of all the styles, ie styles that extend, - // directly or indirectly a platform theme. - for (IResourceValue value : styleMap.values()) { - if (isTheme(value, styleMap)) { - themes.add(value.getName()); - } - } - - // sort them and add them the to the combo. - if (mPlatformThemeCount > 0 && themes.size() > 0) { - mThemeCombo.add(THEME_SEPARATOR); - } - - Collections.sort(themes); - - for (String theme : themes) { - mThemeCombo.add(theme); - } - } - } - - // now get the languages from the project. - Set<String> projectLanguages = project.getLanguages(); - if (projectLanguages != null) { - languages.addAll(projectLanguages); - } - } - } - - // add the languages to the Combo - for (String language : languages) { - mLanguage.add(language); - } - - mDisableUpdates = false; - - // and update the Region UI based on the current language - updateRegionUi(project, frameworkProject); - - // handle default selection of themes - if (mThemeCombo.getItemCount() > 0) { - mThemeCombo.setEnabled(true); - if (selection == -1) { - selection = 0; - } - - if (mThemeCombo.getItemCount() <= selection) { - mThemeCombo.select(0); - } else { - mThemeCombo.select(selection); - } - } else { - mThemeCombo.setEnabled(false); - } - } - - /** - * Returns whether the given <var>style</var> is a theme. - * This is done by making sure the parent is a theme. - * @param value the style to check - * @param styleMap the map of styles for the current project. Key is the style name. - * @return - */ - private boolean isTheme(IResourceValue value, Map<String, IResourceValue> styleMap) { - if (value instanceof IStyleResourceValue) { - IStyleResourceValue style = (IStyleResourceValue)value; - - boolean frameworkStyle = false; - String parentStyle = style.getParentStyle(); - if (parentStyle == null) { - // if there is no specified parent style we look an implied one. - // For instance 'Theme.light' is implied child style of 'Theme', - // and 'Theme.light.fullscreen' is implied child style of 'Theme.light' - String name = style.getName(); - int index = name.lastIndexOf('.'); - if (index != -1) { - parentStyle = name.substring(0, index); - } - } else { - // remove the useless @ if it's there - if (parentStyle.startsWith("@")) { - parentStyle = parentStyle.substring(1); - } - - // check for framework identifier. - if (parentStyle.startsWith("android:")) { - frameworkStyle = true; - parentStyle = parentStyle.substring("android:".length()); - } - - // at this point we could have the format style/<name>. we want only the name - if (parentStyle.startsWith("style/")) { - parentStyle = parentStyle.substring("style/".length()); - } - } - - if (frameworkStyle) { - // if the parent is a framework style, it has to be 'Theme' or 'Theme.*' - return parentStyle.equals("Theme") || parentStyle.startsWith("Theme."); - } else { - // if it's a project style, we check this is a theme. - value = styleMap.get(parentStyle); - if (value != null) { - return isTheme(value, styleMap); - } - } - } - - return false; - } - - /** - * Update the Region UI widget based on the current language selection - * @param projectResources the project resources or {@code null}. - * @param frameworkResources the framework resource or {@code null} - */ - private void updateRegionUi(ProjectResources projectResources, - ProjectResources frameworkResources) { - if (projectResources == null && mEditedFile != null) { - projectResources = ResourceManager.getInstance().getProjectResources( - mEditedFile.getProject()); - } - - if (frameworkResources == null) { - frameworkResources = ResourceManager.getInstance().getFrameworkResources(); - } - - String currentLanguage = mLanguage.getText(); - - Set<String> set = null; - - if (projectResources != null) { - set = projectResources.getRegions(currentLanguage); - } - - if (frameworkResources != null) { - if (set != null) { - Set<String> set2 = frameworkResources.getRegions(currentLanguage); - set.addAll(set2); - } else { - set = frameworkResources.getRegions(currentLanguage); - } - } - - if (set != null) { - mDisableUpdates = true; - - mRegion.removeAll(); - for (String region : set) { - mRegion.add(region); - } - - mDisableUpdates = false; - } - } - - private Map<String, Map<String, IResourceValue>> getConfiguredFrameworkResources() { - if (mConfiguredFrameworkRes == null) { - ProjectResources frameworkRes = ResourceManager.getInstance().getFrameworkResources(); - - if (frameworkRes == null) { - EditorsPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework"); - } - - // get the framework resource values based on the current config - mConfiguredFrameworkRes = frameworkRes.getConfiguredResources(mCurrentConfig); - } - - return mConfiguredFrameworkRes; - } - - /** - * Returns the selection synchronizer object. - * The synchronizer can be used to sync the selection of 2 or more EditPartViewers. - * <p/> - * This is changed from protected to public so that the outline can use it. - * - * @return the synchronizer - */ - @Override - public SelectionSynchronizer getSelectionSynchronizer() { - return super.getSelectionSynchronizer(); - } - - /** - * Returns the edit domain. - * <p/> - * This is changed from protected to public so that the outline can use it. - * - * @return the edit domain - */ - @Override - public DefaultEditDomain getEditDomain() { - return super.getEditDomain(); - } - - /** - * Creates a new layout file from the specificed {@link FolderConfiguration}. - */ - private void createAlternateLayout(final FolderConfiguration config) { - new Job("Create Alternate Resource") { - @Override - protected IStatus run(IProgressMonitor monitor) { - // get the folder name - String folderName = config.getFolderName(ResourceFolderType.LAYOUT); - try { - - // look to see if it exists. - // get the res folder - IFolder res = (IFolder)mEditedFile.getParent().getParent(); - String path = res.getLocation().toOSString(); - - File newLayoutFolder = new File(path + File.separator + folderName); - if (newLayoutFolder.isFile()) { - // this should not happen since aapt would have complained - // before, but if one disable the automatic build, this could - // happen. - String message = String.format("File 'res/%1$s' is in the way!", - folderName); - - EditorsPlugin.displayError("Layout Creation", message); - - return new Status(IStatus.ERROR, - AndroidConstants.EDITORS_PLUGIN_ID, message); - } else if (newLayoutFolder.exists() == false) { - // create it. - newLayoutFolder.mkdir(); - } - - // now create the file - File newLayoutFile = new File(newLayoutFolder.getAbsolutePath() + - File.separator + mEditedFile.getName()); - - newLayoutFile.createNewFile(); - - InputStream input = mEditedFile.getContents(); - - FileOutputStream fos = new FileOutputStream(newLayoutFile); - - byte[] data = new byte[512]; - int count; - while ((count = input.read(data)) != -1) { - fos.write(data, 0, count); - } - - input.close(); - fos.close(); - - // refreshes the res folder to show up the new - // layout folder (if needed) and the file. - // We use a progress monitor to catch the end of the refresh - // to trigger the edit of the new file. - res.refreshLocal(IResource.DEPTH_INFINITE, new IProgressMonitor() { - public void done() { - mCurrentConfig.set(config); - mParent.getDisplay().asyncExec(new Runnable() { - public void run() { - onConfigurationChange(); - }; - }); - } - - public void beginTask(String name, int totalWork) { - // pass - } - - public void internalWorked(double work) { - // pass - } - - public boolean isCanceled() { - // pass - return false; - } - - public void setCanceled(boolean value) { - // pass - } - - public void setTaskName(String name) { - // pass - } - - public void subTask(String name) { - // pass - } - - public void worked(int work) { - // pass - } - }); - } catch (IOException e2) { - String message = String.format( - "Failed to create File 'res/%1$s/%2$s' : %3$s", - folderName, mEditedFile.getName(), e2.getMessage()); - - EditorsPlugin.displayError("Layout Creation", message); - - return new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID, - message, e2); - } catch (CoreException e2) { - String message = String.format( - "Failed to create File 'res/%1$s/%2$s' : %3$s", - folderName, mEditedFile.getName(), e2.getMessage()); - - EditorsPlugin.displayError("Layout Creation", message); - - return e2.getStatus(); - } - - return Status.OK_STATUS; - - } - }.schedule(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java deleted file mode 100644 index dfec17a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.AndroidContentAssist; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; - -/** - * Content Assist Processor for /res/layout XML files - */ -class LayoutContentAssist extends AndroidContentAssist { - - /** - * Constructor for LayoutContentAssist - */ - public LayoutContentAssist() { - super(LayoutDescriptors.getInstance().getDescriptor().getChildren()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java deleted file mode 100644 index c4a8f5c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.TrayDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -/** - * Dialog to choose a non existing {@link FolderConfiguration}. - */ -class LayoutCreatorDialog extends TrayDialog { - - private ConfigurationSelector mSelector; - private Composite mStatusComposite; - private Label mStatusLabel; - private Label mStatusImage; - - private final FolderConfiguration mConfig = new FolderConfiguration(); - private final String mFileName; - - /** - * Creates a dialog, and init the UI from a {@link FolderConfiguration}. - * @param parentShell the parent {@link Shell}. - * @param config The starting configuration. - */ - LayoutCreatorDialog(Shell parentShell, String fileName, FolderConfiguration config) { - super(parentShell); - - mFileName = fileName; - // FIXME: add some data to know what configurations already exist. - mConfig.set(config); - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite top = new Composite(parent, SWT.NONE); - top.setLayoutData(new GridData()); - top.setLayout(new GridLayout(1, false)); - - new Label(top, SWT.NONE).setText( - String.format("Configuration for the alternate version of %1$s", mFileName)); - - mSelector = new ConfigurationSelector(top); - mSelector.setConfiguration(mConfig); - - // parent's layout is a GridLayout as specified in the javadoc. - GridData gd = new GridData(); - gd.widthHint = ConfigurationSelector.WIDTH_HINT; - gd.heightHint = ConfigurationSelector.HEIGHT_HINT; - mSelector.setLayoutData(gd); - - // add a listener to check on the validity of the FolderConfiguration as - // they are built. - mSelector.setOnChangeListener(new Runnable() { - public void run() { - ConfigurationState state = mSelector.getState(); - - switch (state) { - case OK: - mSelector.getConfiguration(mConfig); - - resetStatus(); - mStatusImage.setImage(null); - getButton(IDialogConstants.OK_ID).setEnabled(true); - break; - case INVALID_CONFIG: - ResourceQualifier invalidQualifier = mSelector.getInvalidQualifier(); - mStatusLabel.setText(String.format( - "Invalid Configuration: %1$s has no filter set.", - invalidQualifier.getName())); - mStatusImage.setImage(IconFactory.getInstance().getIcon("warning")); //$NON-NLS-1$ - getButton(IDialogConstants.OK_ID).setEnabled(false); - break; - case REGION_WITHOUT_LANGUAGE: - mStatusLabel.setText( - "The Region qualifier requires the Language qualifier."); - mStatusImage.setImage(IconFactory.getInstance().getIcon("warning")); //$NON-NLS-1$ - getButton(IDialogConstants.OK_ID).setEnabled(false); - break; - } - - // need to relayout, because of the change in size in mErrorImage. - mStatusComposite.layout(); - } - }); - - mStatusComposite = new Composite(top, SWT.NONE); - mStatusComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - GridLayout gl = new GridLayout(2, false); - mStatusComposite.setLayout(gl); - gl.marginHeight = gl.marginWidth = 0; - - mStatusImage = new Label(mStatusComposite, SWT.NONE); - mStatusLabel = new Label(mStatusComposite, SWT.NONE); - mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - resetStatus(); - - return top; - } - - public void getConfiguration(FolderConfiguration config) { - config.set(mConfig); - } - - /** - * resets the status label to show the file that will be created. - */ - private void resetStatus() { - mStatusLabel.setText(String.format("New File: res/%1$s/%2$s", - mConfig.getFolderName(ResourceFolderType.LAYOUT), mFileName)); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java deleted file mode 100644 index f1bedcb..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.layout; - -import com.android.ide.eclipse.common.EclipseUiHelper; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.gef.ui.parts.TreeViewer; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IPartListener; -import org.eclipse.ui.IShowEditorInput; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; -import org.eclipse.ui.views.contentoutline.IContentOutlinePage; -import org.eclipse.ui.views.properties.IPropertySheetPage; -import org.w3c.dom.Document; - -/** - * Multi-page form editor for /res/layout XML files. - */ -public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPartListener { - - public static final String ID = "com.android.ide.eclipse.editors.layout.LayoutEditor"; //$NON-NLS-1$ - - /** Root node of the UI element hierarchy */ - private UiDocumentNode mUiRootNode; - /** Listener to update the root node if the resource framework changes */ - private Runnable mResourceRefreshListener; - - private GraphicalLayoutEditor mGraphicalEditor; - private int mGraphicalEditorIndex; - /** Implementation of the {@link IContentOutlinePage} for this editor */ - private UiContentOutlinePage mOutline; - /** Custom implementation of {@link IPropertySheetPage} for this editor */ - private UiPropertySheetPage mPropertyPage; - - - /** - * Creates the form editor for resources XML files. - */ - public LayoutEditor() { - super(); - initUiRootNode(); - } - - /** - * @return The root node of the UI element hierarchy - */ - @Override - public UiDocumentNode getUiRootNode() { - return mUiRootNode; - } - - // ---- Base Class Overrides ---- - - @Override - public void dispose() { - if (mResourceRefreshListener != null) { - EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener = null; - } - getSite().getPage().removePartListener(this); - - super.dispose(); - } - - /** - * Save the XML. - * <p/> - * The actual save operation is done in the super class by committing - * all data to the XML model and then having the Structured XML Editor - * save the XML. - * <p/> - * Here we just need to tell the graphical editor that the model has - * been saved. - */ - @Override - public void doSave(IProgressMonitor monitor) { - super.doSave(monitor); - if (mGraphicalEditor != null) { - mGraphicalEditor.doSave(monitor); - } - } - - /** - * Returns whether the "save as" operation is supported by this editor. - * <p/> - * Save-As is a valid operation for the ManifestEditor since it acts on a - * single source file. - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return true; - } - - /** - * Create the various form pages. - */ - @Override - protected void createFormPages() { - try { - // The graphical layout editor is now enabled by default. - // In case there's an issue we provide a way to disable it using an - // env variable. - if (System.getenv("ANDROID_DISABLE_LAYOUT") == null) { - if (mGraphicalEditor == null) { - mGraphicalEditor = new GraphicalLayoutEditor(this); - mGraphicalEditorIndex = addPage(mGraphicalEditor, getEditorInput()); - setPageText(mGraphicalEditorIndex, mGraphicalEditor.getTitle()); - } else { - mGraphicalEditor.reloadEditor(); - } - - // update the config based on the opened file. - IEditorInput input = getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder( - fileInput.getFile()); - if (resFolder != null) { - mGraphicalEditor.editNewFile(resFolder.getConfiguration()); - } - } - - // put in place the listener to handle layout recompute only when needed. - getSite().getPage().addPartListener(this); - } - } catch (PartInitException e) { - EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$ - } - } - - /* (non-java doc) - * Change the tab/title name to include the name of the layout. - */ - @Override - protected void setInput(IEditorInput input) { - super.setInput(input); - handleNewInput(input); - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#setInputWithNotify(org.eclipse.ui.IEditorInput) - */ - @Override - protected void setInputWithNotify(IEditorInput input) { - super.setInputWithNotify(input); - handleNewInput(input); - } - - /** - * Called to replace the current {@link IEditorInput} with another one. - * <p/>This is used when {@link MatchingStrategy} returned <code>true</code> which means we're - * opening a different configuration of the same layout. - */ - public void showEditorInput(IEditorInput editorInput) { - // save the current editor input. - doSave(new NullProgressMonitor()); - - // get the current page - int currentPage = getActivePage(); - - // remove the pages, except for the graphical editor, which will be dynamically adapted - // to the new model. - // page after the graphical editor: - int count = getPageCount(); - for (int i = count - 1 ; i > mGraphicalEditorIndex ; i--) { - removePage(i); - } - // pages before the graphical editor - for (int i = mGraphicalEditorIndex - 1 ; i >= 0 ; i--) { - removePage(i); - } - - // set the current input. - setInputWithNotify(editorInput); - - // re-create or reload the pages with the default page shown as the previous active page. - createAndroidPages(); - selectDefaultPage(Integer.toString(currentPage)); - - // update the outline - if (mOutline != null && mGraphicalEditor != null) { - mOutline.reloadModel(); - } - } - - /** - * Processes the new XML Model, which XML root node is given. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - @Override - protected void xmlModelChanged(Document xml_doc) { - mUiRootNode.loadFromXmlNode(xml_doc); - - // update the model first, since it is used by the viewers. - super.xmlModelChanged(xml_doc); - - if (mGraphicalEditor != null) { - mGraphicalEditor.onXmlModelChanged(); - } - - if (mOutline != null) { - mOutline.reloadModel(); - } - } - - /* (non-java doc) - * Returns the IContentOutlinePage when asked for it. - */ - @SuppressWarnings("unchecked") - @Override - public Object getAdapter(Class adapter) { - // for the outline, force it to come from the Graphical Editor. - // This fixes the case where a layout file is opened in XML view first and the outline - // gets stuck in the XML outline. - if (IContentOutlinePage.class == adapter && mGraphicalEditor != null) { - if (mOutline == null) { - mOutline = new UiContentOutlinePage(mGraphicalEditor, new TreeViewer()); - } - - return mOutline; - } - - if (IPropertySheetPage.class == adapter && mGraphicalEditor != null) { - if (mPropertyPage == null) { - mPropertyPage = new UiPropertySheetPage(); - } - - return mPropertyPage; - } - - // return default - return super.getAdapter(adapter); - } - - @Override - protected void pageChange(int newPageIndex) { - super.pageChange(newPageIndex); - - if (mGraphicalEditor != null && newPageIndex == mGraphicalEditorIndex) { - mGraphicalEditor.activated(); - } - } - - // ----- IPartListener Methods ---- - - public void partActivated(IWorkbenchPart part) { - if (part == this) { - if (mGraphicalEditor != null && getActivePage() == mGraphicalEditorIndex) { - mGraphicalEditor.activated(); - } - } - } - - public void partBroughtToTop(IWorkbenchPart part) { - partActivated(part); - } - - public void partClosed(IWorkbenchPart part) { - // pass - } - - public void partDeactivated(IWorkbenchPart part) { - // pass - } - - public void partOpened(IWorkbenchPart part) { - EclipseUiHelper.showView(EclipseUiHelper.CONTENT_OUTLINE_VIEW_ID, false /* activate */); - EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, false /* activate */); - } - - // ---- Local Methods ---- - - /** - * Returns true if the Graphics editor page is visible. - * This <b>must</b> be called from the UI thread. - */ - boolean isGraphicalEditorActive() { - IWorkbenchPartSite workbenchSite = getSite(); - IWorkbenchPage workbenchPage = workbenchSite.getPage(); - - // check if the editor is visible in the workbench page - if (workbenchPage.isPartVisible(this)) { - // and then if the page of the editor is visible (not to be confused with - // the workbench page) - return mGraphicalEditorIndex == getActivePage(); - } - - return false; - } - - /** - * Creates the initial UI Root Node, including the known mandatory elements. - */ - private void initUiRootNode() { - // The root UI node is always created, even if there's no corresponding XML node. - if (mUiRootNode == null) { - DocumentDescriptor desc = LayoutDescriptors.getInstance().getDescriptor(); - mUiRootNode = (UiDocumentNode) desc.createUiNode(); - mUiRootNode.setEditor(this); - - // Add a listener to refresh the root node if the resource framework changes - // by forcing it to parse its own XML - mResourceRefreshListener = new Runnable() { - public void run() { - commitPages(false /* onSave */); - - mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument()); - - if (mOutline != null) { - mOutline.reloadModel(); - } - - if (mGraphicalEditor != null) { - mGraphicalEditor.recomputeLayout(); - } - } - }; - EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener.run(); - } - } - - - /** - * Handles a new input, and update the part name. - * @param input the new input. - */ - private void handleNewInput(IEditorInput input) { - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput) input; - IFile file = fileInput.getFile(); - setPartName(String.format("%1$s", - file.getName())); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java deleted file mode 100644 index cf20288..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IResourceEventListener; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Monitor for file changes triggering a layout redraw. - */ -public final class LayoutReloadMonitor implements IFileListener, IResourceEventListener { - - // singleton, enforced by private constructor. - private final static LayoutReloadMonitor sThis = new LayoutReloadMonitor(); - - /** - * Map of listeners by IProject. - */ - private final Map<IProject, List<ILayoutReloadListener>> mListenerMap = - new HashMap<IProject, List<ILayoutReloadListener>>(); - - private final static int CHANGE_CODE = 0; - private final static int CHANGE_RESOURCES = 1; - private final static int CHANGE_R = 2; - private final static int CHANGE_COUNT = 3; - /** - * List of projects having received a file change. the boolean[] contains 3 values: - * <ul><li>CHANGE_CODE: code change flag.</li> - * <li>CHANGE_RESOURCES: resource change flag.</li> - * <li>CHANGE_R: R clas change flag</li></ul> - */ - private final Map<IProject, boolean[]> mChangedProjects = new HashMap<IProject, boolean[]>(); - - /** - * Classes which implement this interface provide a method to respond to resource changes - * triggering a layout redraw - */ - public interface ILayoutReloadListener { - /** - * Sent when the layout needs to be redrawn - * @param codeChange The trigger happened due to a code change. - * @param rChange The trigger happened due to a change in the R class. - * @param resChange The trigger happened due to a resource change. - */ - void reloadLayout(boolean codeChange, boolean rChange, boolean resChange); - } - - /** - * Returns the single instance of {@link LayoutReloadMonitor}. - */ - public static LayoutReloadMonitor getMonitor() { - return sThis; - } - - private LayoutReloadMonitor() { - ResourceMonitor monitor = ResourceMonitor.getMonitor(); - monitor.addFileListener(this, IResourceDelta.ADDED | IResourceDelta.CHANGED); - monitor.addResourceEventListener(this); - } - - /** - * Adds a listener for a given {@link IProject}. - * @param project - * @param listener - */ - public void addListener(IProject project, ILayoutReloadListener listener) { - synchronized (mListenerMap) { - List<ILayoutReloadListener> list = mListenerMap.get(project); - if (list == null) { - list = new ArrayList<ILayoutReloadListener>(); - mListenerMap.put(project, list); - } - - list.add(listener); - } - } - - /** - * Removes a listener for a given {@link IProject}. - * @param project - * @param listener - */ - public void removeListener(IProject project, ILayoutReloadListener listener) { - synchronized (mListenerMap) { - List<ILayoutReloadListener> list = mListenerMap.get(project); - if (list != null) { - list.remove(listener); - } - } - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener#fileChanged(org.eclipse.core.resources.IFile, org.eclipse.core.resources.IMarkerDelta[], int) - * - * Callback for ResourceMonitor.IFileListener. Called when a file changed. - * This records the changes for each project, but does not notify listeners. - * @see #resourceChangeEventEnd - */ - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) { - // get the file project - IProject project = file.getProject(); - - // if this project has already been marked as modified, we do nothing. - boolean[] changeFlags = mChangedProjects.get(project); - if (changeFlags != null && changeFlags[CHANGE_CODE] && changeFlags[CHANGE_RESOURCES] && - changeFlags[CHANGE_R]) { - return; - } - - // now check that the file is *NOT* a layout file (those automatically trigger a layout - // reload and we don't want to do it twice. - ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(file); - if (resFolder != null) { - if (resFolder.getType() != ResourceFolderType.LAYOUT) { - // this is a resource change! - if (changeFlags == null) { - changeFlags = new boolean[CHANGE_COUNT]; - mChangedProjects.put(project, changeFlags); - } - - changeFlags[CHANGE_RESOURCES] = true; - } - } else if (AndroidConstants.EXT_CLASS.equals(file.getFileExtension())) { - if (file.getName().matches("R[\\$\\.](.*)")) { - // this is a R change! - if (changeFlags == null) { - changeFlags = new boolean[CHANGE_COUNT]; - mChangedProjects.put(project, changeFlags); - } - - changeFlags[CHANGE_R] = true; - } else { - // this is a code change! - if (changeFlags == null) { - changeFlags = new boolean[CHANGE_COUNT]; - mChangedProjects.put(project, changeFlags); - } - - changeFlags[CHANGE_CODE] = true; - } - } - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IResourceEventListener#resourceChangeEventStart() - * - * Callback for ResourceMonitor.IResourceEventListener. Called at the beginning of a resource - * change event. This is called once, while fileChanged can be called several times. - * - */ - public void resourceChangeEventStart() { - // nothing to be done here, it all happens in the resourceChangeEventEnd - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IResourceEventListener#resourceChangeEventEnd() - * - * Callback for ResourceMonitor.IResourceEventListener. Called at the end of a resource - * change event. This is where we notify the listeners. - */ - public void resourceChangeEventEnd() { - // for each IProject that was changed, we notify all the listeners. - synchronized (mListenerMap) { - for (Entry<IProject, boolean[]> project : mChangedProjects.entrySet()) { - List<ILayoutReloadListener> listeners = mListenerMap.get(project.getKey()); - - boolean[] flags = project.getValue(); - - if (listeners != null) { - for (ILayoutReloadListener listener : listeners) { - listener.reloadLayout(flags[CHANGE_CODE], flags[CHANGE_R], - flags[CHANGE_RESOURCES]); - } - } - } - } - - // empty the list. - mChangedProjects.clear(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java deleted file mode 100644 index 1aa1f4c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - - -import com.android.ide.eclipse.editors.AndroidSourceViewerConfig; - -/** - * Source Viewer Configuration that calls in LayoutContentAssist. - */ -public class LayoutSourceViewerConfig extends AndroidSourceViewerConfig { - - public LayoutSourceViewerConfig() { - super(new LayoutContentAssist()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java deleted file mode 100644 index c936be3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; -import org.eclipse.ui.part.FileEditorInput; - -/** - * Page for the layout tree-based form editor. - * - * @deprecated This is being phased out. We use the GraphicalLayoutEditor instead. - */ -public final class LayoutTreePage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "layout_tree_page"; //$NON-NLS-1$ - - /** Container editor */ - LayoutEditor mEditor; - - public LayoutTreePage(LayoutEditor editor) { - super(editor, PAGE_ID, "Layout"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - - String configText = null; - IEditorInput input = mEditor.getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - IFile iFile = fileInput.getFile(); - - ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile); - if (resFolder != null) { - configText = resFolder.getConfiguration().toDisplayString(); - } - } - - if (configText != null) { - form.setText(String.format("Android Layout (%1$s)", configText)); - } else { - form.setText("Android Layout"); - } - - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode rootNode = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, rootNode, - true /* autoCreateRoot */, - null /* no element filters */, - "Layout Elements", - "List of all layout elements in this XML file."); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java deleted file mode 100644 index bb075c2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; - -import org.eclipse.core.resources.IFile; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorMatchingStrategy; -import org.eclipse.ui.IEditorReference; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; - -/** - * Matching strategy for the Layout Editor. This is used to open all configurations of a layout - * in the same editor. - */ -public class MatchingStrategy implements IEditorMatchingStrategy { - - public boolean matches(IEditorReference editorRef, IEditorInput input) { - // first check that the file being opened is a layout file. - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - - // get the IFile object and check it's in one of the layout folders. - IFile iFile = fileInput.getFile(); - ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile); - - // if it's a layout, we know check the name of the fileInput against the name of the - // file being currently edited by the editor since those are independent of the config. - if (resFolder != null && resFolder.getType() == ResourceFolderType.LAYOUT) { - try { - IEditorInput editorInput = editorRef.getEditorInput(); - if (editorInput instanceof FileEditorInput) { - FileEditorInput editorFileInput = (FileEditorInput)editorInput; - IFile editorIFile = editorFileInput.getFile(); - - return editorIFile.getProject().equals(iFile.getProject()) - && editorIFile.getName().equals(iFile.getName()); - } - } catch (PartInitException e) { - // we do nothing, we'll just return false. - } - } - } - return false; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java deleted file mode 100644 index 77b1df4..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; - -import org.eclipse.gef.palette.CombinedTemplateCreationEntry; -import org.eclipse.gef.palette.MarqueeToolEntry; -import org.eclipse.gef.palette.PaletteDrawer; -import org.eclipse.gef.palette.PaletteGroup; -import org.eclipse.gef.palette.PaletteRoot; -import org.eclipse.gef.palette.PanningSelectionToolEntry; -import org.eclipse.gef.requests.CreationFactory; - -import java.util.List; - -/** - * Factory that creates the palette for the {@link GraphicalLayoutEditor}. - */ -public class PaletteFactory { - - private static PaletteRoot sPaletteRoot; - private static Runnable sSdkChangedListener; - - /** Static factory, nothing to instantiate here. */ - private PaletteFactory() { - } - - public static PaletteRoot createPaletteRoot() { - if (sSdkChangedListener == null) { - sSdkChangedListener = new Runnable() { - public void run() { - if (sPaletteRoot != null) { - // The SDK has changed. Remove the drawer groups and rebuild them. - for (int n = sPaletteRoot.getChildren().size() - 1; n >= 0; n--) { - sPaletteRoot.getChildren().remove(n); - } - - addTools(sPaletteRoot); - addViews(sPaletteRoot, "Layouts", - LayoutDescriptors.getInstance().getLayoutDescriptors()); - addViews(sPaletteRoot, "Views", - LayoutDescriptors.getInstance().getViewDescriptors()); - } - } - }; - EditorsPlugin.getDefault().addResourceChangedListener(sSdkChangedListener); - } - - if (sPaletteRoot == null) { - sPaletteRoot = new PaletteRoot(); - sSdkChangedListener.run(); - } - return sPaletteRoot; - } - - private static void addTools(PaletteRoot paletteRoot) { - PaletteGroup group = new PaletteGroup("Tools"); - - // Default tools: selection and marquee selection - PanningSelectionToolEntry entry = new PanningSelectionToolEntry(); - group.add(entry); - paletteRoot.setDefaultEntry(entry); - - group.add(new MarqueeToolEntry()); - - paletteRoot.add(group); - } - - private static void addViews(PaletteRoot paletteRoot, String groupName, - List<ElementDescriptor> descriptors) { - PaletteDrawer group = new PaletteDrawer(groupName); - - for (ElementDescriptor desc : descriptors) { - CombinedTemplateCreationEntry entry = new CombinedTemplateCreationEntry( - desc.getUiName(), // label - desc.getTooltip(), // short description - desc.getClass(), // template - new ElementFactory(desc), // factory - desc.getImageDescriptor(), // small icon - desc.getImageDescriptor() // large icon - ); - group.add(entry); - } - - paletteRoot.add(group); - } - - //------------------------------------------ - - public static class ElementFactory implements CreationFactory { - - private final ElementDescriptor mDescriptor; - - public ElementFactory(ElementDescriptor descriptor) { - mDescriptor = descriptor; - } - - public Object getNewObject() { - return mDescriptor; - } - - public Object getObjectType() { - return mDescriptor; - } - - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java deleted file mode 100644 index d91ecbc..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; -import com.android.ide.eclipse.editors.resources.manager.ProjectClassLoader; -import com.android.ide.eclipse.editors.resources.manager.ProjectResources; -import com.android.layoutlib.api.IProjectCallback; - -import org.eclipse.core.resources.IProject; - -import java.lang.reflect.Constructor; -import java.util.HashMap; - -/** - * Loader for Android Project class in order to use them in the layout editor. - */ -public final class ProjectCallback implements IProjectCallback { - - private final HashMap<String, Class<?>> mLoadedClasses = new HashMap<String, Class<?>>(); - private final IProject mProject; - private final ClassLoader mParentClassLoader; - private final ProjectResources mProjectRes; - private boolean mUsed = false; - private String mNamespace; - - ProjectCallback(ClassLoader classLoader, ProjectResources projectRes, IProject project) { - mParentClassLoader = classLoader; - mProjectRes = projectRes; - mProject = project; - } - - - /** - * {@inheritDoc} - * - * This implementation goes through the output directory of the Eclipse project and loads the - * <code>.class</code> file directly. - */ - @SuppressWarnings("unchecked") - public Object loadView(String className, Class[] constructorSignature, - Object[] constructorParameters) - throws ClassNotFoundException, Exception { - - // look for a cached version - Class<?> clazz = mLoadedClasses.get(className); - if (clazz != null) { - return instantiateClass(clazz, constructorSignature, constructorParameters); - } - - // load the class. - ProjectClassLoader loader = new ProjectClassLoader(mParentClassLoader, mProject); - clazz = loader.loadClass(className); - - if (clazz != null) { - mUsed = true; - mLoadedClasses.put(className, clazz); - return instantiateClass(clazz, constructorSignature, constructorParameters); - } - - return null; - } - - /** - * {@inheritDoc} - * - * Returns the namespace for the project. The namespace contains a standard part + the - * application package. - */ - public String getNamespace() { - if (mNamespace == null) { - AndroidManifestHelper manifest = new AndroidManifestHelper(mProject); - String javaPackage = manifest.getPackageName(); - - mNamespace = String.format(AndroidConstants.NS_CUSTOM_RESOURCES, javaPackage); - } - - return mNamespace; - } - - /* - * (non-Javadoc) - * @see com.android.layoutlib.api.IProjectCallback#resolveResourceValue(int) - */ - public String[] resolveResourceValue(int id) { - if (mProjectRes != null) { - return mProjectRes.resolveResourceValue(id); - } - - return null; - } - - /* - * (non-Javadoc) - * @see com.android.layoutlib.api.IProjectCallback#resolveResourceValue(int[]) - */ - public String resolveResourceValue(int[] id) { - if (mProjectRes != null) { - return mProjectRes.resolveResourceValue(id); - } - - return null; - } - - /* - * (non-Javadoc) - * @see com.android.layoutlib.api.IProjectCallback#getResourceValue(java.lang.String, java.lang.String) - */ - public Integer getResourceValue(String type, String name) { - if (mProjectRes != null) { - return mProjectRes.getResourceValue(type, name); - } - - return null; - } - - /** - * Returns whether the loader has received requests to load custom views. - * <p/>This allows to efficiently only recreate when needed upon code change in the project. - */ - boolean isUsed() { - return mUsed; - } - - /** - * Instantiate a class object, using a specific constructor and parameters. - * @param clazz the class to instantiate - * @param constructorSignature the signature of the constructor to use - * @param constructorParameters the parameters to use in the constructor. - * @return - * @throws Exception - */ - @SuppressWarnings("unchecked") - private Object instantiateClass(Class<?> clazz, Class[] constructorSignature, - Object[] constructorParameters) throws Exception { - Constructor<?> constructor = clazz.getConstructor(constructorSignature); - constructor.setAccessible(true); - return constructor.newInstance(constructorParameters); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java deleted file mode 100644 index 05f8370..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.eclipse.editors.layout; - -import com.android.ide.eclipse.common.EclipseUiHelper; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.layout.parts.UiDocumentTreeEditPart; -import com.android.ide.eclipse.editors.layout.parts.UiElementTreeEditPart; -import com.android.ide.eclipse.editors.layout.parts.UiElementTreeEditPartFactory; -import com.android.ide.eclipse.editors.layout.parts.UiLayoutTreeEditPart; -import com.android.ide.eclipse.editors.layout.parts.UiViewTreeEditPart; -import com.android.ide.eclipse.editors.ui.tree.CopyCutAction; -import com.android.ide.eclipse.editors.ui.tree.PasteAction; -import com.android.ide.eclipse.editors.ui.tree.UiActions; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.gef.EditPartViewer; -import org.eclipse.gef.ui.parts.ContentOutlinePage; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IMenuListener; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.ui.IActionBars; - -import java.util.LinkedList; - -/** - * Implementation of the {@link ContentOutlinePage} to display {@link UiElementNode}. - */ -class UiContentOutlinePage extends ContentOutlinePage { - - private GraphicalLayoutEditor mEditor; - - private Action mAddAction; - private Action mDeleteAction; - private Action mUpAction; - private Action mDownAction; - - private UiOutlineActions mUiActions = new UiOutlineActions(); - - public UiContentOutlinePage(GraphicalLayoutEditor editor, final EditPartViewer viewer) { - super(viewer); - mEditor = editor; - IconFactory factory = IconFactory.getInstance(); - - mAddAction = new Action("Add...") { - @Override - public void run() { - UiElementNode node = getModelSelection(); - - mUiActions.doAdd(node, viewer.getControl().getShell()); - } - }; - mAddAction.setToolTipText("Adds a new element."); - mAddAction.setImageDescriptor(factory.getImageDescriptor("add")); //$NON-NLS-1$ - - mDeleteAction = new Action("Remove...") { - @Override - public void run() { - UiElementNode node = getModelSelection(); - - mUiActions.doRemove(node, viewer.getControl().getShell()); - } - }; - mDeleteAction.setToolTipText("Removes an existing selected element."); - mDeleteAction.setImageDescriptor(factory.getImageDescriptor("delete")); //$NON-NLS-1$ - - mUpAction = new Action("Up") { - @Override - public void run() { - UiElementNode node = getModelSelection(); - - mUiActions.doUp(node); - } - }; - mUpAction.setToolTipText("Moves the selected element up"); - mUpAction.setImageDescriptor(factory.getImageDescriptor("up")); //$NON-NLS-1$ - - mDownAction = new Action("Down") { - @Override - public void run() { - UiElementNode node = getModelSelection(); - - mUiActions.doDown(node); - } - }; - mDownAction.setToolTipText("Moves the selected element down"); - mDownAction.setImageDescriptor(factory.getImageDescriptor("down")); //$NON-NLS-1$ - - // all actions disabled by default. - mAddAction.setEnabled(false); - mDeleteAction.setEnabled(false); - mUpAction.setEnabled(false); - mDownAction.setEnabled(false); - - addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - ISelection selection = event.getSelection(); - - // the selection is never empty. The least it'll contain is the - // UiDocumentTreeEditPart object. - if (selection instanceof StructuredSelection) { - StructuredSelection structSel = (StructuredSelection)selection; - - if (structSel.size() == 1 && - structSel.getFirstElement() instanceof UiDocumentTreeEditPart) { - mDeleteAction.setEnabled(false); - mUpAction.setEnabled(false); - mDownAction.setEnabled(false); - } else { - mDeleteAction.setEnabled(true); - mUpAction.setEnabled(true); - mDownAction.setEnabled(true); - } - - // the "add" button is always enabled, in order to be able to set the - // initial root node - mAddAction.setEnabled(true); - } - } - }); - } - - - /* (non-Javadoc) - * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite) - */ - @Override - public void createControl(Composite parent) { - // create outline viewer page - getViewer().createControl(parent); - - // configure outline viewer - getViewer().setEditPartFactory(new UiElementTreeEditPartFactory()); - - setupOutline(); - setupContextMenu(); - setupTooltip(); - setupDoubleClick(); - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.part.Page#setActionBars(org.eclipse.ui.IActionBars) - * - * Called automatically after createControl - */ - @Override - public void setActionBars(IActionBars actionBars) { - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - toolBarManager.add(mAddAction); - toolBarManager.add(mDeleteAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mUpAction); - toolBarManager.add(mDownAction); - - IMenuManager menuManager = actionBars.getMenuManager(); - menuManager.add(mAddAction); - menuManager.add(mDeleteAction); - menuManager.add(new Separator()); - menuManager.add(mUpAction); - menuManager.add(mDownAction); - } - - /* (non-Javadoc) - * @see org.eclipse.ui.part.IPage#dispose() - */ - @Override - public void dispose() { - breakConnectionWithEditor(); - - // dispose - super.dispose(); - } - - /* (non-Javadoc) - * @see org.eclipse.ui.part.IPage#getControl() - */ - @Override - public Control getControl() { - return getViewer().getControl(); - } - - void setNewEditor(GraphicalLayoutEditor editor) { - mEditor = editor; - setupOutline(); - } - - void breakConnectionWithEditor() { - // unhook outline viewer - mEditor.getSelectionSynchronizer().removeViewer(getViewer()); - } - - private void setupOutline() { - getViewer().setEditDomain(mEditor.getEditDomain()); - - // hook outline viewer - mEditor.getSelectionSynchronizer().addViewer(getViewer()); - - // initialize outline viewer with model - getViewer().setContents(mEditor.getModel()); - } - - private void setupContextMenu() { - MenuManager menuManager = new MenuManager(); - menuManager.setRemoveAllWhenShown(true); - menuManager.addMenuListener(new IMenuListener() { - /** - * The menu is about to be shown. The menu manager has already been - * requested to remove any existing menu item. This method gets the - * tree selection and if it is of the appropriate type it re-creates - * the necessary actions. - */ - public void menuAboutToShow(IMenuManager manager) { - UiElementNode selected = getModelSelection(); - - if (selected != null) { - doCreateMenuAction(manager, selected); - return; - } - doCreateMenuAction(manager, null /* ui_node */); - } - }); - Control control = getControl(); - Menu contextMenu = menuManager.createContextMenu(control); - control.setMenu(contextMenu); - } - - /** - * Adds the menu actions to the context menu when the given UI node is selected in - * the tree view. - * - * @param manager The context menu manager - * @param ui_node The UI node selected in the tree. Can be null, in which case the root - * is to be modified. - */ - private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) { - if (ui_node != null && ui_node.getXmlNode() != null) { - manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(), - null, ui_node, true /* cut */)); - manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(), - null, ui_node, false /* cut */)); - // Paste is not valid if it would add a second element on a terminal element - // which parent is a document -- an XML document can only have one child. This - // means paste is valid if the current UI node can have children or if the parent - // is not a document. - UiElementNode ui_root = ui_node.getUiRoot(); - if (ui_root.getDescriptor().hasChildren() || - !(ui_root.getUiParent() instanceof UiDocumentNode)) { - manager.add(new PasteAction(mEditor.getLayoutEditor(), mEditor.getClipboard(), - ui_node)); - } - manager.add(new Separator()); - } - - // Append "add" and "remove" actions. They do the same thing as the add/remove - // buttons on the side. - manager.add(mAddAction); - manager.add(mDeleteAction); - - manager.add(new Separator()); - - manager.add(mUpAction); - manager.add(mDownAction); - - manager.add(new Separator()); - - Action propertiesAction = new Action("Properties") { - @Override - public void run() { - EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, - true /* activate */); - } - }; - propertiesAction.setToolTipText("Displays properties of the selected element."); - manager.add(propertiesAction); - } - - /** - * Updates the outline view with the model of the {@link GraphicalLayoutEditor}. - * <p/> - * This attemps to preserve the selection, if any. - */ - public void reloadModel() { - // Attemps to preserve the UiNode selection, if any - UiElementNode uiNode = null; - try { - // get current selection using the model rather than the edit part as - // reloading the content may change the actual edit part. - uiNode = getModelSelection(); - - // perform the update - getViewer().setContents(mEditor.getModel()); - - } finally { - // restore selection - setModelSelection(uiNode); - } - } - - /** - * Returns the currently selected element, if any, in the viewer. - * This returns the viewer's elements (i.e. an {@link UiElementTreeEditPart}) - * and not the underlying model node. - * <p/> - * When there is no actual selection, this might still return the root node, - * which is of type {@link UiDocumentTreeEditPart}. - */ - private UiElementTreeEditPart getViewerSelection() { - ISelection selection = getSelection(); - if (selection instanceof StructuredSelection) { - StructuredSelection structuredSelection = (StructuredSelection)selection; - - if (structuredSelection.size() == 1) { - Object selectedObj = structuredSelection.getFirstElement(); - - if (selectedObj instanceof UiElementTreeEditPart) { - return (UiElementTreeEditPart) selectedObj; - } - } - } - - return null; - } - - /** - * Returns the currently selected model element, which is either an - * {@link UiViewTreeEditPart} or an {@link UiLayoutTreeEditPart}. - * <p/> - * Returns null if there is no selection or if the implicit root is "selected" - * (which actually represents the lack of a real element selection.) - */ - private UiElementNode getModelSelection() { - - UiElementTreeEditPart part = getViewerSelection(); - - if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) { - return (UiElementNode) part.getModel(); - } - return null; - } - - /** - * Selects the corresponding edit part in the tree viewer. - */ - private void setViewerSelection(UiElementTreeEditPart selectedPart) { - if (selectedPart != null && !(selectedPart instanceof UiDocumentTreeEditPart)) { - LinkedList<UiElementTreeEditPart> segments = new LinkedList<UiElementTreeEditPart>(); - for (UiElementTreeEditPart part = selectedPart; - !(part instanceof UiDocumentTreeEditPart); - part = (UiElementTreeEditPart) part.getParent()) { - segments.add(0, part); - } - setSelection(new TreeSelection(new TreePath(segments.toArray()))); - } - } - - /** - * Selects the corresponding model element in the tree viewer. - */ - private void setModelSelection(UiElementNode uiNodeToSelect) { - if (uiNodeToSelect != null) { - - // find an edit part that has the requested model element - UiElementTreeEditPart part = findPartForModel( - (UiElementTreeEditPart) getViewer().getContents(), - uiNodeToSelect); - - // if we found a part, select it and reveal it - if (part != null) { - setViewerSelection(part); - getViewer().reveal(part); - } - } - } - - /** - * Utility method that tries to find an edit part that matches a given model UI node. - * - * @param rootPart The root of the viewer edit parts - * @param uiNode The UI node model to find - * @return The part that matches the model or null if it's not in the sub tree. - */ - private UiElementTreeEditPart findPartForModel(UiElementTreeEditPart rootPart, - UiElementNode uiNode) { - if (rootPart.getModel() == uiNode) { - return rootPart; - } - - for (Object part : rootPart.getChildren()) { - if (part instanceof UiElementTreeEditPart) { - UiElementTreeEditPart found = findPartForModel( - (UiElementTreeEditPart) part, uiNode); - if (found != null) { - return found; - } - } - } - - return null; - } - - /** - * Sets up a custom tooltip when hovering over tree items. - * <p/> - * The tooltip will display the element's javadoc, if any, or the item's getText otherwise. - */ - private void setupTooltip() { - final Tree tree = (Tree) getControl(); - - /* - * Reference: - * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup - */ - - final Listener listener = new Listener() { - Shell tip = null; - Label label = null; - - public void handleEvent(Event event) { - switch(event.type) { - case SWT.Dispose: - case SWT.KeyDown: - case SWT.MouseExit: - case SWT.MouseDown: - case SWT.MouseMove: - if (tip != null) { - tip.dispose(); - tip = null; - label = null; - } - break; - case SWT.MouseHover: - if (tip != null) { - tip.dispose(); - tip = null; - label = null; - } - - String tooltip = null; - - TreeItem item = tree.getItem(new Point(event.x, event.y)); - if (item != null) { - Object data = item.getData(); - if (data instanceof UiElementTreeEditPart) { - Object model = ((UiElementTreeEditPart) data).getModel(); - if (model instanceof UiElementNode) { - tooltip = ((UiElementNode) model).getDescriptor().getTooltip(); - } - } - - if (tooltip == null) { - tooltip = item.getText(); - } else { - tooltip = item.getText() + ":\r" + tooltip; - } - } - - - if (tooltip != null) { - Shell shell = tree.getShell(); - Display display = tree.getDisplay(); - - tip = new Shell(shell, SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL); - tip.setBackground(display .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - FillLayout layout = new FillLayout(); - layout.marginWidth = 2; - tip.setLayout(layout); - label = new Label(tip, SWT.NONE); - label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); - label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - label.setData("_TABLEITEM", item); - label.setText(tooltip); - label.addListener(SWT.MouseExit, this); - label.addListener(SWT.MouseDown, this); - Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT); - Rectangle rect = item.getBounds(0); - Point pt = tree.toDisplay(rect.x, rect.y); - tip.setBounds(pt.x, pt.y, size.x, size.y); - tip.setVisible(true); - } - } - } - }; - - tree.addListener(SWT.Dispose, listener); - tree.addListener(SWT.KeyDown, listener); - tree.addListener(SWT.MouseMove, listener); - tree.addListener(SWT.MouseHover, listener); - } - - /** - * Sets up double-click action on the tree. - * <p/> - * By default, double-click (a.k.a. "default selection") on a valid list item will - * show the property view. - */ - private void setupDoubleClick() { - final Tree tree = (Tree) getControl(); - - tree.addListener(SWT.DefaultSelection, new Listener() { - public void handleEvent(Event event) { - EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, - true /* activate */); - } - }); - } - - // --------------- - - private class UiOutlineActions extends UiActions { - - @Override - protected UiDocumentNode getRootNode() { - return mEditor.getModel(); // this is LayoutEditor.getUiRootNode() - } - - // Select the new item - @Override - protected void selectUiNode(UiElementNode uiNodeToSelect) { - setModelSelection(uiNodeToSelect); - } - - @Override - public void commitPendingXmlChanges() { - // Pass. There is nothing to commit before the XML is changed here. - } - - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java deleted file mode 100644 index 41d3747..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.layoutlib.api.IXmlPullParser; - -import org.w3c.dom.Node; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; - -/** - * XmlPullParser implementation on top of {@link UiElementNode}. - * <p/>It's designed to work on layout files, and will most likely not work on other resource - * files. - */ -public final class UiElementPullParser implements IXmlPullParser { - - private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>(); - private int mParsingState = START_DOCUMENT; - private UiElementNode mRoot; - - public UiElementPullParser(UiElementNode top) { - mRoot = top; - push(mRoot); - } - - private UiElementNode getCurrentNode() { - if (mNodeStack.size() > 0) { - return mNodeStack.get(mNodeStack.size()-1); - } - - return null; - } - - private Node getAttribute(int i) { - if (mParsingState != START_TAG) { - throw new IndexOutOfBoundsException(); - } - - // get the current uiNode - UiElementNode uiNode = getCurrentNode(); - - // get its xml node - Node xmlNode = uiNode.getXmlNode(); - - if (xmlNode != null) { - return xmlNode.getAttributes().item(i); - } - - return null; - } - - private void push(UiElementNode node) { - mNodeStack.add(node); - } - - private UiElementNode pop() { - return mNodeStack.remove(mNodeStack.size()-1); - } - - // ------------- IXmlPullParser -------- - - /** - * {@inheritDoc} - * - * This implementation returns the underlying DOM node. - */ - public Object getViewKey() { - return getCurrentNode(); - } - - // ------------- XmlPullParser -------- - - public void setFeature(String name, boolean state) throws XmlPullParserException { - if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { - return; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) { - return; - } - throw new XmlPullParserException("Unsupported feature: " + name); - } - - public boolean getFeature(String name) { - if (FEATURE_PROCESS_NAMESPACES.equals(name)) { - return true; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { - return true; - } - return false; - } - - public void setProperty(String name, Object value) throws XmlPullParserException { - throw new XmlPullParserException("setProperty() not supported"); - } - - public Object getProperty(String name) { - return null; - } - - public void setInput(Reader in) throws XmlPullParserException { - throw new XmlPullParserException("setInput() not supported"); - } - - public void setInput(InputStream inputStream, String inputEncoding) - throws XmlPullParserException { - throw new XmlPullParserException("setInput() not supported"); - } - - public void defineEntityReplacementText(String entityName, String replacementText) - throws XmlPullParserException { - throw new XmlPullParserException("defineEntityReplacementText() not supported"); - } - - public String getNamespacePrefix(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespacePrefix() not supported"); - } - - public String getInputEncoding() { - return null; - } - - public String getNamespace(String prefix) { - throw new RuntimeException("getNamespace() not supported"); - } - - public int getNamespaceCount(int depth) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceCount() not supported"); - } - - public String getPositionDescription() { - return "XML DOM element depth:" + mNodeStack.size(); - } - - public String getNamespaceUri(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceUri() not supported"); - } - - public int getColumnNumber() { - return -1; - } - - public int getLineNumber() { - return -1; - } - - public int getAttributeCount() { - UiElementNode node = getCurrentNode(); - if (node != null) { - return node.getUiAttributes().size(); - } - - return 0; - } - - public String getAttributeName(int i) { - Node attribute = getAttribute(i); - if (attribute != null) { - return attribute.getLocalName(); - } - - return null; - } - - public String getAttributeNamespace(int i) { - Node attribute = getAttribute(i); - if (attribute != null) { - return attribute.getNamespaceURI(); - } - return ""; //$NON-NLS-1$ - } - - public String getAttributePrefix(int i) { - Node attribute = getAttribute(i); - if (attribute != null) { - return attribute.getPrefix(); - } - return null; - } - - public String getAttributeType(int arg0) { - return "CDATA"; - } - - public String getAttributeValue(int i) { - Node attribute = getAttribute(i); - if (attribute != null) { - return attribute.getNodeValue(); - } - - return null; - } - - public String getAttributeValue(String namespace, String localName) { - // get the current uiNode - UiElementNode uiNode = getCurrentNode(); - - // get its xml node - Node xmlNode = uiNode.getXmlNode(); - - if (xmlNode != null) { - Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName); - if (attribute != null) { - return attribute.getNodeValue(); - } - } - - return null; - } - - public int getDepth() { - return mNodeStack.size(); - } - - public int getEventType() throws XmlPullParserException { - return mParsingState; - } - - public String getName() { - if (mParsingState == START_TAG || mParsingState == END_TAG) { - return getCurrentNode().getDescriptor().getXmlLocalName(); - } - - return null; - } - - public String getNamespace() { - if (mParsingState == START_TAG || mParsingState == END_TAG) { - return getCurrentNode().getDescriptor().getNamespace(); - } - - return null; - } - - public String getPrefix() { - if (mParsingState == START_TAG || mParsingState == END_TAG) { - // FIXME will NEVER work - if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$ - return "android"; //$NON-NLS-1$ - } - } - - return null; - } - - public String getText() { - return null; - } - - public char[] getTextCharacters(int[] arg0) { - return null; - } - - public boolean isAttributeDefault(int arg0) { - return false; - } - - public boolean isEmptyElementTag() throws XmlPullParserException { - if (mParsingState == START_TAG) { - return getCurrentNode().getUiChildren().size() == 0; - } - - throw new XmlPullParserException("Must be on START_TAG"); - } - - public boolean isWhitespace() throws XmlPullParserException { - return false; - } - - public int next() throws XmlPullParserException, IOException { - UiElementNode node; - switch (mParsingState) { - case END_DOCUMENT: - throw new XmlPullParserException("Nothing after the end"); - case START_DOCUMENT: - /* intended fall-through */ - case START_TAG: - // get the current node, and look for text or children (children first) - node = getCurrentNode(); - List<UiElementNode> children = node.getUiChildren(); - if (children.size() > 0) { - // move to the new child, and don't change the state. - push(children.get(0)); - - // in case the current state is CURRENT_DOC, we set the proper state. - mParsingState = START_TAG; - } else { - if (mParsingState == START_DOCUMENT) { - // this handles the case where there's no node. - mParsingState = END_DOCUMENT; - } else { - mParsingState = END_TAG; - } - } - break; - case END_TAG: - // look for a sibling. if no sibling, go back to the parent - node = getCurrentNode(); - node = node.getUiNextSibling(); - if (node != null) { - // to go to the sibling, we need to remove the current node, - pop(); - // and add its sibling. - push(node); - mParsingState = START_TAG; - } else { - // move back to the parent - pop(); - - // we have only one element left (mRoot), then we're done with the document. - if (mNodeStack.size() == 1) { - mParsingState = END_DOCUMENT; - } else { - mParsingState = END_TAG; - } - } - break; - case TEXT: - // not used - break; - case CDSECT: - // not used - break; - case ENTITY_REF: - // not used - break; - case IGNORABLE_WHITESPACE: - // not used - break; - case PROCESSING_INSTRUCTION: - // not used - break; - case COMMENT: - // not used - break; - case DOCDECL: - // not used - break; - } - - return mParsingState; - } - - public int nextTag() throws XmlPullParserException, IOException { - int eventType = next(); - if (eventType != START_TAG && eventType != END_TAG) { - throw new XmlPullParserException("expected start or end tag", this, null); - } - return eventType; - } - - public String nextText() throws XmlPullParserException, IOException { - if (getEventType() != START_TAG) { - throw new XmlPullParserException("parser must be on START_TAG to read next text", this, - null); - } - int eventType = next(); - if (eventType == TEXT) { - String result = getText(); - eventType = next(); - if (eventType != END_TAG) { - throw new XmlPullParserException( - "event TEXT it must be immediately followed by END_TAG", this, null); - } - return result; - } else if (eventType == END_TAG) { - return ""; - } else { - throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text", - this, null); - } - } - - public int nextToken() throws XmlPullParserException, IOException { - return next(); - } - - public void require(int type, String namespace, String name) throws XmlPullParserException, - IOException { - if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace())) - || (name != null && !name.equals(getName()))) - throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java deleted file mode 100644 index 8093c90..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.ui.views.properties.PropertySheetEntry; -import org.eclipse.ui.views.properties.PropertySheetPage; - -/** - * A customized property sheet page for the graphical layout editor. - * <p/> - * Currently it just provides a custom tooltip to display attributes javadocs. - */ -public class UiPropertySheetPage extends PropertySheetPage { - - - public UiPropertySheetPage() { - super(); - } - - @Override - public void createControl(Composite parent) { - super.createControl(parent); - - setupTooltip(); - } - - /** - * Sets up a custom tooltip when hovering over tree items. - * <p/> - * The tooltip will display the element's javadoc, if any, or the item's getText otherwise. - */ - private void setupTooltip() { - final Tree tree = (Tree) getControl(); - - /* - * Reference: - * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup - */ - - final Listener listener = new Listener() { - Shell tip = null; - Label label = null; - - public void handleEvent(Event event) { - switch(event.type) { - case SWT.Dispose: - case SWT.KeyDown: - case SWT.MouseExit: - case SWT.MouseDown: - case SWT.MouseMove: - if (tip != null) { - tip.dispose(); - tip = null; - label = null; - } - break; - case SWT.MouseHover: - if (tip != null) { - tip.dispose(); - tip = null; - label = null; - } - - String tooltip = null; - - TreeItem item = tree.getItem(new Point(event.x, event.y)); - if (item != null) { - Object data = item.getData(); - if (data instanceof PropertySheetEntry) { - tooltip = ((PropertySheetEntry) data).getDescription(); - } - - if (tooltip == null) { - tooltip = item.getText(); - } else { - tooltip = item.getText() + ":\r" + tooltip; - } - } - - if (tooltip != null) { - Shell shell = tree.getShell(); - Display display = tree.getDisplay(); - - tip = new Shell(shell, SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL); - tip.setBackground(display .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - FillLayout layout = new FillLayout(); - layout.marginWidth = 2; - tip.setLayout(layout); - label = new Label(tip, SWT.NONE); - label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); - label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - label.setData("_TABLEITEM", item); - label.setText(tooltip); - label.addListener(SWT.MouseExit, this); - label.addListener(SWT.MouseDown, this); - Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT); - Rectangle rect = item.getBounds(0); - Point pt = tree.toDisplay(rect.x, rect.y); - tip.setBounds(pt.x, pt.y, size.x, size.y); - tip.setVisible(true); - } - } - } - }; - - tree.addListener(SWT.Dispose, listener); - tree.addListener(SWT.KeyDown, listener); - tree.addListener(SWT.MouseMove, listener); - tree.addListener(SWT.MouseHover, listener); - - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java deleted file mode 100644 index c3e9b70..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.descriptors; - -import com.android.ide.eclipse.common.resources.ViewClassInfo; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeHierarchy; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; - -import java.util.HashMap; -import java.util.List; - -/** - * Service responsible for creating/managing {@link ElementDescriptor} objects for custom - * View classes per project. - * <p/> - * The service provides an on-demand monitoring of custom classes to check for changes. Monitoring - * starts once a request for an {@link ElementDescriptor} object has been done for a specific - * class.<br> - * The monitoring will notify a listen of any changes in the class triggering a change in its - * associated {@link ElementDescriptor} object. - * <p/> - * If the custom class does not exist, no monitoring is put in place to avoid having to listen - * to all class changes in the projects. - * - */ -public final class CustomViewDescriptorService { - - private static CustomViewDescriptorService sThis = new CustomViewDescriptorService(); - - /** - * Map where keys are the project, and values are another map containing all the known - * custom View class for this project. The custom View class are stored in a map - * where the keys are the fully qualified class name, and the values are their associated - * {@link ElementDescriptor}. - */ - private HashMap<IProject, HashMap<String, ElementDescriptor>> mCustomDescriptorMap = - new HashMap<IProject, HashMap<String, ElementDescriptor>>(); - - /** - * TODO will be used to update the ElementDescriptor of the custom view when it - * is modified (either the class itself or its attributes.xml) - */ - @SuppressWarnings("unused") - private ICustomViewDescriptorListener mListener; - - /** - * Classes which implements this interface provide a method that deal with modifications - * in custom View class triggering a change in its associated {@link ViewClassInfo} object. - */ - public interface ICustomViewDescriptorListener { - /** - * Sent when a custom View class has changed and its {@link ElementDescriptor} was modified. - * @param project the project containing the class. - * @param className the fully qualified class name. - * @param descriptor the updated ElementDescriptor. - */ - public void updatedClassInfo(IProject project, String className, ElementDescriptor descriptor); - } - - /** - * Returns the singleton instance of {@link CustomViewDescriptorService}. - */ - public static CustomViewDescriptorService getInstance() { - return sThis; - } - - /** - * Sets the listener receiving custom View class modification notifications. - * @param listener the listener to receive the notifications. - * - * TODO will be used to update the ElementDescriptor of the custom view when it - * is modified (either the class itself or its attributes.xml) - */ - public void setListener(ICustomViewDescriptorListener listener) { - mListener = listener; - } - - /** - * Returns the {@link ElementDescriptor} for a particular project/class. - * <p/> - * If it is the first time the <code>ElementDescriptor</code> is requested, the method - * will check that the specified class is in fact a custom View class. Once this is - * established, a monitoring for that particular class is initiated. Any change will - * trigger a notification to the {@link ICustomViewDescriptorListener}. - * @param project the project containing the class. - * @param fqClassName the fully qualified name of the class. - * @return a <code>ElementDescriptor</code> or <code>null</code> if the class was not - * a custom View class. - */ - public ElementDescriptor getDescriptor(IProject project, String fqClassName) { - // look in the map first - synchronized (mCustomDescriptorMap) { - HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project); - - if (map != null) { - ElementDescriptor descriptor = map.get(fqClassName); - if (descriptor != null) { - return descriptor; - } - } - - // if we step here, it looks like we haven't created it yet. - // First lets check this is in fact a valid type in the project - - try { - // We expect the project to be both opened and of java type (since it's an android - // project), so we can create a IJavaProject object from our IProject. - IJavaProject javaProject = JavaCore.create(project); - - // replace $ by . in the class name - String javaClassName = fqClassName.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS-2$ - - // look for the IType object for this class - IType type = javaProject.findType(javaClassName); - if (type != null && type.exists()) { - // the type exists. Let's get the parent class and its ViewClassInfo. - - // get the type hierarchy - ITypeHierarchy hierarchy = type.newSupertypeHierarchy( - new NullProgressMonitor()); - - ElementDescriptor parentDescriptor = getDescriptor( - hierarchy.getSuperclass(type), project, hierarchy); - - if (parentDescriptor != null) { - // we have a valid parent, lets create a new ElementDescriptor. - - ViewElementDescriptor descriptor = new ViewElementDescriptor(fqClassName, - fqClassName, // ui_name - fqClassName, // canonical class name - null, // tooltip - null, // sdk_url - getAttributeDescriptor(type, parentDescriptor), - null, // layout attributes - null, // children - false /* mandatory */); - - synchronized (mCustomDescriptorMap) { - map = mCustomDescriptorMap.get(project); - if (map == null) { - map = new HashMap<String, ElementDescriptor>(); - mCustomDescriptorMap.put(project, map); - } - - map.put(fqClassName, descriptor); - } - - //TODO setup listener on this resource change. - - return descriptor; - } - } - } catch (JavaModelException e) { - // there was an error accessing any of the IType, we'll just return null; - } - } - - - return null; - } - - /** - * Computes (if needed) and returns the {@link ElementDescriptor} for the specified type. - * - * @param type - * @param project - * @param typeHierarchy - * @return A ViewElementDescriptor - */ - private ViewElementDescriptor getDescriptor(IType type, IProject project, - ITypeHierarchy typeHierarchy) { - // check if the type is a built-in View class. - List<ElementDescriptor> builtInList = LayoutDescriptors.getInstance().getViewDescriptors(); - - String canonicalName = type.getFullyQualifiedName(); - - for (ElementDescriptor desc : builtInList) { - if (desc instanceof ViewElementDescriptor) { - ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc; - if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) { - return viewDescriptor; - } - } - } - - // it's not a built-in class? Lets look if the superclass is built-in - IType parentType = typeHierarchy.getSuperclass(type); - if (parentType != null) { - ViewElementDescriptor parentDescriptor = getDescriptor(parentType, project, - typeHierarchy); - - if (parentDescriptor != null) { - // parent class is a valid View class with a descriptor, so we create one - // for this class. - ViewElementDescriptor descriptor = new ViewElementDescriptor(canonicalName, - canonicalName, // ui_name - canonicalName, // canonical name - null, // tooltip - null, // sdk_url - getAttributeDescriptor(type, parentDescriptor), - null, // layout attributes - null, // children - false /* mandatory */); - - // add it to the map - synchronized (mCustomDescriptorMap) { - HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project); - - if (map == null) { - map = new HashMap<String, ElementDescriptor>(); - mCustomDescriptorMap.put(project, map); - } - - map.put(canonicalName, descriptor); - - } - - //TODO setup listener on this resource change. - - return descriptor; - } - } - - // class is neither a built-in view class, nor extend one. return null. - return null; - } - - /** - * Returns the array of {@link AttributeDescriptor} for the specified {@link IType}. - * <p/> - * The array should contain the descriptor for this type and all its supertypes. - * @param type the type for which the {@link AttributeDescriptor} are returned. - * @param parentDescriptor the {@link ElementDescriptor} of the direct superclass. - */ - private AttributeDescriptor[] getAttributeDescriptor(IType type, - ElementDescriptor parentDescriptor) { - // TODO add the class attribute descriptors to the parent descriptors. - return parentDescriptor.getAttributes(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java deleted file mode 100644 index 8ad2382..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.ViewClassInfo; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo; -import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * Complete description of the layout structure. - */ -public class LayoutDescriptors { - - // Public attributes names, attributes descriptors and elements descriptors - public static final String ID_ATTR = "id"; //$NON-NLS-1$ - - /** Singleton instance */ - private static LayoutDescriptors sThis; - - /** The document descriptor. Contains all layouts and views linked together. */ - private DocumentDescriptor mDescriptor = - new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$ - - /** The list of all known ViewLayout descriptors. */ - private ArrayList<ElementDescriptor> mLayoutDescriptors = new ArrayList<ElementDescriptor>(); - - /** The list of all known View (not ViewLayout) descriptors. */ - private ArrayList<ElementDescriptor> mViewDescriptors = new ArrayList<ElementDescriptor>(); - - /** Returns a singleton instance of the {@link LayoutDescriptors}. */ - public static synchronized LayoutDescriptors getInstance() { - if (sThis == null) { - sThis = new LayoutDescriptors(); - } - return sThis; - } - - /** @return the document descriptor. Contains all layouts and views linked together. */ - public DocumentDescriptor getDescriptor() { - return mDescriptor; - } - - /** @return The read-only list of all known ViewLayout descriptors. */ - public List<ElementDescriptor> getLayoutDescriptors() { - return Collections.unmodifiableList(mLayoutDescriptors); - } - - /** @return The read-only list of all known View (not ViewLayout) descriptors. */ - public List<ElementDescriptor> getViewDescriptors() { - return Collections.unmodifiableList(mViewDescriptors); - } - - /** - * Updates the document descriptor. - * <p/> - * It first computes the new children of the descriptor and then update them - * all at once. - * <p/> - * TODO: differentiate groups from views in the tree UI? => rely on icons - * <p/> - * - * @param views The list of views in the framework. - * @param layouts The list of layouts in the framework. - */ - public synchronized void updateDescriptors(ViewClassInfo[] views, ViewClassInfo[] layouts) { - ArrayList<ElementDescriptor> newViews = new ArrayList<ElementDescriptor>(); - if (views != null) { - for (ViewClassInfo info : views) { - ElementDescriptor desc = convertView(info); - newViews.add(desc); - } - } - - ArrayList<ElementDescriptor> newLayouts = new ArrayList<ElementDescriptor>(); - if (layouts != null) { - for (ViewClassInfo info : layouts) { - ElementDescriptor desc = convertView(info); - newLayouts.add(desc); - } - } - - ArrayList<ElementDescriptor> newDescriptors = new ArrayList<ElementDescriptor>(); - newDescriptors.addAll(newLayouts); - newDescriptors.addAll(newViews); - ElementDescriptor[] newArray = newDescriptors.toArray( - new ElementDescriptor[newDescriptors.size()]); - - // Link all layouts to everything else here.. recursively - for (ElementDescriptor layoutDesc : newLayouts) { - layoutDesc.setChildren(newArray); - } - - mViewDescriptors = newViews; - mLayoutDescriptors = newLayouts; - mDescriptor.setChildren(newArray); - } - - /** - * Creates an element descriptor from a given {@link ViewClassInfo}. - */ - private ElementDescriptor convertView(ViewClassInfo info) { - String xml_name = info.getShortClassName(); - String tooltip = info.getJavaDoc(); - - // Process all View attributes - ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); - DescriptorsUtils.appendAttributes(attributes, - null, // elementName - AndroidConstants.NS_RESOURCES, - info.getAttributes(), - null, // requiredAttributes - null /* overrides */); - - for (ViewClassInfo link = info.getSuperClass(); - link != null; - link = link.getSuperClass()) { - AttributeInfo[] attrList = link.getAttributes(); - if (attrList.length > 0) { - attributes.add(new SeparatorAttributeDescriptor( - String.format("Attributes from %1$s", link.getShortClassName()))); - DescriptorsUtils.appendAttributes(attributes, - null, // elementName - AndroidConstants.NS_RESOURCES, - attrList, - null, // requiredAttributes - null /* overrides */); - } - } - - // Process all LayoutParams attributes - ArrayList<AttributeDescriptor> layoutAttributes = new ArrayList<AttributeDescriptor>(); - LayoutParamsInfo layoutParams = info.getLayoutData(); - - for(; layoutParams != null; layoutParams = layoutParams.getSuperClass()) { - boolean need_separator = true; - for (AttributeInfo attr_info : layoutParams.getAttributes()) { - if (DescriptorsUtils.containsAttribute(layoutAttributes, - AndroidConstants.NS_RESOURCES, attr_info)) { - continue; - } - if (need_separator) { - String title; - if (layoutParams.getShortClassName().equals( - AndroidConstants.CLASS_LAYOUTPARAMS)) { - title = String.format("Layout Attributes from %1$s", - layoutParams.getViewLayoutClass().getShortClassName()); - } else { - title = String.format("Layout Attributes from %1$s (%2$s)", - layoutParams.getViewLayoutClass().getShortClassName(), - layoutParams.getShortClassName()); - } - layoutAttributes.add(new SeparatorAttributeDescriptor(title)); - need_separator = false; - } - DescriptorsUtils.appendAttribute(layoutAttributes, - null, // elementName - AndroidConstants.NS_RESOURCES, - attr_info, - false, // required - null /* overrides */); - } - } - - return new ViewElementDescriptor(xml_name, - xml_name, // ui_name - info.getCanonicalClassName(), - tooltip, - null, // sdk_url - attributes.toArray(new AttributeDescriptor[attributes.size()]), - layoutAttributes.toArray(new AttributeDescriptor[layoutAttributes.size()]), - null, // children - false /* mandatory */); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java deleted file mode 100644 index d718ebd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.descriptors; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.layout.uimodel.UiViewElementNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * {@link ViewElementDescriptor} describes the properties expected for a given XML element node - * representing a class in an XML Layout file. - * - * @see ElementDescriptor - */ -public final class ViewElementDescriptor extends ElementDescriptor { - - private String mCanonicalClassName; - - /** The list of layout attributes. Can be empty but not null. */ - private AttributeDescriptor[] mLayoutAttributes; - - - /** - * Constructs a new {@link ViewElementDescriptor} based on its XML name, UI name, - * the canonical name of the class it represents, its tooltip, its SDK url, its attributes list, - * its children list and its mandatory flag. - * - * @param xml_name The XML element node name. Case sensitive. - * @param ui_name The XML element name for the user interface, typically capitalized. - * @param canonicalClassName The canonical class name the {@link ViewElementDescriptor} is - * representing. - * @param tooltip An optional tooltip. Can be null or empty. - * @param sdk_url An optional SKD URL. Can be null or empty. - * @param attributes The list of allowed attributes. Can be null or empty. - * @param layoutAttributes The list of layout attributes. Can be null or empty. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). A mandatory - * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory - * UI node MUST have an XML node attached and it will cease to exist when the XML node - * ceases to exist. - */ - public ViewElementDescriptor(String xml_name, String ui_name, - String canonicalClassName, - String tooltip, String sdk_url, - AttributeDescriptor[] attributes, AttributeDescriptor[] layoutAttributes, - ElementDescriptor[] children, boolean mandatory) { - super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory); - mCanonicalClassName = canonicalClassName; - mLayoutAttributes = layoutAttributes != null ? layoutAttributes : new AttributeDescriptor[0]; - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name, the canonical - * name of the class it represents, and its children list. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param canonicalClassName The canonical class name the {@link ViewElementDescriptor} is - * representing. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). A mandatory - * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory - * UI node MUST have an XML node attached and it will cease to exist when the XML node - * ceases to exist. - */ - public ViewElementDescriptor(String xml_name, String canonicalClassName, - ElementDescriptor[] children, - boolean mandatory) { - super(xml_name, children, mandatory); - mCanonicalClassName = canonicalClassName; - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name and children list. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param canonicalClassName The canonical class name the {@link ViewElementDescriptor} is - * representing. - * @param children The list of allowed children. Can be null or empty. - */ - public ViewElementDescriptor(String xml_name, String canonicalClassName, - ElementDescriptor[] children) { - super(xml_name, children); - mCanonicalClassName = canonicalClassName; - } - - /** - * Constructs a new {@link ElementDescriptor} based on its XML name and on the canonical - * name of the class it represents. - * The UI name is build by capitalizing the XML name. - * The UI nodes will be non-mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param canonicalClassName The canonical class name the {@link ViewElementDescriptor} is - * representing. - */ - public ViewElementDescriptor(String xml_name, String canonicalClassName) { - super(xml_name); - mCanonicalClassName = canonicalClassName; - } - - /** - * Returns the canonical name of the class represented by this element descriptor. - */ - public String getCanonicalClassName() { - return mCanonicalClassName; - } - - /** Returns the list of layout attributes. Can be empty but not null. */ - public AttributeDescriptor[] getLayoutAttributes() { - return mLayoutAttributes; - } - - /** - * @return A new {@link UiViewElementNode} linked to this descriptor. - */ - @Override - public UiElementNode createUiNode() { - return new UiViewElementNode(this); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java deleted file mode 100644 index 53a87f5..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.draw2d.AbstractBackground; -import org.eclipse.draw2d.ColorConstants; -import org.eclipse.draw2d.FreeformLayer; -import org.eclipse.draw2d.FreeformLayout; -import org.eclipse.draw2d.Graphics; -import org.eclipse.draw2d.IFigure; -import org.eclipse.draw2d.Label; -import org.eclipse.draw2d.geometry.Insets; -import org.eclipse.draw2d.geometry.Rectangle; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.PaletteData; -import org.eclipse.swt.widgets.Display; - -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; - -/** - * Graphical edit part for the root document. - * <p/> - * It acts as a simple container. - */ -public class UiDocumentEditPart extends UiElementEditPart { - - private Display mDisplay; - private FreeformLayer mLayer; - private ImageBackground mImage; - private Label mChild = null; - - final static class ImageBackground extends AbstractBackground { - - private BufferedImage mBufferedImage; - private Image mImage; - - ImageBackground() { - } - - ImageBackground(BufferedImage image, Display display) { - setImage(image, display); - } - - @Override - public void paintBackground(IFigure figure, Graphics graphics, Insets insets) { - if (mImage != null) { - Rectangle rect = getPaintRectangle(figure, insets); - graphics.drawImage(mImage, rect.x, rect.y); - } - } - - void setImage(BufferedImage image, Display display) { - if (image != null) { - int[] data = ((DataBufferInt)image.getData().getDataBuffer()).getData(); - - ImageData imageData = new ImageData(image.getWidth(), image.getHeight(), 32, - new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF)); - - imageData.setPixels(0, 0, data.length, data, 0); - - mImage = new Image(display, imageData); - } else { - mImage = null; - } - } - - BufferedImage getBufferedImage() { - return mBufferedImage; - } - } - - public UiDocumentEditPart(UiDocumentNode uiDocumentNode, Display display) { - super(uiDocumentNode); - mDisplay = display; - } - - @Override - protected IFigure createFigure() { - mLayer = new FreeformLayer(); - mLayer.setLayoutManager(new FreeformLayout()); - - mLayer.setOpaque(true); - mLayer.setBackgroundColor(ColorConstants.lightGray); - - return mLayer; - } - - @Override - protected void refreshVisuals() { - UiElementNode model = (UiElementNode)getModel(); - - Object editData = model.getEditData(); - if (editData instanceof BufferedImage) { - BufferedImage image = (BufferedImage)editData; - - if (mImage == null || image != mImage.getBufferedImage()) { - mImage = new ImageBackground(image, mDisplay); - } - - mLayer.setBorder(mImage); - - if (mChild != null && mChild.getParent() == mLayer) { - mLayer.remove(mChild); - } - } else if (editData instanceof String) { - mLayer.setBorder(null); - if (mChild == null) { - mChild = new Label(); - } - mChild.setText((String)editData); - - if (mChild != null && mChild.getParent() != mLayer) { - mLayer.add(mChild); - } - Rectangle bounds = mChild.getTextBounds(); - bounds.x = bounds.y = 0; - mLayer.setConstraint(mChild, bounds); - } - - // refresh the children as well - refreshChildrenVisuals(); - } - - @Override - protected void hideSelection() { - // no selection at this level. - } - - @Override - protected void showSelection() { - // no selection at this level. - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java deleted file mode 100644 index af22afb..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; - -import java.util.List; - -/** - * Implementation of {@link UiElementTreeEditPart} for the document root. - */ -public class UiDocumentTreeEditPart extends UiElementTreeEditPart { - - public UiDocumentTreeEditPart(UiDocumentNode model) { - super(model); - } - - @SuppressWarnings("unchecked") - @Override - protected List getModelChildren() { - return getUiNode().getUiChildren(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java deleted file mode 100644 index 548a3a2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.draw2d.geometry.Rectangle; -import org.eclipse.gef.DragTracker; -import org.eclipse.gef.EditPart; -import org.eclipse.gef.EditPolicy; -import org.eclipse.gef.GraphicalEditPart; -import org.eclipse.gef.Request; -import org.eclipse.gef.editparts.AbstractGraphicalEditPart; -import org.eclipse.gef.editpolicies.SelectionEditPolicy; -import org.eclipse.gef.tools.SelectEditPartTracker; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -import java.util.List; - -/** - * An {@link EditPart} for a {@link UiElementNode}. - */ -public abstract class UiElementEditPart extends AbstractGraphicalEditPart - implements IUiUpdateListener { - - public UiElementEditPart(UiElementNode uiElementNode) { - setModel(uiElementNode); - } - - //------------------------- - // Derived classes must define these - - abstract protected void hideSelection(); - abstract protected void showSelection(); - - //------------------------- - // Base class overrides - - @Override - public DragTracker getDragTracker(Request request) { - return new SelectEditPartTracker(this); - } - - @Override - protected void createEditPolicies() { - installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new SelectionEditPolicy() { - @Override - protected void hideSelection() { - UiElementEditPart.this.hideSelection(); - } - - @Override - protected void showSelection() { - UiElementEditPart.this.showSelection(); - } - }); - // TODO add editing policies - } - - /* (non-javadoc) - * Returns a List containing the children model objects. - * Must not return null, instead use the super which returns an empty list. - */ - @SuppressWarnings("unchecked") - @Override - protected List getModelChildren() { - return getUiNode().getUiChildren(); - } - - @Override - public void activate() { - super.activate(); - getUiNode().addUpdateListener(this); - } - - @Override - public void deactivate() { - super.deactivate(); - getUiNode().removeUpdateListener(this); - } - - @Override - protected void refreshVisuals() { - if (getFigure().getParent() != null) { - ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds()); - } - - // update the visuals of the children as well - refreshChildrenVisuals(); - } - - protected void refreshChildrenVisuals() { - if (children != null) { - for (Object child : children) { - if (child instanceof UiElementEditPart) { - UiElementEditPart childPart = (UiElementEditPart)child; - childPart.refreshVisuals(); - } - } - } - } - - //------------------------- - // IUiUpdateListener implementation - - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - // TODO: optimize by refreshing only when needed - switch(state) { - case ATTR_UPDATED: - refreshVisuals(); - break; - case CHILDREN_CHANGED: - refreshChildren(); - - // new children list, need to update the layout - refreshVisuals(); - break; - case CREATED: - refreshVisuals(); - break; - case DELETED: - // pass - break; - } - } - - //------------------------- - // Local methods - - /** @return The object model casted to an {@link UiElementNode} */ - protected final UiElementNode getUiNode() { - return (UiElementNode) getModel(); - } - - protected final ElementDescriptor getDescriptor() { - return getUiNode().getDescriptor(); - } - - protected final UiElementEditPart getEditPartParent() { - EditPart parent = getParent(); - if (parent instanceof UiElementEditPart) { - return (UiElementEditPart)parent; - } - return null; - } - - /** - * Returns a given XML attribute. - * @param attrbName The local name of the attribute. - * @return the attribute as a {@link String}, if it exists, or <code>null</code> - */ - protected final String getStringAttr(String attrName) { - UiElementNode uiNode = getUiNode(); - if (uiNode.getXmlNode() != null) { - Node xmlNode = uiNode.getXmlNode(); - if (xmlNode != null) { - NamedNodeMap nodeAttributes = xmlNode.getAttributes(); - if (nodeAttributes != null) { - Node attr = nodeAttributes.getNamedItemNS( - AndroidConstants.NS_RESOURCES, attrName); - if (attr != null) { - return attr.getNodeValue(); - } - } - } - } - return null; - } - - protected final Rectangle getBounds() { - UiElementNode model = (UiElementNode)getModel(); - - Object editData = model.getEditData(); - if (editData instanceof Rectangle) { - return (Rectangle)editData; // return a copy? - } - - // return a dummy rect - return new Rectangle(0, 0, 0, 0); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java deleted file mode 100644 index fd788dd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.gef.editparts.AbstractTreeEditPart; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.views.contentoutline.IContentOutlinePage; - -/** - * Base {@link AbstractTreeEditPart} to represent {@link UiElementNode} objects in the - * {@link IContentOutlinePage} linked to the layout editor. - */ -public class UiElementTreeEditPart extends AbstractTreeEditPart { - - public UiElementTreeEditPart(UiElementNode uiElementNode) { - setModel(uiElementNode); - } - - @Override - protected void createEditPolicies() { - // TODO Auto-generated method stub - super.createEditPolicies(); - } - - @Override - protected Image getImage() { - return getUiNode().getDescriptor().getIcon(); - } - - @Override - protected String getText() { - return getUiNode().getShortDescription(); - } - - @Override - public void activate() { - if (!isActive()) { - super.activate(); - // TODO - } - } - - @Override - public void deactivate() { - if (isActive()) { - super.deactivate(); - // TODO - } - } - - /** - * Returns the casted model object represented by this {@link AbstractTreeEditPart}. - */ - protected UiElementNode getUiNode() { - return (UiElementNode)getModel(); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java deleted file mode 100644 index de6c404..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.gef.EditPart; -import org.eclipse.gef.EditPartFactory; -import org.eclipse.gef.editparts.AbstractTreeEditPart; -import org.eclipse.ui.views.contentoutline.IContentOutlinePage; - -/** - * {@link EditPartFactory} to create {@link AbstractTreeEditPart} for {@link UiElementNode} objects. - * These objects are used in the {@link IContentOutlinePage} linked to the layout editor. - */ -public class UiElementTreeEditPartFactory implements EditPartFactory { - - public EditPart createEditPart(EditPart context, Object model) { - if (model instanceof UiDocumentNode) { - return new UiDocumentTreeEditPart((UiDocumentNode) model); - } else if (model instanceof UiElementNode) { - UiElementNode node = (UiElementNode) model; - if (node.getDescriptor().hasChildren()) { - return new UiLayoutTreeEditPart(node); - } else { - return new UiViewTreeEditPart(node); - } - } - return null; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java deleted file mode 100644 index 18dcd9c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.gef.EditPart; -import org.eclipse.gef.EditPartFactory; -import org.eclipse.swt.widgets.Display; - -/** - * A factory that returns the appropriate {@link EditPart} for a given model object. - * <p/> - * The only model objects we use are {@link UiElementNode} objects and they are - * edited using {@link UiElementEditPart}. - */ -public class UiElementsEditPartFactory implements EditPartFactory { - - private Display mDisplay; - - public UiElementsEditPartFactory(Display display) { - mDisplay = display; - } - - public EditPart createEditPart(EditPart context, Object model) { - if (model instanceof UiDocumentNode) { - return new UiDocumentEditPart((UiDocumentNode) model, mDisplay); - } else if (model instanceof UiElementNode) { - UiElementNode node = (UiElementNode) model; - - if (node.getDescriptor().hasChildren()) { - return new UiLayoutEditPart(node); - } - - return new UiViewEditPart(node); - } - return null; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java deleted file mode 100644 index d9433ca..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.draw2d.ColorConstants; -import org.eclipse.draw2d.IFigure; -import org.eclipse.draw2d.Label; -import org.eclipse.draw2d.LineBorder; -import org.eclipse.draw2d.XYLayout; -import org.eclipse.gef.EditPolicy; -import org.eclipse.gef.commands.Command; -import org.eclipse.gef.editpolicies.ContainerEditPolicy; -import org.eclipse.gef.requests.CreateRequest; - -/** - * Graphical edit part for an {@link UiElementNode} that represents a ViewLayout. - * <p/> - * It acts as a simple container. - */ -public final class UiLayoutEditPart extends UiElementEditPart { - - public UiLayoutEditPart(UiElementNode uiElementNode) { - super(uiElementNode); - } - - @Override - protected void createEditPolicies() { - super.createEditPolicies(); - - installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy() { - @Override - protected Command getCreateCommand(CreateRequest request) { - return null; - } - }); - } - - @Override - protected IFigure createFigure() { - Label f = new Label(); - f.setLayoutManager(new XYLayout()); - return f; - } - - @Override - protected void hideSelection() { - IFigure f = getFigure(); - if (f instanceof Label) { - f.setBorder(null); - } - } - - @Override - protected void showSelection() { - IFigure f = getFigure(); - if (f instanceof Label) { - f.setBorder(new LineBorder(ColorConstants.red, 1)); - } - } - - public void showDropTarget() { - IFigure f = getFigure(); - if (f instanceof Label) { - f.setBorder(new LineBorder(ColorConstants.blue, 1)); - } - } - - public void hideDropTarget() { - hideSelection(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java deleted file mode 100644 index 4359e23..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import java.util.List; - -/** - * Implementation of {@link UiElementTreeEditPart} for layout objects. - */ -public class UiLayoutTreeEditPart extends UiElementTreeEditPart { - - public UiLayoutTreeEditPart(UiElementNode node) { - super(node); - } - - @SuppressWarnings("unchecked") - @Override - protected List getModelChildren() { - return getUiNode().getUiChildren(); - } - - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java deleted file mode 100644 index b427ead..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.draw2d.ColorConstants; -import org.eclipse.draw2d.IFigure; -import org.eclipse.draw2d.Label; -import org.eclipse.draw2d.LineBorder; - -/** - * Graphical edit part for an {@link UiElementNode} that represents a View. - */ -public class UiViewEditPart extends UiElementEditPart { - - public UiViewEditPart(UiElementNode uiElementNode) { - super(uiElementNode); - } - - @Override - protected IFigure createFigure() { - Label f = new Label(); - return f; - } - - @Override - protected void hideSelection() { - IFigure f = getFigure(); - if (f instanceof Label) { - f.setBorder(null); - } - } - - @Override - protected void showSelection() { - IFigure f = getFigure(); - if (f instanceof Label) { - f.setBorder(new LineBorder(ColorConstants.red, 1)); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java deleted file mode 100644 index 62b5e8a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.parts; - -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Implementation of {@link UiElementTreeEditPart} for view objects. - */ -public class UiViewTreeEditPart extends UiElementTreeEditPart { - - public UiViewTreeEditPart(UiElementNode node) { - super(node); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java deleted file mode 100644 index 75cf4b6..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.layout.uimodel; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; -import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Specialized version of {@link UiElementNode} for the {@link ViewElementDescriptor}s. - */ -public class UiViewElementNode extends UiElementNode { - - private AttributeDescriptor[] mCachedAttributeDescriptors; - - public UiViewElementNode(ViewElementDescriptor elementDescriptor) { - super(elementDescriptor); - } - - /** - * Returns an AttributeDescriptor array that depends on the current UiParent. - * <p/> - * The array merges both "direct" attributes with the descriptor layout attributes. - * The array instance is cached and cleared if the UiParent is changed. - */ - @Override - public AttributeDescriptor[] getAttributeDescriptors() { - if (mCachedAttributeDescriptors != null) { - return mCachedAttributeDescriptors; - } - - UiElementNode ui_parent = getUiParent(); - AttributeDescriptor[] direct_attrs = super.getAttributeDescriptors(); - mCachedAttributeDescriptors = direct_attrs; - - AttributeDescriptor[] layout_attrs = null; - boolean need_xmlns = false; - - if (ui_parent instanceof UiDocumentNode) { - // Limitation: right now the layout behaves as if everything was - // owned by a FrameLayout. - // TODO replace by something user-configurable. - for (ElementDescriptor desc : LayoutDescriptors.getInstance().getLayoutDescriptors()) { - if (desc instanceof ViewElementDescriptor && - desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) { - layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes(); - need_xmlns = true; - break; - } - } - } else if (ui_parent instanceof UiViewElementNode){ - layout_attrs = - ((ViewElementDescriptor) ui_parent.getDescriptor()).getLayoutAttributes(); - } - - if (layout_attrs == null || layout_attrs.length == 0) { - return mCachedAttributeDescriptors; - } - - mCachedAttributeDescriptors = - new AttributeDescriptor[direct_attrs.length + - layout_attrs.length + - (need_xmlns ? 1 : 0)]; - System.arraycopy(direct_attrs, 0, - mCachedAttributeDescriptors, 0, - direct_attrs.length); - System.arraycopy(layout_attrs, 0, - mCachedAttributeDescriptors, direct_attrs.length, - layout_attrs.length); - if (need_xmlns) { - AttributeDescriptor desc = new XmlnsAttributeDescriptor( - "android", //$NON-NLS-1$ - AndroidConstants.NS_RESOURCES); - mCachedAttributeDescriptors[direct_attrs.length + layout_attrs.length] = desc; - } - - return mCachedAttributeDescriptors; - } - - /** - * Sets the parent of this UI node. - * <p/> - * Also removes the cached AttributeDescriptor array that depends on the current UiParent. - */ - @Override - protected void setUiParent(UiElementNode parent) { - super.setUiParent(parent); - mCachedAttributeDescriptors = null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java deleted file mode 100644 index e43c984..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest; - -import com.android.ide.eclipse.editors.AndroidContentAssist; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; - -/** - * Content Assist Processor for AndroidManifest.xml - */ -final class ManifestContentAssist extends AndroidContentAssist { - - /** - * Constructor for ManifestContentAssist - */ - public ManifestContentAssist() { - super(new ElementDescriptor[] { AndroidManifestDescriptors.MANIFEST_ELEMENT }); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java deleted file mode 100644 index 666a066..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidXPathFactory; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.manifest.pages.ApplicationPage; -import com.android.ide.eclipse.editors.manifest.pages.InstrumentationPage; -import com.android.ide.eclipse.editors.manifest.pages.OverviewPage; -import com.android.ide.eclipse.editors.manifest.pages.PermissionPage; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.util.List; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; - -/** - * Multi-page form editor for AndroidManifest.xml. - */ -public final class ManifestEditor extends AndroidEditor { - private final static String EMPTY = ""; //$NON-NLS-1$ - - - /** Root node of the UI element hierarchy */ - private UiElementNode mUiManifestNode; - /** Listener to update the root node if the resource framework changes */ - private Runnable mResourceRefreshListener; - /** The Application Page tab */ - private ApplicationPage mAppPage; - /** The Overview Manifest Page tab */ - private OverviewPage mOverviewPage; - - /** - * Creates the form editor for AndroidManifest.xml. - */ - public ManifestEditor() { - super(); - initUiManifestNode(); - } - - /** - * Return the root node of the UI element hierarchy, which here - * is the "manifest" node. - */ - @Override - public UiElementNode getUiRootNode() { - return mUiManifestNode; - } - - // ---- Base Class Overrides ---- - - @Override - public void dispose() { - if (mResourceRefreshListener != null) { - EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener = null; - } - super.dispose(); - } - - /** - * Returns whether the "save as" operation is supported by this editor. - * <p/> - * Save-As is a valid operation for the ManifestEditor since it acts on a - * single source file. - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return true; - } - - /** - * Creates the various form pages. - */ - @Override - protected void createFormPages() { - try { - addPage(mOverviewPage = new OverviewPage(this)); - addPage(mAppPage = new ApplicationPage(this)); - addPage(new PermissionPage(this)); - addPage(new InstrumentationPage(this)); - } catch (PartInitException e) { - EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$ - } - } - - /* (non-java doc) - * Change the tab/title name to include the project name. - */ - @Override - protected void setInput(IEditorInput input) { - super.setInput(input); - IFile inputFile = getInputFile(); - if (inputFile != null) { - setPartName(String.format("%1$s Manifest", inputFile.getProject().getName())); - } - } - - /** - * Processes the new XML Model, which XML root node is given. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - @Override - protected void xmlModelChanged(Document xml_doc) { - mUiManifestNode.setXmlDocument(xml_doc); - if (xml_doc != null) { - ElementDescriptor manifest_desc = mUiManifestNode.getDescriptor(); - try { - XPath xpath = AndroidXPathFactory.newXPath(); - Node node = (Node) xpath.evaluate("/" + manifest_desc.getXmlName(), //$NON-NLS-1$ - xml_doc, - XPathConstants.NODE); - assert node != null && node.getNodeName().equals(manifest_desc.getXmlName()); - - // Refresh the manifest UI node and all its descendants - mUiManifestNode.loadFromXmlNode(node); - - startMonitoringMarkers(); - } catch (XPathExpressionException e) { - EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$ - manifest_desc.getXmlName()); - } - } - - super.xmlModelChanged(xml_doc); - } - - /** - * Reads and processes the current markers and adds a listener for marker changes. - */ - private void startMonitoringMarkers() { - final IFile inputFile = getInputFile(); - if (inputFile != null) { - updateFromExistingMarkers(inputFile); - - ResourceMonitor.getMonitor().addFileListener(new IFileListener() { - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) { - if (file.equals(inputFile)) { - processMarkerChanges(markerDeltas); - } - } - }, IResourceDelta.CHANGED); - } - } - - /** - * Processes the markers of the specified {@link IFile} and updates the error status of - * {@link UiElementNode}s and {@link UiAttributeNode}s. - * @param inputFile the file being edited. - */ - private void updateFromExistingMarkers(IFile inputFile) { - try { - // get the markers for the file - IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true, - IResource.DEPTH_ZERO); - - UiElementNode app_ui_node = mUiManifestNode.findUiChildNode( - AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName()); - List<UiElementNode> children = app_ui_node.getUiChildren(); - - for (IMarker marker : markers) { - processMarker(marker, children, IResourceDelta.ADDED); - } - } catch (CoreException e) { - // findMarkers can throw an exception, in which case, we'll do nothing. - } - } - - /** - * Processes a {@link IMarker} change. - * @param markerDeltas the list of {@link IMarkerDelta} - */ - private void processMarkerChanges(IMarkerDelta[] markerDeltas) { - UiElementNode app_ui_node = mUiManifestNode.findUiChildNode( - AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName()); - List<UiElementNode> children = app_ui_node.getUiChildren(); - - for (IMarkerDelta markerDelta : markerDeltas) { - processMarker(markerDelta.getMarker(), children, markerDelta.getKind()); - } - } - - /** - * Processes a new/old/updated marker. - * @param marker The marker being added/removed/changed - * @param nodeList the list of activity/service/provider/receiver nodes. - * @param kind the change kind. Can be {@link IResourceDelta#ADDED}, - * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} - */ - private void processMarker(IMarker marker, List<UiElementNode> nodeList, int kind) { - // get the data from the marker - String nodeType = marker.getAttribute(AndroidConstants.MARKER_ATTR_TYPE, EMPTY); - if (nodeType == EMPTY) { - return; - } - - String className = marker.getAttribute(AndroidConstants.MARKER_ATTR_CLASS, EMPTY); - if (className == EMPTY) { - return; - } - - for (UiElementNode ui_node : nodeList) { - if (ui_node.getDescriptor().getXmlName().equals(nodeType)) { - for (UiAttributeNode attr : ui_node.getUiAttributes()) { - if (attr.getDescriptor().getXmlLocalName().equals( - AndroidManifestDescriptors.ANDROID_NAME_ATTR)) { - if (attr.getCurrentValue().equals(className)) { - if (kind == IResourceDelta.REMOVED) { - attr.setHasError(false); - } else { - attr.setHasError(true); - } - return; - } - } - } - } - } - } - - /** - * Creates the initial UI Root Node, including the known mandatory elements. - */ - private void initUiManifestNode() { - // The manifest UI node is always created, even if there's no corresponding XML node. - if (mUiManifestNode == null) { - ElementDescriptor manifest_desc = AndroidManifestDescriptors.MANIFEST_ELEMENT; - mUiManifestNode = manifest_desc.createUiNode(); - mUiManifestNode.setEditor(this); - - // Similarly, always create the /manifest/application and /manifest/uses-sdk nodes - ElementDescriptor app_desc = AndroidManifestDescriptors.APPLICATION_ELEMENT; - boolean present = false; - for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) { - if (ui_node.getDescriptor() == app_desc) { - present = true; - break; - } - } - if (!present) { - mUiManifestNode.appendNewUiChild(app_desc); - } - - app_desc = AndroidManifestDescriptors.USES_SDK_ELEMENT; - present = false; - for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) { - if (ui_node.getDescriptor() == app_desc) { - present = true; - break; - } - } - if (!present) { - mUiManifestNode.appendNewUiChild(app_desc); - } - - // Add a listener to refresh the root node if the resource framework changes - // by forcing it to parse its own XML - mResourceRefreshListener = new Runnable() { - public void run() { - commitPages(false /* onSave */); - - mUiManifestNode.reloadFromXmlNode(mUiManifestNode.getXmlNode()); - if (mOverviewPage != null) { - mOverviewPage.refreshUiApplicationNode(); - } - if (mAppPage != null) { - mAppPage.refreshUiApplicationNode(); - } - } - }; - EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener.run(); - } - } - - /** - * Returns the {@link IFile} being edited, or <code>null</code> if it couldn't be computed. - */ - private IFile getInputFile() { - IEditorInput input = getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput) input; - return fileInput.getFile(); - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java deleted file mode 100644 index 911faa1..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest; - -import org.eclipse.jface.action.IAction; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.ide.IDEActionFactory; -import org.eclipse.ui.part.MultiPageEditorActionBarContributor; -import org.eclipse.ui.texteditor.ITextEditor; -import org.eclipse.ui.texteditor.ITextEditorActionConstants; - -/** - * Manages the installation/deinstallation of global actions for multi-page - * editors. Responsible for the redirection of global actions to the active - * editor. Multi-page contributor replaces the contributors for the individual - * editors in the multi-page editor. - * - * TODO: Doesn't look like we need this. Remove it if not needed. - * @deprecated - */ -final class ManifestEditorContributor extends MultiPageEditorActionBarContributor { - private IEditorPart mActiveEditorPart; - - /** - * Creates a multi-page contributor. - * - * Marked as Private so it can't be instanciated. This is a cheap way to make sure - * it's not being used. As noted in constructor, should be removed if not used. - * @deprecated - */ - private ManifestEditorContributor() { - super(); - } - - /** - * Returns the action registed with the given text editor. - * - * @return IAction or null if editor is null. - */ - protected IAction getAction(ITextEditor editor, String actionID) { - return (editor == null ? null : editor.getAction(actionID)); - } - - /* - * (non-JavaDoc) Method declared in - * AbstractMultiPageEditorActionBarContributor. - */ - - @Override - public void setActivePage(IEditorPart part) { - if (mActiveEditorPart == part) - return; - - mActiveEditorPart = part; - - IActionBars actionBars = getActionBars(); - if (actionBars != null) { - - ITextEditor editor = - (part instanceof ITextEditor) ? (ITextEditor)part : null; - - actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), - getAction(editor, ITextEditorActionConstants.DELETE)); - actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), - getAction(editor, ITextEditorActionConstants.UNDO)); - actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), - getAction(editor, ITextEditorActionConstants.REDO)); - actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), - getAction(editor, ITextEditorActionConstants.CUT)); - actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), - getAction(editor, ITextEditorActionConstants.COPY)); - actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), - getAction(editor, ITextEditorActionConstants.PASTE)); - actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), - getAction(editor, ITextEditorActionConstants.SELECT_ALL)); - actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), - getAction(editor, ITextEditorActionConstants.FIND)); - actionBars.setGlobalActionHandler( - IDEActionFactory.BOOKMARK.getId(), getAction(editor, - IDEActionFactory.BOOKMARK.getId())); - actionBars.updateActionBars(); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java deleted file mode 100644 index e33e1ef..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest; - - -import com.android.ide.eclipse.editors.AndroidSourceViewerConfig; - -/** - * Source Viewer Configuration that calls in ManifestContentAssist. - */ -public final class ManifestSourceViewerConfig extends AndroidSourceViewerConfig { - - public ManifestSourceViewerConfig() { - super(new ManifestContentAssist()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java deleted file mode 100644 index 171eaee..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; - -import org.eclipse.core.runtime.IStatus; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.TreeSet; -import java.util.Map.Entry; - - -/** - * Complete description of the AndroidManifest.xml structure. - * <p/> - * The root element are static instances which always exists. - * However their sub-elements and attributes are created only when the SDK changes or is - * loaded the first time. - */ -public class AndroidManifestDescriptors { - - private static final String MANIFEST_NODE_NAME = "manifest"; //$NON-NLS-1$ - private static final String ANDROID_MANIFEST_STYLEABLE = "AndroidManifest"; //$NON-NLS-1$ - - // Public attributes names, attributes descriptors and elements descriptors - - public static final String ANDROID_LABEL_ATTR = "label"; //$NON-NLS-1$ - public static final String ANDROID_NAME_ATTR = "name"; //$NON-NLS-1$ - public static final String PACKAGE_ATTR = "package"; //$NON-NLS-1$ - - /** The {@link ElementDescriptor} for the root Manifest element. */ - public static final ElementDescriptor MANIFEST_ELEMENT; - /** The {@link ElementDescriptor} for the root Application element. */ - public static final ElementDescriptor APPLICATION_ELEMENT; - - /** The {@link ElementDescriptor} for the root Instrumentation element. */ - public static final ElementDescriptor INTRUMENTATION_ELEMENT; - /** The {@link ElementDescriptor} for the root Permission element. */ - public static final ElementDescriptor PERMISSION_ELEMENT; - /** The {@link ElementDescriptor} for the root UsesPermission element. */ - public static final ElementDescriptor USES_PERMISSION_ELEMENT; - /** The {@link ElementDescriptor} for the root UsesSdk element. */ - public static final ElementDescriptor USES_SDK_ELEMENT; - - /** The {@link ElementDescriptor} for the root PermissionGroup element. */ - public static final ElementDescriptor PERMISSION_GROUP_ELEMENT; - /** The {@link ElementDescriptor} for the root PermissionTree element. */ - public static final ElementDescriptor PERMISSION_TREE_ELEMENT; - - /** Private package attribute for the manifest element. Needs to be handled manually. */ - private static final TextAttributeDescriptor PACKAGE_ATTR_DESC; - - static { - APPLICATION_ELEMENT = createElement("application", null, true); //$NON-NLS-1$ + no child & mandatory - INTRUMENTATION_ELEMENT = createElement("instrumentation"); //$NON-NLS-1$ - - PERMISSION_ELEMENT = createElement("permission"); //$NON-NLS-1$ - USES_PERMISSION_ELEMENT = createElement("uses-permission"); //$NON-NLS-1$ - USES_SDK_ELEMENT = createElement("uses-sdk", null, true); //$NON-NLS-1$ + no child & mandatory - - PERMISSION_GROUP_ELEMENT = createElement("permission-group"); //$NON-NLS-1$ - PERMISSION_TREE_ELEMENT = createElement("permission-tree"); //$NON-NLS-1$ - - MANIFEST_ELEMENT = createElement( - MANIFEST_NODE_NAME, // xml name - new ElementDescriptor[] { - APPLICATION_ELEMENT, - INTRUMENTATION_ELEMENT, - PERMISSION_ELEMENT, - USES_PERMISSION_ELEMENT, - PERMISSION_GROUP_ELEMENT, - PERMISSION_TREE_ELEMENT, - USES_SDK_ELEMENT, - }, - true /* mandatory */); - - // The "package" attribute is treated differently as it doesn't have the standard - // Android XML namespace. - PACKAGE_ATTR_DESC = new PackageAttributeDescriptor(PACKAGE_ATTR, - "Package", - null /* nsUri */, - "This attribute gives a unique name for the package, using a Java-style naming convention to avoid name collisions.\nFor example, applications published by Google could have names of the form com.google.app.appname"); - } - - /** - * Updates the document descriptor. - * <p/> - * It first computes the new children of the descriptor and then updates them - * all at once. - * - * @param manifestMap The map style => attributes from the attrs_manifest.xml file - */ - public static synchronized void updateDescriptors( - Map<String, DeclareStyleableInfo> manifestMap) { - - XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( - "android", //$NON-NLS-1$ - AndroidConstants.NS_RESOURCES); - - // -- setup the various attribute format overrides -- - // The key for each override is "element1,element2,.../attr-xml-local-name" or - // "*/attr-xml-local-name" to match the attribute in any element. - - Map<String, Object> overrides = new HashMap<String, Object>(); - - overrides.put("*/icon", new DescriptorsUtils.ITextAttributeCreator() { //$NON-NLS-1$ - public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri, - String tooltip) { - return new ReferenceAttributeDescriptor( - ResourceType.DRAWABLE, - xmlName, uiName, nsUri, - tooltip); - } - }); - - overrides.put("*/theme", ThemeAttributeDescriptor.class); //$NON-NLS-1$ - overrides.put("*/permission", ListAttributeDescriptor.class); //$NON-NLS-1$ - overrides.put("*/targetPackage", PackageAttributeDescriptor.class); //$NON-NLS-1$ - - overrides.put("action,category,uses-permission/" + ANDROID_NAME_ATTR, //$NON-NLS-1$ - ListAttributeDescriptor.class); - overrides.put("application/" + ANDROID_NAME_ATTR, ApplicationAttributeDescriptor.class); //$NON-NLS-1$ - - overrideClassName(overrides, "activity", AndroidConstants.CLASS_ACTIVITY); //$NON-NLS-1$ - overrideClassName(overrides, "receiver", AndroidConstants.CLASS_BROADCASTRECEIVER); //$NON-NLS-1$ - overrideClassName(overrides, "service", AndroidConstants.CLASS_SERVICE); //$NON-NLS-1$ - overrideClassName(overrides, "provider", AndroidConstants.CLASS_CONTENTPROVIDER); //$NON-NLS-1$ - - // -- list element nodes already created -- - // These elements are referenced by already opened editors, so we want to update them - // but not re-create them when reloading an SDK on the fly. - - HashMap<String, ElementDescriptor> elementDescs = - new HashMap<String, ElementDescriptor>(); - elementDescs.put(MANIFEST_ELEMENT.getXmlLocalName(), MANIFEST_ELEMENT); - elementDescs.put(APPLICATION_ELEMENT.getXmlLocalName(), APPLICATION_ELEMENT); - elementDescs.put(INTRUMENTATION_ELEMENT.getXmlLocalName(), INTRUMENTATION_ELEMENT); - elementDescs.put(PERMISSION_ELEMENT.getXmlLocalName(), PERMISSION_ELEMENT); - elementDescs.put(USES_PERMISSION_ELEMENT.getXmlLocalName(), USES_PERMISSION_ELEMENT); - elementDescs.put(USES_SDK_ELEMENT.getXmlLocalName(), USES_SDK_ELEMENT); - elementDescs.put(PERMISSION_GROUP_ELEMENT.getXmlLocalName(), PERMISSION_GROUP_ELEMENT); - elementDescs.put(PERMISSION_TREE_ELEMENT.getXmlLocalName(), PERMISSION_TREE_ELEMENT); - - // -- - - inflateElement(manifestMap, overrides, elementDescs, - MANIFEST_ELEMENT, "AndroidManifest"); //$NON-NLS-1$ - insertAttribute(MANIFEST_ELEMENT, PACKAGE_ATTR_DESC); - - sanityCheck(manifestMap, MANIFEST_ELEMENT); - } - - /** - * Sets up an attribute override for ANDROID_NAME_ATTR using a ClassAttributeDescriptor - * with the specified class name. - */ - private static void overrideClassName(Map<String, Object> overrides, - String elementName, final String className) { - overrides.put(elementName + "/" + ANDROID_NAME_ATTR, - new DescriptorsUtils.ITextAttributeCreator() { - public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri, - String tooltip) { - if (AndroidConstants.CLASS_ACTIVITY.equals(className)) { - return new ClassAttributeDescriptor( - className, - PostActivityCreationAction.getAction(), - xmlName, uiName + "*", //$NON-NLS-1$ - nsUri, - tooltip, - true /*mandatory */); - } else if (AndroidConstants.CLASS_BROADCASTRECEIVER.equals(className)) { - return new ClassAttributeDescriptor( - className, - PostReceiverCreationAction.getAction(), - xmlName, uiName + "*", //$NON-NLS-1$ - nsUri, - tooltip, - true /*mandatory */); - - } else { - return new ClassAttributeDescriptor( - className, - xmlName, uiName + "*", //$NON-NLS-1$ - nsUri, - tooltip, - true /*mandatory */); - } - } - }); - } - - /** - * Returns a new ElementDescriptor constructed from the information given here - * and the javadoc & attributes extracted from the style map if any. - * <p/> - * Creates an element with no attribute overrides. - */ - private static ElementDescriptor createElement( - String xmlName, - ElementDescriptor[] childrenElements, - boolean mandatory) { - // Creates an element with no attribute overrides. - String styleName = guessStyleName(xmlName); - String sdkUrl = DescriptorsUtils.MANIFEST_SDK_URL + styleName; - String uiName = getUiName(xmlName); - - ElementDescriptor element = new ManifestElementDescriptor(xmlName, uiName, null, sdkUrl, - null, childrenElements, mandatory); - - return element; - } - - /** - * Returns a new ElementDescriptor constructed from its XML local name. - * <p/> - * This version creates an element not mandatory. - */ - private static ElementDescriptor createElement(String xmlName) { - // Creates an element with no child and not mandatory - return createElement(xmlName, null, false); - } - - /** - * Inserts an attribute in this element attribute list if it is not present there yet - * (based on the attribute XML name.) - * The attribute is inserted at the beginning of the attribute list. - */ - private static void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) { - AttributeDescriptor[] attributes = element.getAttributes(); - for (AttributeDescriptor attr : attributes) { - if (attr.getXmlLocalName().equals(newAttr.getXmlLocalName())) { - return; - } - } - - AttributeDescriptor[] newArray = new AttributeDescriptor[attributes.length + 1]; - newArray[0] = newAttr; - System.arraycopy(attributes, 0, newArray, 1, attributes.length); - element.setAttributes(newArray); - } - - /** - * "Inflates" the properties of an {@link ElementDescriptor} from the styleable declaration. - * <p/> - * This first creates all the attributes for the given ElementDescriptor. - * It then find all children of the descriptor, inflate them recursively and set them - * as child to this ElementDescriptor. - * - * @param styleMap The input styleable map for manifest elements & attributes - * @param overrides A list of attribute overrides (to customize the type of the attribute - * descriptors) - * @param existingElementDescs A map of already created element descriptors, keyed by - * XML local name. This is used to use the static elements created initially by this - * class, which are referenced directly by editors (so that reloading an SDK won't - * break these references) - * @param elemDesc The current {@link ElementDescriptor} to inflate. - * @param styleName The name of the {@link ElementDescriptor} to inflate. Its XML local name - * will be guessed automatically from the style name. - */ - private static void inflateElement( - Map<String, DeclareStyleableInfo> styleMap, - Map<String, Object> overrides, - HashMap<String, ElementDescriptor> existingElementDescs, - ElementDescriptor elemDesc, - String styleName) { - assert elemDesc != null; - assert styleName != null; - - // define attributes - DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null; - if (style != null) { - ArrayList<AttributeDescriptor> attrDescs = new ArrayList<AttributeDescriptor>(); - DescriptorsUtils.appendAttributes(attrDescs, - elemDesc.getXmlLocalName(), - AndroidConstants.NS_RESOURCES, - style.getAttributes(), null, overrides); - elemDesc.setTooltip(style.getJavaDoc()); - elemDesc.setAttributes(attrDescs.toArray(new AttributeDescriptor[attrDescs.size()])); - } - - // find all elements that have this one as parent - ArrayList<ElementDescriptor> children = new ArrayList<ElementDescriptor>(); - for (Entry<String, DeclareStyleableInfo> entry : styleMap.entrySet()) { - DeclareStyleableInfo childStyle = entry.getValue(); - boolean isParent = false; - String[] parents = childStyle.getParents(); - if (parents != null) { - for (String parent: parents) { - if (styleName.equals(parent)) { - isParent = true; - break; - } - } - } - if (isParent) { - String childStyleName = entry.getKey(); - String childXmlName = guessXmlName(childStyleName); - - // create or re-use element - ElementDescriptor child = existingElementDescs.get(childXmlName); - if (child == null) { - child = createElement(childXmlName); - existingElementDescs.put(childXmlName, child); - } - children.add(child); - - inflateElement(styleMap, overrides, existingElementDescs, child, childStyleName); - } - } - elemDesc.setChildren(children.toArray(new ElementDescriptor[children.size()])); - } - - /** - * Get an UI name from the element XML name. - * <p/> - * Capitalizes the first letter and replace non-alphabet by a space followed by a capital. - */ - private static String getUiName(String xmlName) { - StringBuilder sb = new StringBuilder(); - - boolean capitalize = true; - for (char c : xmlName.toCharArray()) { - if (capitalize && c >= 'a' && c <= 'z') { - sb.append((char)(c + 'A' - 'a')); - capitalize = false; - } else if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { - sb.append(' '); - capitalize = true; - } else { - sb.append(c); - } - } - - return sb.toString(); - } - - /** - * Guesses the style name for a given XML element name. - * <p/> - * The rules are: - * - capitalize the first letter: - * - if there's a dash, skip it and capitalize the next one - * - prefix AndroidManifest - * The exception is "manifest" which just becomes AndroidManifest. - * <p/> - * Examples: - * - manifest => AndroidManifest - * - application => AndroidManifestApplication - * - uses-permission => AndroidManifestUsesPermission - */ - private static String guessStyleName(String xmlName) { - StringBuilder sb = new StringBuilder(); - - if (!xmlName.equals(MANIFEST_NODE_NAME)) { - boolean capitalize = true; - for (char c : xmlName.toCharArray()) { - if (capitalize && c >= 'a' && c <= 'z') { - sb.append((char)(c + 'A' - 'a')); - capitalize = false; - } else if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { - // not a letter -- skip the character and capitalize the next one - capitalize = true; - } else { - sb.append(c); - } - } - } - - sb.insert(0, ANDROID_MANIFEST_STYLEABLE); - return sb.toString(); - } - - /** - * This method performs a sanity check to make sure all the styles declared in the - * manifestMap are actually defined in the actual element descriptors and reachable from - * the manifestElement root node. - */ - private static void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap, - ElementDescriptor manifestElement) { - TreeSet<String> elementsDeclared = new TreeSet<String>(); - findAllElementNames(manifestElement, elementsDeclared); - - TreeSet<String> stylesDeclared = new TreeSet<String>(); - for (String styleName : manifestMap.keySet()) { - if (styleName.startsWith(ANDROID_MANIFEST_STYLEABLE)) { - stylesDeclared.add(styleName); - } - } - - for (Iterator<String> it = elementsDeclared.iterator(); it.hasNext();) { - String xmlName = it.next(); - String styleName = guessStyleName(xmlName); - if (stylesDeclared.remove(styleName)) { - it.remove(); - } - } - - StringBuilder sb = new StringBuilder(); - if (!stylesDeclared.isEmpty()) { - sb.append("Warning, ADT/SDK Mismatch! The following elements are declared by the SDK but unknown to ADT: "); - for (String name : stylesDeclared) { - name = guessXmlName(name); - - if (name != stylesDeclared.last()) { - sb.append(", "); //$NON-NLS-1$ - } - } - - EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString()); - EditorsPlugin.printToConsole(null, sb); - sb.setLength(0); - } - - if (!elementsDeclared.isEmpty()) { - sb.append("Warning, ADT/SDK Mismatch! The following elements are declared by ADT but not by the SDK: "); - for (String name : elementsDeclared) { - sb.append(name); - if (name != elementsDeclared.last()) { - sb.append(", "); //$NON-NLS-1$ - } - } - - EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString()); - EditorsPlugin.printToConsole(null, sb); - } - } - - /** - * Performs an approximate translation of the style name into a potential - * xml name. This is more or less the reverse from guessStyleName(). - * - * @return The XML local name for a given style name. - */ - private static String guessXmlName(String name) { - StringBuilder sb = new StringBuilder(); - if (ANDROID_MANIFEST_STYLEABLE.equals(name)) { - sb.append(MANIFEST_NODE_NAME); - } else { - name = name.replace(ANDROID_MANIFEST_STYLEABLE, ""); //$NON-NLS-1$ - boolean first_char = true; - for (char c : name.toCharArray()) { - if (c >= 'A' && c <= 'Z') { - if (!first_char) { - sb.append('-'); - } - c = (char) (c - 'A' + 'a'); - } - sb.append(c); - first_char = false; - } - } - return sb.toString(); - } - - /** - * Helper method used by {@link #sanityCheck(Map, ElementDescriptor)} to find all the - * {@link ElementDescriptor} names defined by the tree of descriptors. - * <p/> - * Note: this assumes no circular reference in the tree of {@link ElementDescriptor}s. - */ - private static void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) { - declared.add(element.getXmlName()); - for (ElementDescriptor desc : element.getChildren()) { - findAllElementNames(desc, declared); - } - } - - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java deleted file mode 100644 index eab7f09..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Describes an 'Application' class XML attribute. It is displayed by a - * {@link UiClassAttributeNode}, that restricts creation and selection to classes - * inheriting from android.app.Application. - */ -public class ApplicationAttributeDescriptor extends TextAttributeDescriptor { - - public ApplicationAttributeDescriptor(String xmlLocalName, String uiName, - String nsUri, String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiClassAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiClassAttributeNode("android.app.Application", //$NON-NLS-1$ - null /* postCreationAction */, false /* mandatory */, this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java deleted file mode 100644 index 1144006..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode.IPostTypeCreationAction; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Describes an XML attribute representing a class name. - * It is displayed by a {@link UiClassAttributeNode}. - */ -public class ClassAttributeDescriptor extends TextAttributeDescriptor { - - /** Superclass of the class value. */ - private String mSuperClassName; - - private IPostTypeCreationAction mPostCreationAction; - - /** indicates if the class parameter is mandatory */ - boolean mMandatory; - - /** - * Creates a new {@link ClassAttributeDescriptor} - * @param superClassName the fully qualified name of the superclass of the class represented - * by the attribute. - * @param xmlLocalName The XML name of the attribute (case sensitive, with android: prefix). - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip A non-empty tooltip string or null. - * @param mandatory indicates if the class attribute is mandatory. - */ - public ClassAttributeDescriptor(String superClassName, - String xmlLocalName, String uiName, String nsUri, - String tooltip, boolean mandatory) { - super(xmlLocalName, uiName, nsUri, tooltip); - mSuperClassName = superClassName; - } - - /** - * Creates a new {@link ClassAttributeDescriptor} - * @param superClassName the fully qualified name of the superclass of the class represented - * by the attribute. - * @param postCreationAction the {@link IPostTypeCreationAction} to be executed on the - * newly created class. - * @param xmlLocalName The XML local name of the attribute (case sensitive). - * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. - * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. - * See {@link AndroidConstants#NS_RESOURCES} for a common value. - * @param tooltip A non-empty tooltip string or null. - * @param mandatory indicates if the class attribute is mandatory. - */ - public ClassAttributeDescriptor(String superClassName, - IPostTypeCreationAction postCreationAction, - String xmlLocalName, String uiName, String nsUri, - String tooltip, boolean mandatory) { - super(xmlLocalName, uiName, nsUri, tooltip); - mSuperClassName = superClassName; - mPostCreationAction = postCreationAction; - } - - /** - * @return A new {@link UiClassAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiClassAttributeNode(mSuperClassName, mPostCreationAction, - mMandatory, this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java deleted file mode 100644 index 6e589f7..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Describes a 'Instrumentation' class XML attribute. It is displayed by a - * {@link UiClassAttributeNode}, that restricts creation and selection to classes inheriting from - * android.app.Instrumentation. - */ -public class InstrumentationAttributeDescriptor extends TextAttributeDescriptor { - - public InstrumentationAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiClassAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiClassAttributeNode(AndroidConstants.CLASS_INSTRUMENTATION, - null /* postCreationAction */, true /* mandatory */, this, uiParent); - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java deleted file mode 100644 index d89292b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiManifestElementNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * {@link ManifestElementDescriptor} describes an XML element node, with its - * element name, its possible attributes, its possible child elements but also - * its display name and tooltip. - * - * This {@link ElementDescriptor} is specialized to create {@link UiManifestElementNode} UI nodes. - */ -public class ManifestElementDescriptor extends ElementDescriptor { - - /** - * Constructs a new {@link ManifestElementDescriptor}. - * - * @param xml_name The XML element node name. Case sensitive. - * @param ui_name The XML element name for the user interface, typically capitalized. - * @param tooltip An optional tooltip. Can be null or empty. - * @param sdk_url An optional SKD URL. Can be null or empty. - * @param attributes The list of allowed attributes. Can be null or empty. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). - */ - public ManifestElementDescriptor(String xml_name, String ui_name, String tooltip, String sdk_url, - AttributeDescriptor[] attributes, - ElementDescriptor[] children, - boolean mandatory) { - super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory); - } - - /** - * Constructs a new {@link ManifestElementDescriptor}. - * - * @param xml_name The XML element node name. Case sensitive. - * @param ui_name The XML element name for the user interface, typically capitalized. - * @param tooltip An optional tooltip. Can be null or empty. - * @param sdk_url An optional SKD URL. Can be null or empty. - * @param attributes The list of allowed attributes. Can be null or empty. - * @param children The list of allowed children. Can be null or empty. - */ - public ManifestElementDescriptor(String xml_name, String ui_name, String tooltip, String sdk_url, - AttributeDescriptor[] attributes, - ElementDescriptor[] children) { - super(xml_name, ui_name, tooltip, sdk_url, attributes, children, false); - } - - /** - * This is a shortcut for - * ManifestElementDescriptor(xml_name, xml_name.capitalize(), null, null, null, children). - * This constructor is mostly used for unit tests. - * - * @param xml_name The XML element node name. Case sensitive. - */ - public ManifestElementDescriptor(String xml_name, ElementDescriptor[] children) { - super(xml_name, children); - } - - /** - * This is a shortcut for - * ManifestElementDescriptor(xml_name, xml_name.capitalize(), null, null, null, null). - * This constructor is mostly used for unit tests. - * - * @param xml_name The XML element node name. Case sensitive. - */ - public ManifestElementDescriptor(String xml_name) { - super(xml_name, null); - } - - /** - * @return A new {@link UiElementNode} linked to this descriptor. - */ - @Override - public UiElementNode createUiNode() { - return new UiManifestElementNode(this); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java deleted file mode 100644 index 34c5d0d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiPackageAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Describes a package XML attribute. It is displayed by a {@link UiPackageAttributeNode}. - */ -public class PackageAttributeDescriptor extends TextAttributeDescriptor { - - public PackageAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiPackageAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiPackageAttributeNode(this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java deleted file mode 100644 index 3442c24..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode.IPostTypeCreationAction; - -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaModelException; - -/** - * Action to be executed after an Activity class is created. - */ -class PostActivityCreationAction implements IPostTypeCreationAction { - - private final static PostActivityCreationAction sAction = new PostActivityCreationAction(); - - private PostActivityCreationAction() { - // private constructor to enforce singleton. - } - - - /** - * Returns the action. - */ - public static IPostTypeCreationAction getAction() { - return sAction; - } - - /** - * Processes a newly created Activity. - * - */ - public void processNewType(IType newType) { - try { - String methodContent = - " /** Called when the activity is first created. */\n" + - " @Override\n" + - " public void onCreate(Bundle savedInstanceState) {\n" + - " super.onCreate(savedInstanceState);\n" + - "\n" + - " // TODO Auto-generated method stub\n" + - " }"; - newType.createMethod(methodContent, null /* sibling*/, false /* force */, - new NullProgressMonitor()); - - // we need to add the import for Bundle, so we need the compilation unit. - // Since the type could be enclosed in other types, we loop till we find it. - ICompilationUnit compilationUnit = null; - IJavaElement element = newType; - do { - IJavaElement parentElement = element.getParent(); - if (parentElement != null) { - if (parentElement.getElementType() == IJavaElement.COMPILATION_UNIT) { - compilationUnit = (ICompilationUnit)parentElement; - } - - element = parentElement; - } else { - break; - } - } while (compilationUnit == null); - - if (compilationUnit != null) { - compilationUnit.createImport(AndroidConstants.CLASS_BUNDLE, - null /* sibling */, new NullProgressMonitor()); - } - } catch (JavaModelException e) { - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java deleted file mode 100644 index 5a8137d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode.IPostTypeCreationAction; - -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaModelException; - -/** - * Action to be executed after an BroadcastReceiver class is created. - */ -class PostReceiverCreationAction implements IPostTypeCreationAction { - - private final static PostReceiverCreationAction sAction = new PostReceiverCreationAction(); - - private PostReceiverCreationAction() { - // private constructor to enforce singleton. - } - - /** - * Returns the action. - */ - public static IPostTypeCreationAction getAction() { - return sAction; - } - - /** - * Processes a newly created Activity. - * - */ - public void processNewType(IType newType) { - try { - String methodContent = - " @Override\n" + - " public void onReceive(Context context, Intent intent) {\n" + - " // TODO Auto-generated method stub\n" + - " }"; - newType.createMethod(methodContent, null /* sibling*/, false /* force */, - new NullProgressMonitor()); - - // we need to add the import for Bundle, so we need the compilation unit. - // Since the type could be enclosed in other types, we loop till we find it. - ICompilationUnit compilationUnit = null; - IJavaElement element = newType; - do { - IJavaElement parentElement = element.getParent(); - if (parentElement != null) { - if (parentElement.getElementType() == IJavaElement.COMPILATION_UNIT) { - compilationUnit = (ICompilationUnit)parentElement; - } - - element = parentElement; - } else { - break; - } - } while (compilationUnit == null); - - if (compilationUnit != null) { - compilationUnit.createImport(AndroidConstants.CLASS_CONTEXT, - null /* sibling */, new NullProgressMonitor()); - compilationUnit.createImport(AndroidConstants.CLASS_INTENT, - null /* sibling */, new NullProgressMonitor()); - } - } catch (JavaModelException e) { - // looks like the class already existed (this happens when the user check to create - // inherited abstract methods). - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java deleted file mode 100644 index 4219007..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode; - -/** - * Describes a Theme/Style XML attribute displayed by a {@link UiResourceAttributeNode} - */ -public final class ThemeAttributeDescriptor extends TextAttributeDescriptor { - - public ThemeAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiResourceAttributeNode} linked to this theme descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiResourceAttributeNode(ResourceType.STYLE, this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java deleted file mode 100644 index f8aac1d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.model; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; -import com.android.ide.eclipse.common.project.BaseProjectHelper; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.SectionHelper; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeHierarchy; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.search.IJavaSearchScope; -import org.eclipse.jdt.core.search.SearchEngine; -import org.eclipse.jdt.ui.IJavaElementSearchConstants; -import org.eclipse.jdt.ui.JavaUI; -import org.eclipse.jdt.ui.actions.OpenNewClassWizardAction; -import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension; -import org.eclipse.jdt.ui.dialogs.ITypeInfoRequestor; -import org.eclipse.jdt.ui.dialogs.ITypeSelectionComponent; -import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension; -import org.eclipse.jdt.ui.wizards.NewClassWizardPage; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.dialogs.SelectionDialog; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.w3c.dom.Element; - -import java.util.ArrayList; - -/** - * Represents an XML attribute for a class, that can be modified using a simple text field or - * a dialog to choose an existing class. Also, there's a link to create a new class. - * <p/> - * See {@link UiTextAttributeNode} for more information. - */ -public class UiClassAttributeNode extends UiTextAttributeNode { - - private String mReferenceClass; - private IPostTypeCreationAction mPostCreationAction; - private boolean mMandatory; - - private class HierarchyTypeSelection extends TypeSelectionExtension { - - private IJavaProject mJavaProject; - - public HierarchyTypeSelection(IProject project, String referenceClass) { - mJavaProject = JavaCore.create(project); - mReferenceClass = referenceClass; - } - - @Override - public ITypeInfoFilterExtension getFilterExtension() { - return new ITypeInfoFilterExtension() { - public boolean select(ITypeInfoRequestor typeInfoRequestor) { - String packageName = typeInfoRequestor.getPackageName(); - String typeName = typeInfoRequestor.getTypeName(); - String enclosingType = typeInfoRequestor.getEnclosingName(); - - // build the full class name. - StringBuilder sb = new StringBuilder(packageName); - sb.append('.'); - if (enclosingType.length() > 0) { - sb.append(enclosingType); - sb.append('.'); - } - sb.append(typeName); - - String className = sb.toString(); - - try { - IType type = mJavaProject.findType(className); - if (type != null) { - // get the type hierarchy - ITypeHierarchy hierarchy = type.newSupertypeHierarchy( - new NullProgressMonitor()); - - // if the super class is not the reference class, it may inherit from - // it so we get its supertype. At some point it will be null and we - // will return false; - IType superType = type; - while ((superType = hierarchy.getSuperclass(superType)) != null) { - if (mReferenceClass.equals(superType.getFullyQualifiedName())) { - return true; - } - } - } - } catch (JavaModelException e) { - } - - return false; - } - }; - } - } - - /** - * Classes which implement this interface provide a method processing newly created classes. - */ - public static interface IPostTypeCreationAction { - /** - * Sent to process a newly created class. - * @param newType the IType representing the newly created class. - */ - public void processNewType(IType newType); - } - - /** - * Creates a {@link UiClassAttributeNode} object that will display ui to select or create - * classes. - * @param referenceClass The allowed supertype of the classes that are to be selected - * or created. Can be null. - * @param postCreationAction a {@link IPostTypeCreationAction} object handling post creation - * modification of the class. - * @param mandatory indicates if the class value is mandatory - * @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node. - */ - public UiClassAttributeNode(String referenceClass, IPostTypeCreationAction postCreationAction, - boolean mandatory, AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - - mReferenceClass = referenceClass; - mPostCreationAction = postCreationAction; - mMandatory = mandatory; - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public void createUiControl(final Composite parent, IManagedForm managedForm) { - setManagedForm(managedForm); - FormToolkit toolkit = managedForm.getToolkit(); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - - StringBuilder label = new StringBuilder(); - label.append("<form><p><a href='unused'>"); - label.append(desc.getUiName()); - label.append("</a></p></form>"); - FormText formText = SectionHelper.createFormText(parent, toolkit, true /* isHtml */, - label.toString(), true /* setupLayoutData */); - formText.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(HyperlinkEvent e) { - super.linkActivated(e); - handleLabelClick(); - } - }); - formText.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - SectionHelper.addControlTooltip(formText, desc.getTooltip()); - - Composite composite = toolkit.createComposite(parent); - composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE)); - GridLayout gl = new GridLayout(2, false); - gl.marginHeight = gl.marginWidth = 0; - composite.setLayout(gl); - // Fixes missing text borders under GTK... also requires adding a 1-pixel margin - // for the text field below - toolkit.paintBordersFor(composite); - - final Text text = toolkit.createText(composite, getCurrentValue()); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 1; // Needed by the fixed composite borders under GTK - text.setLayoutData(gd); - Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH); - - setTextWidget(text); - - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - handleBrowseClick(); - } - }); - } - - /* (non-java doc) - * - * Add a modify listener that will check the validity of the class - */ - @Override - protected void onAddValidators(final Text text) { - ModifyListener listener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - try { - String textValue = text.getText().trim(); - if (textValue.length() == 0) { - if (mMandatory) { - setErrorMessage("Value is mandatory", text); - } else { - setErrorMessage(null, text); - } - return; - } - // first we need the current java package. - String javaPackage = getManifestPackage(); - - // build the fully qualified name of the class - String className = AndroidManifestHelper.combinePackageAndClassName(javaPackage, - textValue); - - // only test the vilibility for activities. - boolean testVisibility = AndroidConstants.CLASS_ACTIVITY.equals( - mReferenceClass); - - // test the class - setErrorMessage(BaseProjectHelper.testClassForManifest( - BaseProjectHelper.getJavaProject(getProject()), className, - mReferenceClass, testVisibility), text); - } catch (CoreException ce) { - setErrorMessage(ce.getMessage(), text); - } - } - }; - - text.addModifyListener(listener); - - // Make sure the validator removes its message(s) when the widget is disposed - text.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - // we don't want to use setErrorMessage, because we don't want to reset - // the error flag in the UiAttributeNode - getManagedForm().getMessageManager().removeMessage(text, text); - } - }); - - // Finally call the validator once to make sure the initial value is processed - listener.modifyText(null); - } - - private void handleBrowseClick() { - Text text = getTextWidget(); - - // we need to get the project of the manifest. - IProject project = getProject(); - if (project != null) { - - // Create a search scope including only the source folder of the current - // project. - IJavaSearchScope scope = SearchEngine.createJavaSearchScope( - getPackageFragmentRoots(project), false); - - try { - SelectionDialog dlg = JavaUI.createTypeDialog(text.getShell(), - PlatformUI.getWorkbench().getProgressService(), - scope, - IJavaElementSearchConstants.CONSIDER_CLASSES, // style - false, // no multiple selection - "**", //$NON-NLS-1$ //filter - new HierarchyTypeSelection(project, mReferenceClass)); - dlg.setMessage(String.format("Select class name for element %1$s:", - getUiParent().getBreadcrumbTrailDescription(false /* include_root */))); - if (dlg instanceof ITypeSelectionComponent) { - ((ITypeSelectionComponent)dlg).triggerSearch(); - } - - if (dlg.open() == Window.OK) { - Object[] results = dlg.getResult(); - if (results.length == 1) { - handleNewType((IType)results[0]); - } - } - } catch (JavaModelException e1) { - } - } - } - - private void handleLabelClick() { - // get the current value - String className = getTextWidget().getText().trim(); - - // get the package name from the manifest. - String packageName = getManifestPackage(); - - if (className.length() == 0) { - createNewClass(packageName, null /* className */); - } else { - // build back the fully qualified class name. - String fullClassName = className; - if (className.startsWith(".")) { //$NON-NLS-1$ - fullClassName = packageName + className; - } else { - String[] segments = className.split(AndroidConstants.RE_DOT); - if (segments.length == 1) { - fullClassName = packageName + "." + className; //$NON-NLS-1$ - } - } - - // in case the type is enclosed, we need to replace the $ with . - fullClassName = fullClassName.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS2$ - - // now we try to find the file that contains this class and we open it in the editor. - IProject project = getProject(); - IJavaProject javaProject = JavaCore.create(project); - - try { - IType result = javaProject.findType(fullClassName); - if (result != null) { - JavaUI.openInEditor(result); - } else { - // split the last segment from the fullClassname - int index = fullClassName.lastIndexOf('.'); - if (index != -1) { - createNewClass(fullClassName.substring(0, index), - fullClassName.substring(index+1)); - } else { - createNewClass(packageName, className); - } - } - } catch (JavaModelException e) { - } catch (PartInitException e) { - } - } - } - - private IProject getProject() { - UiElementNode uiNode = getUiParent(); - AndroidEditor editor = uiNode.getEditor(); - IEditorInput input = editor.getEditorInput(); - if (input instanceof IFileEditorInput) { - // from the file editor we can get the IFile object, and from it, the IProject. - IFile file = ((IFileEditorInput)input).getFile(); - return file.getProject(); - } - - return null; - } - - - /** - * Returns the current value of the /manifest/package attribute. - * @return the package or an empty string if not found - */ - private String getManifestPackage() { - // get the root uiNode to get the 'package' attribute value. - UiElementNode rootNode = getUiParent().getUiRoot(); - - Element xmlElement = (Element) rootNode.getXmlNode(); - - if (xmlElement != null) { - return xmlElement.getAttribute(AndroidManifestDescriptors.PACKAGE_ATTR); - } - return ""; //$NON-NLS-1$ - } - - - /** - * Computes and return the {@link IPackageFragmentRoot}s corresponding to the source folders of - * the specified project. - * @param project the project - * @return an array of IPackageFragmentRoot. - */ - private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project) { - ArrayList<IPackageFragmentRoot> result = new ArrayList<IPackageFragmentRoot>(); - try { - IJavaProject javaProject = JavaCore.create(project); - IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); - for (int i = 0; i < roots.length; i++) { - IClasspathEntry entry = roots[i].getRawClasspathEntry(); - if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { - result.add(roots[i]); - } - } - } catch (JavaModelException e) { - } - - return result.toArray(new IPackageFragmentRoot[result.size()]); - } - - private void handleNewType(IType type) { - Text text = getTextWidget(); - - // get the fully qualified name with $ to properly detect the enclosing types. - String name = type.getFullyQualifiedName('$'); - - String packageValue = getManifestPackage(); - - // check if the class doesn't start with the package. - if (packageValue.length() > 0 && name.startsWith(packageValue)) { - // if it does, we remove the package and the first dot. - name = name.substring(packageValue.length() + 1); - - // look for how many segments we have left. - // if one, just write it that way. - // if more than one, write it with a leading dot. - String[] packages = name.split(AndroidConstants.RE_DOT); - if (packages.length == 1) { - text.setText(name); - } else { - text.setText("." + name); //$NON-NLS-1$ - } - } else { - text.setText(name); - } - } - - private void createNewClass(String packageName, String className) { - // create the wizard page for the class creation, and configure it - NewClassWizardPage page = new NewClassWizardPage(); - - // set the parent class - page.setSuperClass(mReferenceClass, true /* canBeModified */); - - // get the source folders as java elements. - IPackageFragmentRoot[] roots = getPackageFragmentRoots(getProject()); - - IPackageFragmentRoot currentRoot = null; - IPackageFragment currentFragment = null; - int packageMatchCount = -1; - - for (IPackageFragmentRoot root : roots) { - // Get the java element for the package. - // This method is said to always return a IPackageFragment even if the - // underlying folder doesn't exist... - IPackageFragment fragment = root.getPackageFragment(packageName); - if (fragment != null && fragment.exists()) { - // we have a perfect match! we use it. - currentRoot = root; - currentFragment = fragment; - packageMatchCount = -1; - break; - } else { - // we don't have a match. we look for the fragment with the best match - // (ie the closest parent package we can find) - try { - IJavaElement[] children; - children = root.getChildren(); - for (IJavaElement child : children) { - if (child instanceof IPackageFragment) { - fragment = (IPackageFragment)child; - if (packageName.startsWith(fragment.getElementName())) { - // its a match. get the number of segments - String[] segments = fragment.getElementName().split("\\."); //$NON-NLS-1$ - if (segments.length > packageMatchCount) { - packageMatchCount = segments.length; - currentFragment = fragment; - currentRoot = root; - } - } - } - } - } catch (JavaModelException e) { - // Couldn't get the children: we just ignore this package root. - } - } - } - - ArrayList<IPackageFragment> createdFragments = null; - - if (currentRoot != null) { - // if we have a perfect match, we set it and we're done. - if (packageMatchCount == -1) { - page.setPackageFragmentRoot(currentRoot, true /* canBeModified*/); - page.setPackageFragment(currentFragment, true /* canBeModified */); - } else { - // we have a partial match. - // create the package. We have to start with the first segment so that we - // know what to delete in case of a cancel. - try { - createdFragments = new ArrayList<IPackageFragment>(); - - int totalCount = packageName.split("\\.").length; //$NON-NLS-1$ - int count = 0; - int index = -1; - // skip the matching packages - while (count < packageMatchCount) { - index = packageName.indexOf('.', index+1); - count++; - } - - // create the rest of the segments, except for the last one as indexOf will - // return -1; - while (count < totalCount - 1) { - index = packageName.indexOf('.', index+1); - count++; - createdFragments.add(currentRoot.createPackageFragment( - packageName.substring(0, index), - true /* force*/, new NullProgressMonitor())); - } - - // create the last package - createdFragments.add(currentRoot.createPackageFragment( - packageName, true /* force*/, new NullProgressMonitor())); - - // set the root and fragment in the Wizard page - page.setPackageFragmentRoot(currentRoot, true /* canBeModified*/); - page.setPackageFragment(createdFragments.get(createdFragments.size()-1), - true /* canBeModified */); - } catch (JavaModelException e) { - // if we can't create the packages, there's a problem. we revert to the default - // package - for (IPackageFragmentRoot root : roots) { - // Get the java element for the package. - // This method is said to always return a IPackageFragment even if the - // underlying folder doesn't exist... - IPackageFragment fragment = root.getPackageFragment(packageName); - if (fragment != null && fragment.exists()) { - page.setPackageFragmentRoot(root, true /* canBeModified*/); - page.setPackageFragment(fragment, true /* canBeModified */); - break; - } - } - } - } - } else if (roots.length > 0) { - // if we haven't found a valid fragment, we set the root to the first source folder. - page.setPackageFragmentRoot(roots[0], true /* canBeModified*/); - } - - // if we have a starting class name we use it - if (className != null) { - page.setTypeName(className, true /* canBeModified*/); - } - - // create the action that will open it the wizard. - OpenNewClassWizardAction action = new OpenNewClassWizardAction(); - action.setConfiguredWizardPage(page); - action.run(); - IJavaElement element = action.getCreatedElement(); - - if (element != null) { - if (element.getElementType() == IJavaElement.TYPE) { - - IType type = (IType)element; - - if (mPostCreationAction != null) { - mPostCreationAction.processNewType(type); - } - - handleNewType(type); - } - } else { - // lets delete the packages we created just for this. - // we need to start with the leaf and go up - if (createdFragments != null) { - try { - for (int i = createdFragments.size() - 1 ; i >= 0 ; i--) { - createdFragments.get(i).delete(true /* force*/, new NullProgressMonitor()); - } - } catch (JavaModelException e) { - e.printStackTrace(); - } - } - } - } - - /** - * Sets the error messages. If message is <code>null</code>, the message is removed. - * @param message the message to set, or <code>null</code> to remove the current message - * @param textWidget the {@link Text} widget associated to the message. - */ - private final void setErrorMessage(String message, Text textWidget) { - if (message != null) { - setHasError(true); - getManagedForm().getMessageManager().addMessage(textWidget, message, null /* data */, - IMessageProvider.ERROR, textWidget); - } else { - setHasError(false); - getManagedForm().getMessageManager().removeMessage(textWidget, textWidget); - } - } - - @Override - public String[] getPossibleValues() { - // TODO: compute a list of existing classes for content assist completion - return null; - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java deleted file mode 100644 index 10ce50d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.model; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.manifest.descriptors.ManifestElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.w3c.dom.Element; - -/** - * Represents an XML node that can be modified by the user interface in the XML editor. - * <p/> - * Each tree viewer used in the application page's parts needs to keep a model representing - * each underlying node in the tree. This interface represents the base type for such a node. - * <p/> - * Each node acts as an intermediary model between the actual XML model (the real data support) - * and the tree viewers or the corresponding page parts. - * <p/> - * Element nodes don't contain data per se. Their data is contained in their attributes - * as well as their children's attributes, see {@link UiAttributeNode}. - * <p/> - * The structure of a given {@link UiElementNode} is declared by a corresponding - * {@link ElementDescriptor}. - */ -public final class UiManifestElementNode extends UiElementNode { - - /** - * Creates a new {@link UiElementNode} described by a given {@link ElementDescriptor}. - * - * @param elementDescriptor The {@link ElementDescriptor} for the XML node. Cannot be null. - */ - public UiManifestElementNode(ManifestElementDescriptor elementDescriptor) { - super(elementDescriptor); - } - - /** - * Computes a short string describing the UI node suitable for tree views. - * Uses the element's attribute "android:name" if present, or the "android:label" one - * followed by the element's name. - * - * @return A short string describing the UI node suitable for tree views. - */ - @Override - public String getShortDescription() { - if (getXmlNode() != null && - getXmlNode() instanceof Element && - getXmlNode().hasAttributes()) { - - // Application and Manifest nodes have a special treatment: they are unique nodes - // so we don't bother trying to differentiate their strings and we fall back to - // just using the UI name below. - ElementDescriptor desc = getDescriptor(); - if (desc != AndroidManifestDescriptors.MANIFEST_ELEMENT && - desc != AndroidManifestDescriptors.APPLICATION_ELEMENT) { - Element elem = (Element) getXmlNode(); - String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, - AndroidManifestDescriptors.ANDROID_NAME_ATTR); - if (attr == null || attr.length() == 0) { - attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, - AndroidManifestDescriptors.ANDROID_LABEL_ATTR); - } - if (attr != null && attr.length() > 0) { - return String.format("%1$s (%2$s)", attr, getDescriptor().getUiName()); - } - } - } - - return String.format("%1$s", getDescriptor().getUiName()); - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java deleted file mode 100644 index 5e02273..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.model; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.ui.JavaUI; -import org.eclipse.jdt.ui.actions.OpenNewPackageWizardAction; -import org.eclipse.jdt.ui.actions.ShowInPackageViewAction; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.dialogs.SelectionDialog; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; - -import java.util.ArrayList; - -/** - * Represents an XML attribute for a package, that can be modified using a simple text field or - * a dialog to choose an existing package. Also, there's a link to create a new package. - * <p/> - * See {@link UiTextAttributeNode} for more information. - */ -public class UiPackageAttributeNode extends UiTextAttributeNode { - - /** - * Creates a {@link UiPackageAttributeNode} object that will display ui to select or create - * a package. - * @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node. - */ - public UiPackageAttributeNode(AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public void createUiControl(final Composite parent, final IManagedForm managedForm) { - setManagedForm(managedForm); - FormToolkit toolkit = managedForm.getToolkit(); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - - StringBuilder label = new StringBuilder(); - label.append("<form><p><a href='unused'>"); //$NON-NLS-1$ - label.append(desc.getUiName()); - label.append("</a></p></form>"); //$NON-NLS-1$ - FormText formText = SectionHelper.createFormText(parent, toolkit, true /* isHtml */, - label.toString(), true /* setupLayoutData */); - formText.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(HyperlinkEvent e) { - super.linkActivated(e); - doLabelClick(); - } - }); - formText.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - SectionHelper.addControlTooltip(formText, desc.getTooltip()); - - Composite composite = toolkit.createComposite(parent); - composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE)); - GridLayout gl = new GridLayout(2, false); - gl.marginHeight = gl.marginWidth = 0; - composite.setLayout(gl); - // Fixes missing text borders under GTK... also requires adding a 1-pixel margin - // for the text field below - toolkit.paintBordersFor(composite); - - final Text text = toolkit.createText(composite, getCurrentValue()); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 1; // Needed by the fixed composite borders under GTK - text.setLayoutData(gd); - - setTextWidget(text); - - Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH); - - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doBrowseClick(); - } - }); - - } - - /* (non-java doc) - * Adds a validator to the text field that calls managedForm.getMessageManager(). - */ - @Override - protected void onAddValidators(final Text text) { - ModifyListener listener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - String package_name = text.getText(); - if (package_name.indexOf('.') < 1) { - getManagedForm().getMessageManager().addMessage(text, - "Package name should contain at least two identifiers.", - null /* data */, IMessageProvider.ERROR, text); - } else { - getManagedForm().getMessageManager().removeMessage(text, text); - } - } - }; - - text.addModifyListener(listener); - - // Make sure the validator removes its message(s) when the widget is disposed - text.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - getManagedForm().getMessageManager().removeMessage(text, text); - } - }); - - // Finally call the validator once to make sure the initial value is processed - listener.modifyText(null); - } - - /** - * Handles response to the Browse button by creating a Package dialog. - * */ - private void doBrowseClick() { - Text text = getTextWidget(); - - // we need to get the project of the manifest. - IProject project = getProject(); - if (project != null) { - - try { - SelectionDialog dlg = JavaUI.createPackageDialog(text.getShell(), - JavaCore.create(project), 0); - dlg.setTitle("Select Android Package"); - dlg.setMessage("Select the package for the Android project."); - dlg.setDefaultImage(EditorsPlugin.getAndroidLogo()); - - if (dlg.open() == Window.OK) { - Object[] results = dlg.getResult(); - if (results.length == 1) { - setPackageTextField((IPackageFragment)results[0]); - } - } - } catch (JavaModelException e1) { - } - } - } - - /** - * Handles response to the Label hyper link being activated. - */ - private void doLabelClick() { - // get the current package name - String package_name = getTextWidget().getText().trim(); - - if (package_name.length() == 0) { - createNewPackage(); - } else { - // Try to select the package in the Package Explorer for the current - // project and the current editor's site. - - IProject project = getProject(); - if (project == null) { - EditorsPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$ - return; - } - - IWorkbenchPartSite site = getUiParent().getEditor().getSite(); - if (site == null) { - EditorsPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$ - return; - } - - for (IPackageFragmentRoot root : getPackageFragmentRoots(project)) { - IPackageFragment fragment = root.getPackageFragment(package_name); - if (fragment != null && fragment.exists()) { - ShowInPackageViewAction action = new ShowInPackageViewAction(site); - action.run(fragment); - // This action's run() doesn't provide the status (although internally it could) - // so we just assume it worked. - return; - } - } - } - } - - /** - * Utility method that returns the project for the current file being edited. - * - * @return The IProject for the current file being edited or null. - */ - private IProject getProject() { - UiElementNode uiNode = getUiParent(); - AndroidEditor editor = uiNode.getEditor(); - IEditorInput input = editor.getEditorInput(); - if (input instanceof IFileEditorInput) { - // from the file editor we can get the IFile object, and from it, the IProject. - IFile file = ((IFileEditorInput)input).getFile(); - return file.getProject(); - } - - return null; - } - - /** - * Utility method that computes and returns the list of {@link IPackageFragmentRoot} - * corresponding to the source folder of the specified project. - * - * @param project the project - * @return an array of IPackageFragmentRoot. Can be empty but not null. - */ - private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project) { - ArrayList<IPackageFragmentRoot> result = new ArrayList<IPackageFragmentRoot>(); - try { - IJavaProject javaProject = JavaCore.create(project); - IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); - for (int i = 0; i < roots.length; i++) { - IClasspathEntry entry = roots[i].getRawClasspathEntry(); - if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { - result.add(roots[i]); - } - } - } catch (JavaModelException e) { - } - - return result.toArray(new IPackageFragmentRoot[result.size()]); - } - - /** - * Utility method that sets the package's text field to the package fragment's name. - * */ - private void setPackageTextField(IPackageFragment type) { - Text text = getTextWidget(); - - String name = type.getElementName(); - - text.setText(name); - } - - - /** - * Displays and handles a "Create Package Wizard". - * - * This is invoked by doLabelClick() when clicking on the hyperlink label with an - * empty package text field. - */ - private void createNewPackage() { - OpenNewPackageWizardAction action = new OpenNewPackageWizardAction(); - - IProject project = getProject(); - action.setSelection(new StructuredSelection(project)); - action.run(); - - IJavaElement element = action.getCreatedElement(); - if (element != null && - element.exists() && - element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { - setPackageTextField((IPackageFragment) element); - } - } - - @Override - public String[] getPossibleValues() { - // TODO: compute a list of existing packages for content assist completion - return null; - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java deleted file mode 100644 index 25bdb0e..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.ui.UiElementPart; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -/** - * Application's attributes section part for Application page. - * <p/> - * This part is displayed at the top of the application page and displays all the possible - * attributes of an application node in the AndroidManifest (icon, class name, label, etc.) - */ -final class ApplicationAttributesPart extends UiElementPart { - - /** Listen to changes to the UI node for <application> and updates the UI */ - private AppNodeUpdateListener mAppNodeUpdateListener; - /** ManagedForm needed to create the UI controls */ - private IManagedForm mManagedForm; - - public ApplicationAttributesPart(Composite body, FormToolkit toolkit, ManifestEditor editor, - UiElementNode applicationUiNode) { - super(body, toolkit, editor, applicationUiNode, - "Application Attributes", // section title - "Defines the attributes specific to the application.", // section description - Section.TWISTIE | Section.EXPANDED); - } - - /** - * Changes and refreshes the Application UI node handle by the this part. - */ - @Override - public void setUiElementNode(UiElementNode uiElementNode) { - super.setUiElementNode(uiElementNode); - - createUiAttributes(mManagedForm); - } - - /* (non-java doc) - * Create the controls to edit the attributes for the given ElementDescriptor. - * <p/> - * This MUST not be called by the constructor. Instead it must be called from - * <code>initialize</code> (i.e. right after the form part is added to the managed form.) - * <p/> - * Derived classes can override this if necessary. - * - * @param managedForm The owner managed form - */ - @Override - protected void createFormControls(final IManagedForm managedForm) { - mManagedForm = managedForm; - setTable(createTableLayout(managedForm.getToolkit(), 4 /* numColumns */)); - - mAppNodeUpdateListener = new AppNodeUpdateListener(); - getUiElementNode().addUpdateListener(mAppNodeUpdateListener); - - createUiAttributes(mManagedForm); - } - - @Override - public void dispose() { - super.dispose(); - if (getUiElementNode() != null && mAppNodeUpdateListener != null) { - getUiElementNode().removeUpdateListener(mAppNodeUpdateListener); - mAppNodeUpdateListener = null; - } - } - - @Override - protected void createUiAttributes(IManagedForm managedForm) { - Composite table = getTable(); - if (table == null || managedForm == null) { - return; - } - - // Remove any old UI controls - for (Control c : table.getChildren()) { - c.dispose(); - } - - UiElementNode uiElementNode = getUiElementNode(); - AttributeDescriptor[] attr_desc_list = uiElementNode.getAttributeDescriptors(); - - // Display the attributes in 2 columns: - // attr 0 | attr 4 - // attr 1 | attr 5 - // attr 2 | attr 6 - // attr 3 | attr 7 - // that is we have to fill the grid in order 0, 4, 1, 5, 2, 6, 3, 7 - // thus index = i/2 + (i is odd * n/2) - int n = attr_desc_list.length; - int n2 = (int) Math.ceil(n / 2.0); - for (int i = 0; i < n; i++) { - AttributeDescriptor attr_desc = attr_desc_list[i / 2 + (i & 1) * n2]; - if (attr_desc instanceof XmlnsAttributeDescriptor) { - // Do not show hidden attributes - continue; - } - - UiAttributeNode ui_attr = uiElementNode.findUiAttribute(attr_desc); - if (ui_attr != null) { - ui_attr.createUiControl(table, managedForm); - } else { - // The XML has an extra attribute which wasn't declared in - // AndroidManifestDescriptors. This is not a problem, we just ignore it. - EditorsPlugin.log(IStatus.WARNING, - "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$ - attr_desc.getXmlLocalName(), - uiElementNode.getDescriptor().getXmlName()); - } - } - - if (n == 0) { - createLabel(table, managedForm.getToolkit(), - "No attributes to display, waiting for SDK to finish loading...", - null /* tooltip */ ); - } - - // Initialize the enabled/disabled state - if (mAppNodeUpdateListener != null) { - mAppNodeUpdateListener.uiElementNodeUpdated(uiElementNode, null /* state, not used */); - } - - // Tell the section that the layout has changed. - layoutChanged(); - } - - /** - * This listener synchronizes the UI with the actual presence of the application XML node. - */ - private class AppNodeUpdateListener implements IUiUpdateListener { - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - // The UiElementNode for the application XML node always exists, even - // if there is no corresponding XML node in the XML file. - // - // We enable the UI here if the XML node is not null. - Composite table = getTable(); - boolean exists = (ui_node.getXmlNode() != null); - if (table != null && table.getEnabled() != exists) { - table.setEnabled(exists); - for (Control c : table.getChildren()) { - c.setEnabled(exists); - } - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java deleted file mode 100644 index 1823278..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.ScrolledForm; - - -/** - * Page for "Application" settings, part of the AndroidManifest form editor. - * <p/> - * Useful reference: - * <a href="http://www.eclipse.org/articles/Article-Forms/article.html"> - * http://www.eclipse.org/articles/Article-Forms/article.html</a> - */ -public final class ApplicationPage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "application_page"; //$NON-NLS-1$ - - /** Container editor */ - ManifestEditor mEditor; - /** The Application Toogle part */ - private ApplicationToggle mTooglePart; - /** The Application Attributes part */ - private ApplicationAttributesPart mAttrPart; - /** The tree view block */ - private UiTreeBlock mTreeBlock; - - public ApplicationPage(ManifestEditor editor) { - super(editor, PAGE_ID, "Application"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Manifest Application"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode appUiNode = getUiApplicationNode(); - - Composite body = form.getBody(); - FormToolkit toolkit = managedForm.getToolkit(); - - // We usually prefer to have a ColumnLayout here. However - // MasterDetailsBlock.createContent() below will reset the body's layout to a grid layout. - mTooglePart = new ApplicationToggle(body, toolkit, mEditor, appUiNode); - mTooglePart.getSection().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - managedForm.addPart(mTooglePart); - mAttrPart = new ApplicationAttributesPart(body, toolkit, mEditor, appUiNode); - mAttrPart.getSection().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - managedForm.addPart(mAttrPart); - - mTreeBlock = new UiTreeBlock(mEditor, appUiNode, - false /* autoCreateRoot */, - null /* element filters */, - "Application Nodes", - "List of all elements in the application"); - mTreeBlock.createContent(managedForm); - } - - /** - * Retrieves the application UI node. Since this is a mandatory node, it *always* - * exists, even if there is no matching XML node. - */ - private UiElementNode getUiApplicationNode() { - ElementDescriptor desc = AndroidManifestDescriptors.APPLICATION_ELEMENT; - return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName()); - } - - /** - * Changes and refreshes the Application UI node handled by the sub parts. - */ - public void refreshUiApplicationNode() { - UiElementNode appUiNode = getUiApplicationNode(); - if (mTooglePart != null) { - mTooglePart.setUiElementNode(appUiNode); - } - if (mAttrPart != null) { - mAttrPart.setUiElementNode(appUiNode); - } - if (mTreeBlock != null) { - mTreeBlock.changeRootAndDescriptors(appUiNode, - null /* element filters */, - true /* refresh */); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java deleted file mode 100644 index daec98c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.ui.UiElementPart; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.Text; - -/** - * Appllication Toogle section part for application page. - */ -final class ApplicationToggle extends UiElementPart { - - /** Checkbox indicating whether an application node is present */ - private Button mCheckbox; - /** Listen to changes to the UI node for <application> and updates the checkbox */ - private AppNodeUpdateListener mAppNodeUpdateListener; - /** Internal flag to know where we're programmatically modifying the checkbox and we want to - * avoid triggering the checkbox's callback. */ - public boolean mInternalModification; - private FormText mTooltipFormText; - - public ApplicationToggle(Composite body, FormToolkit toolkit, ManifestEditor editor, - UiElementNode applicationUiNode) { - super(body, toolkit, editor, applicationUiNode, - "Application Toggle", - null, /* description */ - Section.TWISTIE | Section.EXPANDED); - } - - @Override - public void dispose() { - super.dispose(); - if (getUiElementNode() != null && mAppNodeUpdateListener != null) { - getUiElementNode().removeUpdateListener(mAppNodeUpdateListener); - mAppNodeUpdateListener = null; - } - } - - /** - * Changes and refreshes the Application UI node handle by the this part. - */ - @Override - public void setUiElementNode(UiElementNode uiElementNode) { - super.setUiElementNode(uiElementNode); - - updateTooltip(); - - // Set the state of the checkbox - mAppNodeUpdateListener.uiElementNodeUpdated(getUiElementNode(), - UiUpdateState.CHILDREN_CHANGED); - } - - /** - * Create the controls to edit the attributes for the given ElementDescriptor. - * <p/> - * This MUST not be called by the constructor. Instead it must be called from - * <code>initialize</code> (i.e. right after the form part is added to the managed form.) - * - * @param managedForm The owner managed form - */ - @Override - protected void createFormControls(IManagedForm managedForm) { - FormToolkit toolkit = managedForm.getToolkit(); - Composite table = createTableLayout(toolkit, 1 /* numColumns */); - - mTooltipFormText = createFormText(table, toolkit, true, "<form></form>", - false /* setupLayoutData */); - updateTooltip(); - - mCheckbox = toolkit.createButton(table, - "Define an <application> tag in the AndroidManifest.xml", - SWT.CHECK); - mCheckbox.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); - mCheckbox.setSelection(false); - mCheckbox.addSelectionListener(new CheckboxSelectionListener()); - - mAppNodeUpdateListener = new AppNodeUpdateListener(); - getUiElementNode().addUpdateListener(mAppNodeUpdateListener); - - // Initialize the state of the checkbox - mAppNodeUpdateListener.uiElementNodeUpdated(getUiElementNode(), - UiUpdateState.CHILDREN_CHANGED); - - // Tell the section that the layout has changed. - layoutChanged(); - } - - /** - * Updates the application tooltip in the form text. - * If there is no tooltip, the form text is hidden. - */ - private void updateTooltip() { - boolean isVisible = false; - - String tooltip = getUiElementNode().getDescriptor().getTooltip(); - if (tooltip != null) { - tooltip = DescriptorsUtils.formatFormText(tooltip, - getUiElementNode().getDescriptor(), - FrameworkResourceManager.getInstance().getDocumentationBaseUrl()); - - mTooltipFormText.setText(tooltip, true /* parseTags */, true /* expandURLs */); - mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, EditorsPlugin.getAndroidLogo()); - mTooltipFormText.addHyperlinkListener(getEditor().createHyperlinkListener()); - isVisible = true; - } - - mTooltipFormText.setVisible(isVisible); - } - - /** - * This listener synchronizes the XML application node when the checkbox - * is changed by the user. - */ - private class CheckboxSelectionListener extends SelectionAdapter { - private Node mUndoXmlNode; - private Node mUndoXmlParent; - private Node mUndoXmlNextNode; - private Node mUndoXmlNextElement; - private Document mUndoXmlDocument; - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - if (!mInternalModification && getUiElementNode() != null) { - getUiElementNode().getEditor().editXmlModel(new Runnable() { - public void run() { - if (mCheckbox.getSelection()) { - // The user wants an <application> node. Either restore a previous one - // or create a full new one. - boolean create = true; - if (mUndoXmlNode != null) { - create = !restoreApplicationNode(); - } - if (create) { - getUiElementNode().createXmlNode(); - } - } else { - // Users no longer wants the <application> node. - removeApplicationNode(); - } - } - }); - } - } - - /** - * Restore a previously "saved" application node. - * - * @return True if the node could be restored, false otherwise. - */ - private boolean restoreApplicationNode() { - if (mUndoXmlDocument == null || mUndoXmlNode == null) { - return false; - } - - // Validate node references... - mUndoXmlParent = validateNode(mUndoXmlDocument, mUndoXmlParent); - mUndoXmlNextNode = validateNode(mUndoXmlDocument, mUndoXmlNextNode); - mUndoXmlNextElement = validateNode(mUndoXmlDocument, mUndoXmlNextElement); - - if (mUndoXmlParent == null){ - // If the parent node doesn't exist, try to find a new manifest node. - // If it doesn't exist, create it. - mUndoXmlParent = getUiElementNode().getUiParent().prepareCommit(); - mUndoXmlNextNode = null; - mUndoXmlNextElement = null; - } - - boolean success = false; - if (mUndoXmlParent != null) { - // If the parent is still around, reuse the same node. - - // Ideally we want to insert the node before what used to be its next sibling. - // If that's not possible, we try to insert it before its next sibling element. - // If that's not possible either, it will be inserted at the end of the parent's. - Node next = mUndoXmlNextNode; - if (next == null) { - next = mUndoXmlNextElement; - } - mUndoXmlParent.insertBefore(mUndoXmlNode, next); - if (next == null) { - Text sep = mUndoXmlDocument.createTextNode("\n"); //$NON-NLS-1$ - mUndoXmlParent.insertBefore(sep, null); // insert separator before end tag - } - success = true; - } - - // Remove internal references to avoid using them twice - mUndoXmlParent = null; - mUndoXmlNextNode = null; - mUndoXmlNextElement = null; - mUndoXmlNode = null; - mUndoXmlDocument = null; - return success; - } - - /** - * Validates that the given xml_node is still either the root node or one of its - * direct descendants. - * - * @param root_node The root of the node hierarchy to examine. - * @param xml_node The XML node to find. - * @return Returns xml_node if it is, otherwise returns null. - */ - private Node validateNode(Node root_node, Node xml_node) { - if (root_node == xml_node) { - return xml_node; - } else { - for (Node node = root_node.getFirstChild(); node != null; - node = node.getNextSibling()) { - if (root_node == xml_node || validateNode(node, xml_node) != null) { - return xml_node; - } - } - } - return null; - } - - /** - * Removes the <application> node from the hierarchy. - * Before doing that, we try to remember where it was so that we can put it back - * in the same place. - */ - private void removeApplicationNode() { - // Make sure the node actually exists... - Node xml_node = getUiElementNode().getXmlNode(); - if (xml_node == null) { - return; - } - - // Save its parent, next sibling and next element - mUndoXmlDocument = xml_node.getOwnerDocument(); - mUndoXmlParent = xml_node.getParentNode(); - mUndoXmlNextNode = xml_node.getNextSibling(); - mUndoXmlNextElement = mUndoXmlNextNode; - while (mUndoXmlNextElement != null && - mUndoXmlNextElement.getNodeType() != Node.ELEMENT_NODE) { - mUndoXmlNextElement = mUndoXmlNextElement.getNextSibling(); - } - - // Actually remove the node from the hierarchy and keep it here. - // The returned node looses its parents/siblings pointers. - mUndoXmlNode = getUiElementNode().deleteXmlNode(); - } - } - - /** - * This listener synchronizes the UI (i.e. the checkbox) with the - * actual presence of the application XML node. - */ - private class AppNodeUpdateListener implements IUiUpdateListener { - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - // The UiElementNode for the application XML node always exists, even - // if there is no corresponding XML node in the XML file. - // - // To update the checkbox to reflect the actual state, we just need - // to check if the XML node is null. - try { - mInternalModification = true; - boolean exists = ui_node.getXmlNode() != null; - if (mCheckbox.getSelection() != exists) { - mCheckbox.setSelection(exists); - } - } finally { - mInternalModification = false; - } - - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java deleted file mode 100644 index 8eb6765..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Page for instrumentation settings, part of the AndroidManifest form editor. - */ -public final class InstrumentationPage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "instrumentation_page"; //$NON-NLS-1$ - - /** Container editor */ - ManifestEditor mEditor; - - public InstrumentationPage(ManifestEditor editor) { - super(editor, PAGE_ID, "Instrumentation"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Manifest Instrumentation"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode manifest = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, manifest, - true /* autoCreateRoot */, - new ElementDescriptor[] { AndroidManifestDescriptors.INTRUMENTATION_ELEMENT }, - "Instrumentation", - "List of instrumentations defined in the manifest"); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java deleted file mode 100644 index 4e6521c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.common.project.ExportHelper; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.part.FileEditorInput; - -/** - * Export section part for overview page. - */ -final class OverviewExportPart extends ManifestSectionPart { - - private final OverviewPage mOverviewPage; - - public OverviewExportPart(OverviewPage overviewPage, Composite body, FormToolkit toolkit, ManifestEditor editor) { - super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */); - mOverviewPage = overviewPage; - Section section = getSection(); - section.setText("Exporting"); - section.setDescription("To export the application for distribution, you have the following options:"); - - Composite table = createTableLayout(toolkit, 2 /* numColumns */); - - StringBuffer buf = new StringBuffer(); - buf.append("<form><li><a href=\"wizard\">"); //$NON-NLS-1$ - buf.append("Use the export wizard"); - buf.append("</a></li><li><a href=\"manual\">"); //$NON-NLS-1$ - buf.append("Export an unsigned apk"); - buf.append("</a>"); //$NON-NLS-1$ - buf.append(" and sign it manually"); - buf.append("</li></form>"); //$NON-NLS-1$ - - FormText text = createFormText(table, toolkit, true, buf.toString(), - false /* setupLayoutData */); - text.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(HyperlinkEvent e) { - // get the project from the editor - IEditorInput input = mOverviewPage.mEditor.getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - IFile file = fileInput.getFile(); - IProject project = file.getProject(); - - if ("manual".equals(e.data)) { //$NON-NLS-1$ - // now we can export an unsigned apk for the project. - ExportHelper.exportProject(project); - } else { - // call the export wizard - ExportHelper.startExportWizard(project); - } - } - } - }); - - layoutChanged(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java deleted file mode 100644 index 182c6f3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.UiElementPart; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; -import org.w3c.dom.Node; - -/** - * Generic info section part for overview page - */ -final class OverviewInfoPart extends UiElementPart { - - private IManagedForm mManagedForm; - - public OverviewInfoPart(Composite body, FormToolkit toolkit, ManifestEditor editor) { - super(body, toolkit, editor, - null, // uiElementNode - "General Information", // section title - "Defines general information about the AndroidManifest.xml", // section description - Section.TWISTIE | Section.EXPANDED); - } - - /** - * Retrieves the UiElementNode that this part will edit. The node must exist - * and can't be null, by design, because it's a mandatory node. - */ - private static UiElementNode getManifestUiNode(ManifestEditor editor) { - ElementDescriptor desc = AndroidManifestDescriptors.MANIFEST_ELEMENT; - if (editor.getUiRootNode().getDescriptor() == desc) { - return editor.getUiRootNode(); - } else { - return editor.getUiRootNode().findUiChildNode(desc.getXmlName()); - } - } - - /** - * Retrieves the uses-sdk UI node. Since this is a mandatory node, it *always* - * exists, even if there is no matching XML node. - */ - private UiElementNode getUsesSdkUiNode(ManifestEditor editor) { - ElementDescriptor desc = AndroidManifestDescriptors.USES_SDK_ELEMENT; - return editor.getUiRootNode().findUiChildNode(desc.getXmlName()); - } - - /** - * Overridden in order to capture the current managed form. - * - * {@inheritDoc} - */ - @Override - protected void createFormControls(final IManagedForm managedForm) { - mManagedForm = managedForm; - super.createFormControls(managedForm); - } - - /** - * Removes any existing Attribute UI widgets and recreate them if the SDK has changed. - * <p/> - * This is called by {@link OverviewPage#refreshUiApplicationNode()} when the - * SDK has changed. - */ - public void onSdkChanged() { - createUiAttributes(mManagedForm); - } - - /** - * Overridden to add the description and the ui attributes of both the - * manifest and uses-sdk UI nodes. - * <p/> - * {@inheritDoc} - */ - @Override - protected void fillTable(Composite table, IManagedForm managedForm) { - int n = 0; - - UiElementNode uiNode = getManifestUiNode(getEditor()); - n += insertUiAttributes(uiNode, table, managedForm); - - uiNode = getUsesSdkUiNode(getEditor()); - n += insertUiAttributes(uiNode, table, managedForm); - - if (n == 0) { - createLabel(table, managedForm.getToolkit(), - "No attributes to display, waiting for SDK to finish loading...", - null /* tooltip */ ); - } - - layoutChanged(); - } - - /** - * Overridden to tests whether either the manifest or uses-sdk nodes parts are dirty. - * <p/> - * {@inheritDoc} - * - * @return <code>true</code> if the part is dirty, <code>false</code> - * otherwise. - */ - @Override - public boolean isDirty() { - boolean dirty = super.isDirty(); - - if (!dirty) { - UiElementNode uiNode = getManifestUiNode(getEditor()); - if (uiNode != null) { - for (UiAttributeNode ui_attr : uiNode.getUiAttributes()) { - if (ui_attr.isDirty()) { - markDirty(); - dirty = true; - break; - } - } - } - } - - if (!dirty) { - UiElementNode uiNode = getUsesSdkUiNode(getEditor()); - if (uiNode != null) { - for (UiAttributeNode ui_attr : uiNode.getUiAttributes()) { - if (ui_attr.isDirty()) { - markDirty(); - dirty = true; - break; - } - } - } - } - - return dirty; - } - - /** - * Overridden to save both the manifest or uses-sdk nodes. - * <p/> - * {@inheritDoc} - */ - @Override - public void commit(boolean onSave) { - final UiElementNode manifestUiNode = getManifestUiNode(getEditor()); - final UiElementNode usesSdkUiNode = getUsesSdkUiNode(getEditor()); - - getEditor().editXmlModel(new Runnable() { - public void run() { - if (manifestUiNode != null && manifestUiNode.isDirty()) { - for (UiAttributeNode ui_attr : manifestUiNode.getUiAttributes()) { - ui_attr.commit(); - } - } - - if (usesSdkUiNode != null && usesSdkUiNode.isDirty()) { - for (UiAttributeNode ui_attr : usesSdkUiNode.getUiAttributes()) { - ui_attr.commit(); - } - - if (!usesSdkUiNode.isDirty()) { - // Remove the <uses-sdk> XML element if it is empty. - // Rather than rely on the internal UI state, actually check that the - // XML element has no attributes and no child element so that we don't - // trash some user-generated content. - Node element = usesSdkUiNode.prepareCommit(); - if (element != null && - !element.hasAttributes() && - !element.hasChildNodes()) { - // Important note: we MUST NOT use usesSdkUiNode.deleteXmlNode() - // here, as it would clear the UiAttribute list and thus break the - // link between the controls and the ui attribute field. - // Instead what we want is simply to remove the XML node and let the - // UiElementNode node know. - Node parent = element.getParentNode(); - if (parent != null) { - parent.removeChild(element); - usesSdkUiNode.loadFromXmlNode(null /*xml_node*/); - } - } - } - } - } - }); - - // We need to call super's commit after we synchronized the nodes to make sure we - // reset the dirty flag after all the side effects from committing have occurred. - super.commit(onSave); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java deleted file mode 100644 index 7675fa2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -/** - * Links section part for overview page. - */ -final class OverviewLinksPart extends ManifestSectionPart { - - public OverviewLinksPart(Composite body, FormToolkit toolkit, ManifestEditor editor) { - super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */); - Section section = getSection(); - section.setText("Links"); - section.setDescription("The content of the Android Manifest is made up of three sections. You can also edit the XML directly."); - - Composite table = createTableLayout(toolkit, 2 /* numColumns */); - - StringBuffer buf = new StringBuffer(); - buf.append(String.format("<form><li style=\"image\" value=\"app_img\"><a href=\"page:%1$s\">", // $NON-NLS-1$ - ApplicationPage.PAGE_ID)); - buf.append("Application"); - buf.append("</a>"); //$NON-NLS-1$ - buf.append(": Activities, intent filters, providers, services and receivers."); - buf.append("</li>"); //$NON-NLS-1$ - - buf.append(String.format("<li style=\"image\" value=\"perm_img\"><a href=\"page:%1$s\">", // $NON-NLS-1$ - PermissionPage.PAGE_ID)); - buf.append("Permission"); - buf.append("</a>"); //$NON-NLS-1$ - buf.append(": Permissions defined and permissions used."); - buf.append("</li>"); //$NON-NLS-1$ - - buf.append(String.format("<li style=\"image\" value=\"inst_img\"><a href=\"page:%1$s\">", // $NON-NLS-1$ - InstrumentationPage.PAGE_ID)); - buf.append("Instrumentation"); - buf.append("</a>"); //$NON-NLS-1$ - buf.append(": Instrumentation defined."); - buf.append("</li>"); //$NON-NLS-1$ - - buf.append(String.format("<li style=\"image\" value=\"android_img\"><a href=\"page:%1$s\">", // $NON-NLS-1$ - ManifestEditor.TEXT_EDITOR_ID)); - buf.append("XML Source"); - buf.append("</a>"); //$NON-NLS-1$ - buf.append(": Directly edit the AndroidManifest.xml file."); - buf.append("</li>"); //$NON-NLS-1$ - - buf.append("<li style=\"image\" value=\"android_img\">"); // $NON-NLS-1$ - buf.append("<a href=\"http://code.google.com/android/devel/bblocks-manifest.html\">Documentation</a>: Documentation from the Android SDK for AndroidManifest.xml."); // $NON-NLS-1$ - buf.append("</li>"); //$NON-NLS-1$ - buf.append("</form>"); //$NON-NLS-1$ - - FormText text = createFormText(table, toolkit, true, buf.toString(), - false /* setupLayoutData */); - text.setImage("android_img", EditorsPlugin.getAndroidLogo()); - text.setImage("app_img", getIcon(AndroidManifestDescriptors.APPLICATION_ELEMENT)); - text.setImage("perm_img", getIcon(AndroidManifestDescriptors.PERMISSION_ELEMENT)); - text.setImage("inst_img", getIcon(AndroidManifestDescriptors.INTRUMENTATION_ELEMENT)); - text.addHyperlinkListener(editor.createHyperlinkListener()); - } - - private Image getIcon(ElementDescriptor desc) { - if (desc != null && desc.getIcon() != null) { - return desc.getIcon(); - } - - return EditorsPlugin.getAndroidLogo(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java deleted file mode 100644 index 9e8925a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ColumnLayout; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.ScrolledForm; - - -/** - * Page for overview settings, part of the AndroidManifest form editor. - * <p/> - * Useful reference: - * <a href="http://www.eclipse.org/articles/Article-Forms/article.html"> - * http://www.eclipse.org/articles/Article-Forms/article.html</a> - */ -public final class OverviewPage extends FormPage { - - /** Page id used for switching tabs programmatically */ - final static String PAGE_ID = "overview_page"; //$NON-NLS-1$ - - /** Container editor */ - ManifestEditor mEditor; - /** Overview part (attributes for manifest) */ - private OverviewInfoPart mOverviewPart; - - public OverviewPage(ManifestEditor editor) { - super(editor, PAGE_ID, "Overview"); // tab's label, user visible, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Manifest Overview"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - Composite body = form.getBody(); - FormToolkit toolkit = managedForm.getToolkit(); - ColumnLayout cl = new ColumnLayout(); - cl.minNumColumns = cl.maxNumColumns = 1; - body.setLayout(cl); - mOverviewPart = new OverviewInfoPart(body, toolkit, mEditor); - managedForm.addPart(mOverviewPart); - managedForm.addPart(new OverviewExportPart(this, body, toolkit, mEditor)); - managedForm.addPart(new OverviewLinksPart(body, toolkit, mEditor)); - } - - /** - * Changes and refreshes the Application UI node handle by the sub parts. - */ - public void refreshUiApplicationNode() { - if (mOverviewPart != null) { - mOverviewPart.onSdkChanged(); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java deleted file mode 100644 index a7c0ad5..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.manifest.pages; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Page for permissions settings, part of the AndroidManifest form editor. - * <p/> - * Useful reference: - * <a href="http://www.eclipse.org/articles/Article-Forms/article.html"> - * http://www.eclipse.org/articles/Article-Forms/article.html</a> - */ -public final class PermissionPage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "permission_page"; //$NON-NLS-1$ - - /** Container editor */ - ManifestEditor mEditor; - - public PermissionPage(ManifestEditor editor) { - super(editor, PAGE_ID, "Permissions"); // tab label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Manifest Permissions"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode manifest = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, manifest, - true /* autoCreateRoot */, - new ElementDescriptor[] { - AndroidManifestDescriptors.PERMISSION_ELEMENT, - AndroidManifestDescriptors.USES_PERMISSION_ELEMENT, - AndroidManifestDescriptors.PERMISSION_GROUP_ELEMENT, - AndroidManifestDescriptors.PERMISSION_TREE_ELEMENT - }, - "Permissions", - "List of permissions defined and used by the manifest"); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java deleted file mode 100644 index 57b9a42..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.menu; - -import com.android.ide.eclipse.editors.AndroidContentAssist; -import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors; - -/** - * Content Assist Processor for /res/menu XML files - */ -class MenuContentAssist extends AndroidContentAssist { - - /** - * Constructor for LayoutContentAssist - */ - public MenuContentAssist() { - super(MenuDescriptors.getInstance().getDescriptor().getChildren()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java deleted file mode 100644 index 4bf02fa..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.menu; - -import com.android.ide.eclipse.common.project.AndroidXPathFactory; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; - -/** - * Multi-page form editor for /res/menu XML files. - */ -public class MenuEditor extends AndroidEditor { - - public static final String ID = "com.android.ide.eclipse.editors.menu.MenuEditor"; //$NON-NLS-1$ - - /** Root node of the UI element hierarchy */ - private UiElementNode mUiRootNode; - /** Listener to update the root node if the resource framework changes */ - private Runnable mResourceRefreshListener; - - /** - * Creates the form editor for resources XML files. - */ - public MenuEditor() { - super(); - initUiRootNode(); - } - - /** - * Returns the root node of the UI element hierarchy, which here is - * the "menu" node. - */ - @Override - public UiElementNode getUiRootNode() { - return mUiRootNode; - } - - // ---- Base Class Overrides ---- - - @Override - public void dispose() { - if (mResourceRefreshListener != null) { - EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener = null; - } - super.dispose(); - } - - /** - * Returns whether the "save as" operation is supported by this editor. - * <p/> - * Save-As is a valid operation for the ManifestEditor since it acts on a - * single source file. - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return true; - } - - /** - * Create the various form pages. - */ - @Override - protected void createFormPages() { - try { - addPage(new MenuTreePage(this)); - } catch (PartInitException e) { - EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$ - } - - } - - /* (non-java doc) - * Change the tab/title name to include the project name. - */ - @Override - protected void setInput(IEditorInput input) { - super.setInput(input); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput) input; - IFile file = fileInput.getFile(); - setPartName(String.format("%1$s", file.getName())); - } - } - - /** - * Processes the new XML Model, which XML root node is given. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - @Override - protected void xmlModelChanged(Document xml_doc) { - mUiRootNode.setXmlDocument(xml_doc); - if (xml_doc != null) { - ElementDescriptor root_desc = mUiRootNode.getDescriptor(); - try { - XPath xpath = AndroidXPathFactory.newXPath(); - Node node = (Node) xpath.evaluate("/" + root_desc.getXmlName(), //$NON-NLS-1$ - xml_doc, - XPathConstants.NODE); - if (node == null && root_desc.isMandatory()) { - // Create the root element if it doesn't exist yet (for empty new documents) - node = mUiRootNode.createXmlNode(); - } - - // Refresh the manifest UI node and all its descendants - mUiRootNode.loadFromXmlNode(node); - - // TODO ? startMonitoringMarkers(); - } catch (XPathExpressionException e) { - EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$ - root_desc.getXmlName()); - } - } - - super.xmlModelChanged(xml_doc); - } - - - // ---- Local Methods ---- - - /** - * Creates the initial UI Root Node, including the known mandatory elements. - */ - private void initUiRootNode() { - // The root UI node is always created, even if there's no corresponding XML node. - if (mUiRootNode == null) { - ElementDescriptor desc = MenuDescriptors.getInstance().getDescriptor(); - mUiRootNode = desc.createUiNode(); - mUiRootNode.setEditor(this); - - // Add a listener to refresh the root node if the resource framework changes - // by forcing it to parse its own XML - mResourceRefreshListener = new Runnable() { - public void run() { - commitPages(false /* onSave */); - - mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode()); - } - }; - EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener.run(); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java deleted file mode 100644 index a5e3b09..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.menu; - - -import com.android.ide.eclipse.editors.AndroidSourceViewerConfig; - -/** - * Source Viewer Configuration that calls in MenuContentAssist. - */ -public class MenuSourceViewerConfig extends AndroidSourceViewerConfig { - - public MenuSourceViewerConfig() { - super(new MenuContentAssist()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java deleted file mode 100644 index 994074e..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.menu; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Page for the menu form editor. - */ -public final class MenuTreePage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "layout_tree_page"; //$NON-NLS-1$ - - /** Container editor */ - MenuEditor mEditor; - - public MenuTreePage(MenuEditor editor) { - super(editor, PAGE_ID, "Layout"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Menu"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode rootNode = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, rootNode, - true /* autoCreateRoot */, - null /* no element filters */, - "Menu Elements", - "List of all menu elements in this XML file."); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java deleted file mode 100644 index 941f736..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.menu.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; - -import java.util.ArrayList; -import java.util.Map; - - -/** - * Complete description of the menu structure. - */ -public class MenuDescriptors { - - public static final String MENU_ROOT_ELEMENT = "menu"; //$NON-NLS-1$ - - - - /** Singleton instance */ - private static MenuDescriptors sThis; - - /** The root element descriptor. */ - private ElementDescriptor mDescriptor = null; - - /** Returns a singleton instance of the {@link MenuDescriptors}. */ - public static synchronized MenuDescriptors getInstance() { - if (sThis == null) { - sThis = new MenuDescriptors(); - sThis.updateDescriptors(null); - } - return sThis; - } - - /** @return the root descriptor. */ - public ElementDescriptor getDescriptor() { - return mDescriptor; - } - - /** - * Updates the document descriptor. - * <p/> - * It first computes the new children of the descriptor and then updates them - * all at once. - * - * @param styleMap The map style => attributes from the attrs.xml file - */ - public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) { - - // There are 3 elements: menu, item and group. - // The root element MUST be a menu. - // A top menu can contain items or group: - // - top groups can contain top items - // - top items can contain sub-menus - // A sub menu can contains sub items or sub groups: - // - sub groups can contain sub items - // - sub items cannot contain anything - - if (mDescriptor == null) { - mDescriptor = createElement(styleMap, - MENU_ROOT_ELEMENT, // xmlName - "Menu", // uiName, - null, // TODO SDK URL - null, // extraAttribute - null, // childrenElements, - true /* mandatory */); - } - - // -- sub menu can have sub_items, sub_groups but not sub_menus - - ElementDescriptor sub_item = createElement(styleMap, - "item", // xmlName //$NON-NLS-1$ - "Item", // uiName, - null, // TODO SDK URL - null, // extraAttribute - null, // childrenElements, - false /* mandatory */); - - ElementDescriptor sub_group = createElement(styleMap, - "group", // xmlName //$NON-NLS-1$ - "Group", // uiName, - null, // TODO SDK URL - null, // extraAttribute - new ElementDescriptor[] { sub_item }, // childrenElements, - false /* mandatory */); - - ElementDescriptor sub_menu = createElement(styleMap, - MENU_ROOT_ELEMENT, // xmlName //$NON-NLS-1$ - "Sub-Menu", // uiName, - null, // TODO SDK URL - null, // extraAttribute - new ElementDescriptor[] { sub_item, sub_group }, // childrenElements, - true /* mandatory */); - - // -- top menu can have all top groups and top items (which can have sub menus) - - ElementDescriptor top_item = createElement(styleMap, - "item", // xmlName //$NON-NLS-1$ - "Item", // uiName, - null, // TODO SDK URL - null, // extraAttribute - new ElementDescriptor[] { sub_menu }, // childrenElements, - false /* mandatory */); - - ElementDescriptor top_group = createElement(styleMap, - "group", // xmlName //$NON-NLS-1$ - "Group", // uiName, - null, // TODO SDK URL - null, // extraAttribute - new ElementDescriptor[] { top_item }, // childrenElements, - false /* mandatory */); - - XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor("android", //$NON-NLS-1$ - AndroidConstants.NS_RESOURCES); - - updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$ - mDescriptor.setChildren(new ElementDescriptor[] { top_item, top_group }); - } - - /** - * Returns a new ElementDescriptor constructed from the information given here - * and the javadoc & attributes extracted from the style map if any. - */ - private ElementDescriptor createElement( - Map<String, DeclareStyleableInfo> styleMap, - String xmlName, String uiName, String sdkUrl, - AttributeDescriptor extraAttribute, - ElementDescriptor[] childrenElements, boolean mandatory) { - - ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl, - null, childrenElements, mandatory); - - return updateElement(element, styleMap, - getStyleName(xmlName), - extraAttribute); - } - - /** - * Updates an ElementDescriptor with the javadoc & attributes extracted from the style - * map if any. - */ - private ElementDescriptor updateElement(ElementDescriptor element, - Map<String, DeclareStyleableInfo> styleMap, - String styleName, - AttributeDescriptor extraAttribute) { - ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>(); - - DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null; - if (style != null) { - DescriptorsUtils.appendAttributes(descs, - null, // elementName - AndroidConstants.NS_RESOURCES, - style.getAttributes(), - null, // requiredAttributes - null); // overrides - element.setTooltip(style.getJavaDoc()); - } - - if (extraAttribute != null) { - descs.add(extraAttribute); - } - - element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()])); - return element; - } - - /** - * Returns the style name (i.e. the <declare-styleable> name found in attrs.xml) - * for a given XML element name. - * <p/> - * The rule is that all elements have for style name: - * - their xml name capitalized - * - a "Menu" prefix, except for <menu> itself which is just "Menu". - */ - private String getStyleName(String xmlName) { - String styleName = DescriptorsUtils.capitalize(xmlName); - - // This is NOT the UI Name but the expected internal style name - final String MENU_STYLE_BASE_NAME = "Menu"; //$NON-NLS-1$ - - if (!styleName.equals(MENU_STYLE_BASE_NAME)) { - styleName = MENU_STYLE_BASE_NAME + styleName; - } - return styleName; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java deleted file mode 100644 index 9fe15ab..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources; - -import com.android.ide.eclipse.editors.AndroidContentAssist; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; - -/** - * Content Assist Processor for /res/values and /res/drawable XML files - */ -class ResourcesContentAssist extends AndroidContentAssist { - - /** - * Constructor for ResourcesContentAssist - */ - public ResourcesContentAssist() { - super(new ElementDescriptor[] { ResourcesDescriptors.RESOURCES_ELEMENT }); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java deleted file mode 100644 index bad5699..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources; - -import com.android.ide.eclipse.common.project.AndroidXPathFactory; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; - -/** - * Multi-page form editor for /res/values and /res/drawable XML files. - */ -public class ResourcesEditor extends AndroidEditor { - - public static final String ID = "com.android.ide.eclipse.editors.resources.ResourcesEditor"; //$NON-NLS-1$ - - /** Root node of the UI element hierarchy */ - private UiElementNode mUiResourcesNode; - - - /** - * Creates the form editor for resources XML files. - */ - public ResourcesEditor() { - super(); - initUiResourcesNode(); - } - - /** - * Returns the root node of the UI element hierarchy, which - * here is the "resources" node. - */ - @Override - public UiElementNode getUiRootNode() { - return mUiResourcesNode; - } - - // ---- Base Class Overrides ---- - - /** - * Returns whether the "save as" operation is supported by this editor. - * <p/> - * Save-As is a valid operation for the ManifestEditor since it acts on a - * single source file. - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return true; - } - - /** - * Create the various form pages. - */ - @Override - protected void createFormPages() { - try { - addPage(new ResourcesTreePage(this)); - } catch (PartInitException e) { - EditorsPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$ - EditorsPlugin.getDefault().getLog().log(e.getStatus()); - } - } - - /* (non-java doc) - * Change the tab/title name to include the project name. - */ - @Override - protected void setInput(IEditorInput input) { - super.setInput(input); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput) input; - IFile file = fileInput.getFile(); - setPartName(String.format("%1$s", - file.getName())); - } - } - - /** - * Processes the new XML Model, which XML root node is given. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - @Override - protected void xmlModelChanged(Document xml_doc) { - mUiResourcesNode.setXmlDocument(xml_doc); - if (xml_doc != null) { - ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT; - try { - XPath xpath = AndroidXPathFactory.newXPath(); - Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(), //$NON-NLS-1$ - xml_doc, - XPathConstants.NODE); - assert node != null && node.getNodeName().equals(resources_desc.getXmlName()); - - // Refresh the manifest UI node and all its descendants - mUiResourcesNode.loadFromXmlNode(node); - } catch (XPathExpressionException e) { - EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$ - resources_desc.getXmlName()); - } - } - - super.xmlModelChanged(xml_doc); - } - - - // ---- Local Methods ---- - - /** - * Creates the initial UI Root Node, including the known mandatory elements. - */ - private void initUiResourcesNode() { - // The manifest UI node is always created, even if there's no corresponding XML node. - if (mUiResourcesNode == null) { - ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT; - mUiResourcesNode = resources_desc.createUiNode(); - mUiResourcesNode.setEditor(this); - } - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java deleted file mode 100644 index 1804312..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources; - - -import com.android.ide.eclipse.editors.AndroidSourceViewerConfig; - -/** - * Source Viewer Configuration that calls in ResourcesContentAssist. - */ -public class ResourcesSourceViewerConfig extends AndroidSourceViewerConfig { - - public ResourcesSourceViewerConfig() { - super(new ResourcesContentAssist()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java deleted file mode 100644 index 8cabeca..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolder; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.resources.IFile; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; -import org.eclipse.ui.part.FileEditorInput; - -/** - * Page for instrumentation settings, part of the AndroidManifest form editor. - */ -public final class ResourcesTreePage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "res_tree_page"; //$NON-NLS-1$ - - /** Container editor */ - ResourcesEditor mEditor; - - public ResourcesTreePage(ResourcesEditor editor) { - super(editor, PAGE_ID, "Resources"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - - String configText = null; - IEditorInput input = mEditor.getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - IFile iFile = fileInput.getFile(); - - ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile); - if (resFolder != null) { - configText = resFolder.getConfiguration().toDisplayString(); - } - } - - if (configText != null) { - form.setText(String.format("Android Resources (%1$s)", configText)); - } else { - form.setText("Android Resources"); - } - - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode resources = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, resources, - true /* autoCreateRoot */, - null /* no element filters */, - "Resources Elements", - "List of all resources elements in this XML file."); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java deleted file mode 100644 index 7670fa2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Mobile Country Code. - */ -public final class CountryCodeQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_CODE = -1; - - private final static Pattern sCountryCodePattern = Pattern.compile("^mcc(\\d{3})$");//$NON-NLS-1$ - - private int mCode = DEFAULT_CODE; - - public static final String NAME = "Mobile Country Code"; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link CountryCodeQualifier} object or <code>null</code> - */ - public static CountryCodeQualifier getQualifier(String segment) { - Matcher m = sCountryCodePattern.matcher(segment); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - CountryCodeQualifier qualifier = new CountryCodeQualifier(); - qualifier.mCode = code; - return qualifier; - } - - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link CountryCodeQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getCode()}. - */ - public static String getFolderSegment(int code) { - if (code != DEFAULT_CODE && code >= 100 && code <=999) { // code is 3 digit.) { - return String.format("mcc%1$d", code); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public int getCode() { - return mCode; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Country Code"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("world"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mCode != DEFAULT_CODE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - CountryCodeQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setCountryCodeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof CountryCodeQualifier) { - return mCode == ((CountryCodeQualifier)qualifier).mCode; - } - - return false; - } - - @Override - public int hashCode() { - return mCode; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - return getFolderSegment(mCode); - } - - @Override - public String getStringValue() { - if (mCode != DEFAULT_CODE) { - return String.format("MCC %1$d", mCode); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java deleted file mode 100644 index 3c3e11f..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; - - -/** - * Represents the configuration for Resource Folders. All the properties have a default - * value which means that the property is not set. - */ -public final class FolderConfiguration implements Comparable<FolderConfiguration> { - public final static String QUALIFIER_SEP = "-"; //$NON-NLS-1$ - - private final ResourceQualifier[] mQualifiers = new ResourceQualifier[INDEX_COUNT]; - - private final static int INDEX_COUNTRY_CODE = 0; - private final static int INDEX_NETWORK_CODE = 1; - private final static int INDEX_LANGUAGE = 2; - private final static int INDEX_REGION = 3; - private final static int INDEX_SCREEN_ORIENTATION = 4; - private final static int INDEX_PIXEL_DENSITY = 5; - private final static int INDEX_TOUCH_TYPE = 6; - private final static int INDEX_KEYBOARD_STATE = 7; - private final static int INDEX_TEXT_INPUT_METHOD = 8; - private final static int INDEX_NAVIGATION_METHOD = 9; - private final static int INDEX_SCREEN_DIMENSION = 10; - private final static int INDEX_COUNT = 11; - - /** - * Sets the config from the qualifiers of a given <var>config</var>. - * @param config - */ - public void set(FolderConfiguration config) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - mQualifiers[i] = config.mQualifiers[i]; - } - } - - /** - * Removes the qualifiers from the receiver if they are present (and valid) - * in the given configuration. - */ - public void substract(FolderConfiguration config) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (config.mQualifiers[i] != null && config.mQualifiers[i].isValid()) { - mQualifiers[i] = null; - } - } - } - - /** - * Returns the first invalid qualifier, or <code>null<code> if they are all valid (or if none - * exists). - */ - public ResourceQualifier getInvalidQualifier() { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null && mQualifiers[i].isValid() == false) { - return mQualifiers[i]; - } - } - - // all allocated qualifiers are valid, we return null. - return null; - } - - /** - * Returns whether the Region qualifier is valid. Region qualifier can only be present if a - * Language qualifier is present as well. - * @return true if the Region qualifier is valid. - */ - public boolean checkRegion() { - if (mQualifiers[INDEX_LANGUAGE] == null && mQualifiers[INDEX_REGION] != null) { - return false; - } - - return true; - } - - /** - * Adds a qualifier to the {@link FolderConfiguration} - * @param qualifier the {@link ResourceQualifier} to add. - */ - public void addQualifier(ResourceQualifier qualifier) { - if (qualifier instanceof CountryCodeQualifier) { - mQualifiers[INDEX_COUNTRY_CODE] = qualifier; - } else if (qualifier instanceof NetworkCodeQualifier) { - mQualifiers[INDEX_NETWORK_CODE] = qualifier; - } else if (qualifier instanceof LanguageQualifier) { - mQualifiers[INDEX_LANGUAGE] = qualifier; - } else if (qualifier instanceof RegionQualifier) { - mQualifiers[INDEX_REGION] = qualifier; - } else if (qualifier instanceof ScreenOrientationQualifier) { - mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier; - } else if (qualifier instanceof PixelDensityQualifier) { - mQualifiers[INDEX_PIXEL_DENSITY] = qualifier; - } else if (qualifier instanceof TouchScreenQualifier) { - mQualifiers[INDEX_TOUCH_TYPE] = qualifier; - } else if (qualifier instanceof KeyboardStateQualifier) { - mQualifiers[INDEX_KEYBOARD_STATE] = qualifier; - } else if (qualifier instanceof TextInputMethodQualifier) { - mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier; - } else if (qualifier instanceof NavigationMethodQualifier) { - mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier; - } else if (qualifier instanceof ScreenDimensionQualifier) { - mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier; - } - } - - /** - * Removes a given qualifier from the {@link FolderConfiguration}. - * @param qualifier the {@link ResourceQualifier} to remove. - */ - public void removeQualifier(ResourceQualifier qualifier) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] == qualifier) { - mQualifiers[i] = null; - return; - } - } - } - - public void setCountryCodeQualifier(CountryCodeQualifier qualifier) { - mQualifiers[INDEX_COUNTRY_CODE] = qualifier; - } - - public CountryCodeQualifier getCountryCodeQualifier() { - return (CountryCodeQualifier)mQualifiers[INDEX_COUNTRY_CODE]; - } - - public void setNetworkCodeQualifier(NetworkCodeQualifier qualifier) { - mQualifiers[INDEX_NETWORK_CODE] = qualifier; - } - - public NetworkCodeQualifier getNetworkCodeQualifier() { - return (NetworkCodeQualifier)mQualifiers[INDEX_NETWORK_CODE]; - } - - public void setLanguageQualifier(LanguageQualifier qualifier) { - mQualifiers[INDEX_LANGUAGE] = qualifier; - } - - public LanguageQualifier getLanguageQualifier() { - return (LanguageQualifier)mQualifiers[INDEX_LANGUAGE]; - } - - public void setRegionQualifier(RegionQualifier qualifier) { - mQualifiers[INDEX_REGION] = qualifier; - } - - public RegionQualifier getRegionQualifier() { - return (RegionQualifier)mQualifiers[INDEX_REGION]; - } - - public void setScreenOrientationQualifier(ScreenOrientationQualifier qualifier) { - mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier; - } - - public ScreenOrientationQualifier getScreenOrientationQualifier() { - return (ScreenOrientationQualifier)mQualifiers[INDEX_SCREEN_ORIENTATION]; - } - - public void setPixelDensityQualifier(PixelDensityQualifier qualifier) { - mQualifiers[INDEX_PIXEL_DENSITY] = qualifier; - } - - public PixelDensityQualifier getPixelDensityQualifier() { - return (PixelDensityQualifier)mQualifiers[INDEX_PIXEL_DENSITY]; - } - - public void setTouchTypeQualifier(TouchScreenQualifier qualifier) { - mQualifiers[INDEX_TOUCH_TYPE] = qualifier; - } - - public TouchScreenQualifier getTouchTypeQualifier() { - return (TouchScreenQualifier)mQualifiers[INDEX_TOUCH_TYPE]; - } - - public void setKeyboardStateQualifier(KeyboardStateQualifier qualifier) { - mQualifiers[INDEX_KEYBOARD_STATE] = qualifier; - } - - public KeyboardStateQualifier getKeyboardStateQualifier() { - return (KeyboardStateQualifier)mQualifiers[INDEX_KEYBOARD_STATE]; - } - - public void setTextInputMethodQualifier(TextInputMethodQualifier qualifier) { - mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier; - } - - public TextInputMethodQualifier getTextInputMethodQualifier() { - return (TextInputMethodQualifier)mQualifiers[INDEX_TEXT_INPUT_METHOD]; - } - - public void setNavigationMethodQualifier(NavigationMethodQualifier qualifier) { - mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier; - } - - public NavigationMethodQualifier getNavigationMethodQualifier() { - return (NavigationMethodQualifier)mQualifiers[INDEX_NAVIGATION_METHOD]; - } - - public void setScreenDimensionQualifier(ScreenDimensionQualifier qualifier) { - mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier; - } - - public ScreenDimensionQualifier getScreenDimensionQualifier() { - return (ScreenDimensionQualifier)mQualifiers[INDEX_SCREEN_DIMENSION]; - } - - /** - * Returns whether an object is equals to the receiver. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof FolderConfiguration) { - FolderConfiguration fc = (FolderConfiguration)obj; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - ResourceQualifier qualifier = mQualifiers[i]; - ResourceQualifier fcQualifier = fc.mQualifiers[i]; - if (qualifier != null) { - if (qualifier.equals(fcQualifier) == false) { - return false; - } - } else if (fcQualifier != null) { - return false; - } - } - - return true; - } - - return false; - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - /** - * Returns whether the Configuration has only default values. - */ - public boolean isDefault() { - for (ResourceQualifier irq : mQualifiers) { - if (irq != null) { - return false; - } - } - - return true; - } - - /** - * Returns the name of a folder with the configuration. - */ - public String getFolderName(ResourceFolderType folder) { - StringBuilder result = new StringBuilder(folder.getName()); - - for (ResourceQualifier qualifier : mQualifiers) { - if (qualifier != null) { - result.append(QUALIFIER_SEP); - result.append(qualifier.toString()); - } - } - - return result.toString(); - } - - /** - * Returns a string valid for usage in a folder name, or <code>null</code> if the configuration - * is default. - */ - @Override - public String toString() { - StringBuilder result = null; - - for (ResourceQualifier irq : mQualifiers) { - if (irq != null) { - if (result == null) { - result = new StringBuilder(); - } else { - result.append(QUALIFIER_SEP); - } - result.append(irq.toString()); - } - } - - if (result != null) { - return result.toString(); - } else { - return null; - } - } - - /** - * Returns a string valid for display purpose. - */ - public String toDisplayString() { - if (isDefault()) { - return "default"; - } - - StringBuilder result = null; - int index = 0; - ResourceQualifier qualifier = null; - - // pre- language/region qualifiers - while (index < INDEX_LANGUAGE) { - qualifier = mQualifiers[index++]; - if (qualifier != null) { - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(qualifier.getStringValue()); - - } - } - - // process the language/region qualifier in a custom way, if there are both non null. - if (mQualifiers[INDEX_LANGUAGE] != null && mQualifiers[INDEX_REGION] != null) { - String language = mQualifiers[INDEX_LANGUAGE].getStringValue(); - String region = mQualifiers[INDEX_REGION].getStringValue(); - - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(String.format("%s_%s", language, region)); //$NON-NLS-1$ - - index += 2; - } - - // post language/region qualifiers. - while (index < INDEX_COUNT) { - qualifier = mQualifiers[index++]; - if (qualifier != null) { - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(qualifier.getStringValue()); - - } - } - - return result.toString(); - } - - public int compareTo(FolderConfiguration folderConfig) { - // default are always at the top. - if (isDefault()) { - if (folderConfig.isDefault()) { - return 0; - } - return -1; - } - - // now we compare the qualifiers - for (int i = 0 ; i < INDEX_COUNT; i++) { - ResourceQualifier qualifier1 = mQualifiers[i]; - ResourceQualifier qualifier2 = folderConfig.mQualifiers[i]; - - if (qualifier1 == null) { - if (qualifier2 == null) { - continue; - } else { - return -1; - } - } else { - if (qualifier2 == null) { - return 1; - } else { - int result = qualifier1.compareTo(qualifier2); - - if (result == 0) { - continue; - } - - return result; - } - } - } - - // if we arrive here, all the qualifier matches - return 0; - } - - /** - * Returns whether the configuration match the given reference config. - * <p/>A match means that: - * <ul> - * <li>This config does not use any qualifier not used by the reference config</li> - * <li>The qualifier used by this config have the same values as the qualifiers of - * the reference config.</li> - * </ul> - * @param referenceConfig The reference configuration to test against. - * @return the number of matching qualifiers or -1 if the configurations are not compatible. - */ - public int match(FolderConfiguration referenceConfig) { - int matchCount = 0; - - for (int i = 0 ; i < INDEX_COUNT ; i++) { - ResourceQualifier testQualifier = mQualifiers[i]; - ResourceQualifier referenceQualifier = referenceConfig.mQualifiers[i]; - - // we only care if testQualifier is non null. If it's null, it's a match but - // without increasing the matchCount. - if (testQualifier != null) { - if (referenceQualifier == null) { - return -1; - } else if (testQualifier.equals(referenceQualifier) == false) { - return -1; - } - - // the qualifier match, increment the count - matchCount++; - } - } - return matchCount; - } - - /** - * Returns the index of the first non null {@link ResourceQualifier} starting at index - * <var>startIndex</var> - * @param startIndex - * @return -1 if no qualifier was found. - */ - public int getHighestPriorityQualifier(int startIndex) { - for (int i = startIndex ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - return i; - } - } - - return -1; - } - - /** - * Create default qualifiers. - */ - public void createDefault() { - mQualifiers[INDEX_COUNTRY_CODE] = new CountryCodeQualifier(); - mQualifiers[INDEX_NETWORK_CODE] = new NetworkCodeQualifier(); - mQualifiers[INDEX_LANGUAGE] = new LanguageQualifier(); - mQualifiers[INDEX_REGION] = new RegionQualifier(); - mQualifiers[INDEX_SCREEN_ORIENTATION] = new ScreenOrientationQualifier(); - mQualifiers[INDEX_PIXEL_DENSITY] = new PixelDensityQualifier(); - mQualifiers[INDEX_TOUCH_TYPE] = new TouchScreenQualifier(); - mQualifiers[INDEX_KEYBOARD_STATE] = new KeyboardStateQualifier(); - mQualifiers[INDEX_TEXT_INPUT_METHOD] = new TextInputMethodQualifier(); - mQualifiers[INDEX_NAVIGATION_METHOD] = new NavigationMethodQualifier(); - mQualifiers[INDEX_SCREEN_DIMENSION] = new ScreenDimensionQualifier(); - } - - /** - * Returns an array of all the non null qualifiers. - */ - public ResourceQualifier[] getQualifiers() { - int count = 0; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - count++; - } - } - - ResourceQualifier[] array = new ResourceQualifier[count]; - int index = 0; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - array[index++] = mQualifiers[i]; - } - } - - return array; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java deleted file mode 100644 index ad232ed..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - - - -/** - * Resource Qualifier for keyboard state. - */ -public final class KeyboardStateQualifier extends ResourceQualifier { - - public static final String NAME = "Keyboard State"; - - private KeyboardState mValue = null; - - /** - * Screen Orientation enum. - */ - public static enum KeyboardState { - EXPOSED("keysexposed", "Exposed"), //$NON-NLS-1$ - HIDDEN("keyshidden", "Hidden"); //$NON-NLS-1$ - - private String mValue; - private String mDisplayValue; - - private KeyboardState(String value, String displayValue) { - mValue = value; - mDisplayValue = displayValue; - } - - /** - * Returns the enum for matching the provided qualifier value. - * @param value The qualifier value. - * @return the enum for the qualifier value or null if no matching was found. - */ - static KeyboardState getEnum(String value) { - for (KeyboardState orient : values()) { - if (orient.mValue.equals(value)) { - return orient; - } - } - - return null; - } - - public String getValue() { - return mValue; - } - - public String getDisplayValue() { - return mDisplayValue; - } - - public static int getIndex(KeyboardState value) { - int i = 0; - for (KeyboardState input : values()) { - if (value == input) { - return i; - } - - i++; - } - - return -1; - } - - public static KeyboardState getByIndex(int index) { - int i = 0; - for (KeyboardState value : values()) { - if (i == index) { - return value; - } - i++; - } - return null; - } - } - - public KeyboardStateQualifier() { - // pass - } - - public KeyboardStateQualifier(KeyboardState value) { - mValue = value; - } - - public KeyboardState getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Keyboard"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("keyboard"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - KeyboardState orientation = KeyboardState.getEnum(value); - if (orientation != null) { - KeyboardStateQualifier qualifier = new KeyboardStateQualifier(); - qualifier.mValue = orientation; - config.setKeyboardStateQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof KeyboardStateQualifier) { - return mValue == ((KeyboardStateQualifier)qualifier).mValue; - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return mValue.getValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue.getDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java deleted file mode 100644 index 99c3a43..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Language. - */ -public final class LanguageQualifier extends ResourceQualifier { - private final static Pattern sLanguagePattern = Pattern.compile("^[a-z]{2}$"); //$NON-NLS-1$ - - public static final String NAME = "Language"; - - private String mValue; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link LanguageQualifier} object or <code>null</code> - */ - public static LanguageQualifier getQualifier(String segment) { - if (sLanguagePattern.matcher(segment).matches()) { - LanguageQualifier qualifier = new LanguageQualifier(); - qualifier.mValue = segment; - - return qualifier; - } - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link LanguageQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getValue()}. - */ - public static String getFolderSegment(String value) { - String segment = value.toLowerCase(); - if (sLanguagePattern.matcher(segment).matches()) { - return segment; - } - - return null; - } - - public String getValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("language"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - LanguageQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setLanguageQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof LanguageQualifier) { - if (mValue == null) { - return ((LanguageQualifier)qualifier).mValue == null; - } - return mValue.equals(((LanguageQualifier)qualifier).mValue); - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return getFolderSegment(mValue); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java deleted file mode 100644 index 1a2cf53..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - - - -/** - * Resource Qualifier for Navigation Method. - */ -public final class NavigationMethodQualifier extends ResourceQualifier { - - public static final String NAME = "Navigation Method"; - - private NavigationMethod mValue; - - /** - * Navigation Method enum. - */ - public static enum NavigationMethod { - DPAD("dpad", "D-pad"), //$NON-NLS-1$ - TRACKBALL("trackball", "Trackball"), //$NON-NLS-1$ - WHEEL("wheel", "Wheel"), //$NON-NLS-1$ - NONAV("nonav", "No Navigation"); //$NON-NLS-1$ - - private String mValue; - private String mDisplay; - - private NavigationMethod(String value, String display) { - mValue = value; - mDisplay = display; - } - - /** - * Returns the enum for matching the provided qualifier value. - * @param value The qualifier value. - * @return the enum for the qualifier value or null if no matching was found. - */ - static NavigationMethod getEnum(String value) { - for (NavigationMethod orient : values()) { - if (orient.mValue.equals(value)) { - return orient; - } - } - - return null; - } - - public String getValue() { - return mValue; - } - - public String getDisplayValue() { - return mDisplay; - } - - public static int getIndex(NavigationMethod value) { - int i = 0; - for (NavigationMethod nav : values()) { - if (nav == value) { - return i; - } - - i++; - } - - return -1; - } - - public static NavigationMethod getByIndex(int index) { - int i = 0; - for (NavigationMethod value : values()) { - if (i == index) { - return value; - } - i++; - } - return null; - } - } - - public NavigationMethodQualifier() { - // pass - } - - public NavigationMethodQualifier(NavigationMethod value) { - mValue = value; - } - - public NavigationMethod getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Navigation"; - } - - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("navpad"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - NavigationMethod method = NavigationMethod.getEnum(value); - if (method != null) { - NavigationMethodQualifier qualifier = new NavigationMethodQualifier(); - qualifier.mValue = method; - config.setNavigationMethodQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof NavigationMethodQualifier) { - return mValue == ((NavigationMethodQualifier)qualifier).mValue; - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return mValue.getValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue.getDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java deleted file mode 100644 index ce527a4..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Mobile Network Code Pixel Density. - */ -public final class NetworkCodeQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_CODE = -1; - - private final static Pattern sNetworkCodePattern = Pattern.compile("^mnc(\\d{1,3})$"); //$NON-NLS-1$ - - private int mCode = DEFAULT_CODE; - - public final static String NAME = "Mobile Network Code"; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link CountryCodeQualifier} object or <code>null</code> - */ - public static NetworkCodeQualifier getQualifier(String segment) { - Matcher m = sNetworkCodePattern.matcher(segment); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - NetworkCodeQualifier qualifier = new NetworkCodeQualifier(); - qualifier.mCode = code; - return qualifier; - } - - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link NetworkCodeQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getCode()}. - */ - public static String getFolderSegment(int code) { - if (code != DEFAULT_CODE && code >= 1 && code <= 999) { // code is 1-3 digit. - return String.format("mnc%1$d", code); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public int getCode() { - return mCode; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Network Code"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("mnc"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mCode != DEFAULT_CODE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sNetworkCodePattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return false; - } - - NetworkCodeQualifier qualifier = new NetworkCodeQualifier(); - qualifier.mCode = code; - config.setNetworkCodeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof NetworkCodeQualifier) { - return mCode == ((NetworkCodeQualifier)qualifier).mCode; - } - - return false; - } - - @Override - public int hashCode() { - return mCode; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - return getFolderSegment(mCode); - } - - @Override - public String getStringValue() { - if (mCode != DEFAULT_CODE) { - return String.format("MNC %1$d", mCode); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java deleted file mode 100644 index 0fd05bf..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Pixel Density. - */ -public final class PixelDensityQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_DENSITY = -1; - - private final static Pattern sPixelDensityPattern = Pattern.compile("^(\\d+)dpi$");//$NON-NLS-1$ - - public static final String NAME = "Pixel Density"; - - private int mValue = DEFAULT_DENSITY; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link CountryCodeQualifier} object or <code>null</code> - */ - public static PixelDensityQualifier getQualifier(String folderSegment) { - Matcher m = sPixelDensityPattern.matcher(folderSegment); - if (m.matches()) { - String v = m.group(1); - - int density = -1; - try { - density = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - PixelDensityQualifier qualifier = new PixelDensityQualifier(); - qualifier.mValue = density; - - return qualifier; - } - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link NetworkCodeQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getCode()}. - */ - public static String getFolderSegment(int value) { - if (value != DEFAULT_DENSITY) { - return String.format("%1$ddpi", value); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public int getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("dpi"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != DEFAULT_DENSITY; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - PixelDensityQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setPixelDensityQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof PixelDensityQualifier) { - return mValue == ((PixelDensityQualifier)qualifier).mValue; - } - - return false; - } - - @Override - public int hashCode() { - return mValue; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - return getFolderSegment(mValue); - } - - @Override - public String getStringValue() { - if (mValue != DEFAULT_DENSITY) { - return String.format("%1$d dpi", mValue); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java deleted file mode 100644 index dc4d5fa..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Region. - */ -public final class RegionQualifier extends ResourceQualifier { - private final static Pattern sRegionPattern = Pattern.compile("^r([A-Z]{2})$"); //$NON-NLS-1$ - - public static final String NAME = "Region"; - - private String mValue; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link RegionQualifier} object or <code>null</code> - */ - public static RegionQualifier getQualifier(String segment) { - Matcher m = sRegionPattern.matcher(segment); - if (m.matches()) { - RegionQualifier qualifier = new RegionQualifier(); - qualifier.mValue = m.group(1); - - return qualifier; - } - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link RegionQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getValue()}. - */ - public static String getFolderSegment(String value) { - if (value != null) { - String segment = "r" + value.toUpperCase(); //$NON-NLS-1$ - if (sRegionPattern.matcher(segment).matches()) { - return segment; - } - } - - return ""; //$NON-NLS-1$ - } - - public String getValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("region"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - RegionQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setRegionQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof RegionQualifier) { - if (mValue == null) { - return ((RegionQualifier)qualifier).mValue == null; - } - return mValue.equals(((RegionQualifier)qualifier).mValue); - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - return getFolderSegment(mValue); - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java deleted file mode 100644 index 0257afa..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import org.eclipse.swt.graphics.Image; - -/** - * Base class for resource qualifiers. - * <p/>The resource qualifier classes are designed as immutable. - */ -public abstract class ResourceQualifier implements Comparable<ResourceQualifier> { - - /** - * Returns the human readable name of the qualifier. - */ - public abstract String getName(); - - /** - * Returns a shorter human readable name for the qualifier. - * @see #getName() - */ - public abstract String getShortName(); - - /** - * Returns the icon for the qualifier. - */ - public abstract Image getIcon(); - - /** - * Returns whether the qualifier has a valid filter value. - */ - public abstract boolean isValid(); - - /** - * Check if the value is valid for this qualifier, and if so sets the value - * into a Folder Configuration. - * @param value The value to check and set. Must not be null. - * @param config The folder configuration to receive the value. Must not be null. - * @return true if the value was valid and was set. - */ - public abstract boolean checkAndSet(String value, FolderConfiguration config); - - /** - * Returns a string formated to be used in a folder name. - * <p/>This is declared as abstract to force children classes to implement it. - */ - @Override - public abstract String toString(); - - /** - * Returns a string formatted for display purpose. - */ - public abstract String getStringValue(); - - /** - * Returns <code>true</code> if both objects are equal. - * <p/>This is declared as abstract to force children classes to implement it. - */ - @Override - public abstract boolean equals(Object object); - - /** - * Returns a hash code value for the object. - * <p/>This is declared as abstract to force children classes to implement it. - */ - @Override - public abstract int hashCode(); - - public final int compareTo(ResourceQualifier o) { - return toString().compareTo(o.toString()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java deleted file mode 100644 index a2cc789..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Dimension. - */ -public final class ScreenDimensionQualifier extends ResourceQualifier { - /** Default screen size value. This means the property is not set */ - final static int DEFAULT_SIZE = -1; - - private final static Pattern sDimensionPattern = Pattern.compile( - "^(\\d+)x(\\d+)$"); //$NON-NLS-1$ - - public static final String NAME = "Screen Dimension"; - - /** Screen size 1 value. This is not size X or Y because the folder name always - * contains the biggest size first. So if the qualifier is 400x200, size 1 will always be - * 400 but that'll be X in landscape and Y in portrait. - * Default value is <code>DEFAULT_SIZE</code> */ - private int mValue1 = DEFAULT_SIZE; - - /** Screen size 2 value. This is not size X or Y because the folder name always - * contains the biggest size first. So if the qualifier is 400x200, size 2 will always be - * 200 but that'll be Y in landscape and X in portrait. - * Default value is <code>DEFAULT_SIZE</code> */ - private int mValue2 = DEFAULT_SIZE; - - public int getValue1() { - return mValue1; - } - - public int getValue2() { - return mValue2; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Dimension"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("dimension"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue1 != DEFAULT_SIZE && mValue2 != DEFAULT_SIZE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sDimensionPattern.matcher(value); - if (m.matches()) { - String d1 = m.group(1); - String d2 = m.group(2); - - ScreenDimensionQualifier qualifier = getQualifier(d1, d2); - if (qualifier != null) { - config.setScreenDimensionQualifier(qualifier); - return true; - } - } - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof ScreenDimensionQualifier) { - ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier; - return (mValue1 == q.mValue1 && mValue2 == q.mValue2); - } - - return false; - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - public static ScreenDimensionQualifier getQualifier(String size1, String size2) { - try { - int s1 = Integer.parseInt(size1); - int s2 = Integer.parseInt(size2); - - ScreenDimensionQualifier qualifier = new ScreenDimensionQualifier(); - - if (s1 > s2) { - qualifier.mValue1 = s1; - qualifier.mValue2 = s2; - } else { - qualifier.mValue1 = s2; - qualifier.mValue2 = s1; - } - - return qualifier; - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - } - - return null; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - return String.format("%1$dx%2$d", mValue1, mValue2); //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue1 != -1 && mValue2 != -1) { - return String.format("%1$dx%2$d", mValue1, mValue2); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java deleted file mode 100644 index e30930f..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - -/** - * Resource Qualifier for Screen Orientation. - */ -public final class ScreenOrientationQualifier extends ResourceQualifier { - - public static final String NAME = "Screen Orientation"; - - private ScreenOrientation mValue = null; - - /** - * Screen Orientation enum. - */ - public static enum ScreenOrientation { - PORTRAIT("port", "Portrait"), //$NON-NLS-1$ - LANDSCAPE("land", "Landscape"), //$NON-NLS-1$ - SQUARE("square", "Square"); //$NON-NLS-1$ - - private String mValue; - private String mDisplayValue; - - private ScreenOrientation(String value, String displayValue) { - mValue = value; - mDisplayValue = displayValue; - } - - /** - * Returns the enum for matching the provided qualifier value. - * @param value The qualifier value. - * @return the enum for the qualifier value or null if no matching was found. - */ - static ScreenOrientation getEnum(String value) { - for (ScreenOrientation orient : values()) { - if (orient.mValue.equals(value)) { - return orient; - } - } - - return null; - } - - public String getValue() { - return mValue; - } - - public String getDisplayValue() { - return mDisplayValue; - } - - public static int getIndex(ScreenOrientation orientation) { - int i = 0; - for (ScreenOrientation orient : values()) { - if (orient == orientation) { - return i; - } - - i++; - } - - return -1; - } - - public static ScreenOrientation getByIndex(int index) { - int i = 0; - for (ScreenOrientation orient : values()) { - if (i == index) { - return orient; - } - i++; - } - - return null; - } - } - - public ScreenOrientationQualifier() { - } - - public ScreenOrientationQualifier(ScreenOrientation value) { - mValue = value; - } - - public ScreenOrientation getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Orientation"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("orientation"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - ScreenOrientation orientation = ScreenOrientation.getEnum(value); - if (orientation != null) { - ScreenOrientationQualifier qualifier = new ScreenOrientationQualifier(orientation); - config.setScreenOrientationQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof ScreenOrientationQualifier) { - return mValue == ((ScreenOrientationQualifier)qualifier).mValue; - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return mValue.getValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue.getDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java deleted file mode 100644 index de40138..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - - - - -/** - * Resource Qualifier for Text Input Method. - */ -public final class TextInputMethodQualifier extends ResourceQualifier { - - public static final String NAME = "Text Input Method"; - - private TextInputMethod mValue; - - /** - * Screen Orientation enum. - */ - public static enum TextInputMethod { - NOKEY("nokeys", "No Keys"), //$NON-NLS-1$ - QWERTY("qwerty", "Qwerty"), //$NON-NLS-1$ - TWELVEKEYS("12key", "12 Key"); //$NON-NLS-1$ - - private String mValue; - private String mDisplayValue; - - private TextInputMethod(String value, String displayValue) { - mValue = value; - mDisplayValue = displayValue; - } - - /** - * Returns the enum for matching the provided qualifier value. - * @param value The qualifier value. - * @return the enum for the qualifier value or null if no matching was found. - */ - static TextInputMethod getEnum(String value) { - for (TextInputMethod orient : values()) { - if (orient.mValue.equals(value)) { - return orient; - } - } - - return null; - } - - public String getValue() { - return mValue; - } - - public String getDisplayValue() { - return mDisplayValue; - } - - public static int getIndex(TextInputMethod value) { - int i = 0; - for (TextInputMethod input : values()) { - if (value == input) { - return i; - } - - i++; - } - - return -1; - } - - public static TextInputMethod getByIndex(int index) { - int i = 0; - for (TextInputMethod value : values()) { - if (i == index) { - return value; - } - i++; - } - return null; - } - } - - public TextInputMethodQualifier() { - // pass - } - - public TextInputMethodQualifier(TextInputMethod value) { - mValue = value; - } - - public TextInputMethod getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Text Input"; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("text_input"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - TextInputMethod method = TextInputMethod.getEnum(value); - if (method != null) { - TextInputMethodQualifier qualifier = new TextInputMethodQualifier(); - qualifier.mValue = method; - config.setTextInputMethodQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof TextInputMethodQualifier) { - return mValue == ((TextInputMethodQualifier)qualifier).mValue; - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return mValue.getValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue.getDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java deleted file mode 100644 index 2390e2c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.configurations; - -import com.android.ide.eclipse.editors.IconFactory; - -import org.eclipse.swt.graphics.Image; - - -/** - * Resource Qualifier for Touch Screen type. - */ -public final class TouchScreenQualifier extends ResourceQualifier { - - public static final String NAME = "Touch Screen"; - - private TouchScreenType mValue; - - /** - * Screen Orientation enum. - */ - public static enum TouchScreenType { - NOTOUCH("notouch", "No Touch"), //$NON-NLS-1$ - STYLUS("stylus", "Stylus"), //$NON-NLS-1$ - FINGER("finger", "Finger"); //$NON-NLS-1$ - - private String mValue; - private String mDisplayValue; - - private TouchScreenType(String value, String displayValue) { - mValue = value; - mDisplayValue = displayValue; - } - - /** - * Returns the enum for matching the provided qualifier value. - * @param value The qualifier value. - * @return the enum for the qualifier value or null if no matching was found. - */ - static TouchScreenType getEnum(String value) { - for (TouchScreenType orient : values()) { - if (orient.mValue.equals(value)) { - return orient; - } - } - - return null; - } - - public String getValue() { - return mValue; - } - - public String getDisplayValue() { - return mDisplayValue; - } - - public static int getIndex(TouchScreenType touch) { - int i = 0; - for (TouchScreenType t : values()) { - if (t == touch) { - return i; - } - - i++; - } - - return -1; - } - - public static TouchScreenType getByIndex(int index) { - int i = 0; - for (TouchScreenType value : values()) { - if (i == index) { - return value; - } - i++; - } - - return null; - } - } - - public TouchScreenQualifier() { - // pass - } - - public TouchScreenQualifier(TouchScreenType touchValue) { - mValue = touchValue; - } - - public TouchScreenType getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public Image getIcon() { - return IconFactory.getInstance().getIcon("touch"); //$NON-NLS-1$ - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - TouchScreenType type = TouchScreenType.getEnum(value); - if (type != null) { - TouchScreenQualifier qualifier = new TouchScreenQualifier(); - qualifier.mValue = type; - config.setTouchTypeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof TouchScreenQualifier) { - return mValue == ((TouchScreenQualifier)qualifier).mValue; - } - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String toString() { - if (mValue != null) { - return mValue.getValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getStringValue() { - if (mValue != null) { - return mValue.getDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java deleted file mode 100644 index 92288ba..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.descriptors; - -import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor; -import com.android.ide.eclipse.editors.resources.uimodel.UiColorValueNode; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode; - -/** - * Describes a Color XML element value displayed by an {@link UiColorValueNode}. - */ -public final class ColorValueDescriptor extends TextValueDescriptor { - - public ColorValueDescriptor(String uiName, String tooltip) { - super(uiName, tooltip); - } - - /** - * @return A new {@link UiResourceAttributeNode} linked to this theme descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiColorValueNode(this, uiParent); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java deleted file mode 100644 index bf83d52..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.descriptors; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.resources.uimodel.UiItemElementNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * {@link ItemElementDescriptor} is a special version of {@link ElementDescriptor} that - * uses a specialized {@link UiItemElementNode} for display. - */ -public class ItemElementDescriptor extends ElementDescriptor { - - /** - * Constructs a new {@link ItemElementDescriptor} based on its XML name, UI name, - * tooltip, SDK url, attributes list, children list and mandatory. - * - * @param xml_name The XML element node name. Case sensitive. - * @param ui_name The XML element name for the user interface, typically capitalized. - * @param tooltip An optional tooltip. Can be null or empty. - * @param sdk_url An optional SKD URL. Can be null or empty. - * @param attributes The list of allowed attributes. Can be null or empty. - * @param children The list of allowed children. Can be null or empty. - * @param mandatory Whether this node must always exist (even for empty models). A mandatory - * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory - * UI node MUST have an XML node attached and it will cease to exist when the XML node - * ceases to exist. - */ - public ItemElementDescriptor(String xml_name, String ui_name, - String tooltip, String sdk_url, AttributeDescriptor[] attributes, - ElementDescriptor[] children, boolean mandatory) { - super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory); - } - - @Override - public UiElementNode createUiNode() { - return new UiItemElementNode(this); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java deleted file mode 100644 index 4769cef..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.descriptors; - -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor; - - -/** - * Complete description of the AndroidManifest.xml structure. - */ -public class ResourcesDescriptors { - - - // Public attributes names, attributes descriptors and elements descriptors - - public static final String ROOT_ELEMENT = "resources"; //$NON-NLS-1$ - - public static final String NAME_ATTR = "name"; //$NON-NLS-1$ - public static final String TYPE_ATTR = "type"; //$NON-NLS-1$ - - /** The {@link ElementDescriptor} for the root Manifest element. */ - public static final ElementDescriptor RESOURCES_ELEMENT; - - - static { - - // Common attributes used in many placed - - - // Elements - - ElementDescriptor color_element = new ElementDescriptor( - "color", //$NON-NLS-1$ - "Color", - "A @color@ value specifies an RGB value with an alpha channel, which can be used in various places such as specifying a solid color for a Drawable or the color to use for text. It always begins with a # character and then is followed by the alpha-red-green-blue information in one of the following formats: #RGB, #ARGB, #RRGGBB or #AARRGGBB.", - "http://code.google.com/android/reference/available-resources.html#colorvals", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this color."), - new ColorValueDescriptor( - "Value*", - "A mandatory color value.") - }, - null, // no child nodes - false /* not mandatory */); - - ElementDescriptor string_element = new ElementDescriptor( - "string", //$NON-NLS-1$ - "String", - "@Strings@, with optional simple formatting, can be stored and retrieved as resources. You can add formatting to your string by using three standard HTML tags: b, i, and u. If you use an apostrophe or a quote in your string, you must either escape it or enclose the whole string in the other kind of enclosing quotes.", - "http://code.google.com/android/reference/available-resources.html#stringresources", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this string."), - new TextValueDescriptor( - "Value*", - "A mandatory string value.") - }, - null, // no child nodes - false /* not mandatory */); - - ElementDescriptor item_element = new ItemElementDescriptor( - "item", //$NON-NLS-1$ - "Item", - null, // TODO find javadoc - null, // TODO find link to javadoc - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this resource."), - new ListAttributeDescriptor(TYPE_ATTR, - "Type*", - null /* nsUri */, - "The mandatory type of this resource.", - ResourceType.getNames() - ), - new FlagAttributeDescriptor("format", - "Format", - null /* nsUri */, - "The optional format of this resource.", - new String[] { - "boolean", //$NON-NLS-1$ - "color", //$NON-NLS-1$ - "dimension", //$NON-NLS-1$ - "float", //$NON-NLS-1$ - "fraction", //$NON-NLS-1$ - "integer", //$NON-NLS-1$ - "reference", //$NON-NLS-1$ - "string" //$NON-NLS-1$ - }), - new TextValueDescriptor( - "Value", - "A standard string, hex color value, or reference to any other resource type.") - }, - null, // no child nodes - false /* not mandatory */); - - ElementDescriptor drawable_element = new ElementDescriptor( - "drawable", //$NON-NLS-1$ - "Drawable", - "A @drawable@ defines a rectangle of color. Android accepts color values written in various web-style formats -- a hexadecimal constant in any of the following forms: #RGB, #ARGB, #RRGGBB, #AARRGGBB. Zero in the alpha channel means transparent. The default value is opaque.", - "http://code.google.com/android/reference/available-resources.html#colordrawableresources", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this drawable."), - new TextValueDescriptor( - "Value*", - "A mandatory color value in the form #RGB, #ARGB, #RRGGBB or #AARRGGBB.") - }, - null, // no child nodes - false /* not mandatory */); - - ElementDescriptor dimen_element = new ElementDescriptor( - "dimen", //$NON-NLS-1$ - "Dimension", - "You can create common dimensions to use for various screen elements by defining @dimension@ values in XML. A dimension resource is a number followed by a unit of measurement. Supported units are px (pixels), in (inches), mm (millimeters), pt (points at 72 DPI), dp (density-independent pixels) and sp (scale-independent pixels)", - "http://code.google.com/android/reference/available-resources.html#dimension", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this dimension."), - new TextValueDescriptor( - "Value*", - "A mandatory dimension value is a number followed by a unit of measurement. For example: 10px, 2in, 5sp.") - }, - null, // no child nodes - false /* not mandatory */); - - ElementDescriptor style_element = new ElementDescriptor( - "style", //$NON-NLS-1$ - "Style/Theme", - "Both @styles and themes@ are defined in a style block containing one or more string or numerical values (typically color values), or references to other resources (drawables and so on).", - "http://code.google.com/android/reference/available-resources.html#stylesandthemes", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this theme."), - new TextAttributeDescriptor("parent", // $NON-NLS-1$ - "Parent", - null /* nsUri */, - "An optional parent theme. All values from the specified theme will be inherited into this theme. Any values with identical names that you specify will override inherited values."), - }, - new ElementDescriptor[] { - new ElementDescriptor( - "item", //$NON-NLS-1$ - "Item", - "A value to use in this @theme@. It can be a standard string, a hex color value, or a reference to any other resource type.", - "http://code.google.com/android/reference/available-resources.html#stylesandthemes", //$NON-NLS-1$ - new AttributeDescriptor[] { - new TextAttributeDescriptor(NAME_ATTR, - "Name*", - null /* nsUri */, - "The mandatory name used in referring to this item."), - new TextValueDescriptor( - "Value*", - "A mandatory standard string, hex color value, or reference to any other resource type.") - }, - null, // no child nodes - false /* not mandatory */) - }, - false /* not mandatory */); - - RESOURCES_ELEMENT = new ElementDescriptor( - ROOT_ELEMENT, - "Resources", - null, - "http://code.google.com/android/reference/available-resources.html", //$NON-NLS-1$ - null, // no attributes - new ElementDescriptor[] { - string_element, - color_element, - dimen_element, - drawable_element, - style_element, - item_element - }, - true /* mandatory */); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java deleted file mode 100644 index cc7bec8..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.explorer; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.resources.manager.ProjectResourceItem; -import com.android.ide.eclipse.editors.resources.manager.ProjectResources; -import com.android.ide.eclipse.editors.resources.manager.ResourceFile; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IResourceEventListener; -import com.android.ide.eclipse.editors.wizards.ResourceContentProvider; -import com.android.ide.eclipse.editors.wizards.ResourceLabelProvider; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.ControlListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.ISelectionListener; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.ide.IDE; -import org.eclipse.ui.part.ViewPart; - -import java.util.Iterator; - -/** - * Resource Explorer View. - * <p/> - * This contains a basic Tree view, and uses a TreeViewer to handle the data. - * <p/> - * The view listener to change in selection in the workbench, and update to show the resource - * of the project of the current selected item (either item in the package explorer, or of the - * current editor). - * - * @see ResourceContentProvider - */ -public class ResourceExplorerView extends ViewPart implements ISelectionListener, - IResourceEventListener { - - private final static String PREFS_COLUMN_RES = - AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col1"; //$NON-NLS-1$ - private final static String PREFS_COLUMN_2 = - AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col2"; //$NON-NLS-1$ - - private Tree mTree; - private TreeViewer mTreeViewer; - - private IProject mCurrentProject; - - public ResourceExplorerView() { - } - - @Override - public void createPartControl(Composite parent) { - mTree = new Tree(parent, SWT.SINGLE | SWT.VIRTUAL); - mTree.setLayoutData(new GridData(GridData.FILL_BOTH)); - mTree.setHeaderVisible(true); - mTree.setLinesVisible(true); - - final IPreferenceStore store = EditorsPlugin.getDefault().getPreferenceStore(); - - // create 2 columns. The main one with the resources, and an "info" column. - createTreeColumn(mTree, "Resources", SWT.LEFT, - "abcdefghijklmnopqrstuvwxz", -1, PREFS_COLUMN_RES, store); //$NON-NLS-1$ - createTreeColumn(mTree, "Info", SWT.LEFT, - "0123456789", -1, PREFS_COLUMN_2, store); //$NON-NLS-1$ - - // create the jface wrapper - mTreeViewer = new TreeViewer(mTree); - - mTreeViewer.setContentProvider(new ResourceContentProvider(true /* fullLevels */)); - mTreeViewer.setLabelProvider(new ResourceLabelProvider()); - - // listen to selection change in the workbench. - IWorkbenchPage page = getSite().getPage(); - - page.addSelectionListener(this); - - // init with current selection - selectionChanged(getSite().getPart(), page.getSelection()); - - // add support for double click. - mTreeViewer.addDoubleClickListener(new IDoubleClickListener() { - public void doubleClick(DoubleClickEvent event) { - ISelection sel = event.getSelection(); - - if (sel instanceof IStructuredSelection) { - IStructuredSelection selection = (IStructuredSelection) sel; - - if (selection.size() == 1) { - Object element = selection.getFirstElement(); - - // if it's a resourceFile, we directly open it. - if (element instanceof ResourceFile) { - try { - IDE.openEditor(getSite().getWorkbenchWindow().getActivePage(), - ((ResourceFile)element).getFile().getIFile()); - } catch (PartInitException e) { - } - } else if (element instanceof ProjectResourceItem) { - // if it's a ResourceItem, we open the first file, but only if - // there's no alternate files. - ProjectResourceItem item = (ProjectResourceItem)element; - - if (item.isEditableDirectly()) { - ResourceFile[] files = item.getSourceFileArray(); - if (files[0] != null) { - try { - IDE.openEditor( - getSite().getWorkbenchWindow().getActivePage(), - files[0].getFile().getIFile()); - } catch (PartInitException e) { - } - } - } - } - } - } - } - }); - - // set up the resource manager to send us resource change notification - EditorsPlugin.getDefault().getResourceMonitor().addResourceEventListener(this); - } - - @Override - public void setFocus() { - mTree.setFocus(); - } - - /** - * Processes a new selection. - */ - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - // first we test if the part is an editor. - if (part instanceof IEditorPart) { - // if it is, we check if it's a file editor. - IEditorInput input = ((IEditorPart)part).getEditorInput(); - - if (input instanceof IFileEditorInput) { - // from the file editor we can get the IFile object, and from it, the IProject. - IFile file = ((IFileEditorInput)input).getFile(); - - // get the file project - IProject project = file.getProject(); - - handleProjectSelection(project); - } - } else if (selection instanceof IStructuredSelection) { - // if it's not an editor, we look for structured selection. - for (Iterator<?> it = ((IStructuredSelection) selection).iterator(); - it.hasNext();) { - Object element = it.next(); - IProject project = null; - - // if we are in the navigator or package explorer, the selection could contain a - // IResource object. - if (element instanceof IResource) { - project = ((IResource) element).getProject(); - } else if (element instanceof IJavaElement) { - // if we are in the package explorer on a java element, we handle that too. - IJavaElement javaElement = (IJavaElement)element; - IJavaProject javaProject = javaElement.getJavaProject(); - if (javaProject != null) { - project = javaProject.getProject(); - } - } else if (element instanceof IAdaptable) { - // finally we try to get a project object from IAdaptable. - project = (IProject) ((IAdaptable) element) - .getAdapter(IProject.class); - } - - // if we found a project, handle it, and return. - if (project != null) { - if (handleProjectSelection(project)) { - return; - } - } - } - } - } - - /** - * Handles a project selection. - * @param project the new selected project - * @return true if the project could be processed. - */ - private boolean handleProjectSelection(IProject project) { - try { - // if it's an android project, then we get its resources, and feed them - // to the tree viewer. - if (project.hasNature(AndroidConstants.NATURE)) { - if (mCurrentProject != project) { - ProjectResources projRes = ResourceManager.getInstance().getProjectResources( - project); - if (projRes != null) { - mTreeViewer.setInput(projRes); - mCurrentProject = project; - return true; - } - } - } - } catch (CoreException e) { - } - - return false; - } - - /** - * Create a TreeColumn with the specified parameters. If a - * <code>PreferenceStore</code> object and a preference entry name String - * object are provided then the column will listen to change in its width - * and update the preference store accordingly. - * - * @param parent The Table parent object - * @param header The header string - * @param style The column style - * @param sample_text A sample text to figure out column width if preference - * value is missing - * @param fixedSize a fixed size. If != -1 the column is non resizable - * @param pref_name The preference entry name for column width - * @param prefs The preference store - */ - public void createTreeColumn(Tree parent, String header, int style, - String sample_text, int fixedSize, final String pref_name, - final IPreferenceStore prefs) { - - // create the column - TreeColumn col = new TreeColumn(parent, style); - - if (fixedSize != -1) { - col.setWidth(fixedSize); - col.setResizable(false); - } else { - // if there is no pref store or the entry is missing, we use the sample - // text and pack the column. - // Otherwise we just read the width from the prefs and apply it. - if (prefs == null || prefs.contains(pref_name) == false) { - col.setText(sample_text); - col.pack(); - - // init the prefs store with the current value - if (prefs != null) { - prefs.setValue(pref_name, col.getWidth()); - } - } else { - col.setWidth(prefs.getInt(pref_name)); - } - - // if there is a pref store and a pref entry name, then we setup a - // listener to catch column resize to put the new width value into the store. - if (prefs != null && pref_name != null) { - col.addControlListener(new ControlListener() { - public void controlMoved(ControlEvent e) { - } - - public void controlResized(ControlEvent e) { - // get the new width - int w = ((TreeColumn)e.widget).getWidth(); - - // store in pref store - prefs.setValue(pref_name, w); - } - }); - } - } - - // set the header - col.setText(header); - } - - /** - * Processes a start in a resource event change. - */ - public void resourceChangeEventStart() { - // pass - } - - /** - * Processes the end of a resource change event. - */ - public void resourceChangeEventEnd() { - try { - mTree.getDisplay().asyncExec(new Runnable() { - public void run() { - if (mTree.isDisposed() == false) { - mTreeViewer.refresh(); - } - } - }); - } catch (SWTException e) { - // display is disposed. nothing to do. - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java deleted file mode 100644 index 366f4fd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.runtime.CoreException; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Map; - -/** - * A monitor for the compiled resources. This only monitors changes in the resources of type - * {@link ResourceType#ID}. - */ -public final class CompiledResourcesMonitor implements IFileListener, IProjectListener { - - private final static CompiledResourcesMonitor sThis = new CompiledResourcesMonitor(); - - /** - * Sets up the monitoring system. - * @param monitor The main Resource Monitor. - */ - public static void setupMonitor(ResourceMonitor monitor) { - monitor.addFileListener(sThis, IResourceDelta.ADDED | IResourceDelta.CHANGED); - monitor.addProjectListener(sThis); - } - - /** - * private constructor to prevent construction. - */ - private CompiledResourcesMonitor() { - } - - - /* (non-Javadoc) - * Sent when a file changed : if the file is the R class, then it is parsed again to update - * the internal data. - * - * @param file The file that changed. - * @param markerDeltas The marker deltas for the file. - * @param kind The change kind. This is equivalent to - * {@link IResourceDelta#accept(IResourceDeltaVisitor)} - * - * @see IFileListener#fileChanged - */ - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) { - if (file.getName().equals(AndroidConstants.FN_COMPILED_RESOURCE_CLASS)) { - loadAndParseRClass(file.getProject()); - } - } - - /** - * Processes project close event. - */ - public void projectClosed(IProject project) { - // the ProjectResources object will be removed by the ResourceManager. - } - - /** - * Processes project delete event. - */ - public void projectDeleted(IProject project) { - // the ProjectResources object will be removed by the ResourceManager. - } - - /** - * Processes project open event. - */ - public void projectOpened(IProject project) { - // when the project is opened, we get an ADDED event for each file, so we don't - // need to do anything here. - } - - /** - * Processes existing project at init time. - */ - public void projectOpenedWithWorkspace(IProject project) { - try { - // check this is an android project - if (project.hasNature(AndroidConstants.NATURE)) { - loadAndParseRClass(project); - } - } catch (CoreException e) { - // pass - } - } - - private void loadAndParseRClass(IProject project) { - try { - // first check there's a ProjectResources to store the content - ProjectResources projectResources = ResourceManager.getInstance().getProjectResources( - project); - - if (projectResources != null) { - // create the classname - String className = getRClassName(project); - - // create a temporary class loader to load it. - ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */, - project); - - Class<?> clazz = loader.loadClass(className); - - if (clazz != null) { - // create the maps to store the result of the parsing - Map<String, Map<String, Integer>> resourceValueMap = - new HashMap<String, Map<String, Integer>>(); - Map<Integer, String[]> genericValueToNameMap = - new HashMap<Integer, String[]>(); - Map<IntArrayWrapper, String> styleableValueToNameMap = - new HashMap<IntArrayWrapper, String>(); - - // parse the class - if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap, - resourceValueMap)) { - // now we associate the maps to the project. - projectResources.setCompiledResources(genericValueToNameMap, - styleableValueToNameMap, resourceValueMap); - } - } - } - } catch (ClassNotFoundException e) { - // pass - } - } - - /** - * Parses a R class, and fills maps. - * @param rClass the class to parse - * @param genericValueToNameMap - * @param styleableValueToNameMap - * @param resourceValueMap - * @return - */ - private boolean parseClass(Class<?> rClass, Map<Integer, String[]> genericValueToNameMap, - Map<IntArrayWrapper, String> styleableValueToNameMap, Map<String, - Map<String, Integer>> resourceValueMap) { - try { - for (Class<?> inner : rClass.getDeclaredClasses()) { - String resType = inner.getSimpleName(); - - Map<String, Integer> fullMap = new HashMap<String, Integer>(); - resourceValueMap.put(resType, fullMap); - - for (Field f : inner.getDeclaredFields()) { - // only process static final fields. - int modifiers = f.getModifiers(); - if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { - Class<?> type = f.getType(); - if (type.isArray() && type.getComponentType() == int.class) { - // if the object is an int[] we put it in the styleable map - styleableValueToNameMap.put(new IntArrayWrapper((int[]) f.get(null)), - f.getName()); - } else if (type == int.class) { - Integer value = (Integer) f.get(null); - genericValueToNameMap.put(value, new String[] { f.getName(), resType }); - fullMap.put(f.getName(), value); - } else { - assert false; - } - } - } - } - - return true; - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { - } - return false; - } - - private String getRClassName(IProject project) { - // create the classname - AndroidManifestHelper manifest = new AndroidManifestHelper(project); - String javaPackage = manifest.getPackageName(); - - return javaPackage + ".R"; //$NON-NLS-1$ - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java deleted file mode 100644 index 57c17fc..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -/** - * Represents a resource item that can exist in multiple "alternate" versions. - */ -public class ConfigurableResourceItem extends ProjectResourceItem { - - /** - * Constructs a new Resource Item. - * @param name the name of the resource as it appears in the XML and R.java files. - */ - public ConfigurableResourceItem(String name) { - super(name); - } - - /** - * Returns if the resource item has at least one non-default configuration. - */ - public boolean hasAlternates() { - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault() == false) { - return true; - } - } - - return false; - } - - /** - * Returns whether the resource has a default version, with no qualifier. - */ - public boolean hasDefault() { - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault()) { - return true; - } - } - - // We only want to return false if there's no default and more than 0 items. - return (mFiles.size() == 0); - } - - /** - * Returns the number of alternate versions of this resource. - */ - public int getAlternateCount() { - int count = 0; - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault() == false) { - count++; - } - } - - return count; - } - - /* - * (non-Javadoc) - * Returns whether the item can be edited directly (ie it does not have alternate versions). - */ - @Override - public boolean isEditableDirectly() { - return hasAlternates() == false; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java deleted file mode 100644 index a9f80bd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceType; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -/** - * This class gives access to the bi directional relationship between {@link ResourceType} and - * {@link ResourceFolderType}. - */ -public final class FolderTypeRelationship { - - private final static HashMap<ResourceType, ResourceFolderType[]> mTypeToFolderMap = - new HashMap<ResourceType, ResourceFolderType[]>(); - - private final static HashMap<ResourceFolderType, ResourceType[]> mFolderToTypeMap = - new HashMap<ResourceFolderType, ResourceType[]>(); - - // generate the relationships. - static { - HashMap<ResourceType, List<ResourceFolderType>> typeToFolderMap = - new HashMap<ResourceType, List<ResourceFolderType>>(); - - HashMap<ResourceFolderType, List<ResourceType>> folderToTypeMap = - new HashMap<ResourceFolderType, List<ResourceType>>(); - - add(ResourceType.ANIM, ResourceFolderType.ANIM, typeToFolderMap, folderToTypeMap); - add(ResourceType.ARRAY, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.COLOR, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.COLOR, ResourceFolderType.COLOR, typeToFolderMap, folderToTypeMap); - add(ResourceType.DIMEN, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.DRAWABLE, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.DRAWABLE, ResourceFolderType.DRAWABLE, typeToFolderMap, folderToTypeMap); - add(ResourceType.ID, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.LAYOUT, ResourceFolderType.LAYOUT, typeToFolderMap, folderToTypeMap); - add(ResourceType.MENU, ResourceFolderType.MENU, typeToFolderMap, folderToTypeMap); - add(ResourceType.RAW, ResourceFolderType.RAW, typeToFolderMap, folderToTypeMap); - add(ResourceType.STRING, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.STYLE, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap); - add(ResourceType.XML, ResourceFolderType.XML, typeToFolderMap, folderToTypeMap); - - optimize(typeToFolderMap, folderToTypeMap); - } - - /** - * Returns a list of {@link ResourceType}s that can be generated from files inside a folder - * of the specified type. - * @param folderType The folder type. - * @return an array of {@link ResourceType} - */ - public static ResourceType[] getRelatedResourceTypes(ResourceFolderType folderType) { - ResourceType[] array = mFolderToTypeMap.get(folderType); - if (array != null) { - return array; - } - return new ResourceType[0]; - } - - /** - * Returns a list of {@link ResourceFolderType} that can contain files generating resources - * of the specified type. - * @param resType the type of resource. - * @return an array of {@link ResourceFolderType} - */ - public static ResourceFolderType[] getRelatedFolders(ResourceType resType) { - ResourceFolderType[] array = mTypeToFolderMap.get(resType); - if (array != null) { - return array; - } - return new ResourceFolderType[0]; - } - - /** - * Returns true if the {@link ResourceType} and the {@link ResourceFolderType} values match. - * @param resType the resource type. - * @param folderType the folder type. - * @return true if files inside the folder of the specified {@link ResourceFolderType} - * could generate a resource of the specified {@link ResourceType} - */ - public static boolean match(ResourceType resType, ResourceFolderType folderType) { - ResourceFolderType[] array = mTypeToFolderMap.get(resType); - - if (array != null && array.length > 0) { - for (ResourceFolderType fType : array) { - if (fType == folderType) { - return true; - } - } - } - - return false; - } - - /** - * Adds a {@link ResourceType} - {@link ResourceFolderType} relationship. this indicates that - * a file in the folder can generate a resource of the specified type. - * @param type The resourceType - * @param folder The {@link ResourceFolderType} - * @param folderToTypeMap - * @param typeToFolderMap - */ - private static void add(ResourceType type, ResourceFolderType folder, - HashMap<ResourceType, List<ResourceFolderType>> typeToFolderMap, - HashMap<ResourceFolderType, List<ResourceType>> folderToTypeMap) { - // first we add the folder to the list associated with the type. - List<ResourceFolderType> folderList = typeToFolderMap.get(type); - if (folderList == null) { - folderList = new ArrayList<ResourceFolderType>(); - typeToFolderMap.put(type, folderList); - } - if (folderList.indexOf(folder) == -1) { - folderList.add(folder); - } - - // now we add the type to the list associated with the folder. - List<ResourceType> typeList = folderToTypeMap.get(folder); - if (typeList == null) { - typeList = new ArrayList<ResourceType>(); - folderToTypeMap.put(folder, typeList); - } - if (typeList.indexOf(type) == -1) { - typeList.add(type); - } - } - - /** - * Optimize the map to contains array instead of lists (since the api returns arrays) - * @param typeToFolderMap - * @param folderToTypeMap - */ - private static void optimize(HashMap<ResourceType, List<ResourceFolderType>> typeToFolderMap, - HashMap<ResourceFolderType, List<ResourceType>> folderToTypeMap) { - Set<ResourceType> types = typeToFolderMap.keySet(); - for (ResourceType type : types) { - List<ResourceFolderType> list = typeToFolderMap.get(type); - mTypeToFolderMap.put(type, list.toArray(new ResourceFolderType[list.size()])); - } - - Set<ResourceFolderType> folders = folderToTypeMap.keySet(); - for (ResourceFolderType folder : folders) { - List<ResourceType> list = folderToTypeMap.get(folder); - mFolderToTypeMap.put(folder, list.toArray(new ResourceType[list.size()])); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java deleted file mode 100644 index 552aec9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.IIdResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; - -/** - * Represents a resource item of type {@link ResourceType#ID} - */ -public class IdResourceItem extends ProjectResourceItem implements IIdResourceItem { - - private final boolean mIsDeclaredInline; - - /** - * Constructs a new ResourceItem. - * @param name the name of the resource as it appears in the XML and R.java files. - * @param isDeclaredInline Whether this id was declared inline. - */ - IdResourceItem(String name, boolean isDeclaredInline) { - super(name); - mIsDeclaredInline = isDeclaredInline; - } - - /* - * (non-Javadoc) - * Returns whether the ID resource has been declared inline inside another resource XML file. - */ - public boolean isDeclaredInline() { - return mIsDeclaredInline; - } - - /* (non-Javadoc) - * Returns whether the item can be edited (ie, the id was not declared inline). - */ - @Override - public boolean isEditableDirectly() { - return !mIsDeclaredInline; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java deleted file mode 100644 index 25eb112..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager; - -import java.util.Arrays; - - -/** - * Wrapper around a int[] to provide hashCode/equals support. - */ -public final class IntArrayWrapper { - - private int[] mData; - - public IntArrayWrapper(int[] data) { - mData = data; - } - - public void set(int[] data) { - mData = data; - } - - @Override - public int hashCode() { - return Arrays.hashCode(mData); - } - - @Override - public boolean equals(Object obj) { - if (getClass().equals(obj.getClass())) { - return Arrays.equals(mData, ((IntArrayWrapper)obj).mData); - } - - return super.equals(obj); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java deleted file mode 100644 index 72438a6..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile; -import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.utils.ResourceValue; -import com.android.layoutlib.utils.ValueResourceParser; -import com.android.layoutlib.utils.ValueResourceParser.IValueResourceRepository; - -import org.eclipse.core.runtime.CoreException; -import org.xml.sax.SAXException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Set; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Represents a resource file able to declare multiple resources, which could be of - * different {@link ResourceType}. - * <p/> - * This is typically an XML file inside res/values. - */ -public final class MultiResourceFile extends ResourceFile implements IValueResourceRepository { - - private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); - - private final HashMap<ResourceType, HashMap<String, ResourceValue>> mResourceItems = - new HashMap<ResourceType, HashMap<String, ResourceValue>>(); - - public MultiResourceFile(IAbstractFile file, ResourceFolder folder) { - super(file, folder); - } - - @Override - public ResourceType[] getResourceTypes() { - update(); - - Set<ResourceType> keys = mResourceItems.keySet(); - - return keys.toArray(new ResourceType[keys.size()]); - } - - @Override - public boolean hasResources(ResourceType type) { - update(); - - HashMap<String, ResourceValue> list = mResourceItems.get(type); - return (list != null && list.size() > 0); - } - - @Override - public Collection<ProjectResourceItem> getResources(ResourceType type, - ProjectResources projectResources) { - update(); - - HashMap<String, ResourceValue> list = mResourceItems.get(type); - - ArrayList<ProjectResourceItem> items = new ArrayList<ProjectResourceItem>(); - - if (list != null) { - Collection<ResourceValue> values = list.values(); - for (ResourceValue res : values) { - ProjectResourceItem item = projectResources.findResourceItem(type, res.getName()); - - if (item == null) { - if (type == ResourceType.ID) { - item = new IdResourceItem(res.getName(), false /* isDeclaredInline */); - } else { - item = new ConfigurableResourceItem(res.getName()); - } - items.add(item); - } - - item.add(this); - } - } - - return items; - } - - /** - * Updates the Resource items if necessary. - */ - private void update() { - if (isTouched() == true) { - // reset current content. - mResourceItems.clear(); - - // need to parse the file and find the content. - parseFile(); - - resetTouch(); - } - } - - /** - * Parses the file and creates a list of {@link ResourceType}. - */ - private void parseFile() { - try { - SAXParser parser = sParserFactory.newSAXParser(); - parser.parse(getFile().getContents(), new ValueResourceParser(this, isFramework())); - } catch (ParserConfigurationException e) { - } catch (SAXException e) { - } catch (IOException e) { - } catch (CoreException e) { - } - } - - /** - * Adds a resource item to the list - * @param resType The type of the resource - * @param name The name of the resource. - */ - public void addResourceValue(String resType, ResourceValue value) { - ResourceType type = ResourceType.getEnum(resType); - if (type != null) { - HashMap<String, ResourceValue> list = mResourceItems.get(type); - - // if the list does not exist, create it. - if (list == null) { - list = new HashMap<String, ResourceValue>(); - mResourceItems.put(type, list); - } else { - // look for a possible value already existing. - ResourceValue oldValue = list.get(value.getName()); - - if (oldValue != null) { - oldValue.replaceWith(value); - return; - } - } - - // empty list or no match found? add the given resource - list.put(value.getName(), value); - } - } - - @Override - public IResourceValue getValue(ResourceType type, String name) { - update(); - - // get the list for the given type - HashMap<String, ResourceValue> list = mResourceItems.get(type); - - if (list != null) { - return list.get(name); - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java deleted file mode 100644 index 5658224..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.AndroidConstants; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.IPath; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; - -/** - * ClassLoader able to load class from output of an Eclipse project. - */ -public final class ProjectClassLoader extends ClassLoader { - - private final IJavaProject mJavaProject; - private URLClassLoader mJarClassLoader; - private boolean mInsideJarClassLoader = false; - - public ProjectClassLoader(ClassLoader parentClassLoader, IProject project) { - super(parentClassLoader); - mJavaProject = JavaCore.create(project); - } - - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - try { - // get the project output folder. - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - IPath outputLocation = mJavaProject.getOutputLocation(); - IResource outRes = root.findMember(outputLocation); - if (outRes == null) { - throw new ClassNotFoundException(name); - } - - File outFolder = new File(outRes.getLocation().toOSString()); - - // get the class name segments - String[] segments = name.split("\\."); //$NON-NLS-1$ - - File classFile = getFile(outFolder, segments, 0); - if (classFile == null) { - if (mInsideJarClassLoader == false) { - // if no file matching the class name was found, look in the 3rd party jars - return loadClassFromJar(name); - } else { - throw new ClassNotFoundException(name); - } - } - - // load the content of the file and create the class. - FileInputStream fis = new FileInputStream(classFile); - byte[] data = new byte[(int)classFile.length()]; - int read = 0; - try { - read = fis.read(data); - } catch (IOException e) { - data = null; - } - fis.close(); - - if (data != null) { - Class<?> clazz = defineClass(null, data, 0, read); - if (clazz != null) { - return clazz; - } - } - } catch (Exception e) { - throw new ClassNotFoundException(e.getMessage()); - } - - throw new ClassNotFoundException(name); - } - - /** - * Returns the File matching the a certain path from a root {@link File}. - * <p/>The methods checks that the file ends in .class even though the last segment - * does not. - * @param parent the root of the file. - * @param segments the segments containing the path of the file - * @param index the offset at which to start looking into segments. - * @return - * @throws FileNotFoundException - */ - private File getFile(File parent, String[] segments, int index) - throws FileNotFoundException { - // reached the end with no match? - if (index == segments.length) { - throw new FileNotFoundException(); - } - - String toMatch = segments[index]; - File[] files = parent.listFiles(); - - // we're at the last segments. we look for a matching <file>.class - if (index == segments.length - 1) { - toMatch = toMatch + ".class"; - - if (files != null) { - for (File file : files) { - if (file.isFile() && file.getName().equals(toMatch)) { - return file; - } - } - } - - // no match? abort. - throw new FileNotFoundException(); - } - - String innerClassName = null; - - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - if (toMatch.equals(file.getName())) { - return getFile(file, segments, index+1); - } - } else if (file.getName().startsWith(toMatch)) { - if (innerClassName == null) { - StringBuilder sb = new StringBuilder(segments[index]); - for (int i = index + 1 ; i < segments.length ; i++) { - sb.append('$'); - sb.append(segments[i]); - } - sb.append(".class"); - - innerClassName = sb.toString(); - } - - if (file.getName().equals(innerClassName)) { - return file; - } - } - } - } - - return null; - } - - /** - * Loads a class from the 3rd party jar present in the project - * @param name - * @return - * @throws ClassNotFoundException - */ - private Class<?> loadClassFromJar(String name) throws ClassNotFoundException { - if (mJarClassLoader == null) { - // get the OS path to all the external jars - URL[] jars = getExternalJars(); - - mJarClassLoader = new URLClassLoader(jars, this /* parent */); - } - - try { - // because a class loader always look in its parent loader first, we need to know - // that we are querying the jar classloader. This will let us know to not query - // it again for classes we don't find, or this would create an infinite loop. - mInsideJarClassLoader = true; - return mJarClassLoader.loadClass(name); - } finally { - mInsideJarClassLoader = false; - } - } - - /** - * Returns an array of external jar files used by the project. - * @return an array of OS-specific absolute file paths - */ - private final URL[] getExternalJars() { - // get a java project from it - IJavaProject javaProject = JavaCore.create(mJavaProject.getProject()); - - IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); - - ArrayList<URL> oslibraryList = new ArrayList<URL>(); - IClasspathEntry[] classpaths = javaProject.readRawClasspath(); - if (classpaths != null) { - for (IClasspathEntry e : classpaths) { - if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY || - e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { - // if this is a classpath variable reference, we resolve it. - if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { - e = JavaCore.getResolvedClasspathEntry(e); - } - - // get the IPath - IPath path = e.getPath(); - - // get the file name. if it's the framework jar, we ignore that file. - // since we now use classpath container, this is here for legacy purpose only. - if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) { - continue; - } - - // check the name ends with .jar - if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) { - boolean local = false; - IResource resource = wsRoot.findMember(path); - if (resource != null && resource.exists() && - resource.getType() == IResource.FILE) { - local = true; - try { - oslibraryList.add( - new File(resource.getLocation().toOSString()).toURL()); - } catch (MalformedURLException mue) { - // pass - } - } - - if (local == false) { - // if the jar path doesn't match a workspace resource, - // then we get an OSString and check if this links to a valid file. - String osFullPath = path.toOSString(); - - File f = new File(osFullPath); - if (f.exists()) { - try { - oslibraryList.add(f.toURL()); - } catch (MalformedURLException mue) { - // pass - } - } - } - } - } - } - } - - return oslibraryList.toArray(new URL[oslibraryList.size()]); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java deleted file mode 100644 index ba770b2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.android.ide.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Base class for Resource Item coming from an Android Project. - */ -public abstract class ProjectResourceItem extends ResourceItem { - - private final static Comparator<ResourceFile> sComparator = new Comparator<ResourceFile>() { - public int compare(ResourceFile file1, ResourceFile file2) { - // get both FolderConfiguration and compare them - FolderConfiguration fc1 = file1.getFolder().getConfiguration(); - FolderConfiguration fc2 = file2.getFolder().getConfiguration(); - - return fc1.compareTo(fc2); - } - }; - - /** - * List of files generating this ResourceItem. - */ - protected final ArrayList<ResourceFile> mFiles = new ArrayList<ResourceFile>(); - - /** - * Constructs a new ResourceItem. - * @param name the name of the resource as it appears in the XML and R.java files. - */ - public ProjectResourceItem(String name) { - super(name); - } - - /** - * Returns whether the resource item is editable directly. - * <p/> - * This is typically the case for resources that don't have alternate versions, or resources - * of type {@link ResourceType#ID} that aren't declared inline. - */ - public abstract boolean isEditableDirectly(); - - /** - * Adds a new version of this resource item, by adding its {@link ResourceFile}. - * @param file the {@link ResourceFile} object. - */ - protected void add(ResourceFile file) { - mFiles.add(file); - } - - /** - * Reset the item by emptying its version list. - */ - protected void reset() { - mFiles.clear(); - } - - /** - * Returns the sorted list of {@link ResourceItem} objects for this resource item. - */ - public ResourceFile[] getSourceFileArray() { - ArrayList<ResourceFile> list = new ArrayList<ResourceFile>(); - list.addAll(mFiles); - - Collections.sort(list, sComparator); - - return list.toArray(new ResourceFile[list.size()]); - } - - /** - * Returns the list of {@link ResourceItem} objects for this resource item. - */ - public List<ResourceFile> getSourceFileList() { - return Collections.unmodifiableList(mFiles); - } - - - /** - * Replaces the content of the receiver with the ResourceItem received as parameter. - * @param item - */ - protected void replaceWith(ProjectResourceItem item) { - mFiles.clear(); - mFiles.addAll(item.mFiles); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java deleted file mode 100644 index b0881fa..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java +++ /dev/null @@ -1,810 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.IResourceRepository; -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.LanguageQualifier; -import com.android.ide.eclipse.editors.resources.configurations.RegionQualifier; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder; -import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.utils.ResourceValue; - -import org.eclipse.core.resources.IFolder; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Represents the resources of a project. This is a file view of the resources, with handling - * for the alternate resource types. For a compiled view use CompiledResources. - */ -public class ProjectResources implements IResourceRepository { - private final HashMap<ResourceFolderType, List<ResourceFolder>> mFolderMap = - new HashMap<ResourceFolderType, List<ResourceFolder>>(); - - private final HashMap<ResourceType, List<ProjectResourceItem>> mResourceMap = - new HashMap<ResourceType, List<ProjectResourceItem>>(); - - /** Map of (name, id) for resources of type {@link ResourceType#ID} coming from R.java */ - private Map<String, Map<String, Integer>> mResourceValueMap; - /** Map of (id, [name, resType]) for all resources coming from R.java */ - private Map<Integer, String[]> mResIdValueToNameMap; - /** Map of (int[], name) for styleable resources coming from R.java */ - private Map<IntArrayWrapper, String> mStyleableValueToNameMap; - - /** Cached list of {@link IdResourceItem}. This is mix of IdResourceItem created by - * {@link MultiResourceFile} for ids coming from XML files under res/values and - * {@link IdResourceItem} created manually, from the list coming from R.java */ - private final ArrayList<IdResourceItem> mIdResourceList = new ArrayList<IdResourceItem>(); - - private final boolean mIsFrameworkRepository; - - private final IntArrayWrapper mWrapper = new IntArrayWrapper(null); - - public ProjectResources(boolean isFrameworkRepository) { - mIsFrameworkRepository = isFrameworkRepository; - } - - public boolean isSystemRepository() { - return mIsFrameworkRepository; - } - - /** - * Adds a Folder Configuration to the project. - * @param type The resource type. - * @param config The resource configuration. - * @param folder The workspace folder object. - * @return the {@link ResourceFolder} object associated to this folder. - */ - protected ResourceFolder add(ResourceFolderType type, FolderConfiguration config, - IAbstractFolder folder) { - // get the list for the resource type - List<ResourceFolder> list = mFolderMap.get(type); - - if (list == null) { - list = new ArrayList<ResourceFolder>(); - - ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository); - list.add(cf); - - mFolderMap.put(type, list); - - return cf; - } - - // look for an already existing folder configuration. - for (ResourceFolder cFolder : list) { - if (cFolder.mConfiguration.equals(config)) { - // config already exist. Nothing to be done really, besides making sure - // the IFolder object is up to date. - cFolder.mFolder = folder; - return cFolder; - } - } - - // If we arrive here, this means we didn't find a matching configuration. - // So we add one. - ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository); - list.add(cf); - - return cf; - } - - /** - * Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}. - * @param type The type of the folder - * @param folder the IFolder object. - */ - protected void removeFolder(ResourceFolderType type, IFolder folder) { - // get the list of folders for the resource type. - List<ResourceFolder> list = mFolderMap.get(type); - - if (list != null) { - int count = list.size(); - for (int i = 0 ; i < count ; i++) { - ResourceFolder resFolder = list.get(i); - if (resFolder.getFolder().getIFolder().equals(folder)) { - // we found the matching ResourceFolder. we need to remove it. - list.remove(i); - - // we now need to invalidate this resource type. - // The easiest way is to touch one of the other folders of the same type. - if (list.size() > 0) { - list.get(0).touch(); - } else { - // if the list is now empty, and we have a single ResouceType out of this - // ResourceFolderType, then we are done. - // However, if another ResourceFolderType can generate similar ResourceType - // than this, we need to update those ResourceTypes as well. - // For instance, if the last "drawable-*" folder is deleted, we need to - // refresh the ResourceItem associated with ResourceType.DRAWABLE. - // Those can be found in ResourceFolderType.DRAWABLE but also in - // ResourceFolderType.VALUES. - // If we don't find a single folder to touch, then it's fine, as the top - // level items (the list of generated resource types) is not cached - // (for now) - - // get the lists of ResourceTypes generated by this ResourceFolderType - ResourceType[] resTypes = FolderTypeRelationship.getRelatedResourceTypes( - type); - - // for each of those, make sure to find one folder to touch so that the - // list of ResourceItem associated with the type is rebuilt. - for (ResourceType resType : resTypes) { - // get the list of folder that can generate this type - ResourceFolderType[] folderTypes = - FolderTypeRelationship.getRelatedFolders(resType); - - // we only need to touch one folder in any of those (since it's one - // folder per type, not per folder type). - for (ResourceFolderType folderType : folderTypes) { - List<ResourceFolder> resFolders = mFolderMap.get(folderType); - - if (resFolders != null && resFolders.size() > 0) { - resFolders.get(0).touch(); - break; - } - } - } - } - - // we're done updating/touching, we can stop - break; - } - } - } - } - - - /** - * Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}. - * @param type The {@link ResourceFolderType} - */ - public List<ResourceFolder> getFolders(ResourceFolderType type) { - return mFolderMap.get(type); - } - - /* (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.IResourceRepository#getAvailableResourceTypes() - */ - public ResourceType[] getAvailableResourceTypes() { - ArrayList<ResourceType> list = new ArrayList<ResourceType>(); - - // For each key, we check if there's a single ResourceType match. - // If not, we look for the actual content to give us the resource type. - - for (ResourceFolderType folderType : mFolderMap.keySet()) { - ResourceType types[] = FolderTypeRelationship.getRelatedResourceTypes(folderType); - if (types.length == 1) { - // before we add it we check if it's not already present, since a ResourceType - // could be created from multiple folders, even for the folders that only create - // one type of resource (drawable for instance, can be created from drawable/ and - // values/) - if (list.indexOf(types[0]) == -1) { - list.add(types[0]); - } - } else { - // there isn't a single resource type out of this folder, so we look for all - // content. - List<ResourceFolder> folders = mFolderMap.get(folderType); - if (folders != null) { - for (ResourceFolder folder : folders) { - Collection<ResourceType> folderContent = folder.getResourceTypes(); - - // then we add them, but only if they aren't already in the list. - for (ResourceType folderResType : folderContent) { - if (list.indexOf(folderResType) == -1) { - list.add(folderResType); - } - } - } - } - } - } - - // in case ResourceType.ID haven't been added yet because there's no id defined - // in XML, we check on the list of compiled id resources. - if (list.indexOf(ResourceType.ID) == -1 && mResourceValueMap != null) { - Map<String, Integer> map = mResourceValueMap.get(ResourceType.ID.getName()); - if (map != null && map.size() > 0) { - list.add(ResourceType.ID); - } - } - - // at this point the list is full of ResourceType defined in the files. - // We need to sort it. - Collections.sort(list); - - return list.toArray(new ResourceType[list.size()]); - } - - /* (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.IResourceRepository#getResources(com.android.ide.eclipse.common.resources.ResourceType) - */ - public ProjectResourceItem[] getResources(ResourceType type) { - checkAndUpdate(type); - - if (type == ResourceType.ID) { - synchronized (mIdResourceList) { - return mIdResourceList.toArray(new ProjectResourceItem[mIdResourceList.size()]); - } - } - - List<ProjectResourceItem> items = mResourceMap.get(type); - - return items.toArray(new ProjectResourceItem[items.size()]); - } - - /* (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.IResourceRepository#hasResources(com.android.ide.eclipse.common.resources.ResourceType) - */ - public boolean hasResources(ResourceType type) { - checkAndUpdate(type); - - if (type == ResourceType.ID) { - synchronized (mIdResourceList) { - return mIdResourceList.size() > 0; - } - } - - List<ProjectResourceItem> items = mResourceMap.get(type); - return (items != null && items.size() > 0); - } - - /** - * Returns the {@link ResourceFolder} associated with a {@link IFolder}. - * @param folder The {@link IFolder} object. - * @return the {@link ResourceFolder} or null if it was not found. - */ - public ResourceFolder getResourceFolder(IFolder folder) { - for (List<ResourceFolder> list : mFolderMap.values()) { - for (ResourceFolder resFolder : list) { - if (resFolder.getFolder().getIFolder().equals(folder)) { - return resFolder; - } - } - } - - return null; - } - - /** - * Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and - * configuration. - * <p/>This only works with files generating one resource named after the file (for instance, - * layouts, bitmap based drawable, xml, anims). - * @return the matching file or <code>null</code> if no match was found. - */ - public ResourceFile getMatchingFile(String name, ResourceFolderType type, - FolderConfiguration config) { - // get the folders for the given type - List<ResourceFolder> folders = mFolderMap.get(type); - - // look for folders containing a file with the given name. - ArrayList<ResourceFolder> matchingFolders = new ArrayList<ResourceFolder>(); - - // remove the folders that do not have a file with the given name, or if their config - // is incompatible. - for (int i = 0 ; i < folders.size(); i++) { - ResourceFolder folder = folders.get(i); - - if (folder.hasFile(name) == true) { - matchingFolders.add(folder); - } - } - - // from those, get the folder with a config matching the given reference configuration. - Resource match = findMatchingConfiguredResource(matchingFolders, config); - - // do we have a matching folder? - if (match instanceof ResourceFolder) { - // get the ResourceFile from the filename - return ((ResourceFolder)match).getFile(name); - } - - return null; - } - - /** - * Returns the resources values matching a given {@link FolderConfiguration}. - * @param referenceConfig the configuration that each value must match. - */ - public Map<String, Map<String, IResourceValue>> getConfiguredResources( - FolderConfiguration referenceConfig) { - - Map<String, Map<String, IResourceValue>> map = - new HashMap<String, Map<String, IResourceValue>>(); - - // special case for Id since there's a mix of compiled id (declared inline) and id declared - // in the XML files. - if (mIdResourceList.size() > 0) { - Map<String, IResourceValue> idMap = new HashMap<String, IResourceValue>(); - String idType = ResourceType.ID.getName(); - for (IdResourceItem id : mIdResourceList) { - // FIXME: cache the ResourceValue! - idMap.put(id.getName(), new ResourceValue(idType, id.getName(), - mIsFrameworkRepository)); - } - - map.put(ResourceType.ID.getName(), idMap); - } - - Set<ResourceType> keys = mResourceMap.keySet(); - for (ResourceType key : keys) { - // we don't process ID resources since we already did it above. - if (key != ResourceType.ID) { - map.put(key.getName(), getConfiguredResource(key, referenceConfig)); - } - } - - return map; - } - - /** - * Loads all the resources. Essentially this forces to load the values from the - * {@link ResourceFile} objects to make sure they are up to date and loaded - * in {@link #mResourceMap}. - */ - public void loadAll() { - // gets all the resource types available. - ResourceType[] types = getAvailableResourceTypes(); - - // loop on them and load them - for (ResourceType type: types) { - checkAndUpdate(type); - } - } - - /** - * Resolves a compiled resource id into the resource name and type - * @param id - * @return an array of 2 strings { name, type } or null if the id could not be resolved - */ - public String[] resolveResourceValue(int id) { - if (mResIdValueToNameMap != null) { - return mResIdValueToNameMap.get(id); - } - - return null; - } - - /** - * Resolves a compiled resource id of type int[] into the resource name. - * @param id - * @return - */ - public String resolveResourceValue(int[] id) { - if (mStyleableValueToNameMap != null) { - mWrapper.set(id); - return mStyleableValueToNameMap.get(mWrapper); - } - - return null; - } - - /** - * Returns the value of a resource by its type and name. - * @param type - * @param name - * @return - */ - public Integer getResourceValue(String type, String name) { - if (mResourceValueMap != null) { - Map<String, Integer> map = mResourceValueMap.get(type); - if (map != null) { - return map.get(name); - } - } - - return null; - } - - /** - * Returns the list of languages used in the resources. - */ - public Set<String> getLanguages() { - Set<String> set = new HashSet<String>(); - - Collection<List<ResourceFolder>> folderList = mFolderMap.values(); - for (List<ResourceFolder> folderSubList : folderList) { - for (ResourceFolder folder : folderSubList) { - FolderConfiguration config = folder.getConfiguration(); - LanguageQualifier lang = config.getLanguageQualifier(); - if (lang != null) { - set.add(lang.getStringValue()); - } - } - } - - return set; - } - - /** - * Returns the list of regions used in the resources with the given language. - * @param currentLanguage the current language the region must be associated with - * @return - */ - public Set<String> getRegions(String currentLanguage) { - Set<String> set = new HashSet<String>(); - - Collection<List<ResourceFolder>> folderList = mFolderMap.values(); - for (List<ResourceFolder> folderSubList : folderList) { - for (ResourceFolder folder : folderSubList) { - FolderConfiguration config = folder.getConfiguration(); - - // get the language - LanguageQualifier lang = config.getLanguageQualifier(); - if (lang != null && lang.getStringValue().equals(currentLanguage)) { - RegionQualifier region = config.getRegionQualifier(); - if (region != null) { - set.add(region.getStringValue()); - } - } - } - } - - return set; - } - - /** - * Returns a map of (resource name, resource value) for the given {@link ResourceType}. - * <p/>The values returned are taken from the resource files best matching a given - * {@link FolderConfiguration}. - * @param type the type of the resources. - * @param referenceConfig the configuration to best match. - */ - private Map<String, IResourceValue> getConfiguredResource(ResourceType type, - FolderConfiguration referenceConfig) { - // get the resource item for the given type - List<ProjectResourceItem> items = mResourceMap.get(type); - - // create the map - HashMap<String, IResourceValue> map = new HashMap<String, IResourceValue>(); - - for (ProjectResourceItem item : items) { - // get the source files generating this resource - List<ResourceFile> list = item.getSourceFileList(); - - // look for the best match for the given configuration - Resource match = findMatchingConfiguredResource(list, referenceConfig); - - if (match instanceof ResourceFile) { - ResourceFile matchResFile = (ResourceFile)match; - - // get the value of this configured resource. - IResourceValue value = matchResFile.getValue(type, item.getName()); - - if (value != null) { - map.put(item.getName(), value); - } - } - } - - return map; - } - - /** - * Returns the best matching {@link Resource}. - * @param resources the list of {@link Resource} to choose from. - * @param referenceConfig the {@link FolderConfiguration} to match. - */ - private Resource findMatchingConfiguredResource(List<? extends Resource> resources, - FolderConfiguration referenceConfig) { - // look for resources with the maximum number of qualifier match. - int currentMax = -1; - ArrayList<Resource> matchingResources = new ArrayList<Resource>(); - for (int i = 0 ; i < resources.size(); i++) { - Resource res = resources.get(i); - - int count = res.getConfiguration().match(referenceConfig); - if (count > currentMax) { - matchingResources.clear(); - matchingResources.add(res); - currentMax = count; - } else if (count != -1 && count == currentMax) { - matchingResources.add(res); - } - } - - // if we have more than one match, we look for the match with the qualifiers with the - // highest priority. - Resource resMatch = null; - if (matchingResources.size() == 1) { - resMatch = matchingResources.get(0); - } else if (matchingResources.size() > 1) { - // More than one resource with the same number of qualifier match. - // We loop, looking for the resource with the highest priority qualifiers. - ArrayList<Resource> tmpResources = new ArrayList<Resource>(); - int startIndex = 0; - while (matchingResources.size() > 1) { - int highest = -1; - for (int i = 0 ; i < matchingResources.size() ; i++) { - Resource folder = matchingResources.get(i); - - // get highest priority qualifiers. - int m = folder.getConfiguration().getHighestPriorityQualifier(startIndex); - - // add to the list if highest. - if (m != -1) { - if (highest == -1 || m == highest) { - tmpResources.add(folder); - highest = m; - } else if (m < highest) { // highest priority == lowest index. - tmpResources.clear(); - tmpResources.add(folder); - } - } - } - - // at this point, we have a list with 1+ resources that all have the same highest - // priority qualifiers. Go through the list again looking for the next highest - // priority qualifier. - startIndex = highest + 1; - - // this should not happen, but it's better to check. - if (matchingResources.size() == tmpResources.size() && highest == -1) { - // this means all the resources match with the same qualifiers - // (highest == -1 means we reached the end of the qualifier list) - // In this case, we arbitrarily take the first resource. - matchingResources.clear(); - matchingResources.add(tmpResources.get(0)); - } else { - matchingResources.clear(); - matchingResources.addAll(tmpResources); - } - tmpResources.clear(); - } - - // we should have only one match here. - resMatch = matchingResources.get(0); - } - - return resMatch; - } - - /** - * Checks if the list of {@link ResourceItem}s for the specified {@link ResourceType} needs - * to be updated. - * @param type the Resource Type. - */ - private void checkAndUpdate(ResourceType type) { - // get the list of folder that can output this type - ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type); - - for (ResourceFolderType folderType : folderTypes) { - List<ResourceFolder> folders = mFolderMap.get(folderType); - - if (folders != null) { - for (ResourceFolder folder : folders) { - if (folder.isTouched()) { - // if this folder is touched we need to update all the types that can - // be generated from a file in this folder. - // This will include 'type' obviously. - ResourceType[] resTypes = FolderTypeRelationship.getRelatedResourceTypes( - folderType); - for (ResourceType resType : resTypes) { - update(resType); - } - return; - } - } - } - } - } - - /** - * Updates the list of {@link ResourceItem} objects associated with a {@link ResourceType}. - * This will reset the touch status of all the folders that can generate this resource type. - * @param type the Resource Type. - */ - private void update(ResourceType type) { - // get the cache list, and lets make a backup - List<ProjectResourceItem> items = mResourceMap.get(type); - List<ProjectResourceItem> backup = new ArrayList<ProjectResourceItem>(); - - if (items == null) { - items = new ArrayList<ProjectResourceItem>(); - mResourceMap.put(type, items); - } else { - // backup the list - backup.addAll(items); - - // we reset the list itself. - items.clear(); - } - - // get the list of folder that can output this type - ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type); - - for (ResourceFolderType folderType : folderTypes) { - List<ResourceFolder> folders = mFolderMap.get(folderType); - - if (folders != null) { - for (ResourceFolder folder : folders) { - items.addAll(folder.getResources(type, this)); - folder.resetTouch(); - } - } - } - - // now items contains the new list. We "merge" it with the backup list. - // Basically, we need to keep the old instances of ResourceItem (where applicable), - // but replace them by the content of the new items. - // This will let the resource explorer keep the expanded state of the nodes whose data - // is a ResourceItem object. - if (backup.size() > 0) { - // this is not going to change as we're only replacing instances. - int count = items.size(); - - for (int i = 0 ; i < count;) { - // get the "new" item - ProjectResourceItem item = items.get(i); - - // look for a similar item in the old list. - ProjectResourceItem foundOldItem = null; - for (ProjectResourceItem oldItem : backup) { - if (oldItem.getName().equals(item.getName())) { - foundOldItem = oldItem; - break; - } - } - - if (foundOldItem != null) { - // erase the data of the old item with the data from the new one. - foundOldItem.replaceWith(item); - - // remove the old and new item from their respective lists - items.remove(i); - backup.remove(foundOldItem); - - // add the old item to the new list - items.add(foundOldItem); - } else { - // this is a new item, we skip to the next object - i++; - } - } - } - - // if this is the ResourceType.ID, we create the actual list, from this list and - // the compiled resource list. - if (type == ResourceType.ID) { - mergeIdResources(); - } else { - // else this is the list that will actually be displayed, so we sort it. - Collections.sort(items); - } - } - - /** - * Looks up an existing {@link ProjectResourceItem} by {@link ResourceType} and name. - * @param type the Resource Type. - * @param name the Resource name. - * @return the existing ResourceItem or null if no match was found. - */ - protected ProjectResourceItem findResourceItem(ResourceType type, String name) { - List<ProjectResourceItem> list = mResourceMap.get(type); - - for (ProjectResourceItem item : list) { - if (name.equals(item.getName())) { - return item; - } - } - - return null; - } - - /** - * Sets compiled resource information. - * @param resIdValueToNameMap a map of compiled resource id to resource name. - * The map is acquired by the {@link ProjectResources} object. - * @param styleableValueMap - * @param resourceValueMap a map of (name, id) for resources of type {@link ResourceType#ID}. - * The list is acquired by the {@link ProjectResources} object. - */ - void setCompiledResources(Map<Integer, String[]> resIdValueToNameMap, - Map<IntArrayWrapper, String> styleableValueMap, - Map<String, Map<String, Integer>> resourceValueMap) { - mResourceValueMap = resourceValueMap; - mResIdValueToNameMap = resIdValueToNameMap; - mStyleableValueToNameMap = styleableValueMap; - mergeIdResources(); - } - - /** - * Merges the list of ID resource coming from R.java and the list of ID resources - * coming from XML declaration into the cached list {@link #mIdResourceList}. - */ - void mergeIdResources() { - // get the list of IDs coming from XML declaration. Those ids are present in - // mCompiledIdResources already, so we'll need to use those instead of creating - // new IdResourceItem - List<ProjectResourceItem> xmlIdResources = mResourceMap.get(ResourceType.ID); - - synchronized (mIdResourceList) { - // copy the currently cached items. - ArrayList<IdResourceItem> oldItems = new ArrayList<IdResourceItem>(); - oldItems.addAll(mIdResourceList); - - // empty the current list - mIdResourceList.clear(); - - // get the list of compile id resources. - Map<String, Integer> idMap = null; - if (mResourceValueMap != null) { - idMap = mResourceValueMap.get(ResourceType.ID.getName()); - } - - if (idMap == null) { - if (xmlIdResources != null) { - for (ProjectResourceItem resourceItem : xmlIdResources) { - // check the actual class just for safety. - if (resourceItem instanceof IdResourceItem) { - mIdResourceList.add((IdResourceItem)resourceItem); - } - } - } - } else { - // loop on the full list of id, and look for a match in the old list, - // in the list coming from XML (in case a new XML item was created.) - - Set<String> idSet = idMap.keySet(); - - idLoop: for (String idResource : idSet) { - // first look in the XML list in case an id went from inline to XML declared. - if (xmlIdResources != null) { - for (ProjectResourceItem resourceItem : xmlIdResources) { - if (resourceItem instanceof IdResourceItem && - resourceItem.getName().equals(idResource)) { - mIdResourceList.add((IdResourceItem)resourceItem); - continue idLoop; - } - } - } - - // if we haven't found it, look in the old items. - int count = oldItems.size(); - for (int i = 0 ; i < count ; i++) { - IdResourceItem resourceItem = oldItems.get(i); - if (resourceItem.getName().equals(idResource)) { - oldItems.remove(i); - mIdResourceList.add(resourceItem); - continue idLoop; - } - } - - // if we haven't found it, it looks like it's a new id that was - // declared inline. - mIdResourceList.add(new IdResourceItem(idResource, - true /* isDeclaredInline */)); - } - } - - // now we sort the list - Collections.sort(mIdResourceList); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java deleted file mode 100644 index dd8d080..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; - -/** - * Base class for file system resource items (Folders, Files). - */ -public abstract class Resource { - private boolean mTouched = true; - - /** - * Returns the {@link FolderConfiguration} for this object. - */ - public abstract FolderConfiguration getConfiguration(); - - /** - * Indicates that the underlying file was changed. - */ - public final void touch() { - mTouched = true; - } - - public final boolean isTouched() { - return mTouched; - } - - public final void resetTouch() { - mTouched = false; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java deleted file mode 100644 index f927a9a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile; -import com.android.layoutlib.api.IResourceValue; - -import java.util.Collection; - -/** - * Represents a Resource file (a file under $Project/res/) - */ -public abstract class ResourceFile extends Resource { - - private final IAbstractFile mFile; - private final ResourceFolder mFolder; - - protected ResourceFile(IAbstractFile file, ResourceFolder folder) { - mFile = file; - mFolder = folder; - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.Resource#getConfiguration() - */ - @Override - public FolderConfiguration getConfiguration() { - return mFolder.getConfiguration(); - } - - /** - * Returns the IFile associated with the ResourceFile. - */ - public final IAbstractFile getFile() { - return mFile; - } - - /** - * Returns the parent folder as a {@link ResourceFolder}. - */ - public final ResourceFolder getFolder() { - return mFolder; - } - - /** - * Returns whether the resource is a framework resource. - */ - public final boolean isFramework() { - return mFolder.isFramework(); - } - - /** - * Returns the list of {@link ResourceType} generated by the file. - */ - public abstract ResourceType[] getResourceTypes(); - - /** - * Returns whether the file generated a resource of a specific type. - * @param type The {@link ResourceType} - */ - public abstract boolean hasResources(ResourceType type); - - /** - * Get the list of {@link ProjectResourceItem} of a specific type generated by the file. - * This method must make sure not to create duplicate. - * @param type The type of {@link ProjectResourceItem} to return. - * @param projectResources The global Project Resource object, allowing the implementation to - * query for already existing {@link ProjectResourceItem} - * @return The list of <b>new</b> {@link ProjectResourceItem} - * @see ProjectResources#findResourceItem(ResourceType, String) - */ - public abstract Collection<ProjectResourceItem> getResources(ResourceType type, - ProjectResources projectResources); - - /** - * Returns the value of a resource generated by this file by {@link ResourceType} and name. - * <p/>If no resource match, <code>null</code> is returned. - * @param type the type of the resource. - * @param name the name of the resource. - */ - public abstract IResourceValue getValue(ResourceType type, String name); -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java deleted file mode 100644 index 6db0d94..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Resource Folder class. Contains list of {@link ResourceFile}s, - * the {@link FolderConfiguration}, and a link to the workspace {@link IFolder} object. - */ -public final class ResourceFolder extends Resource { - ResourceFolderType mType; - FolderConfiguration mConfiguration; - IAbstractFolder mFolder; - ArrayList<ResourceFile> mFiles = null; - private final boolean mIsFramework; - - /** - * Creates a new {@link ResourceFolder} - * @param type The type of the folder - * @param config The configuration of the folder - * @param folder The associated {@link IAbstractFolder} object. - * @param isFrameworkRepository - */ - public ResourceFolder(ResourceFolderType type, FolderConfiguration config, - IAbstractFolder folder, boolean isFrameworkRepository) { - mType = type; - mConfiguration = config; - mFolder = folder; - mIsFramework = isFrameworkRepository; - } - - /** - * Adds a {@link ResourceFile} to the folder. - * @param file The {@link ResourceFile}. - */ - public void addFile(ResourceFile file) { - if (mFiles == null) { - mFiles = new ArrayList<ResourceFile>(); - } - - mFiles.add(file); - } - - /** - * Attempts to remove the {@link ResourceFile} associated with a specified {@link IFile}. - * @param file the IFile object. - */ - public void removeFile(IFile file) { - if (mFiles != null) { - int count = mFiles.size(); - for (int i = 0 ; i < count ; i++) { - ResourceFile resFile = mFiles.get(i); - if (resFile != null) { - IFile iFile = resFile.getFile().getIFile(); - if (iFile != null && iFile.equals(file)) { - mFiles.remove(i); - touch(); - } - } - } - } - } - - /** - * Returns the {@link IFolder} associated with this object. - */ - public IAbstractFolder getFolder() { - return mFolder; - } - - /** - * Returns the {@link ResourceFolderType} of this object. - */ - public ResourceFolderType getType() { - return mType; - } - - /** - * Returns whether the folder is a framework resource folder. - */ - public boolean isFramework() { - return mIsFramework; - } - - /** - * Returns the list of {@link ResourceType}s generated by the files inside this folder. - */ - public Collection<ResourceType> getResourceTypes() { - ArrayList<ResourceType> list = new ArrayList<ResourceType>(); - - if (mFiles != null) { - for (ResourceFile file : mFiles) { - ResourceType[] types = file.getResourceTypes(); - - // loop through those and add them to the main list, - // if they are not already present - if (types != null) { - for (ResourceType resType : types) { - if (list.indexOf(resType) == -1) { - list.add(resType); - } - } - } - } - } - - return list; - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.Resource#getConfiguration() - */ - @Override - public FolderConfiguration getConfiguration() { - return mConfiguration; - } - - /** - * Returns whether the folder contains a file with the given name. - * @param name the name of the file. - */ - public boolean hasFile(String name) { - return mFolder.hasFile(name); - } - - /** - * Returns the {@link ResourceFile} matching a {@link IAbstractFile} object. - * @param file The {@link IFile} object. - * @return the {@link ResourceFile} or null if no match was found. - */ - public ResourceFile getFile(IAbstractFile file) { - if (mFiles != null) { - for (ResourceFile f : mFiles) { - if (f.getFile().equals(file)) { - return f; - } - } - } - return null; - } - - /** - * Returns the {@link ResourceFile} matching a {@link IFile} object. - * @param file The {@link IFile} object. - * @return the {@link ResourceFile} or null if no match was found. - */ - public ResourceFile getFile(IFile file) { - if (mFiles != null) { - for (ResourceFile f : mFiles) { - IFile iFile = f.getFile().getIFile(); - if (iFile != null && iFile.equals(file)) { - return f; - } - } - } - return null; - } - - - /** - * Returns the {@link ResourceFile} matching a given name. - * @param file The name of the file to return. - * @return the {@link ResourceFile} or <code>null</code> if no match was found. - */ - public ResourceFile getFile(String filename) { - if (mFiles != null) { - for (ResourceFile f : mFiles) { - if (f.getFile().getName().equals(filename)) { - return f; - } - } - } - return null; - } - - /** - * Returns whether a file in the folder is generating a resource of a specified type. - * @param type The {@link ResourceType} being looked up. - */ - public boolean hasResources(ResourceType type) { - // Check if the folder type is able to generate resource of the type that was asked. - // this is a first check to avoid going through the files. - ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type); - - boolean valid = false; - for (ResourceFolderType rft : folderTypes) { - if (rft == mType) { - valid = true; - break; - } - } - - if (valid) { - if (mFiles != null) { - for (ResourceFile f : mFiles) { - if (f.hasResources(type)) { - return true; - } - } - } - } - return false; - } - - /** - * Get the list of {@link ResourceItem} of a specific type generated by all the files - * in the folder. - * This method must make sure not to create duplicates. - * @param type The type of {@link ResourceItem} to return. - * @param projectResources The global Project Resource object, allowing the implementation to - * query for already existing {@link ResourceItem} - * @return The list of <b>new</b> {@link ResourceItem} - * @see ProjectResources#findResourceItem(ResourceType, String) - */ - public Collection<ProjectResourceItem> getResources(ResourceType type, - ProjectResources projectResources) { - Collection<ProjectResourceItem> list = new ArrayList<ProjectResourceItem>(); - if (mFiles != null) { - for (ResourceFile f : mFiles) { - list.addAll(f.getResources(type, projectResources)); - } - } - return list; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java deleted file mode 100644 index bd93301..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; - -/** - * Enum representing a type of resource folder. - */ -public enum ResourceFolderType { - ANIM(AndroidConstants.FD_ANIM), - COLOR(AndroidConstants.FD_COLOR), - DRAWABLE(AndroidConstants.FD_DRAWABLE), - LAYOUT(AndroidConstants.FD_LAYOUT), - MENU(AndroidConstants.FD_MENU), - RAW(AndroidConstants.FD_RAW), - VALUES(AndroidConstants.FD_VALUES), - XML(AndroidConstants.FD_XML); - - private final String mName; - - ResourceFolderType(String name) { - mName = name; - } - - public String getName() { - return mName; - } - - /** - * Returns the enum by name. - * @param name The enum string value. - * @return the enum or null if not found. - */ - public static ResourceFolderType getTypeByName(String name) { - for (ResourceFolderType rType : values()) { - if (rType.mName.equals(name)) { - return rType; - } - } - return null; - } - - /** - * Returns the {@link ResourceFolderType} from the folder name - * @param folderName The name of the folder. This must be a valid folder name in the format - * <code>resType[-resqualifiers[-resqualifiers[...]]</code> - * @return the <code>ResourceFolderType</code> representing the type of the folder, or - * <code>null</code> if no matching type was found. - */ - public static ResourceFolderType getFolderType(String folderName) { - // split the name of the folder in segments. - String[] folderSegments = folderName.split(FolderConfiguration.QUALIFIER_SEP); - - // get the enum for the resource type. - return getTypeByName(folderSegments[0]); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java deleted file mode 100644 index 64942ed..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFolderListener; -import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener; -import com.android.ide.eclipse.editors.resources.manager.files.FileWrapper; -import com.android.ide.eclipse.editors.resources.manager.files.FolderWrapper; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder; -import com.android.ide.eclipse.editors.resources.manager.files.IFileWrapper; -import com.android.ide.eclipse.editors.resources.manager.files.IFolderWrapper; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; - -public final class ResourceManager implements IProjectListener, IFolderListener, IFileListener { - - private final static ResourceManager sThis = new ResourceManager(); - - /** List of the qualifier object helping for the parsing of folder names */ - private final ResourceQualifier[] mQualifiers; - - /** - * Map associating project resource with project objects. - */ - private final HashMap<IProject, ProjectResources> mMap = - new HashMap<IProject, ProjectResources>(); - - private ProjectResources mFrameworkResources = null; - - /** - * Sets up the resource manager with the global resource monitor. - * @param monitor The global resource monitor - */ - public static void setup(ResourceMonitor monitor) { - monitor.addProjectListener(sThis); - int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED; - monitor.addFolderListener(sThis, mask); - monitor.addFileListener(sThis, mask); - - CompiledResourcesMonitor.setupMonitor(monitor); - } - - /** - * Returns the singleton instance. - */ - public static ResourceManager getInstance() { - return sThis; - } - - /** - * Returns the resources of a project. - * @param project The project - * @return a ProjectResources object or null if none was found. - */ - public ProjectResources getProjectResources(IProject project) { - return mMap.get(project); - } - - /** - * Returns the resources of the framework. - * <p/>This could be <code>null</code> if the parsing failed. - */ - public ProjectResources getFrameworkResources() { - return mFrameworkResources; - } - - /** - * Processes folder event. - */ - public void folderChanged(IFolder folder, int kind) { - ProjectResources resources; - - final IProject project = folder.getProject(); - - try { - if (project.hasNature(AndroidConstants.NATURE) == false) { - return; - } - } catch (CoreException e) { - // can't get the project nature? return! - return; - } - - switch (kind) { - case IResourceDelta.ADDED: - // checks if the folder is under res. - IPath path = folder.getFullPath(); - - // the path will be project/res/<something> - if (path.segmentCount() == 3) { - if (isInResFolder(path)) { - // get the project and its resource object. - resources = mMap.get(project); - - // if it doesn't exist, we create it. - if (resources == null) { - resources = new ProjectResources(false /* isFrameworkRepository */); - mMap.put(project, resources); - } - - processFolder(new IFolderWrapper(folder), resources); - } - } - break; - case IResourceDelta.CHANGED: - resources = mMap.get(folder.getProject()); - if (resources != null) { - ResourceFolder resFolder = resources.getResourceFolder(folder); - if (resFolder != null) { - resFolder.touch(); - } - } - break; - case IResourceDelta.REMOVED: - resources = mMap.get(folder.getProject()); - if (resources != null) { - // lets get the folder type - ResourceFolderType type = ResourceFolderType.getFolderType(folder.getName()); - - resources.removeFolder(type, folder); - } - break; - } - } - - /* (non-Javadoc) - * Sent when a file changed. Depending on the file being changed, and the type of change (ADDED, - * REMOVED, CHANGED), the file change is processed to update the resource manager data. - * - * @param file The file that changed. - * @param markerDeltas The marker deltas for the file. - * @param kind The change kind. This is equivalent to - * {@link IResourceDelta#accept(IResourceDeltaVisitor)} - * - * @see IFileListener#fileChanged - */ - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) { - ProjectResources resources; - - final IProject project = file.getProject(); - - try { - if (project.hasNature(AndroidConstants.NATURE) == false) { - return; - } - } catch (CoreException e) { - // can't get the project nature? return! - return; - } - - switch (kind) { - case IResourceDelta.ADDED: - // checks if the file is under res/something. - IPath path = file.getFullPath(); - - if (path.segmentCount() == 4) { - if (isInResFolder(path)) { - // get the project and its resources - resources = mMap.get(project); - - IContainer container = file.getParent(); - if (container instanceof IFolder && resources != null) { - - ResourceFolder folder = resources.getResourceFolder((IFolder)container); - - if (folder != null) { - processFile(new IFileWrapper(file), folder); - } - } - } - } - break; - case IResourceDelta.CHANGED: - // try to find a matching ResourceFile - resources = mMap.get(project); - if (resources != null) { - IContainer container = file.getParent(); - if (container instanceof IFolder) { - ResourceFolder resFolder = resources.getResourceFolder((IFolder)container); - - // we get the delete on the folder before the file, so it is possible - // the associated ResourceFolder doesn't exist anymore. - if (resFolder != null) { - // get the resourceFile, and touch it. - ResourceFile resFile = resFolder.getFile(file); - if (resFile != null) { - resFile.touch(); - } - } - } - } - break; - case IResourceDelta.REMOVED: - // try to find a matching ResourceFile - resources = mMap.get(project); - if (resources != null) { - IContainer container = file.getParent(); - if (container instanceof IFolder) { - ResourceFolder resFolder = resources.getResourceFolder((IFolder)container); - - // we get the delete on the folder before the file, so it is possible - // the associated ResourceFolder doesn't exist anymore. - if (resFolder != null) { - // remove the file - resFolder.removeFile(file); - } - } - } - break; - } - } - - public void projectClosed(IProject project) { - mMap.remove(project); - } - - public void projectDeleted(IProject project) { - mMap.remove(project); - } - - public void projectOpened(IProject project) { - createProject(project); - } - - public void projectOpenedWithWorkspace(IProject project) { - createProject(project); - } - - /** - * Returns the {@link ResourceFolder} for the given file or <code>null</code> if none exists. - */ - public ResourceFolder getResourceFolder(IFile file) { - IContainer container = file.getParent(); - if (container.getType() == IResource.FOLDER) { - IFolder parent = (IFolder)container; - IProject project = file.getProject(); - - ProjectResources resources = getProjectResources(project); - if (resources != null) { - return resources.getResourceFolder(parent); - } - } - - return null; - } - - /** - * Loads the framework resources. - * @param osFilePath the path to the folder containing all the versions of the framework - * resources - */ - public void loadFrameworkResources(String osResourcesPath) { - // for now only load the default framework resources - osResourcesPath += AndroidConstants.FD_DEFAULT_RES; - - File frameworkRes = new File(osResourcesPath); - if (frameworkRes.isDirectory()) { - mFrameworkResources = new ProjectResources(true /* isFrameworkRepository */); - - try { - File[] files = frameworkRes.listFiles(); - for (File file : files) { - if (file.isDirectory()) { - ResourceFolder resFolder = processFolder(new FolderWrapper(file), - mFrameworkResources); - - if (resFolder != null) { - // now we process the content of the folder - File[] children = file.listFiles(); - - for (File childRes : children) { - if (childRes.isFile()) { - processFile(new FileWrapper(childRes), resFolder); - } - } - } - - } - } - - // now that we have loaded the files, we need to force load the resources from them - mFrameworkResources.loadAll(); - - } catch (IOException e) { - // since we test that folders are folders, and files are files, this shouldn't - // happen. We can ignore it. - } - } - } - - /** - * Initial project parsing to gather resource info. - * @param project - */ - private void createProject(IProject project) { - if (project.isOpen()) { - try { - if (project.hasNature(AndroidConstants.NATURE) == false) { - return; - } - } catch (CoreException e1) { - // can't check the nature of the project? ignore it. - return; - } - - IFolder resourceFolder = project.getFolder(AndroidConstants.FD_RESOURCES); - - ProjectResources projectResources = mMap.get(project); - if (projectResources == null) { - projectResources = new ProjectResources(false /* isFrameworkRepository */); - mMap.put(project, projectResources); - } - - if (resourceFolder != null && resourceFolder.exists()) { - try { - IResource[] resources = resourceFolder.members(); - - for (IResource res : resources) { - if (res.getType() == IResource.FOLDER) { - IFolder folder = (IFolder)res; - ResourceFolder resFolder = processFolder(new IFolderWrapper(folder), - projectResources); - - if (resFolder != null) { - // now we process the content of the folder - IResource[] files = folder.members(); - - for (IResource fileRes : files) { - if (fileRes.getType() == IResource.FILE) { - IFile file = (IFile)fileRes; - - processFile(new IFileWrapper(file), resFolder); - } - } - } - } - } - } catch (CoreException e) { - // This happens if the project is closed or if the folder doesn't exist. - // Since we already test for that, we can ignore this exception. - } - } - } - } - - /** - * Creates a {@link FolderConfiguration} matching the folder segments. - * @param folderSegments The segments of the folder name. The first segments should contain - * the name of the folder - * @return a FolderConfiguration object, or null if the folder name isn't valid.. - */ - public FolderConfiguration getConfig(String[] folderSegments) { - FolderConfiguration config = new FolderConfiguration(); - - // we are going to loop through the segments, and match them with the first - // available qualifier. If the segment doesn't match we try with the next qualifier. - // Because the order of the qualifier is fixed, we do not reset the first qualifier - // after each sucessful segment. - // If we run out of qualifier before processing all the segments, we fail. - - int qualifierIndex = 0; - int qualifierCount = mQualifiers.length; - - for (int i = 1 ; i < folderSegments.length; i++) { - String seg = folderSegments[i]; - if (seg.length() > 0) { - while (qualifierIndex < qualifierCount && - mQualifiers[qualifierIndex].checkAndSet(seg, config) == false) { - qualifierIndex++; - } - - // if we reached the end of the qualifier we didn't find a matching qualifier. - if (qualifierIndex == qualifierCount) { - return null; - } - - } else { - return null; - } - } - - return config; - } - - /** - * Processes a folder and adds it to the list of the project resources. - * @param folder the folder to process - * @param project the folder's project. - * @return the ConfiguredFolder created from this folder, or null if the process failed. - */ - private ResourceFolder processFolder(IAbstractFolder folder, ProjectResources project) { - // split the name of the folder in segments. - String[] folderSegments = folder.getName().split(FolderConfiguration.QUALIFIER_SEP); - - // get the enum for the resource type. - ResourceFolderType type = ResourceFolderType.getTypeByName(folderSegments[0]); - - if (type != null) { - // get the folder configuration. - FolderConfiguration config = getConfig(folderSegments); - - if (config != null) { - ResourceFolder configuredFolder = project.add(type, config, folder); - - return configuredFolder; - } - } - - return null; - } - - /** - * Processes a file and adds it to its parent folder resource. - * @param file - * @param folder - */ - private void processFile(IAbstractFile file, ResourceFolder folder) { - // get the type of the folder - ResourceFolderType type = folder.getType(); - - // look for this file if it's already been created - ResourceFile resFile = folder.getFile(file); - - if (resFile != null) { - // invalidate the file - resFile.touch(); - } else { - // create a ResourceFile for it. - - // check if that's a single or multi resource type folder. For now we define this by - // the number of possible resource type output by files in the folder. This does - // not make the difference between several resource types from a single file or - // the ability to have 2 files in the same folder generating 2 different types of - // resource. The former is handled by MultiResourceFile properly while we don't - // handle the latter. If we were to add this behavior we'd have to change this call. - ResourceType[] types = FolderTypeRelationship.getRelatedResourceTypes(type); - - if (types.length == 1) { - resFile = new SingleResourceFile(file, folder); - } else { - resFile = new MultiResourceFile(file, folder); - } - - // add it to the folder - folder.addFile(resFile); - } - } - - /** - * Returns true if the path is under /project/res/ - * @param path a workspace relative path - * @return true if the path is under /project res/ - */ - private boolean isInResFolder(IPath path) { - return AndroidConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1)); - } - - /** - * Private constructor to enforce singleton design. - */ - ResourceManager() { - // get the default qualifiers. - FolderConfiguration defaultConfig = new FolderConfiguration(); - defaultConfig.createDefault(); - mQualifiers = defaultConfig.getQualifiers(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java deleted file mode 100644 index 45a020c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.project.BaseProjectHelper; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.core.IJavaModel; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; - -import java.util.ArrayList; - -/** - * Resource Monitor for the whole editor plugin. Other, more simple, listeners can register to - * that one. - */ -public class ResourceMonitor implements IResourceChangeListener { - - private final static ResourceMonitor sThis = new ResourceMonitor(); - - /** - * Classes which implement this interface provide a method that deals - * with file change events. - */ - public interface IFileListener { - /** - * Sent when a file changed. - * @param file The file that changed. - * @param markerDeltas The marker deltas for the file. - * @param kind The change kind. This is equivalent to - * {@link IResourceDelta#accept(IResourceDeltaVisitor)} - */ - public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind); - } - - /** - * Classes which implements this interface provide methods dealing with project events. - */ - public interface IProjectListener { - /** - * Sent for each opened android project at the time the listener is put in place. - * @param project the opened project. - */ - public void projectOpenedWithWorkspace(IProject project); - /** - * Sent when a project is opened. - * @param project the project being opened. - */ - public void projectOpened(IProject project); - /** - * Sent when a project is closed. - * @param project the project being closed. - */ - public void projectClosed(IProject project); - /** - * Sent when a project is deleted. - * @param project the project about to be deleted. - */ - public void projectDeleted(IProject project); - } - - /** - * Classes which implement this interface provide a method that deals - * with folder change events - */ - public interface IFolderListener { - /** - * Sent when a folder changed. - * @param folder The file that was changed - * @param kind The change kind. This is equivalent to {@link IResourceDelta#getKind()} - */ - public void folderChanged(IFolder folder, int kind); - } - - /** - * Interface for a listener to be notified when resource change event starts and ends. - */ - public interface IResourceEventListener { - public void resourceChangeEventStart(); - public void resourceChangeEventEnd(); - } - - /** - * Base listener bundle to associate a listener to an event mask. - */ - private static class ListenerBundle { - /** Mask value to accept all events */ - public final static int MASK_NONE = -1; - - /** - * Event mask. Values accepted are IResourceDelta.### - * @see IResourceDelta#ADDED - * @see IResourceDelta#REMOVED - * @see IResourceDelta#CHANGED - * @see IResourceDelta#ADDED_PHANTOM - * @see IResourceDelta#REMOVED_PHANTOM - * */ - int kindMask; - } - - /** - * Listener bundle for file event. - */ - private static class FileListenerBundle extends ListenerBundle { - - /** The file listener */ - IFileListener listener; - } - - /** - * Listener bundle for folder event. - */ - private static class FolderListenerBundle extends ListenerBundle { - /** The file listener */ - IFolderListener listener; - } - - private final ArrayList<FileListenerBundle> mFileListeners = - new ArrayList<FileListenerBundle>(); - - private final ArrayList<FolderListenerBundle> mFolderListeners = - new ArrayList<FolderListenerBundle>(); - - private final ArrayList<IProjectListener> mProjectListeners = new ArrayList<IProjectListener>(); - - private final ArrayList<IResourceEventListener> mEventListeners = - new ArrayList<IResourceEventListener>(); - - private IWorkspace mWorkspace; - - /** - * Delta visitor for resource changes. - */ - private final class DeltaVisitor implements IResourceDeltaVisitor { - - public boolean visit(IResourceDelta delta) { - IResource r = delta.getResource(); - int type = r.getType(); - if (type == IResource.FILE) { - int kind = delta.getKind(); - // notify the listeners. - for (FileListenerBundle bundle : mFileListeners) { - if (bundle.kindMask == ListenerBundle.MASK_NONE - || (bundle.kindMask & kind) != 0) { - bundle.listener.fileChanged((IFile)r, delta.getMarkerDeltas(), kind); - } - } - return false; - } else if (type == IResource.FOLDER) { - int kind = delta.getKind(); - // notify the listeners. - for (FolderListenerBundle bundle : mFolderListeners) { - if (bundle.kindMask == ListenerBundle.MASK_NONE - || (bundle.kindMask & kind) != 0) { - bundle.listener.folderChanged((IFolder)r, kind); - } - } - return true; - } else if (type == IResource.PROJECT) { - int flags = delta.getFlags(); - - if (flags == IResourceDelta.OPEN) { - // the project is opening or closing. - IProject project = (IProject)r; - - // the OPEN flag represent a toggle in the open/close state of the - // project, but this is sent before the project actually toggles - // its state. - // This means that if the project is closing, isOpen() will return true. - boolean isClosing = project.isOpen(); - if (isClosing) { - // notify the listeners. - for (IProjectListener pl : mProjectListeners) { - pl.projectClosed(project); - } - } else { - // notify the listeners. - for (IProjectListener pl : mProjectListeners) { - pl.projectOpened(project); - } - } - } - } - - return true; - } - } - - public static ResourceMonitor getMonitor() { - return sThis; - } - - - /** - * Starts the resource monitoring. - * @param ws The current workspace. - * @return The monitor object. - */ - public static ResourceMonitor startMonitoring(IWorkspace ws) { - if (sThis != null) { - ws.addResourceChangeListener(sThis, - IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE); - sThis.mWorkspace = ws; - } - return sThis; - } - - /** - * Stops the resource monitoring. - * @param ws The current workspace. - */ - public static void stopMonitoring(IWorkspace ws) { - if (sThis != null) { - ws.removeResourceChangeListener(sThis); - - sThis.mFileListeners.clear(); - sThis.mProjectListeners.clear(); - } - } - - /** - * Adds a file listener. - * @param listener The listener to receive the events. - * @param kindMask The event mask to filter out specific events. - * {@link ListenerBundle#MASK_NONE} will forward all events. - */ - public synchronized void addFileListener(IFileListener listener, int kindMask) { - FileListenerBundle bundle = new FileListenerBundle(); - bundle.listener = listener; - bundle.kindMask = kindMask; - - mFileListeners.add(bundle); - } - - /** - * Adds a folder listener. - * @param listener The listener to receive the events. - * @param kindMask The event mask to filter out specific events. - * {@link ListenerBundle#MASK_NONE} will forward all events. - */ - public synchronized void addFolderListener(IFolderListener listener, int kindMask) { - FolderListenerBundle bundle = new FolderListenerBundle(); - bundle.listener = listener; - bundle.kindMask = kindMask; - - mFolderListeners.add(bundle); - } - - /** - * Adds a project listener. - * @param listener The listener to receive the events. - */ - public synchronized void addProjectListener(IProjectListener listener) { - mProjectListeners.add(listener); - - // we need to look at the opened projects and give them to the listener. - - // get the list of opened android projects. - IWorkspaceRoot workspaceRoot = mWorkspace.getRoot(); - IJavaModel javaModel = JavaCore.create(workspaceRoot); - IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(javaModel); - - for (IJavaProject androidProject : androidProjects) { - listener.projectOpenedWithWorkspace(androidProject.getProject()); - } - } - - public synchronized void addResourceEventListener(IResourceEventListener listener) { - mEventListeners.add(listener); - } - - /** - * Processes the workspace resource change events. - */ - public void resourceChanged(IResourceChangeEvent event) { - // notify the event listeners of a start. - for (IResourceEventListener listener : mEventListeners) { - listener.resourceChangeEventStart(); - } - - if (event.getType() == IResourceChangeEvent.PRE_DELETE) { - // a project is being deleted. Lets get the project object and remove - // its compiled resource list. - IResource r = event.getResource(); - IProject project = r.getProject(); - - // notify the listeners. - for (IProjectListener pl : mProjectListeners) { - pl.projectDeleted(project); - } - } else { - // this a regular resource change. We get the delta and go through it with a visitor. - IResourceDelta delta = event.getDelta(); - - DeltaVisitor visitor = new DeltaVisitor(); - try { - delta.accept(visitor); - } catch (CoreException e) { - } - } - - // we're done, notify the event listeners. - for (IResourceEventListener listener : mEventListeners) { - listener.resourceChangeEventEnd(); - } - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java deleted file mode 100644 index 1211236..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.manager; - -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile; -import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.utils.ResourceValue; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.parsers.SAXParserFactory; - -/** - * Represents a resource file describing a single resource. - * <p/> - * This is typically an XML file inside res/anim, res/layout, or res/menu or an image file - * under res/drawable. - */ -public class SingleResourceFile extends ResourceFile { - - private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); - static { - sParserFactory.setNamespaceAware(true); - } - - private final static Pattern sXmlPattern = Pattern.compile("^(.+)\\.xml", //$NON-NLS-1$ - Pattern.CASE_INSENSITIVE); - - private final static Pattern[] sDrawablePattern = new Pattern[] { - Pattern.compile("^(.+)\\.9\\.png", Pattern.CASE_INSENSITIVE), //$NON-NLS-1$ - Pattern.compile("^(.+)\\.png", Pattern.CASE_INSENSITIVE), //$NON-NLS-1$ - Pattern.compile("^(.+)\\.jpg", Pattern.CASE_INSENSITIVE), //$NON-NLS-1$ - Pattern.compile("^(.+)\\.gif", Pattern.CASE_INSENSITIVE), //$NON-NLS-1$ - }; - - private String mResourceName; - private ResourceType mType; - private IResourceValue mValue; - - public SingleResourceFile(IAbstractFile file, ResourceFolder folder) { - super(file, folder); - - // we need to infer the type of the resource from the folder type. - // This is easy since this is a single Resource file. - ResourceType[] types = FolderTypeRelationship.getRelatedResourceTypes(folder.getType()); - mType = types[0]; - - // compute the resource name - mResourceName = getResourceName(mType); - - mValue = new ResourceValue(mType.getName(), getResourceName(mType), file.getOsLocation(), - isFramework()); - } - - @Override - public ResourceType[] getResourceTypes() { - return FolderTypeRelationship.getRelatedResourceTypes(getFolder().getType()); - } - - @Override - public boolean hasResources(ResourceType type) { - return FolderTypeRelationship.match(type, getFolder().getType()); - } - - @Override - public Collection<ProjectResourceItem> getResources(ResourceType type, - ProjectResources projectResources) { - - // looking for an existing ResourceItem with this name and type - ProjectResourceItem item = projectResources.findResourceItem(type, mResourceName); - - ArrayList<ProjectResourceItem> items = new ArrayList<ProjectResourceItem>(); - - if (item == null) { - item = new ConfigurableResourceItem(mResourceName); - items.add(item); - } - - // add this ResourceFile to the ResourceItem - item.add(this); - - return items; - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.ResourceFile#getValue(com.android.ide.eclipse.common.resources.ResourceType, java.lang.String) - * - * This particular implementation does not care about the type or name since a - * SingleResourceFile represents a file generating only one resource. - * The value returned is the full absolute path of the file in OS form. - */ - @Override - public IResourceValue getValue(ResourceType type, String name) { - return mValue; - } - - /** - * Returns the name of the resources. - * @param type - * @return - */ - private String getResourceName(ResourceType type) { - // get the name from the filename. - String name = getFile().getName(); - - if (type == ResourceType.ANIM || type == ResourceType.LAYOUT || type == ResourceType.MENU || - type == ResourceType.COLOR || type == ResourceType.XML) { - Matcher m = sXmlPattern.matcher(name); - if (m.matches()) { - return m.group(1); - } - } else if (type == ResourceType.DRAWABLE) { - for (Pattern p : sDrawablePattern) { - Matcher m = p.matcher(name); - if (m.matches()) { - return m.group(1); - } - } - - // also try the Xml pattern for selector/shape based drawable. - Matcher m = sXmlPattern.matcher(name); - if (m.matches()) { - return m.group(1); - } - } - return name; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java deleted file mode 100644 index 0a14214..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.CoreException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -/** - * An implementation of {@link IAbstractFile} on top of a {@link File} object. - * - */ -public class FileWrapper implements IAbstractFile { - - private File mFile; - - /** - * Constructs a {@link FileWrapper} object. If {@link File#isFile()} returns <code>false</code> - * then an {@link IOException} is thrown. - */ - public FileWrapper(File file) throws IOException { - if (file.isFile() == false) { - throw new IOException("FileWrapper must wrap a File object representing an existing file!"); //$NON-NLS-1$ - } - - mFile = file; - } - - public InputStream getContents() throws CoreException { - try { - return new FileInputStream(mFile); - } catch (FileNotFoundException e) { - // we'll return null below. - } - - return null; - } - - public IFile getIFile() { - return null; - } - - public String getOsLocation() { - return mFile.getAbsolutePath(); - } - - public String getName() { - return mFile.getName(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof FileWrapper) { - return mFile.equals(((FileWrapper)obj).mFile); - } - - if (obj instanceof File) { - return mFile.equals((File)obj); - } - - return super.equals(obj); - } - - @Override - public int hashCode() { - return mFile.hashCode(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java deleted file mode 100644 index 8afea33..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFolder; - -import java.io.File; -import java.io.IOException; - -/** - * An implementation of {@link IAbstractFolder} on top of a {@link File} object. - */ -public class FolderWrapper implements IAbstractFolder { - - private File mFolder; - - /** - * Constructs a {@link FileWrapper} object. If {@link File#isDirectory()} returns - * <code>false</code> then an {@link IOException} is thrown. - */ - public FolderWrapper(File folder) throws IOException { - if (folder.isDirectory() == false) { - throw new IOException("FileWrapper must wrap a File object representing an existing folder!"); //$NON-NLS-1$ - } - - mFolder = folder; - } - - public boolean hasFile(String name) { - return false; - } - - public String getName() { - return mFolder.getName(); - } - - public IFolder getIFolder() { - return null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof FolderWrapper) { - return mFolder.equals(((FolderWrapper)obj).mFolder); - } - - if (obj instanceof File) { - return mFolder.equals((File)obj); - } - - return super.equals(obj); - } - - @Override - public int hashCode() { - return mFolder.hashCode(); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java deleted file mode 100644 index 7e807f9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.CoreException; - -import java.io.InputStream; - -/** - * A file. - */ -public interface IAbstractFile extends IAbstractResource { - - /** - * Returns an {@link InputStream} object on the file content. - * @throws CoreException - */ - InputStream getContents() throws CoreException; - - /** - * Returns the OS path of the file location. - */ - String getOsLocation(); - - /** - * Returns the {@link IFile} object that the receiver could represent. Can be <code>null</code> - */ - IFile getIFile(); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java deleted file mode 100644 index b35283d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFolder; - -/** - * A folder. - */ -public interface IAbstractFolder extends IAbstractResource { - - /** - * Returns true if the receiver contains a file with a given name - * @param name the name of the file. This is the name without the path leading to the - * parent folder. - */ - boolean hasFile(String name); - - /** - * Returns the {@link IFolder} object that the receiver could represent. - * Can be <code>null</code> - */ - IFolder getIFolder(); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java deleted file mode 100644 index daf243d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFile; - -import java.io.File; - -/** - * Base representation of a file system resource.<p/> - * This somewhat limited interface is designed to let classes use file-system resources, without - * having the manually handle {@link IFile} and/or {@link File} manually. - */ -public interface IAbstractResource { - - /** - * Returns the name of the resource. - */ - String getName(); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java deleted file mode 100644 index 441c65b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.CoreException; - -import java.io.InputStream; - -/** - * An implementation of {@link IAbstractFile} on top of an {@link IFile} object. - */ -public class IFileWrapper implements IAbstractFile { - - private IFile mFile; - - public IFileWrapper(IFile file) { - mFile = file; - } - - public InputStream getContents() throws CoreException { - return mFile.getContents(); - } - - public String getOsLocation() { - return mFile.getLocation().toOSString(); - } - - public String getName() { - return mFile.getName(); - } - - public IFile getIFile() { - return mFile; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof IFileWrapper) { - return mFile.equals(((IFileWrapper)obj).mFile); - } - - if (obj instanceof IFile) { - return mFile.equals((IFile)obj); - } - - return super.equals(obj); - } - - @Override - public int hashCode() { - return mFile.hashCode(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java deleted file mode 100644 index 92b5c07..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.manager.files; - -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; - -/** - * An implementation of {@link IAbstractFolder} on top of an {@link IFolder} object. - */ -public class IFolderWrapper implements IAbstractFolder { - - private IFolder mFolder; - - public IFolderWrapper(IFolder folder) { - mFolder = folder; - } - - public String getName() { - return mFolder.getName(); - } - - public boolean hasFile(String name) { - try { - IResource[] files = mFolder.members(); - for (IResource file : files) { - if (name.equals(file.getName())) { - return true; - } - } - } catch (CoreException e) { - // we'll return false below. - } - - return false; - } - - public IFolder getIFolder() { - return mFolder; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof IFolderWrapper) { - return mFolder.equals(((IFolderWrapper)obj).mFolder); - } - - if (obj instanceof IFolder) { - return mFolder.equals((IFolder)obj); - } - - return super.equals(obj); - } - - @Override - public int hashCode() { - return mFolder.hashCode(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java deleted file mode 100644 index 29453e9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.resources.uimodel; - -import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.editors.uimodel.UiTextValueNode; - -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.widgets.Text; - -import java.util.regex.Pattern; - -/** - * Displays and edits a color XML element value with a custom validator. - * <p/> - * See {@link UiAttributeNode} for more information. - */ -public class UiColorValueNode extends UiTextValueNode { - - /** Accepted RGBA formats are one of #RGB, #ARGB, #RRGGBB or #AARRGGBB. */ - private static final Pattern RGBA_REGEXP = Pattern.compile( - "#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})"); //$NON-NLS-1$ - - public UiColorValueNode(TextValueDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /* (non-java doc) - * - * Add a modify listener that will check colors have the proper format, - * that is one of #RGB, #ARGB, #RRGGBB or #AARRGGBB. - */ - @Override - protected void onAddValidators(final Text text) { - ModifyListener listener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - String color = text.getText(); - if (RGBA_REGEXP.matcher(color).matches()) { - getManagedForm().getMessageManager().removeMessage(text, text); - } else { - getManagedForm().getMessageManager().addMessage(text, - "Accepted color formats are one of #RGB, #ARGB, #RRGGBB or #AARRGGBB.", - null /* data */, IMessageProvider.ERROR, text); - } - } - }; - - text.addModifyListener(listener); - - // Make sure the validator removes its message(s) when the widget is disposed - text.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - getManagedForm().getMessageManager().removeMessage(text, text); - } - }); - - // Finally call the validator once to make sure the initial value is processed - listener.modifyText(null); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java deleted file mode 100644 index 89649f5..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.resources.uimodel; - -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.resources.descriptors.ItemElementDescriptor; -import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * {@link UiItemElementNode} is apecial version of {@link UiElementNode} that - * customizes the element display to include the item type attribute if present. - */ -public class UiItemElementNode extends UiElementNode { - - /** - * Creates a new {@link UiElementNode} described by a given {@link ItemElementDescriptor}. - * - * @param elementDescriptor The {@link ItemElementDescriptor} for the XML node. Cannot be null. - */ - public UiItemElementNode(ItemElementDescriptor elementDescriptor) { - super(elementDescriptor); - } - - @Override - public String getShortDescription() { - Node xmlNode = getXmlNode(); - if (xmlNode != null && xmlNode instanceof Element && xmlNode.hasAttributes()) { - - Element elem = (Element) xmlNode; - String type = elem.getAttribute(ResourcesDescriptors.TYPE_ATTR); - String name = elem.getAttribute(ResourcesDescriptors.NAME_ATTR); - if (type != null && name != null && type.length() > 0 && name.length() > 0) { - type = DescriptorsUtils.capitalize(type); - return String.format("%1$s (%2$s %3$s)", name, type, getDescriptor().getUiName()); - } - } - - return super.getShortDescription(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java deleted file mode 100644 index 5fb479f..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.jface.viewers.DialogCellEditor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusAdapter; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.TraverseEvent; -import org.eclipse.swt.events.TraverseListener; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Text; - -import java.text.MessageFormat; - -/** - * Custom DialogCellEditor, replacing the Label with an editable {@link Text} widget. - * <p/>Also set the button to {@link SWT#FLAT} to make sure it looks good on MacOS X. - * <p/>Most of the code comes from TextCellEditor. - */ -public abstract class EditableDialogCellEditor extends DialogCellEditor { - - private Text text; - - private ModifyListener modifyListener; - - /** - * State information for updating action enablement - */ - private boolean isSelection = false; - - private boolean isDeleteable = false; - - private boolean isSelectable = false; - - EditableDialogCellEditor(Composite parent) { - super(parent); - } - - /* - * Re-implement this method only to properly set the style in the button, or it won't look - * good in MacOS X - */ - @Override - protected Button createButton(Composite parent) { - Button result = new Button(parent, SWT.DOWN | SWT.FLAT); - result.setText("..."); //$NON-NLS-1$ - return result; - } - - - @Override - protected Control createContents(Composite cell) { - text = new Text(cell, SWT.SINGLE); - text.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - handleDefaultSelection(e); - } - }); - text.addKeyListener(new KeyAdapter() { - // hook key pressed - see PR 14201 - @Override - public void keyPressed(KeyEvent e) { - keyReleaseOccured(e); - - // as a result of processing the above call, clients may have - // disposed this cell editor - if ((getControl() == null) || getControl().isDisposed()) { - return; - } - checkSelection(); // see explanation below - checkDeleteable(); - checkSelectable(); - } - }); - text.addTraverseListener(new TraverseListener() { - public void keyTraversed(TraverseEvent e) { - if (e.detail == SWT.TRAVERSE_ESCAPE - || e.detail == SWT.TRAVERSE_RETURN) { - e.doit = false; - } - } - }); - // We really want a selection listener but it is not supported so we - // use a key listener and a mouse listener to know when selection changes - // may have occurred - text.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent e) { - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - }); - text.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - EditableDialogCellEditor.this.focusLost(); - } - }); - text.setFont(cell.getFont()); - text.setBackground(cell.getBackground()); - text.setText("");//$NON-NLS-1$ - text.addModifyListener(getModifyListener()); - return text; - } - - /** - * Checks to see if the "deletable" state (can delete/ - * nothing to delete) has changed and if so fire an - * enablement changed notification. - */ - private void checkDeleteable() { - boolean oldIsDeleteable = isDeleteable; - isDeleteable = isDeleteEnabled(); - if (oldIsDeleteable != isDeleteable) { - fireEnablementChanged(DELETE); - } - } - - /** - * Checks to see if the "selectable" state (can select) - * has changed and if so fire an enablement changed notification. - */ - private void checkSelectable() { - boolean oldIsSelectable = isSelectable; - isSelectable = isSelectAllEnabled(); - if (oldIsSelectable != isSelectable) { - fireEnablementChanged(SELECT_ALL); - } - } - - /** - * Checks to see if the selection state (selection / - * no selection) has changed and if so fire an - * enablement changed notification. - */ - private void checkSelection() { - boolean oldIsSelection = isSelection; - isSelection = text.getSelectionCount() > 0; - if (oldIsSelection != isSelection) { - fireEnablementChanged(COPY); - fireEnablementChanged(CUT); - } - } - - /* (non-Javadoc) - * Method declared on CellEditor. - */ - @Override - protected void doSetFocus() { - if (text != null) { - text.selectAll(); - text.setFocus(); - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jface.viewers.DialogCellEditor#updateContents(java.lang.Object) - */ - @Override - protected void updateContents(Object value) { - Assert.isTrue(text != null && (value == null || (value instanceof String))); - if (value != null) { - text.removeModifyListener(getModifyListener()); - text.setText((String) value); - text.addModifyListener(getModifyListener()); - } - } - - /** - * The <code>TextCellEditor</code> implementation of - * this <code>CellEditor</code> framework method returns - * the text string. - * - * @return the text string - */ - @Override - protected Object doGetValue() { - return text.getText(); - } - - - /** - * Processes a modify event that occurred in this text cell editor. - * This framework method performs validation and sets the error message - * accordingly, and then reports a change via <code>fireEditorValueChanged</code>. - * Subclasses should call this method at appropriate times. Subclasses - * may extend or reimplement. - * - * @param e the SWT modify event - */ - protected void editOccured(ModifyEvent e) { - String value = text.getText(); - if (value == null) { - value = "";//$NON-NLS-1$ - } - Object typedValue = value; - boolean oldValidState = isValueValid(); - boolean newValidState = isCorrect(typedValue); - - if (!newValidState) { - // try to insert the current value into the error message. - setErrorMessage(MessageFormat.format(getErrorMessage(), - new Object[] { value })); - } - valueChanged(oldValidState, newValidState); - } - - /** - * Return the modify listener. - */ - private ModifyListener getModifyListener() { - if (modifyListener == null) { - modifyListener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - editOccured(e); - } - }; - } - return modifyListener; - } - - /** - * Handles a default selection event from the text control by applying the editor - * value and deactivating this cell editor. - * - * @param event the selection event - * - * @since 3.0 - */ - protected void handleDefaultSelection(SelectionEvent event) { - // same with enter-key handling code in keyReleaseOccured(e); - fireApplyEditorValue(); - deactivate(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method returns <code>true</code> if - * the current selection is not empty. - */ - @Override - public boolean isCopyEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return text.getSelectionCount() > 0; - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method returns <code>true</code> if - * the current selection is not empty. - */ - @Override - public boolean isCutEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return text.getSelectionCount() > 0; - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method returns <code>true</code> - * if there is a selection or if the caret is not positioned - * at the end of the text. - */ - @Override - public boolean isDeleteEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return text.getSelectionCount() > 0 - || text.getCaretPosition() < text.getCharCount(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method always returns <code>true</code>. - */ - @Override - public boolean isPasteEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return true; - } - - /** - * Check if save all is enabled - * @return true if it is - */ - public boolean isSaveAllEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return true; - } - - /** - * Returns <code>true</code> if this cell editor is - * able to perform the select all action. - * <p> - * This default implementation always returns - * <code>false</code>. - * </p> - * <p> - * Subclasses may override - * </p> - * @return <code>true</code> if select all is possible, - * <code>false</code> otherwise - */ - @Override - public boolean isSelectAllEnabled() { - if (text == null || text.isDisposed()) { - return false; - } - return text.getCharCount() > 0; - } - - /** - * Processes a key release event that occurred in this cell editor. - * <p> - * The <code>TextCellEditor</code> implementation of this framework method - * ignores when the RETURN key is pressed since this is handled in - * <code>handleDefaultSelection</code>. - * An exception is made for Ctrl+Enter for multi-line texts, since - * a default selection event is not sent in this case. - * </p> - * - * @param keyEvent the key event - */ - @Override - protected void keyReleaseOccured(KeyEvent keyEvent) { - if (keyEvent.character == '\r') { // Return key - // Enter is handled in handleDefaultSelection. - // Do not apply the editor value in response to an Enter key event - // since this can be received from the IME when the intent is -not- - // to apply the value. - // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control - // - // An exception is made for Ctrl+Enter for multi-line texts, since - // a default selection event is not sent in this case. - if (text != null && !text.isDisposed() - && (text.getStyle() & SWT.MULTI) != 0) { - if ((keyEvent.stateMask & SWT.CTRL) != 0) { - super.keyReleaseOccured(keyEvent); - } - } - return; - } - super.keyReleaseOccured(keyEvent); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method copies the - * current selection to the clipboard. - */ - @Override - public void performCopy() { - text.copy(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method cuts the - * current selection to the clipboard. - */ - @Override - public void performCut() { - text.cut(); - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method deletes the - * current selection or, if there is no selection, - * the character next character from the current position. - */ - @Override - public void performDelete() { - if (text.getSelectionCount() > 0) { - // remove the contents of the current selection - text.insert(""); //$NON-NLS-1$ - } else { - // remove the next character - int pos = text.getCaretPosition(); - if (pos < text.getCharCount()) { - text.setSelection(pos, pos + 1); - text.insert(""); //$NON-NLS-1$ - } - } - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method pastes the - * the clipboard contents over the current selection. - */ - @Override - public void performPaste() { - text.paste(); - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - - /** - * The <code>TextCellEditor</code> implementation of this - * <code>CellEditor</code> method selects all of the - * current text. - */ - @Override - public void performSelectAll() { - text.selectAll(); - checkSelection(); - checkDeleteable(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java deleted file mode 100644 index d095376..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.android.ide.eclipse.editors.ui; - -import org.eclipse.jface.resource.CompositeImageDescriptor; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.DecorationOverlayIcon; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; - -/** - * ImageDescriptor that adds a error marker. - * Based on {@link DecorationOverlayIcon} only available in Eclipse 3.3 - */ -public class ErrorImageComposite extends CompositeImageDescriptor { - - private Image mBaseImage; - private ImageDescriptor mErrorImageDescriptor; - private Point mSize; - - public ErrorImageComposite(Image baseImage) { - mBaseImage = baseImage; - mErrorImageDescriptor = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( - ISharedImages.IMG_OBJS_ERROR_TSK); - mSize = new Point(baseImage.getBounds().width, baseImage.getBounds().height); - } - - @Override - protected void drawCompositeImage(int width, int height) { - ImageData baseData = mBaseImage.getImageData(); - drawImage(baseData, 0, 0); - - ImageData overlayData = mErrorImageDescriptor.getImageData(); - if (overlayData.width == baseData.width && baseData.height == baseData.height) { - overlayData = overlayData.scaledTo(14, 14); - drawImage(overlayData, -3, mSize.y - overlayData.height + 3); - } else { - drawImage(overlayData, 0, mSize.y - overlayData.height); - } - } - - @Override - protected Point getSize() { - return mSize; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java deleted file mode 100644 index ccae099..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** - * DialogCellEditor able to receive a {@link UiFlagAttributeNode} in the {@link #setValue(Object)} - * method. - * <p/>The dialog box opened is the same as the one in the ui created by - * {@link UiFlagAttributeNode#createUiControl(Composite, org.eclipse.ui.forms.IManagedForm)} - */ -public class FlagValueCellEditor extends EditableDialogCellEditor { - - private UiFlagAttributeNode mUiFlagAttribute; - - public FlagValueCellEditor(Composite parent) { - super(parent); - } - - @Override - protected Object openDialogBox(Control cellEditorWindow) { - if (mUiFlagAttribute != null) { - String currentValue = (String)getValue(); - return mUiFlagAttribute.showDialog(cellEditorWindow.getShell(), currentValue); - } - - return null; - } - - @Override - protected void doSetValue(Object value) { - if (value instanceof UiFlagAttributeNode) { - mUiFlagAttribute = (UiFlagAttributeNode)value; - super.doSetValue(mUiFlagAttribute.getCurrentValue()); - return; - } - - super.doSetValue(value); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java deleted file mode 100644 index 304dd14..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.uimodel.UiListAttributeNode; - -import org.eclipse.jface.viewers.ComboBoxCellEditor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CCombo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** - * ComboBoxCellEditor able to receive a {@link UiListAttributeNode} in the {@link #setValue(Object)} - * method, and returning a {@link String} in {@link #getValue()} instead of an {@link Integer}. - */ -public class ListValueCellEditor extends ComboBoxCellEditor { - private String[] mItems; - private CCombo mCombo; - - public ListValueCellEditor(Composite parent) { - super(parent, new String[0], SWT.DROP_DOWN); - } - - @Override - protected Control createControl(Composite parent) { - mCombo = (CCombo) super.createControl(parent); - return mCombo; - } - - @Override - protected void doSetValue(Object value) { - if (value instanceof UiListAttributeNode) { - UiListAttributeNode uiListAttribute = (UiListAttributeNode)value; - - // set the possible values in the combo - String[] items = uiListAttribute.getPossibleValues(); - mItems = new String[items.length]; - System.arraycopy(items, 0, mItems, 0, items.length); - setItems(mItems); - - // now edit the current value of the attribute - String attrValue = uiListAttribute.getCurrentValue(); - mCombo.setText(attrValue); - - return; - } - - // default behavior - super.doSetValue(value); - } - - @Override - protected Object doGetValue() { - String comboText = mCombo.getText(); - if (comboText == null) { - return ""; //$NON-NLS-1$ - } - return comboText; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java deleted file mode 100644 index 4fc0ab3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** - * DialogCellEditor able to receive a {@link UiFlagAttributeNode} in the {@link #setValue(Object)} - * method. - * <p/>The dialog box opened is the same as the one in the ui created by - * {@link UiFlagAttributeNode#createUiControl(Composite, org.eclipse.ui.forms.IManagedForm)} - */ -public class ResourceValueCellEditor extends EditableDialogCellEditor { - - private UiResourceAttributeNode mUiResourceAttribute; - - public ResourceValueCellEditor(Composite parent) { - super(parent); - } - - @Override - protected Object openDialogBox(Control cellEditorWindow) { - if (mUiResourceAttribute != null) { - String currentValue = (String)getValue(); - return mUiResourceAttribute.showDialog(cellEditorWindow.getShell(), currentValue); - } - - return null; - } - - @Override - protected void doSetValue(Object value) { - if (value instanceof UiResourceAttributeNode) { - mUiResourceAttribute = (UiResourceAttributeNode)value; - super.doSetValue(mUiResourceAttribute.getCurrentValue()); - return; - } - - super.doSetValue(value); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java deleted file mode 100644 index 7942024..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; - -import org.eclipse.jface.text.DefaultInformationControl; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseTrackListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.SectionPart; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.eclipse.ui.forms.widgets.TableWrapLayout; - -import java.lang.reflect.Method; - -/** - * Helper for the AndroidManifest form editor. - * - * Helps create a new SectionPart with sensible default parameters, - * create default layout or add typical widgets. - * - * IMPORTANT: This is NOT a generic class. It makes a lot of assumptions on the - * UI as used by the form editor for the AndroidManifest. - * - * TODO: Consider moving to a common package. - */ -public final class SectionHelper { - - /** - * Utility class that derives from SectionPart, constructs the Section with - * sensible defaults (with a title and a description) and provide some shorthand - * methods for creating typically UI (label and text, form text.) - */ - static public class ManifestSectionPart extends SectionPart { - - /** - * Construct a SectionPart that uses a title bar and a description. - * It's up to the caller to call setText() and setDescription(). - * <p/> - * The section style includes a description and a title bar by default. - * - * @param body The parent (e.g. FormPage body) - * @param toolkit Form Toolkit - */ - public ManifestSectionPart(Composite body, FormToolkit toolkit) { - this(body, toolkit, 0, false); - } - - /** - * Construct a SectionPart that uses a title bar and a description. - * It's up to the caller to call setText() and setDescription(). - * <p/> - * The section style includes a description and a title bar by default. - * You can add extra styles, like Section.TWISTIE. - * - * @param body The parent (e.g. FormPage body). - * @param toolkit Form Toolkit. - * @param extra_style Extra styles (on top of description and title bar). - * @param use_description True if the Section.DESCRIPTION style should be added. - */ - public ManifestSectionPart(Composite body, FormToolkit toolkit, - int extra_style, boolean use_description) { - super(body, toolkit, extra_style | - Section.TITLE_BAR | - (use_description ? Section.DESCRIPTION : 0)); - } - - // Create non-static methods of helpers just for convenience - - /** - * Creates a new composite with a TableWrapLayout set with a given number of columns. - * - * If the parent composite is a Section, the new composite is set as a client. - * - * @param toolkit Form Toolkit - * @param numColumns Desired number of columns. - * @return The new composite. - */ - public Composite createTableLayout(FormToolkit toolkit, int numColumns) { - return SectionHelper.createTableLayout(getSection(), toolkit, numColumns); - } - - /** - * Creates a label widget. - * If the parent layout if a TableWrapLayout, maximize it to span over all columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param label The string for the label. - * @param tooltip An optional tooltip for the label and text. Can be null. - * @return The new created label - */ - public Label createLabel(Composite parent, FormToolkit toolkit, String label, - String tooltip) { - return SectionHelper.createLabel(parent, toolkit, label, tooltip); - } - - /** - * Creates two widgets: a label and a text field. - * - * This expects the parent composite to have a TableWrapLayout with 2 columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param label The string for the label. - * @param value The initial value of the text field. Can be null. - * @param tooltip An optional tooltip for the label and text. Can be null. - * @return The new created Text field (the label is not returned) - */ - public Text createLabelAndText(Composite parent, FormToolkit toolkit, String label, - String value, String tooltip) { - return SectionHelper.createLabelAndText(parent, toolkit, label, value, tooltip); - } - - /** - * Creates a FormText widget. - * - * This expects the parent composite to have a TableWrapLayout with 2 columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param isHtml True if the form text will contain HTML that must be interpreted as - * rich text (i.e. parse tags & expand URLs). - * @param label The string for the label. - * @param setupLayoutData indicates whether the created form text receives a TableWrapData - * through the setLayoutData method. In some case, creating it will make the table parent - * huge, which we don't want. - * @return The new created FormText. - */ - public FormText createFormText(Composite parent, FormToolkit toolkit, boolean isHtml, - String label, boolean setupLayoutData) { - return SectionHelper.createFormText(parent, toolkit, isHtml, label, setupLayoutData); - } - - /** - * Forces the section to recompute its layout and redraw. - * This is needed after the content of the section has been changed at runtime. - */ - public void layoutChanged() { - Section section = getSection(); - - // Calls getSection().reflow(), which is the same that Section calls - // when the expandable state is changed and the height changes. - // Since this is protected, some reflection is needed to invoke it. - try { - Method reflow; - reflow = section.getClass().getDeclaredMethod("reflow", (Class<?>[])null); - reflow.setAccessible(true); - reflow.invoke(section); - } catch (Exception e) { - EditorsPlugin.log(e, "Error when invoking Section.reflow"); - } - - section.layout(true /* changed */, true /* all */); - } - } - - /** - * Creates a new composite with a TableWrapLayout set with a given number of columns. - * - * If the parent composite is a Section, the new composite is set as a client. - * - * @param composite The parent (e.g. a Section or SectionPart) - * @param toolkit Form Toolkit - * @param numColumns Desired number of columns. - * @return The new composite. - */ - static public Composite createTableLayout(Composite composite, FormToolkit toolkit, - int numColumns) { - Composite table = toolkit.createComposite(composite); - TableWrapLayout layout = new TableWrapLayout(); - layout.numColumns = numColumns; - table.setLayout(layout); - toolkit.paintBordersFor(table); - if (composite instanceof Section) { - ((Section) composite).setClient(table); - } - return table; - } - - /** - * Creates a new composite with a GridLayout set with a given number of columns. - * - * If the parent composite is a Section, the new composite is set as a client. - * - * @param composite The parent (e.g. a Section or SectionPart) - * @param toolkit Form Toolkit - * @param numColumns Desired number of columns. - * @return The new composite. - */ - static public Composite createGridLayout(Composite composite, FormToolkit toolkit, - int numColumns) { - Composite grid = toolkit.createComposite(composite); - GridLayout layout = new GridLayout(); - layout.numColumns = numColumns; - grid.setLayout(layout); - toolkit.paintBordersFor(grid); - if (composite instanceof Section) { - ((Section) composite).setClient(grid); - } - return grid; - } - - /** - * Creates two widgets: a label and a text field. - * - * This expects the parent composite to have a TableWrapLayout with 2 columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param label_text The string for the label. - * @param value The initial value of the text field. Can be null. - * @param tooltip An optional tooltip for the label and text. Can be null. - * @return The new created Text field (the label is not returned) - */ - static public Text createLabelAndText(Composite parent, FormToolkit toolkit, String label_text, - String value, String tooltip) { - Label label = toolkit.createLabel(parent, label_text); - label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - Text text = toolkit.createText(parent, value); - text.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE)); - - addControlTooltip(label, tooltip); - return text; - } - - /** - * Creates a label widget. - * If the parent layout if a TableWrapLayout, maximize it to span over all columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param label_text The string for the label. - * @param tooltip An optional tooltip for the label and text. Can be null. - * @return The new created label - */ - static public Label createLabel(Composite parent, FormToolkit toolkit, String label_text, - String tooltip) { - Label label = toolkit.createLabel(parent, label_text); - - TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB); - if (parent.getLayout() instanceof TableWrapLayout) { - twd.colspan = ((TableWrapLayout) parent.getLayout()).numColumns; - } - label.setLayoutData(twd); - - addControlTooltip(label, tooltip); - return label; - } - - /** - * Associates a tooltip with a control. - * - * This mirrors the behavior from org.eclipse.pde.internal.ui.editor.text.PDETextHover - * - * @param control The control to which associate the tooltip. - * @param tooltip The tooltip string. Can use \n for multi-lines. Will not display if null. - */ - static public void addControlTooltip(final Control control, String tooltip) { - if (control == null || tooltip == null || tooltip.length() == 0) { - return; - } - - // Some kinds of controls already properly implement tooltip display. - if (control instanceof Button) { - control.setToolTipText(tooltip); - return; - } - - control.setToolTipText(null); - - final DefaultInformationControl ic = new DefaultInformationControl(control.getShell()); - ic.setInformation(tooltip); - Point sz = ic.computeSizeHint(); - ic.setSize(sz.x, sz.y); - ic.setVisible(false); // initially hidden - - control.addMouseTrackListener(new MouseTrackListener() { - public void mouseEnter(MouseEvent e) { - } - - public void mouseExit(MouseEvent e) { - ic.setVisible(false); - } - - public void mouseHover(MouseEvent e) { - ic.setLocation(control.toDisplay(10, 25)); // same offset as in PDETextHover - ic.setVisible(true); - } - }); - } - - /** - * Creates a FormText widget. - * - * This expects the parent composite to have a TableWrapLayout with 2 columns. - * - * @param parent The parent (e.g. composite from CreateTableLayout()) - * @param toolkit Form Toolkit - * @param isHtml True if the form text will contain HTML that must be interpreted as - * rich text (i.e. parse tags & expand URLs). - * @param label The string for the label. - * @param setupLayoutData indicates whether the created form text receives a TableWrapData - * through the setLayoutData method. In some case, creating it will make the table parent - * huge, which we don't want. - * @return The new created FormText. - */ - static public FormText createFormText(Composite parent, FormToolkit toolkit, - boolean isHtml, String label, boolean setupLayoutData) { - FormText text = toolkit.createFormText(parent, true /* track focus */); - if (setupLayoutData) { - TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB); - twd.maxWidth = AndroidEditor.TEXT_WIDTH_HINT; - if (parent.getLayout() instanceof TableWrapLayout) { - twd.colspan = ((TableWrapLayout) parent.getLayout()).numColumns; - } - text.setLayoutData(twd); - } - text.setWhitespaceNormalized(true); - text.setText(label, isHtml /* parseTags */, isHtml /* expandURLs */); - return text; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java deleted file mode 100644 index 2fe5783..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; - -import org.eclipse.jface.viewers.TextCellEditor; -import org.eclipse.swt.widgets.Composite; - -/** - * TextCellEditor able to receive a {@link UiAttributeNode} in the {@link #setValue(Object)} - * method. - */ -public class TextValueCellEditor extends TextCellEditor { - - public TextValueCellEditor(Composite parent) { - super(parent); - } - - @Override - protected void doSetValue(Object value) { - if (value instanceof UiAttributeNode) { - super.doSetValue(((UiAttributeNode)value).getCurrentValue()); - return; - } - - super.doSetValue(value); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java deleted file mode 100644 index 69adebd..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.ManifestEditor; -import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -/** - * Generic page's section part that displays all attributes of a given {@link UiElementNode}. - * <p/> - * This part is designed to be displayed in a page that has a table column layout. - * It is linked to a specific {@link UiElementNode} and automatically displays all of its - * attributes, manages its dirty state and commits the attributes when necessary. - * <p/> - * No derivation is needed unless the UI or workflow needs to be extended. - */ -public class UiElementPart extends ManifestSectionPart { - - /** A reference to the container editor */ - private ManifestEditor mEditor; - /** The {@link UiElementNode} manipulated by this SectionPart. It can be null. */ - private UiElementNode mUiElementNode; - /** Table that contains all the attributes */ - private Composite mTable; - - public UiElementPart(Composite body, FormToolkit toolkit, ManifestEditor editor, - UiElementNode uiElementNode, String sectionTitle, String sectionDescription, - int extra_style) { - super(body, toolkit, extra_style, sectionDescription != null); - mEditor = editor; - mUiElementNode = uiElementNode; - setupSection(sectionTitle, sectionDescription); - - if (uiElementNode == null) { - // This is serious and should never happen. Instead of crashing, simply abort. - // There will be no UI, which will prevent further damage. - EditorsPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$ - return; - } - } - - /** - * Returns the Editor associated with this part. - */ - public ManifestEditor getEditor() { - return mEditor; - } - - /** - * Returns the {@link UiElementNode} associated with this part. - */ - public UiElementNode getUiElementNode() { - return mUiElementNode; - } - - /** - * Changes the element node handled by this part. - * - * @param uiElementNode The new element node for the part. - */ - public void setUiElementNode(UiElementNode uiElementNode) { - mUiElementNode = uiElementNode; - } - - /** - * Initializes the form part. - * <p/> - * This is called by the owning managed form as soon as the part is added to the form, - * which happens right after the part is actually created. - */ - @Override - public void initialize(IManagedForm form) { - super.initialize(form); - createFormControls(form); - } - - /** - * Setup the section that contains this part. - * <p/> - * This is called by the constructor to set the section's title and description - * with parameters given in the constructor. - * <br/> - * Derived class override this if needed, however in most cases the default - * implementation should be enough. - * - * @param sectionTitle The section part's title - * @param sectionDescription The section part's description - */ - protected void setupSection(String sectionTitle, String sectionDescription) { - Section section = getSection(); - section.setText(sectionTitle); - section.setDescription(sectionDescription); - } - - /** - * Create the controls to edit the attributes for the given ElementDescriptor. - * <p/> - * This MUST not be called by the constructor. Instead it must be called from - * <code>initialize</code> (i.e. right after the form part is added to the managed form.) - * <p/> - * Derived classes can override this if necessary. - * - * @param managedForm The owner managed form - */ - protected void createFormControls(IManagedForm managedForm) { - setTable(createTableLayout(managedForm.getToolkit(), 2 /* numColumns */)); - - createUiAttributes(managedForm); - } - - /** - * Sets the table where the attribute UI needs to be created. - */ - protected void setTable(Composite table) { - mTable = table; - } - - /** - * Returns the table where the attribute UI needs to be created. - */ - protected Composite getTable() { - return mTable; - } - - /** - * Add all the attribute UI widgets into the underlying table layout. - * - * @param managedForm The owner managed form - */ - protected void createUiAttributes(IManagedForm managedForm) { - Composite table = getTable(); - if (table == null || managedForm == null) { - return; - } - - // Remove any old UI controls - for (Control c : table.getChildren()) { - c.dispose(); - } - - fillTable(table, managedForm); - - // Tell the section that the layout has changed. - layoutChanged(); - } - - /** - * Actually fills the table. - * This is called by {@link #createUiAttributes(IManagedForm)} to populate the new - * table. The default implementation is to use - * {@link #insertUiAttributes(UiElementNode, Composite, IManagedForm)} to actually - * place the attributes of the default {@link UiElementNode} in the table. - * <p/> - * Derived classes can override this to add controls in the table before or after. - * - * @param table The table to fill. It must have 2 columns. - * @param managedForm The managed form for new controls. - */ - protected void fillTable(Composite table, IManagedForm managedForm) { - int inserted = insertUiAttributes(mUiElementNode, table, managedForm); - - if (inserted == 0) { - createLabel(table, managedForm.getToolkit(), - "No attributes to display, waiting for SDK to finish loading...", - null /* tooltip */ ); - } - } - - /** - * Insert the UI attributes of the given {@link UiElementNode} in the given table. - * - * @param uiNode The {@link UiElementNode} that contains the attributes to display. - * Must not be null. - * @param table The table to fill. It must have 2 columns. - * @param managedForm The managed form for new controls. - * @return The number of UI attributes inserted. It is >= 0. - */ - protected int insertUiAttributes(UiElementNode uiNode, Composite table, IManagedForm managedForm) { - if (uiNode == null || table == null || managedForm == null) { - return 0; - } - - // To iterate over all attributes, we use the {@link ElementDescriptor} instead - // of the {@link UiElementNode} because the attributes' order is guaranteed in the - // descriptor but not in the node itself. - AttributeDescriptor[] attr_desc_list = uiNode.getAttributeDescriptors(); - for (AttributeDescriptor attr_desc : attr_desc_list) { - if (attr_desc instanceof XmlnsAttributeDescriptor) { - // Do not show hidden attributes - continue; - } - - UiAttributeNode ui_attr = uiNode.findUiAttribute(attr_desc); - if (ui_attr != null) { - ui_attr.createUiControl(table, managedForm); - } else { - // The XML has an extra attribute which wasn't declared in - // AndroidManifestDescriptors. This is not a problem, we just ignore it. - EditorsPlugin.log(IStatus.WARNING, - "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$ - attr_desc.getXmlLocalName(), - uiNode.getDescriptor().getXmlName()); - } - } - return attr_desc_list.length; - } - - /** - * Tests whether the part is dirty i.e. its widgets have state that is - * newer than the data in the model. - * <p/> - * This is done by iterating over all attributes and updating the super's - * internal dirty flag. Stop once at least one attribute is dirty. - * - * @return <code>true</code> if the part is dirty, <code>false</code> - * otherwise. - */ - @Override - public boolean isDirty() { - if (mUiElementNode != null && !super.isDirty()) { - for (UiAttributeNode ui_attr : mUiElementNode.getUiAttributes()) { - if (ui_attr.isDirty()) { - markDirty(); - break; - } - } - } - return super.isDirty(); - } - - /** - * If part is displaying information loaded from a model, this method - * instructs it to commit the new (modified) data back into the model. - * - * @param onSave - * indicates if commit is called during 'save' operation or for - * some other reason (for example, if form is contained in a - * wizard or a multi-page editor and the user is about to leave - * the page). - */ - @Override - public void commit(boolean onSave) { - if (mUiElementNode != null) { - mEditor.editXmlModel(new Runnable() { - public void run() { - for (UiAttributeNode ui_attr : mUiElementNode.getUiAttributes()) { - ui_attr.commit(); - } - } - }); - } - - // We need to call super's commit after we synchronized the nodes to make sure we - // reset the dirty flag after all the side effects from committing have occurred. - super.commit(onSave); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java deleted file mode 100644 index 7e38032..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.apache.xml.serialize.Method; -import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.XMLSerializer; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.document.NodeContainer; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.io.StringWriter; - - -/** - * Provides Cut and Copy actions for the tree nodes. - */ -public class CopyCutAction extends Action { - private UiElementNode mUiNode; - private boolean mPerformCut; - private final AndroidEditor mEditor; - private final Clipboard mClipboard; - private final ICommitXml mXmlCommit; - - /** - * Creates a new Copy or Cut action. - * - * @param ui_node The UI node to cut or copy. It *must* have a non-null XML node. - * @param perform_cut True if the operation is cut, false if it is copy. - */ - public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit, - UiElementNode ui_node, boolean perform_cut) { - super(perform_cut ? "Cut" : "Copy"); - mEditor = editor; - mClipboard = clipboard; - mXmlCommit = xmlCommit; - - ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); - if (perform_cut) { - setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); - setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); - setDisabledImageDescriptor( - images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED)); - } else { - setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); - setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); - setDisabledImageDescriptor( - images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED)); - } - - mUiNode = ui_node; - mPerformCut = perform_cut; - } - - /** - * Performs the cut or copy action. - * First an XML serializer is used to turn the existing XML node into a valid - * XML fragment, which is added as text to the clipboard. - */ - @Override - public void run() { - super.run(); - try { - String data = null; - - // Get the data directly from the editor. - - // Commit the current pages first, to make sure the XML is in sync. - if (mXmlCommit != null) { - mXmlCommit.commitPendingXmlChanges(); - } - - // Committing may change the XML structure. - Node xml_node = mUiNode.getXmlNode(); - if (xml_node == null) { - return; - } - - IStructuredModel model = mEditor.getModelForRead(); - try { - IStructuredDocument sse_doc = mEditor.getStructuredDocument(); - if (xml_node instanceof NodeContainer) { - // The easy way to get the source of an SSE XML node. - data = ((NodeContainer) xml_node).getSource(); - } else if (xml_node instanceof IndexedRegion && sse_doc != null) { - // Try harder. - IndexedRegion region = (IndexedRegion) xml_node; - int start = region.getStartOffset(); - int end = region.getEndOffset(); - - if (end > start) { - data = sse_doc.get(start, end - start); - } - } - } catch (BadLocationException e) { - // the region offset was invalid. ignore. - } finally { - model.releaseFromRead(); - } - - // In the unlikely event that IStructuredDocument failed to extract the text - // directly from the editor, try to fall back on a direct XML serialization - // of the XML node. This uses the generic Node interface with no SSE tricks. - if (data == null) { - StringWriter sw = new StringWriter(); - XMLSerializer serializer = new XMLSerializer(sw, - new OutputFormat(Method.XML, - OutputFormat.Defaults.Encoding /* utf-8 */, - true /* indent */)); - // Serialize will throw an IOException if it fails. - serializer.serialize((Element) xml_node); - data = sw.toString(); - } - - if (data != null && data.length() > 0) { - mClipboard.setContents( - new Object[] { data }, - new Transfer[] { TextTransfer.getInstance() }); - if (mPerformCut) { - mUiNode.deleteXmlNode(); - } - } - } catch (Exception e) { - EditorsPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$ - mUiNode.getBreadcrumbTrailDescription(true)); - } - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java deleted file mode 100644 index 8b6aa0e..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.eclipse.editors.ui.tree; - -/** - * Interface for an object that can commit its changes to the underlying XML model - */ -public interface ICommitXml { - - /** Commits pending data to the underlying XML model. */ - public void commitPendingXmlChanges(); - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java deleted file mode 100644 index 00e44ab..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog; -import org.eclipse.ui.dialogs.ISelectionStatusValidator; - -import java.util.Arrays; - -/** - * A selection dialog to select the type of the new element node to - * created, either in the application node or the selected sub node. - */ -public class NewItemSelectionDialog extends AbstractElementListSelectionDialog { - - /** The UI node selected in the tree view before creating the new item selection dialog. - * Can be null -- which means new items must be created in the root_node. */ - private UiElementNode mSelectedUiNode; - /** The root node chosen by the user, either root_node or the one passed - * to the constructor if not null */ - private UiElementNode mChosenRootNode; - private UiElementNode mLocalRootNode; - /** The descriptor of the elements to be displayed as root in this tree view. All elements - * of the same type in the root will be displayed. */ - private ElementDescriptor[] mDescriptorFilters; - - /** - * Creates the new item selection dialog. - * - * @param shell The parent shell for the list. - * @param labelProvider ILabelProvider for the list. - * @param descriptorFilters The element allows at the root of the tree - * @param ui_node The selected node, or null if none is selected. - * @param root_node The root of the Ui Tree, either the UiDocumentNode or a sub-node. - */ - public NewItemSelectionDialog(Shell shell, ILabelProvider labelProvider, - ElementDescriptor[] descriptorFilters, - UiElementNode ui_node, - UiElementNode root_node) { - super(shell, labelProvider); - mDescriptorFilters = descriptorFilters; - mLocalRootNode = root_node; - - // Only accept the UI node if it is not the UI root node and it can have children. - // If the node cannot have children, select its parent as a potential target. - if (ui_node != null && ui_node != mLocalRootNode) { - if (ui_node.getDescriptor().hasChildren()) { - mSelectedUiNode = ui_node; - } else { - UiElementNode parent = ui_node.getUiParent(); - if (parent != null && parent != mLocalRootNode) { - mSelectedUiNode = parent; - } - } - } - - setHelpAvailable(false); - setMultipleSelection(false); - - setValidator(new ISelectionStatusValidator() { - public IStatus validate(Object[] selection) { - if (selection.length == 1 && selection[0] instanceof ViewElementDescriptor) { - return new Status(IStatus.OK, // severity - AndroidConstants.EDITORS_PLUGIN_ID, //plugin id - IStatus.OK, // code - ((ViewElementDescriptor) selection[0]).getCanonicalClassName(), //msg - null); // exception - } else if (selection.length == 1 && selection[0] instanceof ElementDescriptor) { - return new Status(IStatus.OK, // severity - AndroidConstants.EDITORS_PLUGIN_ID, //plugin id - IStatus.OK, // code - "", //$NON-NLS-1$ // msg - null); // exception - } else { - return new Status(IStatus.ERROR, // severity - AndroidConstants.EDITORS_PLUGIN_ID, //plugin id - IStatus.ERROR, // code - "Invalid selection", // msg, translatable - null); // exception - } - } - }); - } - - /** - * @return The root node selected by the user, either root node or the - * one passed to the constructor if not null. - */ - public UiElementNode getChosenRootNode() { - return mChosenRootNode; - } - - /** - * Internal helper to compute the result. Returns the selection from - * the list view, if any. - */ - @Override - protected void computeResult() { - setResult(Arrays.asList(getSelectedElements())); - } - - /** - * Creates the dialog area. - * - * First add a radio area, which may be either 2 radio controls or - * just a message area if there's only one choice (the app root node). - * - * Then uses the default from the AbstractElementListSelectionDialog - * which is to add both a filter text and a filtered list. Adding both - * is necessary (since the base class accesses both internal directly - * fields without checking for null pointers.) - * - * Finally sets the initial selection list. - */ - @Override - protected Control createDialogArea(Composite parent) { - Composite contents = (Composite) super.createDialogArea(parent); - - createRadioControl(contents); - createFilterText(contents); - createFilteredList(contents); - - // Initialize the list state. - // This must be done after the filtered list as been created. - chooseNode(mChosenRootNode); - setSelection(getInitialElementSelections().toArray()); - return contents; - } - - /** - * Creates the message text widget and sets layout data. - * @param content the parent composite of the message area. - */ - private Composite createRadioControl(Composite content) { - - if (mSelectedUiNode != null) { - Button radio1 = new Button(content, SWT.RADIO); - radio1.setText(String.format("Create a new element at the top level, in %1$s.", - mLocalRootNode.getShortDescription())); - - Button radio2 = new Button(content, SWT.RADIO); - radio2.setText(String.format("Create a new element in the selected element, %1$s.", - mSelectedUiNode.getBreadcrumbTrailDescription(false /* include_root */))); - - // Set the initial selection before adding the listeners - // (they can't be run till the filtered list has been created) - radio1.setSelection(false); - radio2.setSelection(true); - mChosenRootNode = mSelectedUiNode; - - radio1.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - chooseNode(mLocalRootNode); - } - }); - - radio2.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - chooseNode(mSelectedUiNode); - } - }); - } else { - setMessage(String.format("Create a new element at the top level, in %1$s.", - mLocalRootNode.getShortDescription())); - createMessageArea(content); - - mChosenRootNode = mLocalRootNode; - } - - return content; - } - - /** - * Internal helper to remember the root node choosen by the user. - * It also sets the list view to the adequate list of children that can - * be added to the chosen root node. - * - * If the chosen root node is mLocalRootNode and a descriptor filter was specified - * when creating the master-detail part, we use this as the set of nodes that - * can be created on the root node. - * - * @param ui_node The chosen root node, either mLocalRootNode or - * mSelectedUiNode. - */ - private void chooseNode(UiElementNode ui_node) { - mChosenRootNode = ui_node; - - if (ui_node == mLocalRootNode && - mDescriptorFilters != null && - mDescriptorFilters.length != 0) { - setListElements(mDescriptorFilters); - } else { - setListElements(ui_node.getDescriptor().getChildren()); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java deleted file mode 100644 index 68580b0..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.xml.core.internal.document.NodeContainer; -import org.w3c.dom.Node; - - -/** - * Provides Paste operation for the tree nodes - */ -public class PasteAction extends Action { - private UiElementNode mUiNode; - private final AndroidEditor mEditor; - private final Clipboard mClipboard; - - public PasteAction(AndroidEditor editor, Clipboard clipboard, UiElementNode ui_node) { - super("Paste"); - mEditor = editor; - mClipboard = clipboard; - - ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); - setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); - setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); - setDisabledImageDescriptor( - images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED)); - - mUiNode = ui_node; - } - - /** - * Performs the paste operation. - */ - @Override - public void run() { - super.run(); - - final String data = (String) mClipboard.getContents(TextTransfer.getInstance()); - if (data != null) { - IStructuredModel model = mEditor.getModelForEdit(); - try { - IStructuredDocument sse_doc = mEditor.getStructuredDocument(); - if (sse_doc != null) { - if (mUiNode.getDescriptor().hasChildren()) { - // This UI Node can have children. The new XML is - // inserted as the first child. - - if (mUiNode.getUiChildren().size() > 0) { - // There's already at least one child, so insert right before it. - Node xml_node = mUiNode.getUiChildren().get(0).getXmlNode(); - if (xml_node instanceof IndexedRegion) { // implies xml_node != null - IndexedRegion region = (IndexedRegion) xml_node; - sse_doc.replace(region.getStartOffset(), 0, data); - return; // we're done, no need to try the other cases - } - } - - // If there's no first XML node child. Create one by - // inserting at the end of the *start* tag. - Node xml_node = mUiNode.getXmlNode(); - if (xml_node instanceof NodeContainer) { - NodeContainer container = (NodeContainer) xml_node; - IStructuredDocumentRegion start_tag = - container.getStartStructuredDocumentRegion(); - if (start_tag != null) { - sse_doc.replace(start_tag.getEndOffset(), 0, data); - return; // we're done, no need to try the other case - } - } - } - - // This UI Node doesn't accept children. The new XML is inserted as the - // next sibling. This also serves as a fallback if all the previous - // attempts failed. However, this is not possible if the current node - // has for parent a document -- an XML document can only have one root, - // with no siblings. - if (!(mUiNode.getUiParent() instanceof UiDocumentNode)) { - Node xml_node = mUiNode.getXmlNode(); - if (xml_node instanceof IndexedRegion) { - IndexedRegion region = (IndexedRegion) xml_node; - sse_doc.replace(region.getEndOffset(), 0, data); - } - } - } - - } catch (BadLocationException e) { - EditorsPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$ - mUiNode.getBreadcrumbTrailDescription(true), data); - } finally { - model.releaseFromEdit(); - } - } - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java deleted file mode 100644 index b3d0755..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.swt.widgets.Shell; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -/** - * Performs basic actions on an XML tree: add node, remove node, move up/down. - */ -public abstract class UiActions implements ICommitXml { - - public UiActions() { - } - - //--------------------- - // Actual implementations must override these to provide specific hooks - - /** Returns the UiDocumentNode for the current model. */ - abstract protected UiElementNode getRootNode(); - - /** Commits pending data before the XML model is modified. */ - abstract public void commitPendingXmlChanges(); - - /** - * Utility method to select an outline item based on its model node - * - * @param ui_node The node to select. Can be null (in which case nothing should happen) - */ - abstract protected void selectUiNode(UiElementNode ui_node); - - //--------------------- - - /** - * Called when the "Add..." button next to the tree view is selected. - * <p/> - * This simplified version of doAdd does not support descriptor filters and creates - * a new {@link UiModelTreeLabelProvider} for each call. - */ - public void doAdd(UiElementNode ui_node, Shell shell) { - doAdd(ui_node, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider()); - } - - /** - * Called when the "Add..." button next to the tree view is selected. - * - * Displays a selection dialog that lets the user select which kind of node - * to create, depending on the current selection. - */ - public void doAdd(UiElementNode ui_node, - ElementDescriptor[] descriptorFilters, - Shell shell, ILabelProvider labelProvider) { - // If the root node is a document with already a root, use it as the root node - UiElementNode root_node = getRootNode(); - if (root_node instanceof UiDocumentNode && - root_node.getUiChildren().size() > 0) { - root_node = root_node.getUiChildren().get(0); - } - - NewItemSelectionDialog dlg = new NewItemSelectionDialog( - shell, - labelProvider, - descriptorFilters, - ui_node, root_node); - dlg.open(); - Object[] results = dlg.getResult(); - if (results != null && results.length > 0) { - UiElementNode ui_new = addNewTreeElement(dlg.getChosenRootNode(), - (ElementDescriptor) results[0]); - - selectUiNode(ui_new); - } - } - - /** - * Called when the "Remove" button is selected. - * - * If the tree has a selection, remove it. - * This simply deletes the XML node attached to the UI node: when the XML model fires the - * update event, the tree will get refreshed. - */ - public void doRemove(final UiElementNode ui_node, Shell shell) { - if (MessageDialog.openQuestion(shell, - "Remove element from Android XML", // title - String.format("Do you really want to remove %1$s?", - ui_node.getBreadcrumbTrailDescription(false /* include_root */)))) { - commitPendingXmlChanges(); - getRootNode().getEditor().editXmlModel(new Runnable() { - public void run() { - UiElementNode previous = ui_node.getUiPreviousSibling(); - UiElementNode parent = ui_node.getUiParent(); - - // delete node - ui_node.deleteXmlNode(); - - // try to select the previous sibling or the parent - if (previous != null) { - selectUiNode(previous); - } else if (parent != null) { - selectUiNode(parent); - } - } - }); - } - } - - /** - * Called when the "Up" button is selected. - * <p/> - * If the tree has a selection, move it up, either in the child list or as the last child - * of the previous parent. - */ - public void doUp(final UiElementNode ui_node) { - final Node[] select_xml_node = { null }; - // the node will move either up to its parent or grand-parent - UiElementNode search_root = ui_node.getUiParent(); - if (search_root != null && search_root.getUiParent() != null) { - search_root = search_root.getUiParent(); - } - - commitPendingXmlChanges(); - getRootNode().getEditor().editXmlModel(new Runnable() { - public void run() { - Node xml_node = ui_node.getXmlNode(); - if (xml_node != null) { - Node xml_parent = xml_node.getParentNode(); - if (xml_parent != null) { - UiElementNode ui_prev = ui_node.getUiPreviousSibling(); - if (ui_prev != null && ui_prev.getXmlNode() != null) { - // This node is not the first one of the parent, so it can be - // removed and then inserted before its previous sibling. - // If the previous sibling can have children, though, then it - // is inserted at the end of the children list. - Node xml_prev = ui_prev.getXmlNode(); - if (ui_prev.getDescriptor().hasChildren()) { - xml_prev.appendChild(xml_parent.removeChild(xml_node)); - select_xml_node[0] = xml_node; - } else { - xml_parent.insertBefore( - xml_parent.removeChild(xml_node), - xml_prev); - select_xml_node[0] = xml_node; - } - } else if (!(xml_parent instanceof Document) && - xml_parent.getParentNode() != null && - !(xml_parent.getParentNode() instanceof Document)) { - // If the node is the first one of the child list of its - // parent, move it up in the hierarchy as previous sibling - // to the parent. This is only possible if the parent of the - // parent is not a document. - Node grand_parent = xml_parent.getParentNode(); - grand_parent.insertBefore(xml_parent.removeChild(xml_node), - xml_parent); - select_xml_node[0] = xml_node; - } - } - } - } - }); - - if (select_xml_node[0] == null) { - // The XML node has not been moved, we can just select the same UI node - selectUiNode(ui_node); - } else { - // The XML node has moved. At this point the UI model has been reloaded - // and the XML node has been affected to a new UI node. Find that new UI - // node and select it. - if (search_root == null) { - search_root = ui_node.getUiRoot(); - } - if (search_root != null) { - selectUiNode(search_root.findXmlNode(select_xml_node[0])); - } - } - } - - /** - * Called when the "Down" button is selected. - * - * If the tree has a selection, move it down, either in the same child list or as the - * first child of the next parent. - */ - public void doDown(final UiElementNode ui_node) { - final Node[] select_xml_node = { null }; - // the node will move either down to its parent or grand-parent - UiElementNode search_root = ui_node.getUiParent(); - if (search_root != null && search_root.getUiParent() != null) { - search_root = search_root.getUiParent(); - } - - commitPendingXmlChanges(); - getRootNode().getEditor().editXmlModel(new Runnable() { - public void run() { - Node xml_node = ui_node.getXmlNode(); - if (xml_node != null) { - Node xml_parent = xml_node.getParentNode(); - if (xml_parent != null) { - UiElementNode ui_next = ui_node.getUiNextSibling(); - if (ui_next != null && ui_next.getXmlNode() != null) { - // This node is not the last one of the parent, so it can be - // removed and then inserted after its next sibling. - // If the next sibling is a node that can have children, though, - // then the node is inserted as the first child. - Node xml_next = ui_next.getXmlNode(); - if (ui_next.getDescriptor().hasChildren()) { - // Note: insertBefore works as append if the ref node is - // null, i.e. when the node doesn't have children yet. - xml_next.insertBefore(xml_parent.removeChild(xml_node), - xml_next.getFirstChild()); - select_xml_node[0] = xml_node; - } else { - // Insert "before after next" ;-) - xml_parent.insertBefore(xml_parent.removeChild(xml_node), - xml_next.getNextSibling()); - select_xml_node[0] = xml_node; - } - } else if (!(xml_parent instanceof Document) && - xml_parent.getParentNode() != null && - !(xml_parent.getParentNode() instanceof Document)) { - // This node is the last node of its parent. - // If neither the parent nor the grandparent is a document, - // then the node can be insert right after the parent. - Node grand_parent = xml_parent.getParentNode(); - grand_parent.insertBefore(xml_parent.removeChild(xml_node), - xml_parent.getNextSibling()); - select_xml_node[0] = xml_node; - } - } - } - } - }); - - if (select_xml_node[0] == null) { - // The XML node has not been moved, we can just select the same UI node - selectUiNode(ui_node); - } else { - // The XML node has moved. At this point the UI model has been reloaded - // and the XML node has been affected to a new UI node. Find that new UI - // node and select it. - if (search_root == null) { - search_root = ui_node.getUiRoot(); - } - if (search_root != null) { - selectUiNode(search_root.findXmlNode(select_xml_node[0])); - } - } - } - - //--------------------- - - /** - * Adds a new element of the given descriptor's type to the given UI parent node. - * - * This actually creates the corresponding XML node in the XML model, which in turn - * will refresh the current tree view. - * - * @param ui_parent An existing UI node or null to add to the tree root - * @param elementDescriptor The descriptor of the element to add - * @return The {@link UiElementNode} that has been added to the UI tree. - */ - private UiElementNode addNewTreeElement(UiElementNode ui_parent, - ElementDescriptor elementDescriptor) { - commitPendingXmlChanges(); - final UiElementNode ui_new = ui_parent.appendNewUiChild(elementDescriptor); - UiElementNode root_node = getRootNode(); - - root_node.getEditor().editXmlModel(new Runnable() { - public void run() { - DescriptorsUtils.setDefaultLayoutAttributes(ui_new); - ui_new.createXmlNode(); - } - }); - return ui_new; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java deleted file mode 100644 index 010e30e..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; -import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ITreeSelection; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.ui.forms.IDetailsPage; -import org.eclipse.ui.forms.IFormPart; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.events.ExpansionEvent; -import org.eclipse.ui.forms.events.IExpansionListener; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.forms.widgets.SharedScrolledComposite; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.eclipse.ui.forms.widgets.TableWrapLayout; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; - -import java.util.Collection; -import java.util.HashSet; - -/** - * Details page for the {@link UiElementNode} nodes in the tree view. - * <p/> - * See IDetailsBase for more details. - */ -class UiElementDetail implements IDetailsPage { - - /** The master-detail part, composed of a main tree and an auxiliary detail part */ - private ManifestSectionPart mMasterPart; - - private Section mMasterSection; - private UiElementNode mCurrentUiElementNode; - private Composite mCurrentTable; - private boolean mIsDirty; - - private IManagedForm mManagedForm; - - private final UiTreeBlock mTree; - - public UiElementDetail(UiTreeBlock tree) { - mTree = tree; - mMasterPart = mTree.getMasterPart(); - mManagedForm = mMasterPart.getManagedForm(); - } - - /* (non-java doc) - * Initializes the part. - */ - public void initialize(IManagedForm form) { - mManagedForm = form; - } - - /* (non-java doc) - * Creates the contents of the page in the provided parent. - */ - public void createContents(Composite parent) { - mMasterSection = createMasterSection(parent); - } - - /* (non-java doc) - * Called when the provided part has changed selection state. - * <p/> - * Only reply when our master part originates the selection. - */ - public void selectionChanged(IFormPart part, ISelection selection) { - if (part == mMasterPart && - !selection.isEmpty() && - selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - - Object first = tree_selection.getFirstElement(); - if (first instanceof UiElementNode) { - UiElementNode ui_node = (UiElementNode) first; - createUiAttributeControls(mManagedForm, ui_node); - } - } - } - - /* (non-java doc) - * Instructs it to commit the new (modified) data back into the model. - */ - public void commit(boolean onSave) { - - IStructuredModel model = mTree.getEditor().getModelForEdit(); - try { - // Notify the model we're about to change data... - model.aboutToChangeModel(); - - if (mCurrentUiElementNode != null) { - mCurrentUiElementNode.commit(); - } - - // Finally reset the dirty flag if everything was saved properly - mIsDirty = false; - } catch (Exception e) { - EditorsPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$ - } finally { - // Notify the model we're done modifying it. This must *always* be executed. - model.changedModel(); - model.releaseFromEdit(); - } - } - - public void dispose() { - // pass - } - - - /* (non-java doc) - * Returns true if the part has been modified with respect to the data - * loaded from the model. - */ - public boolean isDirty() { - if (mCurrentUiElementNode != null && mCurrentUiElementNode.isDirty()) { - markDirty(); - } - return mIsDirty; - } - - public boolean isStale() { - // pass - return false; - } - - /** - * Called by the master part when the tree is refreshed after the framework resources - * have been reloaded. - */ - public void refresh() { - if (mCurrentTable != null) { - mCurrentTable.dispose(); - mCurrentTable = null; - } - mCurrentUiElementNode = null; - mMasterSection.getParent().pack(true /* changed */); - } - - public void setFocus() { - // pass - } - - public boolean setFormInput(Object input) { - // pass - return false; - } - - /** - * Creates a TableWrapLayout in the DetailsPage, which in turns contains a Section. - * - * All the UI should be created in a layout which parent is the mSection itself. - * The hierarchy is: - * <pre> - * DetailPage - * + TableWrapLayout - * + Section (with title/description && fill_grab horizontal) - * + TableWrapLayout [*] - * + Labels/Forms/etc... [*] - * </pre> - * Both items marked with [*] are created by the derived classes to fit their needs. - * - * @param parent Parent of the mSection (from createContents) - * @return The new Section - */ - private Section createMasterSection(Composite parent) { - TableWrapLayout layout = new TableWrapLayout(); - layout.topMargin = 0; - parent.setLayout(layout); - - FormToolkit toolkit = mManagedForm.getToolkit(); - Section section = toolkit.createSection(parent, Section.TITLE_BAR); - section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); - return section; - } - - /** - * Create the ui attribute controls to edit the attributes for the given - * ElementDescriptor. - * <p/> - * This is called by the constructor. - * Derived classes can override this if necessary. - * - * @param managedForm The managed form - */ - private void createUiAttributeControls( - final IManagedForm managedForm, - final UiElementNode ui_node) { - - final ElementDescriptor elem_desc = ui_node.getDescriptor(); - mMasterSection.setText(String.format("Attributes for %1$s", ui_node.getShortDescription())); - - if (mCurrentUiElementNode != ui_node) { - // Before changing the table, commit all dirty state. - if (mIsDirty) { - commit(false); - } - if (mCurrentTable != null) { - mCurrentTable.dispose(); - mCurrentTable = null; - } - - // To iterate over all attributes, we use the {@link ElementDescriptor} instead - // of the {@link UiElementNode} because the attributes order is guaranteed in the - // descriptor but not in the node itself. - AttributeDescriptor[] attr_desc_list = ui_node.getAttributeDescriptors(); - - // If the attribute list contains at least one SeparatorAttributeDescriptor, - // sub-sections will be used. This needs to be known early as it influences the - // creation of the master table. - boolean useSubsections = false; - for (AttributeDescriptor attr_desc : attr_desc_list) { - if (attr_desc instanceof SeparatorAttributeDescriptor) { - // Sub-sections will be used. The default sections should no longer be - useSubsections = true; - break; - } - } - - FormToolkit toolkit = managedForm.getToolkit(); - Composite masterTable = SectionHelper.createTableLayout(mMasterSection, - toolkit, useSubsections ? 1 : 2 /* numColumns */); - mCurrentTable = masterTable; - - mCurrentUiElementNode = ui_node; - - if (elem_desc.getTooltip() != null) { - String tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(), - elem_desc, - FrameworkResourceManager.getInstance().getDocumentationBaseUrl()); - - try { - FormText text = SectionHelper.createFormText(masterTable, toolkit, - true /* isHtml */, tooltip, true /* setupLayoutData */); - text.addHyperlinkListener(mTree.getEditor().createHyperlinkListener()); - Image icon = elem_desc.getIcon(); - if (icon != null) { - text.setImage(DescriptorsUtils.IMAGE_KEY, icon); - } - } catch(Exception e) { - // The FormText parser is really really basic and will fail as soon as the - // HTML javadoc is ever so slightly malformatted. - EditorsPlugin.log(e, - "Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$ - ui_node.getDescriptor().getXmlName(), - tooltip); - - // Fallback to a pure text tooltip, no fancy HTML - tooltip = DescriptorsUtils.formatTooltip(elem_desc.getTooltip()); - Label label = SectionHelper.createLabel(masterTable, toolkit, - tooltip, tooltip); - } - } - - Composite table = useSubsections ? null : masterTable; - - for (AttributeDescriptor attr_desc : attr_desc_list) { - if (attr_desc instanceof XmlnsAttributeDescriptor) { - // Do not show hidden attributes - continue; - } else if (table == null || attr_desc instanceof SeparatorAttributeDescriptor) { - String title = null; - if (attr_desc instanceof SeparatorAttributeDescriptor) { - // xmlName is actually the label of the separator - title = attr_desc.getXmlLocalName(); - } else { - title = String.format("Attributes from %1$s", elem_desc.getUiName()); - } - - table = createSubSectionTable(toolkit, masterTable, title); - if (attr_desc instanceof SeparatorAttributeDescriptor) { - continue; - } - } - - UiAttributeNode ui_attr = ui_node.findUiAttribute(attr_desc); - - if (ui_attr != null) { - ui_attr.createUiControl(table, managedForm); - - if (ui_attr.getCurrentValue() != null && - ui_attr.getCurrentValue().length() > 0) { - ((Section) table.getParent()).setExpanded(true); - } - } else { - // The XML has an extra unknown attribute. - // This is not expected to happen so it is ignored. - EditorsPlugin.log(IStatus.INFO, - "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$ - attr_desc.getXmlLocalName(), - ui_node.getDescriptor().getXmlName()); - } - } - - // Create a sub-section for the unknown attributes. - // It is initially hidden till there are some attributes to show here. - final Composite unknownTable = createSubSectionTable(toolkit, masterTable, - "Unknown XML Attributes"); - unknownTable.getParent().setVisible(false); // set section to not visible - final HashSet<UiAttributeNode> reference = new HashSet<UiAttributeNode>(); - - final IUiUpdateListener updateListener = new IUiUpdateListener() { - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - if (state == UiUpdateState.ATTR_UPDATED) { - updateUnknownAttributesSection(ui_node, unknownTable, managedForm, - reference); - } - } - }; - ui_node.addUpdateListener(updateListener); - - // remove the listener when the UI is disposed - unknownTable.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - ui_node.removeUpdateListener(updateListener); - } - }); - - updateUnknownAttributesSection(ui_node, unknownTable, managedForm, reference); - - mMasterSection.getParent().pack(true /* changed */); - } - } - - /** - * Create a sub Section and its embedding wrapper table with 2 columns. - * @return The table, child of a new section. - */ - private Composite createSubSectionTable(FormToolkit toolkit, - Composite masterTable, String title) { - - // The Section composite seems to ignore colspan when assigned a TableWrapData so - // if the parent is a table with more than one column an extra table with one column - // is inserted to respect colspan. - int parentNumCol = ((TableWrapLayout) masterTable.getLayout()).numColumns; - if (parentNumCol > 1) { - masterTable = SectionHelper.createTableLayout(masterTable, toolkit, 1); - TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB); - twd.maxWidth = AndroidEditor.TEXT_WIDTH_HINT; - twd.colspan = parentNumCol; - masterTable.setLayoutData(twd); - } - - Composite table; - Section section = toolkit.createSection(masterTable, - Section.TITLE_BAR | Section.TWISTIE); - - // Add an expansion listener that will trigger a reflow on the parent - // ScrolledPageBook (which is actually a SharedScrolledComposite). This will - // recompute the correct size and adjust the scrollbar as needed. - section.addExpansionListener(new IExpansionListener() { - public void expansionStateChanged(ExpansionEvent e) { - reflowMasterSection(); - } - - public void expansionStateChanging(ExpansionEvent e) { - // pass - } - }); - - section.setText(title); - section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, - TableWrapData.TOP)); - table = SectionHelper.createTableLayout(section, toolkit, 2 /* numColumns */); - return table; - } - - /** - * Reflow the parent ScrolledPageBook (which is actually a SharedScrolledComposite). - * This will recompute the correct size and adjust the scrollbar as needed. - */ - private void reflowMasterSection() { - for(Composite c = mMasterSection; c != null; c = c.getParent()) { - if (c instanceof SharedScrolledComposite) { - ((SharedScrolledComposite) c).reflow(true /* flushCache */); - break; - } - } - } - - /** - * Updates the unknown attributes section for the UI Node. - */ - private void updateUnknownAttributesSection(UiElementNode ui_node, - final Composite unknownTable, final IManagedForm managedForm, - HashSet<UiAttributeNode> reference) { - Collection<UiAttributeNode> ui_attrs = ui_node.getUnknownUiAttributes(); - Section section = ((Section) unknownTable.getParent()); - boolean needs_reflow = false; - - // The table was created hidden, show it if there are unknown attributes now - if (ui_attrs.size() > 0 && !section.isVisible()) { - section.setVisible(true); - needs_reflow = true; - } - - // Compare the new attribute set with the old "reference" one - boolean has_differences = ui_attrs.size() != reference.size(); - if (!has_differences) { - for (UiAttributeNode ui_attr : ui_attrs) { - if (!reference.contains(ui_attr)) { - has_differences = true; - break; - } - } - } - - if (has_differences) { - needs_reflow = true; - reference.clear(); - - // Remove all children of the table - for (Control c : unknownTable.getChildren()) { - c.dispose(); - } - - // Recreate all attributes UI - for (UiAttributeNode ui_attr : ui_attrs) { - reference.add(ui_attr); - ui_attr.createUiControl(unknownTable, managedForm); - - if (ui_attr.getCurrentValue() != null && ui_attr.getCurrentValue().length() > 0) { - section.setExpanded(true); - } - } - } - - if (needs_reflow) { - reflowMasterSection(); - } - } - - /** - * Marks the part dirty. Called as a result of user interaction with the widgets in the - * section. - */ - private void markDirty() { - if (!mIsDirty) { - mIsDirty = true; - mManagedForm.dirtyStateChanged(); - } - } -} - - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java deleted file mode 100644 index 9f34d9e..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -import java.util.ArrayList; - -/** - * UiModelTreeContentProvider is a trivial implementation of {@link ITreeContentProvider} - * where elements are expected to be instances of {@link UiElementNode}. - */ -class UiModelTreeContentProvider implements ITreeContentProvider { - - /** The root {@link UiElementNode} which contains all the elements that are to be - * manipulated by this tree view. In general this is the manifest UI node. */ - private UiElementNode mUiRootNode; - /** The descriptor of the elements to be displayed as root in this tree view. All elements - * of the same type in the root will be displayed. */ - private ElementDescriptor[] mDescriptorFilters; - - public UiModelTreeContentProvider(UiElementNode uiRootNode, - ElementDescriptor[] descriptorFilters) { - mUiRootNode = uiRootNode; - mDescriptorFilters = descriptorFilters; - } - - /* (non-java doc) - * Returns all the UI node children of the given element or null if not the right kind - * of object. */ - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof UiElementNode) { - UiElementNode node = (UiElementNode) parentElement; - return node.getUiChildren().toArray(); - } - return null; - } - - /* (non-java doc) - * Returns the parent of a given UI node or null if it's a root node or it's not the - * right kind of node. */ - public Object getParent(Object element) { - if (element instanceof UiElementNode) { - UiElementNode node = (UiElementNode) element; - return node.getUiParent(); - } - return null; - } - - /* (non-java doc) - * Returns true if the UI node has any UI children nodes. */ - public boolean hasChildren(Object element) { - if (element instanceof UiElementNode) { - UiElementNode node = (UiElementNode) element; - return node.getUiChildren().size() > 0; - } - return false; - } - - /* (non-java doc) - * Get root elements for the tree. These are all the UI nodes that - * match the filter descriptor in the current root node. - * <p/> - * Although not documented, it seems this method should not return null. - * At worse, it should return new Object[0]. - * <p/> - * inputElement is not currently used. The root node and the filter are given - * by the enclosing class. - */ - public Object[] getElements(Object inputElement) { - ArrayList<UiElementNode> roots = new ArrayList<UiElementNode>(); - if (mUiRootNode != null) { - for (UiElementNode ui_node : mUiRootNode.getUiChildren()) { - if (mDescriptorFilters == null || mDescriptorFilters.length == 0) { - roots.add(ui_node); - } else { - for (ElementDescriptor filter : mDescriptorFilters) { - if (ui_node.getDescriptor() == filter) { - roots.add(ui_node); - } - } - } - } - } - - return roots.toArray(); - } - - public void dispose() { - // pass - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // pass - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java deleted file mode 100644 index ff5f24c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.ui.ErrorImageComposite; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.swt.graphics.Image; - -/** - * UiModelTreeLabelProvider is a trivial implementation of {@link ILabelProvider} - * where elements are expected to derive from {@link UiElementNode} or - * from {@link ElementDescriptor}. - * - * It is used by both the master tree viewer and by the list in the Add... selection dialog. - */ -public class UiModelTreeLabelProvider implements ILabelProvider { - - public UiModelTreeLabelProvider() { - } - - /** - * Returns the element's logo with a fallback on the android logo. - */ - public Image getImage(Object element) { - ElementDescriptor desc = null; - if (element instanceof ElementDescriptor) { - Image img = ((ElementDescriptor) element).getIcon(); - if (img != null) { - return img; - } - } else if (element instanceof UiElementNode) { - UiElementNode node = (UiElementNode) element; - desc = node.getDescriptor(); - if (desc != null) { - Image img = desc.getIcon(); - if (img != null) { - if (node.hasError()) { - //TODO: cache image - return new ErrorImageComposite(img).createImage(); - } else { - return img; - } - } - } - } - return EditorsPlugin.getAndroidLogo(); - } - - /** - * Uses UiElementNode.shortDescription for the label for this tree item. - */ - public String getText(Object element) { - if (element instanceof ElementDescriptor) { - ElementDescriptor desc = (ElementDescriptor) element; - return desc.getUiName(); - } else if (element instanceof UiElementNode) { - UiElementNode node = (UiElementNode) element; - return node.getShortDescription(); - } - return element.toString(); - } - - public void addListener(ILabelProviderListener listener) { - // pass - } - - public void dispose() { - // pass - } - - public boolean isLabelProperty(Object element, String property) { - // pass - return false; - } - - public void removeListener(ILabelProviderListener listener) { - // pass - } -} - - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java deleted file mode 100644 index 7e7bd68..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.ui.tree; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; -import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IMenuListener; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.ITreeSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.ui.forms.DetailsPart; -import org.eclipse.ui.forms.IDetailsPage; -import org.eclipse.ui.forms.IDetailsPageProvider; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.MasterDetailsBlock; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -import java.util.LinkedList; - -/** - * {@link UiTreeBlock} is a {@link MasterDetailsBlock} which displays a tree view for - * a specific set of {@link UiElementNode}. - * <p/> - * For a given UI element node, the tree view displays all first-level children that - * match a given type (given by an {@link ElementDescriptor}. All children from these - * nodes are also displayed. - * <p/> - * In the middle next to the tree are some controls to add or delete tree nodes. - * On the left is a details part that displays all the visible UI attributes for a given - * selected UI element node. - */ -public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml { - - /** Height hint for the tree view. Helps the grid layout resize properly on smaller screens. */ - private static final int TREE_HEIGHT_HINT = 50; - - /** Container editor */ - AndroidEditor mEditor; - /** The root {@link UiElementNode} which contains all the elements that are to be - * manipulated by this tree view. In general this is the manifest UI node. */ - private UiElementNode mUiRootNode; - /** The descriptor of the elements to be displayed as root in this tree view. All elements - * of the same type in the root will be displayed. */ - private ElementDescriptor[] mDescriptorFilters; - /** The title for the master-detail part (displayed on the top "tab" on top of the tree) */ - private String mTitle; - /** The description for the master-detail part (displayed on top of the tree view) */ - private String mDescription; - /** The master-detail part, composed of a main tree and an auxiliary detail part */ - private ManifestSectionPart mMasterPart; - /** The tree viewer in the master-detail part */ - private TreeViewer mTreeViewer; - /** The "add" button for the tree view */ - private Button mAddButton; - /** The "remove" button for the tree view */ - private Button mRemoveButton; - /** The "up" button for the tree view */ - private Button mUpButton; - /** The "down" button for the tree view */ - private Button mDownButton; - /** The Managed Form used to create the master part */ - private IManagedForm mManagedForm; - /** Reference to the details part of the tree master block. */ - private DetailsPart mDetailsPart; - /** Reference to the clipboard for copy-paste */ - private Clipboard mClipboard; - /** Listener to refresh the tree viewer when the parent's node has been updated */ - private IUiUpdateListener mUiRefreshListener; - /** Listener to enable/disable the UI based on the application node's presence */ - private IUiUpdateListener mUiEnableListener; - - private UiTreeActions mUiTreeActions; - - private final boolean mAutoCreateRoot; - - - /** - * Creates a new {@link MasterDetailsBlock} that will display all UI nodes matching the - * given filter in the given root node. - * - * @param editor The parent manifest editor. - * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are - * to be manipulated by this tree view. In general this is the manifest UI node or the - * application UI node. This cannot be null. - * @param autoCreateRoot True if the root node can be created on-demand (i.e. as needed as - * soon as children exist). False if an external entity controls the existence of the - * root node. In practise, this is false for the manifest application page (the actual - * "application" node is managed by the ApplicationToggle part) whereas it is true - * for all other tree pages. - * @param descriptorFilters A list of descriptors of the elements to be displayed as root in - * this tree view. Use null or an empty list to accept any kind of node. - * @param title Title for the section - * @param description Description for the section - */ - public UiTreeBlock(AndroidEditor editor, - UiElementNode uiRootNode, - boolean autoCreateRoot, - ElementDescriptor[] descriptorFilters, - String title, - String description) { - mEditor = editor; - mUiRootNode = uiRootNode; - mAutoCreateRoot = autoCreateRoot; - mDescriptorFilters = descriptorFilters; - mTitle = title; - mDescription = description; - } - - /** @returns The container editor */ - AndroidEditor getEditor() { - return mEditor; - } - - /** @returns The reference to the clipboard for copy-paste */ - Clipboard getClipboard() { - return mClipboard; - } - - /** @returns The master-detail part, composed of a main tree and an auxiliary detail part */ - ManifestSectionPart getMasterPart() { - return mMasterPart; - } - - @Override - protected void createMasterPart(final IManagedForm managedForm, Composite parent) { - FormToolkit toolkit = managedForm.getToolkit(); - - mManagedForm = managedForm; - mMasterPart = new ManifestSectionPart(parent, toolkit); - Section section = mMasterPart.getSection(); - section.setText(mTitle); - section.setDescription(mDescription); - section.setLayout(new GridLayout()); - section.setLayoutData(new GridData(GridData.FILL_BOTH)); - - Composite grid = SectionHelper.createGridLayout(section, toolkit, 2); - - Tree tree = createTreeViewer(toolkit, grid, managedForm); - createButtons(toolkit, grid); - createTreeContextMenu(tree); - createSectionActions(section, toolkit); - } - - private void createSectionActions(Section section, FormToolkit toolkit) { - ToolBarManager manager = new ToolBarManager(SWT.FLAT); - ToolBar toolbar = manager.createControl(section); - section.setTextClient(toolbar); - - manager.add(new TreeSortAction()); - manager.update(true /*force*/); - } - - /** - * Creates the tree and its viewer - * @return The tree control - */ - private Tree createTreeViewer(FormToolkit toolkit, Composite grid, - final IManagedForm managedForm) { - // Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here. - // However the class must be adapted to create an adapted toolkit tree. - final Tree tree = toolkit.createTree(grid, SWT.SINGLE); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.widthHint = AndroidEditor.TEXT_WIDTH_HINT; - gd.heightHint = TREE_HEIGHT_HINT; - tree.setLayoutData(gd); - - mTreeViewer = new TreeViewer(tree); - mTreeViewer.setContentProvider(new UiModelTreeContentProvider( - mUiRootNode, mDescriptorFilters)); - mTreeViewer.setLabelProvider(new UiModelTreeLabelProvider()); - mTreeViewer.setInput("unused"); //$NON-NLS-1$ - - // Create a listener that reacts to selections on the tree viewer. - // When a selection is made, ask the managed form to propagate an event to - // all parts in the managed form. - // This is picked up by UiElementDetail.selectionChanged(). - mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - managedForm.fireSelectionChanged(mMasterPart, event.getSelection()); - adjustTreeButtons(event.getSelection()); - } - }); - - // Create three listeners: - // - One to refresh the tree viewer when the parent's node has been updated - // - One to refresh the tree viewer when the framework resources have changed - // - One to enable/disable the UI based on the application node's presence. - mUiRefreshListener = new IUiUpdateListener() { - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - mTreeViewer.refresh(); - } - }; - - mUiEnableListener = new IUiUpdateListener() { - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - // The UiElementNode for the application XML node always exists, even - // if there is no corresponding XML node in the XML file. - // - // Normally, we enable the UI here if the XML node is not null. - // - // However if mAutoCreateRoot is true, the root node will be created on-demand - // so the tree/block is always enabled. - boolean exists = mAutoCreateRoot || (ui_node.getXmlNode() != null); - if (mMasterPart != null) { - Section section = mMasterPart.getSection(); - if (section.getEnabled() != exists) { - section.setEnabled(exists); - for (Control c : section.getChildren()) { - c.setEnabled(exists); - } - } - } - } - }; - - final Runnable resourceRefreshListener = new Runnable() { - public void run() { - // If a details part has been created, we need to "refresh" it too. - if (mDetailsPart != null) { - // The details part does not directly expose access to its internal - // page book. Instead it is possible to resize the page book to 0 and then - // back to its original value, which as the side effect of removing all - // existing cached pages. - int limit = mDetailsPart.getPageLimit(); - mDetailsPart.setPageLimit(0); - mDetailsPart.setPageLimit(limit); - } - // Refresh the tree, preserving the selection if possible. - mTreeViewer.refresh(); - } - }; - - // Setup the listeners - changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */); - - // Listen on resource framework changes to refresh the tree - EditorsPlugin.getDefault().addResourceChangedListener(resourceRefreshListener); - - // Remove listeners when the tree widget gets disposed. - tree.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - UiElementNode node = mUiRootNode.getUiParent() != null ? - mUiRootNode.getUiParent() : - mUiRootNode; - - node.removeUpdateListener(mUiRefreshListener); - mUiRootNode.removeUpdateListener(mUiEnableListener); - - EditorsPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener); - if (mClipboard != null) { - mClipboard.dispose(); - mClipboard = null; - } - } - }); - - // Get a new clipboard reference. It is disposed when the tree is disposed. - mClipboard = new Clipboard(tree.getDisplay()); - - return tree; - } - - /** - * Changes the UI root node and the descriptor filters of the tree. - * <p/> - * This removes the listeners attached to the old root node and reattaches them to the - * new one. - * - * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are - * to be manipulated by this tree view. In general this is the manifest UI node or the - * application UI node. This cannot be null. - * @param descriptorFilters A list of descriptors of the elements to be displayed as root in - * this tree view. Use null or an empty list to accept any kind of node. - * @param forceRefresh If tree, forces the tree to refresh - */ - public void changeRootAndDescriptors(UiElementNode uiRootNode, - ElementDescriptor[] descriptorFilters, boolean forceRefresh) { - UiElementNode node; - - // Remove previous listeners if any - if (mUiRootNode != null) { - node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode; - node.removeUpdateListener(mUiRefreshListener); - mUiRootNode.removeUpdateListener(mUiEnableListener); - } - - mUiRootNode = uiRootNode; - mDescriptorFilters = descriptorFilters; - - // Listen on structural changes on the root node of the tree - // If the node has a parent, listen on the parent instead. - node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode; - node.addUpdateListener(mUiRefreshListener); - - // Use the root node to listen to its presence. - mUiRootNode.addUpdateListener(mUiEnableListener); - - // Initialize the enabled/disabled state - mUiEnableListener.uiElementNodeUpdated(mUiRootNode, null /* state, not used */); - - if (forceRefresh) { - mTreeViewer.refresh(); - } - } - - /** - * Creates the buttons next to the tree. - */ - private void createButtons(FormToolkit toolkit, Composite grid) { - - mUiTreeActions = new UiTreeActions(); - - Composite button_grid = SectionHelper.createGridLayout(grid, toolkit, 1); - button_grid.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); - mAddButton = toolkit.createButton(button_grid, "Add...", SWT.PUSH); - SectionHelper.addControlTooltip(mAddButton, "Adds a new element."); - mAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | - GridData.VERTICAL_ALIGN_BEGINNING)); - - mAddButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeAdd(); - } - }); - - mRemoveButton = toolkit.createButton(button_grid, "Remove...", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Removes an existing selected element."); - mRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mRemoveButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeRemove(); - } - }); - - mUpButton = toolkit.createButton(button_grid, "Up", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element up."); - mUpButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mUpButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeUp(); - } - }); - - mDownButton = toolkit.createButton(button_grid, "Down", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element down."); - mDownButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mDownButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeDown(); - } - }); - - adjustTreeButtons(TreeSelection.EMPTY); - } - - private void createTreeContextMenu(Tree tree) { - MenuManager menuManager = new MenuManager(); - menuManager.setRemoveAllWhenShown(true); - menuManager.addMenuListener(new IMenuListener() { - /** - * The menu is about to be shown. The menu manager has already been - * requested to remove any existing menu item. This method gets the - * tree selection and if it is of the appropriate type it re-creates - * the necessary actions. - */ - public void menuAboutToShow(IMenuManager manager) { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first != null && first instanceof UiElementNode) { - UiElementNode ui_node = (UiElementNode) first; - doCreateMenuAction(manager, ui_node); - return; - } - } - doCreateMenuAction(manager, null /* ui_node */); - } - }); - Menu contextMenu = menuManager.createContextMenu(tree); - tree.setMenu(contextMenu); - } - - /** - * Adds the menu actions to the context menu when the given UI node is selected in - * the tree view. - * - * @param manager The context menu manager - * @param ui_node The UI node selected in the tree. Can be null, in which case the root - * is to be modified. - */ - private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) { - Action action; - - if (ui_node != null && ui_node.getXmlNode() != null) { - manager.add(new CopyCutAction(getEditor(), getClipboard(), - this, ui_node, true /* cut */)); - manager.add(new CopyCutAction(getEditor(), getClipboard(), - this, ui_node, false /* cut */)); - // Paste is not valid if it would add a second element on a terminal element - // which parent is a document -- an XML document can only have one child. This - // means paste is valid if the current UI node can have children or if the parent - // is not a document. - if (mUiRootNode.getDescriptor().hasChildren() || - !(mUiRootNode.getUiParent() instanceof UiDocumentNode)) { - manager.add(new PasteAction(getEditor(), getClipboard(), ui_node)); - } - manager.add(new Separator()); - } - - // Append "add" and "remove" actions. They do the same thing as the add/remove - // buttons on the side. - - manager.add(new Action("Add...", EditorsPlugin.getAndroidLogoDesc()) { - @Override - public void run() { - super.run(); - doTreeAdd(); - } - }); - - if (ui_node != null) { - manager.add(new Action("Remove", EditorsPlugin.getAndroidLogoDesc()) { - @Override - public void run() { - super.run(); - doTreeRemove(); - } - }); - } - - manager.add(new Separator()); - - if (ui_node != null) { - manager.add(new Action("Up", EditorsPlugin.getAndroidLogoDesc()) { - @Override - public void run() { - super.run(); - doTreeUp(); - } - }); - } - - if (ui_node != null) { - manager.add(new Action("Down", EditorsPlugin.getAndroidLogoDesc()) { - @Override - public void run() { - super.run(); - doTreeDown(); - } - }); - } - } - - - /** - * This is called by the tree when a selection is made. - * It enables/disables the buttons associated with the tree depending on the current - * selection. - * - * @param selection The current tree selection (same as mTreeViewer.getSelection()) - */ - private void adjustTreeButtons(ISelection selection) { - mRemoveButton.setEnabled(!selection.isEmpty() && selection instanceof ITreeSelection); - mUpButton.setEnabled(!selection.isEmpty() && selection instanceof ITreeSelection); - mDownButton.setEnabled(!selection.isEmpty() && selection instanceof ITreeSelection); - } - - /** - * An adapter/wrapper to use the add/remove/up/down tree edit actions. - */ - private class UiTreeActions extends UiActions { - @Override - protected UiElementNode getRootNode() { - return mUiRootNode; - } - - @Override - protected void selectUiNode(UiElementNode uiNodeToSelect) { - // Select the new item - if (uiNodeToSelect != null) { - LinkedList<UiElementNode> segments = new LinkedList<UiElementNode>(); - for (UiElementNode ui_node = uiNodeToSelect; ui_node != mUiRootNode; - ui_node = ui_node.getUiParent()) { - segments.add(0, ui_node); - } - mTreeViewer.setSelection(new TreeSelection(new TreePath(segments.toArray()))); - } - } - - @Override - public void commitPendingXmlChanges() { - commitManagedForm(); - } - } - - /** - * Called when the "Add..." button next to the tree view is selected. - * - * Displays a selection dialog that lets the user select which kind of node - * to create, depending on the current selection. - */ - private void doTreeAdd() { - UiElementNode ui_node = mUiRootNode; - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first != null && first instanceof UiElementNode) { - ui_node = (UiElementNode) first; - } - } - - mUiTreeActions.doAdd( - ui_node, - mDescriptorFilters, - mTreeViewer.getControl().getShell(), - (ILabelProvider) mTreeViewer.getLabelProvider()); - } - - /** - * Called when the "Remove" button is selected. - * - * If the tree has a selection, remove it. - * This simply deletes the XML node attached to the UI node: when the XML model fires the - * update event, the tree will get refreshed. - */ - protected void doTreeRemove() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first instanceof UiElementNode) { - final UiElementNode ui_node = (UiElementNode) first; - - mUiTreeActions.doRemove(ui_node, mTreeViewer.getControl().getShell()); - } - } - } - - /** - * Called when the "Up" button is selected. - * <p/> - * If the tree has a selection, move it up, either in the child list or as the last child - * of the previous parent. - */ - protected void doTreeUp() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first instanceof UiElementNode) { - final UiElementNode ui_node = (UiElementNode) first; - - mUiTreeActions.doUp(ui_node); - } - } - } - - /** - * Called when the "Down" button is selected. - * - * If the tree has a selection, move it down, either in the same child list or as the - * first child of the next parent. - */ - protected void doTreeDown() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first instanceof UiElementNode) { - final UiElementNode ui_node = (UiElementNode) first; - - mUiTreeActions.doDown(ui_node); - } - } - } - - /** - * Commits the current managed form (the one associated with our master part). - * As a side effect, this will commit the current UiElementDetails page. - */ - void commitManagedForm() { - if (mManagedForm != null) { - mManagedForm.commit(false /* onSave */); - } - } - - /* Implements ICommitXml for CopyCutAction */ - public void commitPendingXmlChanges() { - commitManagedForm(); - } - - @Override - protected void createToolBarActions(IManagedForm managedForm) { - // pass - } - - @Override - protected void registerPages(DetailsPart detailsPart) { - // Keep a reference on the details part (the super class doesn't provide a getter - // for it.) - mDetailsPart = detailsPart; - - // The page selection mechanism does not use pages registered by association with - // a node class. Instead it uses a custom details page provider that provides a - // new UiElementDetail instance for each node instance. A limit of 5 pages is - // then set (the value is arbitrary but should be reasonable) for the internal - // page book. - detailsPart.setPageLimit(5); - - final UiTreeBlock tree = this; - - detailsPart.setPageProvider(new IDetailsPageProvider() { - public IDetailsPage getPage(Object key) { - if (key instanceof UiElementNode) { - return new UiElementDetail(tree); - } - return null; - } - - public Object getPageKey(Object object) { - return object; // use node object as key - } - }); - } - - /** - * Adds a sort action to the tree viewer. - */ - private class TreeSortAction extends Action { - - private ViewerComparator mComparator; - - public TreeSortAction() { - setToolTipText("Sorts elements alphabetically."); - setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$ - - if (mTreeViewer != null) { - boolean is_sorted = mTreeViewer.getComparator() != null; - setChecked(is_sorted); - } - } - - /** - * Called when the button is selected. Toggle the tree viewer comparator. - */ - @Override - public void run() { - if (mTreeViewer == null) { - notifyResult(false /*success*/); - return; - } - - ViewerComparator comp = mTreeViewer.getComparator(); - if (comp != null) { - // Tree is currently sorted. - // Save currently comparator and remove it - mComparator = comp; - mTreeViewer.setComparator(null); - } else { - // Tree is not currently sorted. - // Reuse or add a new comparator. - if (mComparator == null) { - mComparator = new ViewerComparator(); - } - mTreeViewer.setComparator(mComparator); - } - - notifyResult(true /*success*/); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java deleted file mode 100644 index 4c368d9..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.eclipse.editors.uimodel; - -/** - * This interface decoration indicates that a given UiAttributeNode can both - * set and get its current value. - */ -public interface IUiSettableAttributeNode { - - /** Returns the current value of the node. */ - public String getCurrentValue(); - - /** Sets the current value of the node. */ - public void setCurrentValue(String value); - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java deleted file mode 100644 index 12cb31b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - - -/** - * Listen to update notifications in UI nodes. - */ -public interface IUiUpdateListener { - - /** Update state of the UI node */ - public enum UiUpdateState { - /** The node's attributes have been updated. They may or may not actually have changed. */ - ATTR_UPDATED, - /** The node sub-structure (i.e. child nodes) has changed */ - CHILDREN_CHANGED, - /** The XML counterpart for the UI node has just been created. */ - CREATED, - /** The XML counterpart for the UI node has just been deleted. - * Note that mandatory UI nodes are never actually deleted. */ - DELETED - } - - /** - * Indicates that an UiElementNode has been updated. - * <p/> - * This happens when an {@link UiElementNode} is refreshed to match the - * XML model. The actual UI element node may or may not have changed. - * - * @param ui_node The {@link UiElementNode} being updated. - */ - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java deleted file mode 100644 index 17b077a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; - -import org.w3c.dom.Node; - -/** - * Represents an XML attribute in that can be modified using a simple text field - * in the XML editor's user interface. - * <p/> - * The XML attribute has no default value. When unset, the text field is blank. - * When updating the XML, if the field is empty, the attribute will be removed - * from the XML element. - * <p/> - * See {@link UiAttributeNode} for more information. - */ -public abstract class UiAbstractTextAttributeNode extends UiAttributeNode - implements IUiSettableAttributeNode { - - protected static final String DEFAULT_VALUE = ""; //$NON-NLS-1$ - - /** Prevent internal listener from firing when internally modifying the text */ - private boolean mInternalTextModification; - /** Last value read from the XML model */ - private String mCurrentValue = DEFAULT_VALUE; - - public UiAbstractTextAttributeNode(AttributeDescriptor attributeDescriptor, - UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /** Returns the current value of the node. */ - @Override - public final String getCurrentValue() { - return mCurrentValue; - } - - /** Sets the current value of the node. */ - public final void setCurrentValue(String value) { - mCurrentValue = value; - } - - /** Returns if the attribute node is valid, and its UI has been created. */ - public abstract boolean isValid(); - - /** Returns the text value present in the UI. */ - public abstract String getTextWidgetValue(); - - /** Sets the text value to be displayed in the UI. */ - public abstract void setTextWidgetValue(String value); - - - /** - * Updates the current text field's value when the XML has changed. - * <p/> - * The caller doesn't really know if attributes have changed, - * so it will call this to refresh the attribute anyway. The value - * is only set if it has changed. - * <p/> - * This also resets the "dirty" flag. - */ - @Override - public void updateValue(Node xml_attribute_node) { - mCurrentValue = DEFAULT_VALUE; - if (xml_attribute_node != null) { - mCurrentValue = xml_attribute_node.getNodeValue().trim(); - } - - if (isValid() && !getTextWidgetValue().equals(mCurrentValue)) { - try { - mInternalTextModification = true; - setTextWidgetValue(mCurrentValue); - setDirty(false); - } finally { - mInternalTextModification = false; - } - } - } - - /* (non-java doc) - * Called by the user interface when the editor is saved or its state changed - * and the modified attributes must be committed (i.e. written) to the XML model. - */ - @Override - public void commit() { - UiElementNode parent = getUiParent(); - if (parent != null && isValid() && isDirty()) { - String value = getTextWidgetValue().trim(); - if (parent.commitAttributeToXml(this, value)) { - mCurrentValue = value; - setDirty(false); - } - } - } - - protected final boolean isInInternalTextModification() { - return mInternalTextModification; - } - - protected final void setInInternalTextModification(boolean internalTextModification) { - mInternalTextModification = internalTextModification; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java deleted file mode 100644 index 5972f22..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.forms.IManagedForm; -import org.w3c.dom.Node; - -/** - * Represents an XML attribute that can be modified by the XML editor's user interface. - * <p/> - * The characteristics of an {@link UiAttributeNode} are declared by a - * corresponding {@link AttributeDescriptor}. - * <p/> - * This is an abstract class. Derived classes must implement the creation of the UI - * and manage its synchronization with the XML. - */ -public abstract class UiAttributeNode { - - private AttributeDescriptor mDescriptor; - private UiElementNode mUiParent; - private boolean mIsDirty; - private boolean mHasError; - - /** Creates a new {@link UiAttributeNode} linked to a specific {@link AttributeDescriptor} - * and the corresponding runtine {@link UiElementNode} parent. */ - public UiAttributeNode(AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { - mDescriptor = attributeDescriptor; - mUiParent = uiParent; - } - - /** Returns the {@link AttributeDescriptor} specific to this UI attribute node */ - public final AttributeDescriptor getDescriptor() { - return mDescriptor; - } - - /** Returns the {@link UiElementNode} that owns this {@link UiAttributeNode} */ - public final UiElementNode getUiParent() { - return mUiParent; - } - - /** Returns the current value of the node. */ - public abstract String getCurrentValue(); - - /** - * @return True if the attribute has been changed since it was last loaded - * from the XML model. - */ - public final boolean isDirty() { - return mIsDirty; - } - - /** - * Sets whether the attribute is dirty and also notifies the editor some part's dirty - * flag as changed. - * <p/> - * Subclasses should set the to true as a result of user interaction with the widgets in - * the section and then should set to false when the commit() method completed. - */ - public void setDirty(boolean isDirty) { - boolean old_value = mIsDirty; - mIsDirty = isDirty; - // TODO: for unknown attributes, getParent() != null && getParent().getEditor() != null - if (old_value != isDirty) { - getUiParent().getEditor().editorDirtyStateChanged(); - } - } - - /** - * Sets the error flag value. - * @param errorFlag the error flag - */ - public final void setHasError(boolean errorFlag) { - mHasError = errorFlag; - } - - /** - * Returns whether this node has errors. - */ - public final boolean hasError() { - return mHasError; - } - - /** - * Called once by the parent user interface to creates the necessary - * user interface to edit this attribute. - * <p/> - * This method can be called more than once in the life cycle of an UI node, - * typically when the UI is part of a master-detail tree, as pages are swapped. - * - * @param parent The composite where to create the user interface. - * @param managedForm The managed form owning this part. - */ - public abstract void createUiControl(Composite parent, IManagedForm managedForm); - - /** - * Used to get a list of all possible values for this UI attribute. - * <p/> - * This is used, among other things, by the XML Content Assists to complete values - * for an attribute. - * <p/> - * Implementations that do not have any known values should return null. - * - * @return A list of possible completion values or null. - */ - public abstract String[] getPossibleValues(); - - /** - * Called when the XML is being loaded or has changed to - * update the value held by this user interface attribute node. - * <p/> - * The XML Node <em>may</em> be null, which denotes that the attribute is not - * specified in the XML model. In general, this means the "default" value of the - * attribute should be used. - * <p/> - * The caller doesn't really know if attributes have changed, - * so it will call this to refresh the attribute anyway. It's up to the - * UI implementation to minimize refreshes. - * - * @param xml_attribute_node - */ - public abstract void updateValue(Node xml_attribute_node); - - /** - * Called by the user interface when the editor is saved or its state changed - * and the modified attributes must be committed (i.e. written) to the XML model. - * <p/> - * Important behaviors: - * <ul> - * <li>The caller *must* have called IStructuredModel.aboutToChangeModel before. - * The implemented methods must assume it is safe to modify the XML model. - * <li>On success, the implementation *must* call setDirty(false). - * <li>On failure, the implementation can fail with an exception, which - * is trapped and logged by the caller, or do nothing, whichever is more - * appropriate. - * </ul> - */ - public abstract void commit(); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java deleted file mode 100644 index 113738f..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -/** - * Represents an XML document node that can be modified by the user interface in the XML editor. - * <p/> - * The structure of a given {@link UiDocumentNode} is declared by a corresponding - * {@link DocumentDescriptor}. - */ -public class UiDocumentNode extends UiElementNode { - - /** - * Creates a new {@link UiDocumentNode} described by a given {@link DocumentDescriptor}. - * - * @param documentDescriptor The {@link DocumentDescriptor} for the XML node. Cannot be null. - */ - public UiDocumentNode(DocumentDescriptor documentDescriptor) { - super(documentDescriptor); - } - - /** - * Computes a short string describing the UI node suitable for tree views. - * Uses the element's attribute "android:name" if present, or the "android:label" one - * followed by the element's name. - * - * @return A short string describing the UI node suitable for tree views. - */ - @Override - public String getShortDescription() { - return "Document"; //$NON-NLS-1$ - } - - /** - * Computes a "breadcrumb trail" description for this node. - * - * @param include_root Whether to include the root (e.g. "Manifest") or not. Has no effect - * when called on the root node itself. - * @return The "breadcrumb trail" description for this node. - */ - @Override - public String getBreadcrumbTrailDescription(boolean include_root) { - return "Document"; //$NON-NLS-1$ - } - - /** - * This method throws an exception when attempted to assign a parent, since XML documents - * cannot have a parent. It is OK to assign null. - */ - @Override - protected void setUiParent(UiElementNode parent) { - if (parent != null) { - // DEBUG. Change to log warning. - throw new UnsupportedOperationException("Documents can't have UI parents"); //$NON-NLS-1$ - } - super.setUiParent(null); - } - - /** - * Populate this element node with all values from the given XML node. - * - * This fails if the given XML node has a different element name -- it won't change the - * type of this ui node. - * - * This method can be both used for populating values the first time and updating values - * after the XML model changed. - * - * @param xml_node The XML node to mirror - * @return Returns true if the XML structure has changed (nodes added, removed or replaced) - */ - @Override - public boolean loadFromXmlNode(Node xml_node) { - boolean structure_changed = (getXmlDocument() != xml_node); - setXmlDocument((Document) xml_node); - structure_changed |= super.loadFromXmlNode(xml_node); - if (structure_changed) { - invokeUiUpdateListeners(UiUpdateState.CHILDREN_CHANGED); - } - return structure_changed; - } - - /** - * This method throws an exception if there is no underlying XML document. - * <p/> - * XML documents cannot be created per se -- they are a by-product of the StructuredEditor - * XML parser. - * - * @return The current value of getXmlDocument(). - */ - @Override - public Node createXmlNode() { - if (getXmlDocument() == null) { - // By design, a document node cannot be created, it is owned by the XML parser. - // By "design" this should never happen since the XML parser always creates an XML - // document container, even for an empty file. - throw new UnsupportedOperationException("Documents cannot be created"); //$NON-NLS-1$ - } - return getXmlDocument(); - } - - /** - * This method throws an exception and does not even try to delete the XML document. - * <p/> - * XML documents cannot be deleted per se -- they are a by-product of the StructuredEditor - * XML parser. - * - * @return The removed node or null if it didn't exist in the firtst place. - */ - @Override - public Node deleteXmlNode() { - // DEBUG. Change to log warning. - throw new UnsupportedOperationException("Documents cannot be deleted"); //$NON-NLS-1$ - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java deleted file mode 100644 index 22b68b3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java +++ /dev/null @@ -1,1434 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.CustomViewDescriptorService; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; -import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; -import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; -import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.views.properties.IPropertyDescriptor; -import org.eclipse.ui.views.properties.IPropertySource; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.Text; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -/** - * Represents an XML node that can be modified by the user interface in the XML editor. - * <p/> - * Each tree viewer used in the application page's parts needs to keep a model representing - * each underlying node in the tree. This interface represents the base type for such a node. - * <p/> - * Each node acts as an intermediary model between the actual XML model (the real data support) - * and the tree viewers or the corresponding page parts. - * <p/> - * Element nodes don't contain data per se. Their data is contained in their attributes - * as well as their children's attributes, see {@link UiAttributeNode}. - * <p/> - * The structure of a given {@link UiElementNode} is declared by a corresponding - * {@link ElementDescriptor}. - * <p/> - * The class implements {@link IPropertySource}, in order to fill the Eclipse property tab when - * an element is selected. The {@link AttributeDescriptor} are used property descriptors. - */ -public class UiElementNode implements IPropertySource { - - /** List of prefixes removed from android:id strings when creating short descriptions. */ - private static String[] ID_PREFIXES = { - "@android:id/", //$NON-NLS-1$ - "@+id/", "@id/", "@+", "@" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - - /** The element descriptor for the node. Always present, never null. */ - private ElementDescriptor mDescriptor; - /** The parent element node in the UI model. It is null for a root element or until - * the node is attached to its parent. */ - private UiElementNode mUiParent; - /** The {@link AndroidEditor} handling the UI hierarchy. This is defined only for the - * root node. All children have the value set to null and query their parent. */ - private AndroidEditor mEditor; - /** The XML {@link Document} model that is being mirror by the UI model. This is defined - * only for the root node. All children have the value set to null and query their parent. */ - private Document mXmlDocument; - /** The XML {@link Node} mirror by this UI node. This can be null for mandatory UI node which - * have no corresponding XML node or for new UI nodes before their XML node is set. */ - private Node mXmlNode; - /** The list of all UI children nodes. Can be empty but never null. There's one UI children - * node per existing XML children node. */ - private ArrayList<UiElementNode> mUiChildren; - /** The list of <em>all</em> UI attributes, as declared in the {@link ElementDescriptor}. - * The list is always defined and never null. Unlike the UiElementNode children list, this - * is always defined, even for attributes that do not exist in the XML model -- that's because - * "missing" attributes in the XML model simply mean a default value is used. Also note that - * the underlying collection is a map, so order is not respected. To get the desired attribute - * order, iterate through the {@link ElementDescriptor}'s attribute list. */ - private HashMap<AttributeDescriptor, UiAttributeNode> mUiAttributes; - private HashSet<UiAttributeNode> mUnknownUiAttributes; - /** A read-only view of the UI children node collection. */ - private List<UiElementNode> mReadOnlyUiChildren; - /** A read-only view of the UI attributes collection. */ - private Collection<UiAttributeNode> mReadOnlyUiAttributes; - /** A map of hidden attribute descriptors. Key is the XML name. */ - private Map<String, AttributeDescriptor> mCachedHiddenAttributes; - /** An optional list of {@link IUiUpdateListener}. Most element nodes will not have any - * listeners attached, so the list is only created on demand and can be null. */ - private ArrayList<IUiUpdateListener> mUiUpdateListeners; - /** Error Flag */ - private boolean mHasError; - /** Temporary data used by the editors. This data is not sync'ed with the XML */ - private Object mEditData; - - /** - * Creates a new {@link UiElementNode} described by a given {@link ElementDescriptor}. - * - * @param elementDescriptor The {@link ElementDescriptor} for the XML node. Cannot be null. - */ - public UiElementNode(ElementDescriptor elementDescriptor) { - mDescriptor = elementDescriptor; - clearContent(); - } - - /** - * Clears the {@link UiElementNode} by resetting the children list and - * the {@link UiAttributeNode}s list. - * Also resets the attached XML node, document, editor if any. - * <p/> - * The parent {@link UiElementNode} node is not reset so that it's position - * in the hierarchy be left intact, if any. - */ - /* package */ void clearContent() { - mXmlNode = null; - mXmlDocument = null; - mEditor = null; - clearAttributes(); - mReadOnlyUiChildren = null; - if (mUiChildren == null) { - mUiChildren = new ArrayList<UiElementNode>(); - } else { - // We can't remove mandatory nodes, we just clear them. - for (int i = mUiChildren.size() - 1; i >= 0; --i) { - removeUiChildAtIndex(i); - } - } - } - - /** - * Clears the internal list of attributes, the read-only cached version of it - * and the read-only cached hidden attribute list. - */ - private void clearAttributes() { - mUiAttributes = null; - mReadOnlyUiAttributes = null; - mCachedHiddenAttributes = null; - mUnknownUiAttributes = new HashSet<UiAttributeNode>(); - } - - /** - * Gets or creates the internal UiAttributes list. - * <p/> - * When the descriptor derives from ViewElementDescriptor, this list depends on the - * current UiParent node. - * - * @return A new set of {@link UiAttributeNode} that matches the expected - * attributes for this node. - */ - private HashMap<AttributeDescriptor, UiAttributeNode> getInternalUiAttributes() { - if (mUiAttributes == null) { - AttributeDescriptor[] attr_list = getAttributeDescriptors(); - mUiAttributes = new HashMap<AttributeDescriptor, UiAttributeNode>(attr_list.length); - for (AttributeDescriptor desc : attr_list) { - UiAttributeNode ui_node = desc.createUiNode(this); - if (ui_node != null) { // Some AttributeDescriptors do not have UI associated - mUiAttributes.put(desc, ui_node); - } - } - } - return mUiAttributes; - } - - /** - * Computes a short string describing the UI node suitable for tree views. - * Uses the element's attribute "android:name" if present, or the "android:label" one - * followed by the element's name. - * - * @return A short string describing the UI node suitable for tree views. - */ - public String getShortDescription() { - if (mXmlNode != null && mXmlNode instanceof Element && mXmlNode.hasAttributes()) { - - // Application and Manifest nodes have a special treatment: they are unique nodes - // so we don't bother trying to differentiate their strings and we fall back to - // just using the UI name below. - Element elem = (Element) mXmlNode; - - String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, - AndroidManifestDescriptors.ANDROID_NAME_ATTR); - if (attr == null || attr.length() == 0) { - attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, - AndroidManifestDescriptors.ANDROID_LABEL_ATTR); - } - if (attr == null || attr.length() == 0) { - attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR); - } - if (attr == null || attr.length() == 0) { - attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, - LayoutDescriptors.ID_ATTR); - - if (attr != null && attr.length() > 0) { - for (String prefix : ID_PREFIXES) { - if (attr.startsWith(prefix)) { - attr = attr.substring(prefix.length()); - break; - } - } - } - } - if (attr != null && attr.length() > 0) { - return String.format("%1$s (%2$s)", attr, mDescriptor.getUiName()); - } - } - - return String.format("%1$s", mDescriptor.getUiName()); - } - - /** - * Computes a "breadcrumb trail" description for this node. - * It will look something like "Manifest > Application > .myactivity (Activity) > Intent-Filter" - * - * @param include_root Whether to include the root (e.g. "Manifest") or not. Has no effect - * when called on the root node itself. - * @return The "breadcrumb trail" description for this node. - */ - public String getBreadcrumbTrailDescription(boolean include_root) { - StringBuilder sb = new StringBuilder(getShortDescription()); - - for (UiElementNode ui_node = getUiParent(); - ui_node != null; - ui_node = ui_node.getUiParent()) { - if (!include_root && ui_node.getUiParent() == null) { - break; - } - sb.insert(0, String.format("%1$s > ", ui_node.getShortDescription())); //$NON-NLS-1$ - } - - return sb.toString(); - } - - /** - * Sets the XML {@link Document}. - * <p/> - * The XML {@link Document} is initially null. The XML {@link Document} must be set only on the - * UI root element node (this method takes care of that.) - */ - public void setXmlDocument(Document xml_doc) { - if (mUiParent == null) { - mXmlDocument = xml_doc; - } else { - mUiParent.setXmlDocument(xml_doc); - } - } - - /** - * Returns the XML {@link Document}. - * <p/> - * The value is initially null until the UI node is attached to its UI parent -- the value - * of the document is then propagated. - * - * @return the XML {@link Document} or the parent's XML {@link Document} or null. - */ - public Document getXmlDocument() { - if (mXmlDocument != null) { - return mXmlDocument; - } else if (mUiParent != null) { - return mUiParent.getXmlDocument(); - } - return null; - } - - /** - * Returns the XML node associated with this UI node. - * <p/> - * Some {@link ElementDescriptor} are declared as being "mandatory". This means the - * corresponding UI node will exist even if there is no corresponding XML node. Such structure - * is created and enforced by the parent of the tree, not the element themselves. However - * such nodes will likely not have an XML node associated, so getXmlNode() can return null. - * - * @return The associated XML node. Can be null for mandatory nodes. - */ - public Node getXmlNode() { - return mXmlNode; - } - - /** - * Returns the {@link ElementDescriptor} for this node. This is never null. - * <p/> - * Do not use this to call getDescriptor().getAttributes(), instead call - * getAttributeDescriptors() which can be overriden by derived classes. - */ - public ElementDescriptor getDescriptor() { - return mDescriptor; - } - - /** - * Returns the {@link AttributeDescriptor} array for the descriptor of this node. - * <p/> - * Use this instead of getDescriptor().getAttributes() -- derived classes can override - * this to manipulate the attribute descriptor list depending on the current UI node. - */ - public AttributeDescriptor[] getAttributeDescriptors() { - return mDescriptor.getAttributes(); - } - - /** - * Returns the hidden {@link AttributeDescriptor} array for the descriptor of this node. - * This is a subset of the getAttributeDescriptors() list. - * <p/> - * Use this instead of getDescriptor().getHiddenAttributes() -- potentially derived classes - * could override this to manipulate the attribute descriptor list depending on the current - * UI node. There's no need for it right now so keep it private. - */ - private Map<String, AttributeDescriptor> getHiddenAttributeDescriptors() { - if (mCachedHiddenAttributes == null) { - mCachedHiddenAttributes = new HashMap<String, AttributeDescriptor>(); - for (AttributeDescriptor attr_desc : getAttributeDescriptors()) { - if (attr_desc instanceof XmlnsAttributeDescriptor) { - mCachedHiddenAttributes.put( - ((XmlnsAttributeDescriptor) attr_desc).getXmlNsName(), - attr_desc); - } - } - } - return mCachedHiddenAttributes; - } - - /** - * Sets the parent of this UiElementNode. - * <p/> - * The root node has no parent. - */ - protected void setUiParent(UiElementNode parent) { - mUiParent = parent; - // Invalidate the internal UiAttributes list, as it may depend on the actual UiParent. - clearAttributes(); - } - - /** - * @return The parent {@link UiElementNode} or null if this is the root node. - */ - public UiElementNode getUiParent() { - return mUiParent; - } - - /** - * Returns The root {@link UiElementNode}. - */ - public UiElementNode getUiRoot() { - UiElementNode root = this; - while (root.mUiParent != null) { - root = root.mUiParent; - } - - return root; - } - - /** - * Returns the previous UI sibling of this UI node. - * If the node does not have a previous sibling, returns null. - */ - public UiElementNode getUiPreviousSibling() { - if (mUiParent != null) { - List<UiElementNode> childlist = mUiParent.getUiChildren(); - if (childlist != null && childlist.size() > 1 && childlist.get(0) != this) { - int index = childlist.indexOf(this); - return index > 0 ? childlist.get(index - 1) : null; - } - } - return null; - } - - /** - * Returns the next UI sibling of this UI node. - * If the node does not have a next sibling, returns null. - */ - public UiElementNode getUiNextSibling() { - if (mUiParent != null) { - List<UiElementNode> childlist = mUiParent.getUiChildren(); - if (childlist != null) { - int size = childlist.size(); - if (size > 1 && childlist.get(size - 1) != this) { - int index = childlist.indexOf(this); - return index >= 0 && index < size - 1 ? childlist.get(index + 1) : null; - } - } - } - return null; - } - - /** - * Sets the {@link AndroidEditor} handling this {@link UiElementNode} hierarchy. - * <p/> - * The editor must always be set on the root node. This method takes care of that. - */ - public void setEditor(AndroidEditor editor) { - if (mUiParent == null) { - mEditor = editor; - } else { - mUiParent.setEditor(editor); - } - } - - /** - * Returns the {@link AndroidEditor} that embeds this {@link UiElementNode}. - * <p/> - * The value is initially null until the node is attached to its parent -- the value - * of the root node is then propagated. - * - * @return The embedding {@link AndroidEditor} or null. - */ - public AndroidEditor getEditor() { - return mUiParent == null ? mEditor : mUiParent.getEditor(); - } - - /** - * @return A read-only version of the children collection. - */ - public List<UiElementNode> getUiChildren() { - if (mReadOnlyUiChildren == null) { - mReadOnlyUiChildren = Collections.unmodifiableList(mUiChildren); - } - return mReadOnlyUiChildren; - } - - /** - * @return A read-only version of the attributes collection. - */ - public Collection<UiAttributeNode> getUiAttributes() { - if (mReadOnlyUiAttributes == null) { - mReadOnlyUiAttributes = Collections.unmodifiableCollection( - getInternalUiAttributes().values()); - } - return mReadOnlyUiAttributes; - } - - /** - * @return A read-only version of the unknown attributes collection. - */ - public Collection<UiAttributeNode> getUnknownUiAttributes() { - return Collections.unmodifiableCollection(mUnknownUiAttributes); - } - - /** - * Sets the error flag value. - * @param errorFlag the error flag - */ - public final void setHasError(boolean errorFlag) { - mHasError = errorFlag; - } - - /** - * Returns whether this node, its attributes, or one of the children nodes (and attributes) - * has errors. - */ - public final boolean hasError() { - if (mHasError) { - return true; - } - - // get the error value from the attributes. - Collection<UiAttributeNode> attributes = getInternalUiAttributes().values(); - for (UiAttributeNode attribute : attributes) { - if (attribute.hasError()) { - return true; - } - } - - // and now from the children. - for (UiElementNode child : mUiChildren) { - if (child.hasError()) { - return true; - } - } - - return false; - } - - /** - * Adds a new {@link IUiUpdateListener} to the internal update listener list. - */ - public void addUpdateListener(IUiUpdateListener listener) { - if (mUiUpdateListeners == null) { - mUiUpdateListeners = new ArrayList<IUiUpdateListener>(); - } - if (!mUiUpdateListeners.contains(listener)) { - mUiUpdateListeners.add(listener); - } - } - - /** - * Removes an existing {@link IUiUpdateListener} from the internal update listener list. - * Does nothing if the list is empty or the listener is not registered. - */ - public void removeUpdateListener(IUiUpdateListener listener) { - if (mUiUpdateListeners != null) { - mUiUpdateListeners.remove(listener); - } - } - - /** - * Finds a child node relative to this node using a path-like expression. - * F.ex. "node1/node2" would find a child "node1" that contains a child "node2" and - * returns the latter. If there are multiple nodes with the same name at the same - * level, always uses the first one found. - * - * @param path The path like expression to select a child node. - * @return The ui node found or null. - */ - public UiElementNode findUiChildNode(String path) { - String[] items = path.split("/"); //$NON-NLS-1$ - UiElementNode ui_node = this; - for (String item : items) { - boolean next_segment = false; - for (UiElementNode c : ui_node.mUiChildren) { - if (c.getDescriptor().getXmlName().equals(item)) { - ui_node = c; - next_segment = true; - break; - } - } - if (!next_segment) { - return null; - } - } - return ui_node; - } - - /** - * Finds an {@link UiElementNode} which contains the give XML {@link Node}. - * Looks recursively in all children UI nodes. - * - * @param xmlNode The XML node to look for. - * @return The {@link UiElementNode} that contains xmlNode or null if not found, - */ - public UiElementNode findXmlNode(Node xmlNode) { - if (xmlNode == null) { - return null; - } - if (getXmlNode() == xmlNode) { - return this; - } - - for (UiElementNode uiChild : mUiChildren) { - UiElementNode found = uiChild.findXmlNode(xmlNode); - if (found != null) { - return found; - } - } - - return null; - } - - /** - * Returns the {@link UiAttributeNode} matching this attribute descriptor or - * null if not found. - * - * @param attr_desc The {@link AttributeDescriptor} to match. - * @return the {@link UiAttributeNode} matching this attribute descriptor or null - * if not found. - */ - public UiAttributeNode findUiAttribute(AttributeDescriptor attr_desc) { - return getInternalUiAttributes().get(attr_desc); - } - - /** - * Populate this element node with all values from the given XML node. - * - * This fails if the given XML node has a different element name -- it won't change the - * type of this ui node. - * - * This method can be both used for populating values the first time and updating values - * after the XML model changed. - * - * @param xml_node The XML node to mirror - * @return Returns true if the XML structure has changed (nodes added, removed or replaced) - */ - public boolean loadFromXmlNode(Node xml_node) { - boolean structure_changed = (mXmlNode != xml_node); - mXmlNode = xml_node; - if (xml_node != null) { - updateAttributeList(xml_node); - structure_changed |= updateElementList(xml_node); - invokeUiUpdateListeners(structure_changed ? UiUpdateState.CHILDREN_CHANGED - : UiUpdateState.ATTR_UPDATED); - } - return structure_changed; - } - - /** - * Clears the UI node and reload it from the given XML node. - * <p/> - * This works by clearing all references to any previous XML or UI nodes and - * then reloads the XML document from scratch. The editor reference is kept. - * <p/> - * This is used in the special case where the ElementDescriptor structure has changed. - * Rather than try to diff inflated UI nodes (as loadFromXmlNode does), we don't bother - * and reload everything. This is not subtle and should be used very rarely. - * - * @param xml_node The XML node or document to reload. Can be null. - */ - public void reloadFromXmlNode(Node xml_node) { - // The editor needs to be preserved, it is not affected by an XML change. - AndroidEditor editor = getEditor(); - clearContent(); - setEditor(editor); - if (xml_node != null) { - setXmlDocument(xml_node.getOwnerDocument()); - } - // This will reload all the XML and recreate the UI structure from scratch. - loadFromXmlNode(xml_node); - } - - /** - * Called by attributes when they want to commit their value - * to an XML node. - * <p/> - * For mandatory nodes, this makes sure the underlying XML element node - * exists in the model. If not, it is created and assigned as the underlying - * XML node. - * </br> - * For non-mandatory nodes, simply return the underlying XML node, which - * must always exists. - * - * @return The XML node matching this {@link UiElementNode} or null. - */ - public Node prepareCommit() { - if (getDescriptor().isMandatory()) { - createXmlNode(); - // The new XML node has been created. - // We don't need to refresh using loadFromXmlNode() since there are - // no attributes or elements that need to be loading into this node. - } - return getXmlNode(); - } - - /** - * Commits the attributes (all internal, inherited from UI parent & unknown attributes). - * This is called by the UI when the embedding part needs to be committed. - */ - public void commit() { - for (UiAttributeNode ui_attr : getInternalUiAttributes().values()) { - ui_attr.commit(); - } - - for (UiAttributeNode ui_attr : mUnknownUiAttributes) { - ui_attr.commit(); - } - } - - /** - * Returns true if the part has been modified with respect to the data - * loaded from the model. - */ - public boolean isDirty() { - for (UiAttributeNode ui_attr : getInternalUiAttributes().values()) { - if (ui_attr.isDirty()) { - return true; - } - } - - for (UiAttributeNode ui_attr : mUnknownUiAttributes) { - if (ui_attr.isDirty()) { - return true; - } - } - - return false; - } - - /** - * Creates the underlying XML element node for this UI node if it doesn't already - * exists. - * - * @return The new value of getXmlNode() (can be null if creation failed) - */ - public Node createXmlNode() { - if (mXmlNode != null) { - return null; - } - Node parentXmlNode = null; - if (mUiParent != null) { - parentXmlNode = mUiParent.prepareCommit(); - if (parentXmlNode == null) { - // The parent failed to create its own backing XML node. Abort. - // No need to throw an exception, the parent will most likely - // have done so itself. - return null; - } - } - - String element_name = getDescriptor().getXmlName(); - Document doc = getXmlDocument(); - - // We *must* have a root node. If not, we need to abort. - if (doc == null) { - throw new RuntimeException( - String.format("Missing XML document for %1$s XML node.", element_name)); - } - - // If we get here and parent_xml_node is null, the node is to be created - // as the root node of the document (which can't be null, cf check above). - if (parentXmlNode == null) { - parentXmlNode = doc; - } - - mXmlNode = doc.createElement(element_name); - parentXmlNode.appendChild(mXmlNode); - // Insert a separator after the tag, to make it easier to read - Text sep = doc.createTextNode("\n"); - parentXmlNode.appendChild(sep); - - // Set all initial attributes in the XML node if they are not empty. - // Iterate on the descriptor list to get the desired order and then use the - // internal values, if any. - for (AttributeDescriptor attr_desc : getAttributeDescriptors()) { - if (attr_desc instanceof XmlnsAttributeDescriptor) { - XmlnsAttributeDescriptor desc = (XmlnsAttributeDescriptor) attr_desc; - Attr attr = doc.createAttributeNS(XmlnsAttributeDescriptor.XMLNS_URI, - desc.getXmlNsName()); - attr.setValue(desc.getValue()); - attr.setPrefix(desc.getXmlNsPrefix()); - mXmlNode.getAttributes().setNamedItemNS(attr); - } else { - UiAttributeNode ui_attr = mUiAttributes.get(attr_desc); - commitAttributeToXml(ui_attr, ui_attr.getCurrentValue()); - } - } - - invokeUiUpdateListeners(UiUpdateState.CREATED); - return mXmlNode; - } - - /** - * Removes the XML node corresponding to this UI node if it exists - * and also removes all mirrored information in this UI node (i.e. children, attributes) - * - * @return The removed node or null if it didn't exist in the firtst place. - */ - public Node deleteXmlNode() { - if (mXmlNode == null) { - return null; - } - - // First clear the internals of the node and *then* actually deletes the XML - // node (because doing so will generate an update even and this node may be - // revisited via loadFromXmlNode). - Node old_xml_node = mXmlNode; - clearContent(); - - Node xml_parent = old_xml_node.getParentNode(); - if (xml_parent == null) { - xml_parent = getXmlDocument(); - } - old_xml_node = xml_parent.removeChild(old_xml_node); - - invokeUiUpdateListeners(UiUpdateState.DELETED); - return old_xml_node; - } - - /** - * Updates the element list for this UiElementNode. - * At the end, the list of children UiElementNode here will match the one from the - * provided XML {@link Node}: - * <ul> - * <li> Walk both the current ui children list and the xml children list at the same time. - * <li> If we have a new xml child but already reached the end of the ui child list, add the - * new xml node. - * <li> Otherwise, check if the xml node is referenced later in the ui child list and if so, - * move it here. It means the XML child list has been reordered. - * <li> Otherwise, this is a new XML node that we add in the middle of the ui child list. - * <li> At the end, we may have finished walking the xml child list but still have remaining - * ui children, simply delete them as they matching trailing xml nodes that have been - * removed unless they are mandatory ui nodes. - * </ul> - * Note that only the first case is used when populating the ui list the first time. - * - * @param xml_node The XML node to mirror - * @return True when the XML structure has changed. - */ - protected boolean updateElementList(Node xml_node) { - boolean structure_changed = false; - int ui_index = 0; - Node xml_child = xml_node.getFirstChild(); - while (xml_child != null) { - if (xml_child.getNodeType() == Node.ELEMENT_NODE) { - String element_name = xml_child.getNodeName(); - UiElementNode ui_node = null; - if (mUiChildren.size() <= ui_index) { - // A new node is being added at the end of the list - ElementDescriptor desc = mDescriptor.findChildrenDescriptor(element_name, - false /* recursive */); - if (desc == null) { - // Unknown node. Create a temporary descriptor for it. - // most important we want to auto-add unknown attributes to it. - AndroidEditor editor = getEditor(); - IEditorInput editorInput = editor.getEditorInput(); - if (editorInput instanceof IFileEditorInput) { - IFileEditorInput fileInput = (IFileEditorInput)editorInput; - desc = CustomViewDescriptorService.getInstance().getDescriptor( - fileInput.getFile().getProject(), element_name); - if (desc == null) { - desc = new ElementDescriptor(element_name); - } - } else { - desc = new ElementDescriptor(element_name); - // TODO associate a new "?" icon to this descriptor. - } - } - structure_changed = true; - ui_node = appendNewUiChild(desc); - ui_index++; - } else { - // A new node is being inserted or moved. - // Note: mandatory nodes can be created without an XML node in which case - // getXmlNode() is null. - UiElementNode ui_child; - int n = mUiChildren.size(); - for (int j = ui_index; j < n; j++) { - ui_child = mUiChildren.get(j); - if (ui_child.getXmlNode() != null && ui_child.getXmlNode() == xml_child) { - if (j > ui_index) { - // Found the same XML node at some later index, now move it here. - mUiChildren.remove(j); - mUiChildren.add(ui_index, ui_child); - structure_changed = true; - } - ui_node = ui_child; - ui_index++; - break; - } - } - - if (ui_node == null) { - // Look for an unused mandatory node with no XML node attached - // referencing the same XML element name - for (int j = ui_index; j < n; j++) { - ui_child = mUiChildren.get(j); - if (ui_child.getXmlNode() == null && - ui_child.getDescriptor().isMandatory() && - ui_child.getDescriptor().getXmlName().equals(element_name)) { - if (j > ui_index) { - // Found it, now move it here - mUiChildren.remove(j); - mUiChildren.add(ui_index, ui_child); - } - // assign the XML node to this empty mandatory element. - ui_child.mXmlNode = xml_child; - structure_changed = true; - ui_node = ui_child; - ui_index++; - } - } - } - - if (ui_node == null) { - // Inserting new node - ElementDescriptor desc = mDescriptor.findChildrenDescriptor(element_name, - false /* recursive */); - if (desc == null) { - // Unknown element. Simply ignore it. - EditorsPlugin.log(IStatus.WARNING, - "AndroidManifest: Ignoring unknown '%s' XML element", //$NON-NLS-1$ - element_name); - } else { - structure_changed = true; - ui_node = insertNewUiChild(ui_index, desc); - ui_index++; - } - } - } - if (ui_node != null) { - // If we touched an UI Node, even an existing one, refresh its content. - // For new nodes, this will populate them recursively. - structure_changed |= ui_node.loadFromXmlNode(xml_child); - } - } - xml_child = xml_child.getNextSibling(); - } - - // There might be extra UI nodes at the end if the XML node list got shorter. - for (int index = mUiChildren.size() - 1; index >= ui_index; --index) { - structure_changed |= removeUiChildAtIndex(index); - } - - return structure_changed; - } - - /** - * Internal helper to remove an UI child node given by its index in the - * internal child list. - * - * Also invokes the update listener on the node to be deleted. - * - * @param ui_index The index of the UI child to remove, range 0 .. mUiChildren.size()-1 - * @return True if the structure has changed - * @throws IndexOutOfBoundsException if index is out of mUiChildren's bounds. Of course you - * know that could never happen unless the computer is on fire or something. - */ - private boolean removeUiChildAtIndex(int ui_index) { - UiElementNode ui_node = mUiChildren.get(ui_index); - invokeUiUpdateListeners(UiUpdateState.DELETED); - if (ui_node.getDescriptor().isMandatory()) { - // We can't remove a mandatory node, we just clear its content. - - // A mandatory node with no XML means it doesn't really exist, so it can't be - // deleted. - boolean xml_exists = (ui_node.getXmlNode() != null); - - ui_node.clearContent(); - return xml_exists; - } else { - mUiChildren.remove(ui_index); - return true; - } - } - - /** - * Creates a new {@link UiElementNode} from the given {@link ElementDescriptor} - * and appends it to the end of the element children list. - * - * @param descriptor The {@link ElementDescriptor} that knows how to create the UI node. - * @return The new UI node that has been appended - */ - public UiElementNode appendNewUiChild(ElementDescriptor descriptor) { - UiElementNode ui_node; - ui_node = descriptor.createUiNode(); - mUiChildren.add(ui_node); - ui_node.setUiParent(this); - ui_node.invokeUiUpdateListeners(UiUpdateState.CREATED); - return ui_node; - } - - /** - * Creates a new {@link UiElementNode} from the given {@link ElementDescriptor} - * and inserts it in the element children list at the specified position. - * - * @param index The position where to insert in the element children list. - * @param descriptor The {@link ElementDescriptor} that knows how to create the UI node. - * @return The new UI node. - */ - private UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) { - UiElementNode ui_node; - ui_node = descriptor.createUiNode(); - mUiChildren.add(index, ui_node); - ui_node.setUiParent(this); - ui_node.invokeUiUpdateListeners(UiUpdateState.CREATED); - return ui_node; - } - - /** - * Updates the {@link UiAttributeNode} list for this {@link UiElementNode}. - * <p/> - * For a given {@link UiElementNode}, the attribute list always exists in - * full and is totally independent of whether the XML model actually - * has the corresponding attributes. - * <p/> - * For each attribute declared in this {@link UiElementNode}, get - * the corresponding XML attribute. It may not exist, in which case the - * value will be null. We don't really know if a value has changed, so - * the updateValue() is called on the UI sattribute in all cases. - * - * @param xmlNode The XML node to mirror - */ - protected void updateAttributeList(Node xmlNode) { - NamedNodeMap xmlAttrMap = xmlNode.getAttributes(); - HashSet<Node> visited = new HashSet<Node>(); - - // For all known (i.e. expected) UI attributes, find an existing XML attribute of - // same (uri, local name) and update the internal Ui attribute value. - for (UiAttributeNode uiAttr : getInternalUiAttributes().values()) { - AttributeDescriptor desc = uiAttr.getDescriptor(); - if (!(desc instanceof SeparatorAttributeDescriptor)) { - Node xmlAttr = xmlAttrMap == null ? null : - xmlAttrMap.getNamedItemNS(desc.getNamespaceUri(), desc.getXmlLocalName()); - uiAttr.updateValue(xmlAttr); - visited.add(xmlAttr); - } - } - - // Clone the current list of unknown attributes. We'll then remove from this list when - // we still attributes which are still unknown. What will be left are the old unknown - // attributes that have been deleted in the current XML attribute list. - @SuppressWarnings("unchecked") //$NON-NLS-1$ - HashSet<UiAttributeNode> deleted = (HashSet<UiAttributeNode>) mUnknownUiAttributes.clone(); - - // We need to ignore hidden attributes. - Map<String, AttributeDescriptor> hiddenAttrDesc = getHiddenAttributeDescriptors(); - - // Traverse the actual XML attribute list to find unknown attributes - if (xmlAttrMap != null) { - for (int i = 0; i < xmlAttrMap.getLength(); i++) { - Node xmlAttr = xmlAttrMap.item(i); - // Ignore attributes which have actual descriptors - if (visited.contains(xmlAttr)) { - continue; - } - - String xmlFullName = xmlAttr.getNodeName(); - - // Ignore attributes which are hidden (based on the prefix:localName key) - if (hiddenAttrDesc.containsKey(xmlFullName)) { - continue; - } - - String xmlAttrLocalName = xmlAttr.getLocalName(); - String xmlNsUri = xmlAttr.getNamespaceURI(); - - UiAttributeNode uiAttr = null; - for (UiAttributeNode a : mUnknownUiAttributes) { - String aLocalName = a.getDescriptor().getXmlLocalName(); - String aNsUri = a.getDescriptor().getNamespaceUri(); - if (aLocalName.equals(xmlAttrLocalName) && - (aNsUri == xmlNsUri || (aNsUri != null && aNsUri.equals(xmlNsUri)))) { - // This attribute is still present in the unknown list - uiAttr = a; - // It has not been deleted - deleted.remove(a); - break; - } - } - if (uiAttr == null) { - // Create a new unknown attribute - TextAttributeDescriptor desc = new TextAttributeDescriptor( - xmlAttrLocalName, // xml name - xmlFullName, // ui name - xmlNsUri, // NS uri - "Unknown XML attribute"); // tooltip, translatable - uiAttr = desc.createUiNode(this); - mUnknownUiAttributes.add(uiAttr); - } - - uiAttr.updateValue(xmlAttr); - } - - // Remove from the internal list unknown attributes that have been deleted from the xml - for (UiAttributeNode a : deleted) { - mUnknownUiAttributes.remove(a); - } - } - } - - /** - * Invoke all registered {@link IUiUpdateListener} listening on this UI updates for this node. - */ - protected void invokeUiUpdateListeners(UiUpdateState state) { - if (mUiUpdateListeners != null) { - for (IUiUpdateListener listener : mUiUpdateListeners) { - try { - listener.uiElementNodeUpdated(this, state); - } catch (Exception e) { - // prevent a crashing listener from crashing the whole invocation chain - EditorsPlugin.log(e, "UIElement Listener failed: %s, state=%s", //$NON-NLS-1$ - getBreadcrumbTrailDescription(true), - state.toString()); - } - } - } - } - - // --- for derived implementations only --- - - // TODO doc - protected void setXmlNode(Node xml_node) { - mXmlNode = xml_node; - } - - /** - * Sets the temporary data used by the editors. - * @param data the data. - */ - public void setEditData(Object data) { - mEditData = data; - } - - /** - * Returns the temporary data used by the editors for this object. - * @return the data, or <code>null</code> if none has been set. - */ - public Object getEditData() { - return mEditData; - } - - public void refreshUi() { - invokeUiUpdateListeners(UiUpdateState.ATTR_UPDATED); - } - - - // ------------- Helpers - - /** - * Helper method to commit a single attribute value to XML. - * <p/> - * This method updates the XML regardless of the current XML value. - * Callers should check first if an update is needed. - * If the new value is empty, the XML attribute will be actually removed. - * <p/> - * Note that the caller MUST ensure that modifying the underlying XML model is - * safe and must take care of marking the model as dirty if necessary. - * - * @param uiAttr The attribute node to commit. Must be a child of this UiElementNode. - * @param newValue The new value to set. - * @return True if the XML attribute was modified or removed, false if nothing changed. - */ - public boolean commitAttributeToXml(UiAttributeNode uiAttr, String newValue) { - // Get (or create) the underlying XML element node that contains the attributes. - Node element = prepareCommit(); - if (element != null) { - String attrLocalName = uiAttr.getDescriptor().getXmlLocalName(); - String attrNsUri = uiAttr.getDescriptor().getNamespaceUri(); - - NamedNodeMap attrMap = element.getAttributes(); - if (newValue == null || newValue.length() == 0) { - // Remove attribute if it's empty - if (attrMap.getNamedItemNS(attrNsUri, attrLocalName) != null) { - attrMap.removeNamedItemNS(attrNsUri, attrLocalName); - return true; - } - } else { - // Add or replace an attribute - Document doc = element.getOwnerDocument(); - if (doc != null) { - Attr attr = doc.createAttributeNS(attrNsUri, attrLocalName); - attr.setValue(newValue); - attr.setPrefix(lookupNamespacePrefix(element, attrNsUri)); - attrMap.setNamedItemNS(attr); - return true; - } - } - } - return false; - } - - /** - * Returns the namespace prefix matching the requested namespace URI. - * If no such declaration is found, returns the default "android" prefix. - * - * @param node The current node. Must not be null. - * @param nsUri The namespace URI of which the prefix is to be found, - * e.g. AndroidConstants.NS_RESOURCES - * @return The first prefix declared or the default "android" prefix. - */ - private String lookupNamespacePrefix(Node node, String nsUri) { - // Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java - // The following code emulates this simple call: - // String prefix = node.lookupPrefix(AndroidConstants.NS_RESOURCES); - - // if the requested URI is null, it denotes an attribute with no namespace. - if (nsUri == null) { - return null; - } - - // per XML specification, the "xmlns" URI is reserved - if (XmlnsAttributeDescriptor.XMLNS_URI.equals(nsUri)) { - return "xmlns"; //$NON-NLS-1$ - } - - HashSet<String> visited = new HashSet<String>(); - Document doc = node == null ? null : node.getOwnerDocument(); - - for (; node != null && node.getNodeType() == Node.ELEMENT_NODE; - node = node.getParentNode()) { - NamedNodeMap attrs = node.getAttributes(); - for (int n = attrs.getLength() - 1; n >= 0; --n) { - Node attr = attrs.item(n); - if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$ - String uri = attr.getNodeValue(); - String nsPrefix = attr.getLocalName(); - if (AndroidConstants.NS_RESOURCES.equals(uri)) { - return nsPrefix; - } - visited.add(nsPrefix); - } - } - } - - // Use a sensible default prefix if we can't find one. - // We need to make sure the prefix is not one that was declared in the scope - // visited above. - String prefix = AndroidConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$ - String base = prefix; - for (int i = 1; visited.contains(prefix); i++) { - prefix = base + Integer.toString(i); - } - - // Also create & define this prefix/URI in the XML document as an attribute in the - // first element of the document. - if (doc != null) { - node = doc.getFirstChild(); - while (node != null && node.getNodeType() != Node.ELEMENT_NODE) { - node = node.getNextSibling(); - } - if (node != null) { - Attr attr = doc.createAttributeNS(XmlnsAttributeDescriptor.XMLNS_URI, prefix); - attr.setValue(nsUri); - attr.setPrefix("xmlns"); //$NON-NLS-1$ - node.getAttributes().setNamedItemNS(attr); - } - } - - return prefix; - } - - /** - * Utility method to internally set the value of a text attribute for the current - * UiElementNode. - * <p/> - * This method is a helper. It silently ignores the errors such as the requested - * attribute not being present in the element or attribute not being settable. - * It accepts inherited attributes (such as layout). - * <p/> - * This does not commit to the XML model. It does mark the attribute node as dirty. - * This is up to the caller. - * - * @param attrXmlName The XML name of the attribute to modify - * @param value The new value for the attribute. - * @param override True if the value must be set even if one already exists. - */ - public void setAttributeValue(String attrXmlName, String value, boolean override) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) { - AttributeDescriptor ui_desc = entry.getKey(); - if (ui_desc.getXmlLocalName().equals(attrXmlName)) { - UiAttributeNode ui_attr = entry.getValue(); - // Not all attributes are editable, ignore those which are not - if (ui_attr instanceof IUiSettableAttributeNode) { - String current = ui_attr.getCurrentValue(); - if (override || current == null || current.length() == 0) { - ((IUiSettableAttributeNode) ui_attr).setCurrentValue(value); - // mark the attribute as dirty since their internal content - // as been modified, but not the underlying XML model - ui_attr.setDirty(true); - } - } - break; - } - } - } - - /** - * Utility method to retrieve the internal value of an attribute. - * <p/> - * Note that this retrieves the *field* value if the attribute has some UI, and - * not the actual XML value. They may differ if the attribute is dirty. - * - * @param attrXmlName The XML name of the attribute to modify - * @return The current internal value for the attribute or null in case of error. - */ - public String getAttributeValue(String attrXmlName) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) { - AttributeDescriptor ui_desc = entry.getKey(); - if (ui_desc.getXmlLocalName().equals(attrXmlName)) { - UiAttributeNode ui_attr = entry.getValue(); - return ui_attr.getCurrentValue(); - } - } - return null; - } - - // ------ IPropertySource methods - - public Object getEditableValue() { - return null; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors() - * - * Returns the property descriptor for this node. Since the descriptors are not linked to the - * data, the AttributeDescriptor are used directly. - */ - public IPropertyDescriptor[] getPropertyDescriptors() { - List<IPropertyDescriptor> propDescs = new ArrayList<IPropertyDescriptor>(); - - // get the standard descriptors - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - Set<AttributeDescriptor> keys = attributeMap.keySet(); - - - // we only want the descriptor that do implement the IPropertyDescriptor interface. - for (AttributeDescriptor key : keys) { - if (key instanceof IPropertyDescriptor) { - propDescs.add((IPropertyDescriptor)key); - } - } - - // now get the descriptor from the unknown attributes - for (UiAttributeNode unknownNode : mUnknownUiAttributes) { - if (unknownNode.getDescriptor() instanceof IPropertyDescriptor) { - propDescs.add((IPropertyDescriptor)unknownNode.getDescriptor()); - } - } - - // TODO cache this maybe, as it's not going to change (except for unknown descriptors) - return propDescs.toArray(new IPropertyDescriptor[propDescs.size()]); - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object) - * - * Returns the value of a given property. The id is the result of IPropertyDescriptor.getId(), - * which return the AttributeDescriptor itself. - */ - public Object getPropertyValue(Object id) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - UiAttributeNode attribute = attributeMap.get(id); - - if (attribute == null) { - // look for the id in the unknown attributes. - for (UiAttributeNode unknownAttr : mUnknownUiAttributes) { - if (id == unknownAttr.getDescriptor()) { - return unknownAttr; - } - } - } - - return attribute; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object) - * - * Returns whether the property is set. In our case this is if the string is non empty. - */ - public boolean isPropertySet(Object id) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - UiAttributeNode attribute = attributeMap.get(id); - - if (attribute != null) { - return attribute.getCurrentValue().length() > 0; - } - - // look for the id in the unknown attributes. - for (UiAttributeNode unknownAttr : mUnknownUiAttributes) { - if (id == unknownAttr.getDescriptor()) { - return unknownAttr.getCurrentValue().length() > 0; - } - } - - return false; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object) - * - * Reset the property to its default value. For now we simply empty it. - */ - public void resetPropertyValue(Object id) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - UiAttributeNode attribute = attributeMap.get(id); - if (attribute != null) { - // TODO: reset the value of the attribute - - return; - } - - // look for the id in the unknown attributes. - for (UiAttributeNode unknownAttr : mUnknownUiAttributes) { - if (id == unknownAttr.getDescriptor()) { - // TODO: reset the value of the attribute - - return; - } - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object) - * - * Set the property value. id is the result of IPropertyDescriptor.getId(), which is the - * AttributeDescriptor itself. Value should be a String. - */ - public void setPropertyValue(Object id, Object value) { - HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes(); - - UiAttributeNode attribute = attributeMap.get(id); - - if (attribute == null) { - // look for the id in the unknown attributes. - for (UiAttributeNode unknownAttr : mUnknownUiAttributes) { - if (id == unknownAttr.getDescriptor()) { - attribute = unknownAttr; - break; - } - } - } - - if (attribute != null) { - final UiAttributeNode fAttribute = attribute; - - // get the current value and compare it to the new value - String oldValue = fAttribute.getCurrentValue(); - final String newValue = (String)value; - - if (oldValue.equals(newValue)) { - return; - } - - AndroidEditor editor = getEditor(); - editor.editXmlModel(new Runnable() { - public void run() { - commitAttributeToXml(fAttribute, newValue); - } - }); - } - } - - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java deleted file mode 100644 index 4e0a8c7..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.resource.FontDescriptor; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.TableItem; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.dialogs.SelectionStatusDialog; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -/** - * Represents an XML attribute that is defined by a set of flag values, - * i.e. enum names separated by pipe (|) characters. - * - * Note: in Android resources, a "flag" is a list of fixed values where one or - * more values can be selected using an "or", e.g. "align='left|top'". - * By contrast, an "enum" is a list of fixed values of which only one can be - * selected at a given time, e.g. "gravity='right'". - * <p/> - * This class handles the "flag" case. - * The "enum" case is done using {@link UiListAttributeNode}. - */ -public class UiFlagAttributeNode extends UiTextAttributeNode { - - public UiFlagAttributeNode(FlagAttributeDescriptor attributeDescriptor, - UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public void createUiControl(Composite parent, IManagedForm managedForm) { - setManagedForm(managedForm); - FormToolkit toolkit = managedForm.getToolkit(); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - - Label label = toolkit.createLabel(parent, desc.getUiName()); - label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip())); - - Composite composite = toolkit.createComposite(parent); - composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE)); - GridLayout gl = new GridLayout(2, false); - gl.marginHeight = gl.marginWidth = 0; - composite.setLayout(gl); - // Fixes missing text borders under GTK... also requires adding a 1-pixel margin - // for the text field below - toolkit.paintBordersFor(composite); - - final Text text = toolkit.createText(composite, getCurrentValue()); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 1; // Needed by the fixed composite borders under GTK - text.setLayoutData(gd); - final Button selectButton = toolkit.createButton(composite, "Select...", SWT.PUSH); - - setTextWidget(text); - - selectButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - - String currentText = getTextWidgetValue(); - - String result = showDialog(selectButton.getShell(), currentText); - - if (result != null) { - setTextWidgetValue(result); - } - } - }); - } - - /** - * Get the flag names, either from the initial names set in the attribute - * or by querying the framework resource parser. - */ - @Override - public String[] getPossibleValues() { - String attr_name = getDescriptor().getXmlLocalName(); - String element_name = getUiParent().getDescriptor().getXmlName(); - - String[] values = null; - - if (getDescriptor() instanceof FlagAttributeDescriptor && - ((FlagAttributeDescriptor) getDescriptor()).getNames() != null) { - // Get enum values from the descriptor - values = ((FlagAttributeDescriptor) getDescriptor()).getNames(); - } - - if (values == null) { - // or from the framework resource manager - values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name); - } - - return values; - } - - /** - * Shows a dialog letting the user choose a set of enum, and returns a string - * containing the result. - */ - public String showDialog(Shell shell, String currentValue) { - FlagSelectionDialog dlg = new FlagSelectionDialog( - shell, currentValue.trim().split("\\s*\\|\\s*")); //$NON-NLS-1$ - dlg.open(); - Object[] result = dlg.getResult(); - if (result != null) { - StringBuilder buf = new StringBuilder(); - for (Object name : result) { - if (name instanceof String) { - if (buf.length() > 0) { - buf.append("|"); //$NON-NLS-1$ - } - buf.append(name); - } - } - - return buf.toString(); - } - - return null; - - } - - /** - * Displays a list of flag names with checkboxes. - */ - private class FlagSelectionDialog extends SelectionStatusDialog { - - private Set<String> mCurrentSet; - private Table mTable; - - public FlagSelectionDialog(Shell parentShell, String[] currentNames) { - super(parentShell); - - mCurrentSet = new HashSet<String>(); - for (String name : currentNames) { - if (name.length() > 0) { - mCurrentSet.add(name); - } - } - - int shellStyle = getShellStyle(); - setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE); - } - - @Override - protected void computeResult() { - if (mTable != null) { - ArrayList<String> results = new ArrayList<String>(); - - for (TableItem item : mTable.getItems()) { - if (item.getChecked()) { - results.add((String)item.getData()); - } - } - - setResult(results); - } - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite composite= new Composite(parent, SWT.NONE); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - composite.setLayout(new GridLayout(1, true)); - composite.setFont(parent.getFont()); - - Label label = new Label(composite, SWT.NONE); - label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - label.setText(String.format("Select the flag values for attribute %1$s:", - ((FlagAttributeDescriptor) getDescriptor()).getUiName())); - - mTable = new Table(composite, SWT.CHECK | SWT.BORDER); - GridData data = new GridData(); - // The 60,18 hints are the ones used by AbstractElementListSelectionDialog - data.widthHint = convertWidthInCharsToPixels(60); - data.heightHint = convertHeightInCharsToPixels(18); - data.grabExcessVerticalSpace = true; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.FILL; - mTable.setLayoutData(data); - - mTable.setHeaderVisible(false); - final TableColumn column = new TableColumn(mTable, SWT.NONE); - - // List all the expected flag names and check those which are currently used - String[] names = getPossibleValues(); - if (names != null) { - for (String name : names) { - TableItem item = new TableItem(mTable, SWT.NONE); - item.setText(name); - item.setData(name); - - boolean hasName = mCurrentSet.contains(name); - item.setChecked(hasName); - if (hasName) { - mCurrentSet.remove(name); - } - } - } - - // If there are unknown flag names currently used, display them at the end if the - // table already checked. - if (!mCurrentSet.isEmpty()) { - FontDescriptor fontDesc = JFaceResources.getDialogFontDescriptor(); - fontDesc = fontDesc.withStyle(SWT.ITALIC); - Font font = fontDesc.createFont(JFaceResources.getDialogFont().getDevice()); - - for (String name : mCurrentSet) { - TableItem item = new TableItem(mTable, SWT.NONE); - item.setText(String.format("%1$s (unknown flag)", name)); - item.setData(name); - item.setChecked(true); - item.setFont(font); - } - } - - // Add a listener that will resize the column to the full width of the table - // so that only one column appears in the table even if the dialog is resized. - ControlAdapter listener = new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = mTable.getClientArea(); - column.setWidth(r.width); - } - }; - - mTable.addControlListener(listener); - listener.controlResized(null /* event not used */); - - // Add a selection listener that will check/uncheck items when they are double-clicked - mTable.addSelectionListener(new SelectionAdapter() { - /** Default selection means double-click on "most" platforms */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - i.setChecked(!i.getChecked()); - } - super.widgetDefaultSelected(e); - } - }); - - Dialog.applyDialogFont(composite); - setHelpAvailable(false); - - return composite; - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java deleted file mode 100644 index 261e146..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; - -/** - * Represents an XML attribute which has possible built-in values, and can be modified by - * an editable Combo box. - * <p/> - * See {@link UiTextAttributeNode} for more information. - */ -public class UiListAttributeNode extends UiAbstractTextAttributeNode { - - protected Combo mCombo; - - public UiListAttributeNode(ListAttributeDescriptor attributeDescriptor, - UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public final void createUiControl(final Composite parent, IManagedForm managedForm) { - FormToolkit toolkit = managedForm.getToolkit(); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - - Label label = toolkit.createLabel(parent, desc.getUiName()); - label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip())); - - int style = SWT.DROP_DOWN; - mCombo = new Combo(parent, style); - TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE); - twd.maxWidth = 100; - mCombo.setLayoutData(twd); - - fillCombo(); - - setTextWidgetValue(getCurrentValue()); - - mCombo.addModifyListener(new ModifyListener() { - /** - * Sent when the text is modified, whether by the user via manual - * input or programmatic input via setText(). - * <p/> - * Simply mark the attribute as dirty if it really changed. - * The container SectionPart will collect these flag and manage them. - */ - public void modifyText(ModifyEvent e) { - if (!isInInternalTextModification() && - !isDirty() && - mCombo != null && - getCurrentValue() != null && - !mCombo.getText().equals(getCurrentValue())) { - setDirty(true); - } - } - }); - - // Remove self-reference when the widget is disposed - mCombo.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - mCombo = null; - } - }); - } - - protected void fillCombo() { - String[] values = getPossibleValues(); - - if (values == null) { - EditorsPlugin.log(IStatus.ERROR, - "FrameworkResourceManager did not provide values yet for %1$s", - getDescriptor().getXmlLocalName()); - } else { - for (String value : values) { - mCombo.add(value); - } - } - } - - /** - * Get the list values, either from the initial values set in the attribute - * or by querying the framework resource parser. - */ - @Override - public String[] getPossibleValues() { - AttributeDescriptor descriptor = getDescriptor(); - UiElementNode uiParent = getUiParent(); - - String attr_name = descriptor.getXmlLocalName(); - String element_name = uiParent.getDescriptor().getXmlName(); - - // FrameworkResourceManager expects a specific prefix for the attribute. - String prefix = ""; - if (AndroidConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) { - prefix = "android:"; //$NON-NLS-1$ - } else if (XmlnsAttributeDescriptor.XMLNS_URI.equals(descriptor.getNamespaceUri())) { - prefix = "xmlns:"; //$NON-NLS-1$ - } - attr_name = prefix + attr_name; - - String[] values = null; - - if (descriptor instanceof ListAttributeDescriptor && - ((ListAttributeDescriptor) descriptor).getValues() != null) { - // Get enum values from the descriptor - values = ((ListAttributeDescriptor) descriptor).getValues(); - } - - if (values == null) { - // or from the framework resource manager - // get the great-grand-parent descriptor. - - // the parent should always exist. - UiElementNode grandParentNode = uiParent.getUiParent(); - - String greatGrandParentNodeName = null; - if (grandParentNode != null) { - UiElementNode greatGrandParentNode = grandParentNode.getUiParent(); - if (greatGrandParentNode != null) { - greatGrandParentNodeName = greatGrandParentNode.getDescriptor().getXmlName(); - } - } - values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name, - greatGrandParentNodeName); - } - - return values; - } - - @Override - public String getTextWidgetValue() { - if (mCombo != null) { - return mCombo.getText(); - } - - return null; - } - - @Override - public final boolean isValid() { - return mCombo != null; - } - - @Override - public void setTextWidgetValue(String value) { - if (mCombo != null) { - mCombo.setText(value); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java deleted file mode 100644 index 132ccc0..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.common.resources.FrameworkResourceManager; -import com.android.ide.eclipse.common.resources.IResourceRepository; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; -import com.android.ide.eclipse.editors.ui.SectionHelper; -import com.android.ide.eclipse.editors.wizards.ReferenceChooserDialog; -import com.android.ide.eclipse.editors.wizards.ResourceChooser; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; - -/** - * Represents an XML attribute for a resource that can be modified using a simple text field or - * a dialog to choose an existing resource. - * <p/> - * It can be configured to represent any kind of resource, by providing the desired - * {@link ResourceType} in the constructor. - * <p/> - * See {@link UiTextAttributeNode} for more information. - */ -public class UiResourceAttributeNode extends UiTextAttributeNode { - - private ResourceType mType; - - public UiResourceAttributeNode(ResourceType type, - AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - - mType = type; - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public void createUiControl(final Composite parent, IManagedForm managedForm) { - setManagedForm(managedForm); - FormToolkit toolkit = managedForm.getToolkit(); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - - Label label = toolkit.createLabel(parent, desc.getUiName()); - label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE)); - SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip())); - - Composite composite = toolkit.createComposite(parent); - composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE)); - GridLayout gl = new GridLayout(2, false); - gl.marginHeight = gl.marginWidth = 0; - composite.setLayout(gl); - // Fixes missing text borders under GTK... also requires adding a 1-pixel margin - // for the text field below - toolkit.paintBordersFor(composite); - - final Text text = toolkit.createText(composite, getCurrentValue()); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 1; // Needed by the fixed composite borders under GTK - text.setLayoutData(gd); - Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH); - - setTextWidget(text); - - // TODO Add a validator using onAddModifyListener - - browseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - String result = showDialog(parent.getShell(), text.getText().trim()); - if (result != null) { - text.setText(result); - } - } - }); - } - - /** - * Shows a dialog letting the user choose a set of enum, and returns a string - * containing the result. - */ - public String showDialog(Shell shell, String currentValue) { - // we need to get the project of the manifest. - UiElementNode uiNode = getUiParent(); - AndroidEditor editor = uiNode.getEditor(); - IEditorInput input = editor.getEditorInput(); - if (input instanceof IFileEditorInput) { - // from the file editor we can get the IFile object, and from it, the IProject. - IFile file = ((IFileEditorInput)input).getFile(); - IProject project = file.getProject(); - - // get the resource repository for this project and the system resources. - IResourceRepository projectRepository = - ResourceManager.getInstance().getProjectResources(project); - - if (mType != null) { - IResourceRepository systemRepository = - FrameworkResourceManager.getInstance().getSystemResources(); - - // open a resource chooser dialog for specified resource type. - ResourceChooser dlg = new ResourceChooser(mType, - projectRepository, systemRepository, shell); - - dlg.setCurrentResource(currentValue); - - if (dlg.open() == Window.OK) { - return dlg.getCurrentResource(); - } - } else { - ReferenceChooserDialog dlg = new ReferenceChooserDialog(projectRepository, - shell); - - dlg.setCurrentResource(currentValue); - - if (dlg.open() == Window.OK) { - return dlg.getCurrentResource(); - } - } - } - - return null; - } - - @Override - public String[] getPossibleValues() { - // TODO: compute a list of existing resources for content assist completion - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java deleted file mode 100644 index 192f752..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.TableWrapData; -import org.eclipse.ui.forms.widgets.TableWrapLayout; -import org.w3c.dom.Node; - -/** - * {@link UiSeparatorAttributeNode} does not represent any real attribute. - * <p/> - * It is used to separate groups of attributes visually. - */ -public class UiSeparatorAttributeNode extends UiAttributeNode { - - /** Creates a new {@link UiAttributeNode} linked to a specific {@link AttributeDescriptor} */ - public UiSeparatorAttributeNode(SeparatorAttributeDescriptor attrDesc, - UiElementNode uiParent) { - super(attrDesc, uiParent); - } - - /** Returns the current value of the node. */ - @Override - public String getCurrentValue() { - // There is no value here. - return null; - } - - /** - * Sets whether the attribute is dirty and also notifies the editor some part's dirty - * flag as changed. - * <p/> - * Subclasses should set the to true as a result of user interaction with the widgets in - * the section and then should set to false when the commit() method completed. - */ - @Override - public void setDirty(boolean isDirty) { - // This is never dirty. - } - - /** - * Called once by the parent user interface to creates the necessary - * user interface to edit this attribute. - * <p/> - * This method can be called more than once in the life cycle of an UI node, - * typically when the UI is part of a master-detail tree, as pages are swapped. - * - * @param parent The composite where to create the user interface. - * @param managedForm The managed form owning this part. - */ - @Override - public void createUiControl(Composite parent, IManagedForm managedForm) { - FormToolkit toolkit = managedForm.getToolkit(); - Composite row = toolkit.createComposite(parent); - - TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB); - if (parent.getLayout() instanceof TableWrapLayout) { - twd.colspan = ((TableWrapLayout) parent.getLayout()).numColumns; - } - row.setLayoutData(twd); - row.setLayout(new GridLayout(3, false /* equal width */)); - - Label sep = toolkit.createSeparator(row, SWT.HORIZONTAL); - GridData gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); - gd.widthHint = 16; - sep.setLayoutData(gd); - - Label label = toolkit.createLabel(row, getDescriptor().getXmlLocalName()); - label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); - - sep = toolkit.createSeparator(row, SWT.HORIZONTAL); - sep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - } - - /** No completion values for this UI attribute. */ - @Override - public String[] getPossibleValues() { - return null; - } - - /** - * Called when the XML is being loaded or has changed to - * update the value held by this user interface attribute node. - * <p/> - * The XML Node <em>may</em> be null, which denotes that the attribute is not - * specified in the XML model. In general, this means the "default" value of the - * attribute should be used. - * <p/> - * The caller doesn't really know if attributes have changed, - * so it will call this to refresh the attribute anyway. It's up to the - * UI implementation to minimize refreshes. - * - * @param xml_attribute_node - */ - @Override - public void updateValue(Node xml_attribute_node) { - // No value to update. - } - - /** - * Called by the user interface when the editor is saved or its state changed - * and the modified attributes must be committed (i.e. written) to the XML model. - * <p/> - * Important behaviors: - * <ul> - * <li>The caller *must* have called IStructuredModel.aboutToChangeModel before. - * The implemented methods must assume it is safe to modify the XML model. - * <li>On success, the implementation *must* call setDirty(false). - * <li>On failure, the implementation can fail with an exception, which - * is trapped and logged by the caller, or do nothing, whichever is more - * appropriate. - * </ul> - */ - @Override - public void commit() { - // No value to commit. - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java deleted file mode 100644 index 4c53f4c..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.ui.SectionHelper; - -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.TableWrapData; - -/** - * Represents an XML attribute in that can be modified using a simple text field - * in the XML editor's user interface. - * <p/> - * The XML attribute has no default value. When unset, the text field is blank. - * When updating the XML, if the field is empty, the attribute will be removed - * from the XML element. - * <p/> - * See {@link UiAttributeNode} for more information. - */ -public class UiTextAttributeNode extends UiAbstractTextAttributeNode { - - /** Text field */ - private Text mText; - /** The managed form, set only once createUiControl has been called. */ - private IManagedForm mManagedForm; - - public UiTextAttributeNode(AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /* (non-java doc) - * Creates a label widget and an associated text field. - * <p/> - * As most other parts of the android manifest editor, this assumes the - * parent uses a table layout with 2 columns. - */ - @Override - public void createUiControl(Composite parent, IManagedForm managedForm) { - setManagedForm(managedForm); - TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor(); - Text text = SectionHelper.createLabelAndText(parent, managedForm.getToolkit(), - desc.getUiName(), getCurrentValue(), - DescriptorsUtils.formatTooltip(desc.getTooltip())); - - setTextWidget(text); - } - - /** No completion values for this UI attribute. */ - @Override - public String[] getPossibleValues() { - return null; - } - - /** - * Sets the internal managed form. - * This is usually set by createUiControl. - */ - protected void setManagedForm(IManagedForm managedForm) { - mManagedForm = managedForm; - } - - /** - * @return The managed form, set only once createUiControl has been called. - */ - protected IManagedForm getManagedForm() { - return mManagedForm; - } - - /* (non-java doc) - * Returns if the attribute node is valid, and its UI has been created. - */ - @Override - public boolean isValid() { - return mText != null; - } - - @Override - public String getTextWidgetValue() { - if (mText != null) { - return mText.getText(); - } - - return null; - } - - @Override - public void setTextWidgetValue(String value) { - if (mText != null) { - mText.setText(value); - } - } - - /** - * Sets the Text widget object, and prepares it to handle modification and synchronization - * with the XML node. - * @param textWidget - */ - protected final void setTextWidget(Text textWidget) { - mText = textWidget; - - if (textWidget != null) { - // Sets the with hint for the text field. Derived classes can always override it. - // This helps the grid layout to resize correctly on smaller screen sizes. - Object data = textWidget.getLayoutData(); - if (data == null) { - } else if (data instanceof GridData) { - ((GridData)data).widthHint = AndroidEditor.TEXT_WIDTH_HINT; - } else if (data instanceof TableWrapData) { - ((TableWrapData)data).maxWidth = 100; - } - - mText.addModifyListener(new ModifyListener() { - /** - * Sent when the text is modified, whether by the user via manual - * input or programmatic input via setText(). - * <p/> - * Simply mark the attribute as dirty if it really changed. - * The container SectionPart will collect these flag and manage them. - */ - public void modifyText(ModifyEvent e) { - if (!isInInternalTextModification() && - !isDirty() && - mText != null && - getCurrentValue() != null && - !mText.getText().equals(getCurrentValue())) { - setDirty(true); - } - } - }); - - // Remove self-reference when the widget is disposed - mText.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - mText = null; - } - }); - } - - onAddValidators(mText); - } - - /** - * Called after the text widget as been created. - * <p/> - * Derived classes typically want to: - * <li> Create a new {@link ModifyListener} and attach it to the given {@link Text} widget. - * <li> In the modify listener, call getManagedForm().getMessageManager().addMessage() - * and getManagedForm().getMessageManager().removeMessage() as necessary. - * <li> Call removeMessage in a new text.addDisposeListener. - * <li> Call the validator once to setup the initial messages as needed. - * <p/> - * The base implementation does nothing. - * - * @param text The {@link Text} widget to validate. - */ - protected void onAddValidators(Text text) { - } - - /** - * Returns the text widget. - */ - protected final Text getTextWidget() { - return mText; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java deleted file mode 100644 index 5c1db05..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.uimodel; - -import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.Text; - -/** - * Represents an XML element value in that can be modified using a simple text field - * in the XML editor's user interface. - */ -public class UiTextValueNode extends UiTextAttributeNode { - - public UiTextValueNode(TextValueDescriptor attributeDescriptor, UiElementNode uiParent) { - super(attributeDescriptor, uiParent); - } - - /** - * Updates the current text field's value when the XML has changed. - * <p/> - * The caller doesn't really know if value of the element has changed, - * so it will call this to refresh the value anyway. The value - * is only set if it has changed. - * <p/> - * This also resets the "dirty" flag. - */ - @Override - public void updateValue(Node xml_attribute_node) { - setCurrentValue(DEFAULT_VALUE); - - // The argument xml_attribute_node is not used here. It should always be - // null since this is not an attribute. What we want is the "text value" of - // the parent element, which is actually the first text node of the element. - - UiElementNode parent = getUiParent(); - if (parent != null) { - Node xml_node = parent.getXmlNode(); - if (xml_node != null) { - for (Node xml_child = xml_node.getFirstChild(); - xml_child != null; - xml_child = xml_child.getNextSibling()) { - if (xml_child.getNodeType() == Node.TEXT_NODE) { - setCurrentValue(xml_child.getNodeValue()); - break; - } - } - } - } - - if (isValid() && !getTextWidgetValue().equals(getCurrentValue())) { - try { - setInInternalTextModification(true); - setTextWidgetValue(getCurrentValue()); - setDirty(false); - } finally { - setInInternalTextModification(false); - } - } - } - - /* (non-java doc) - * Called by the user interface when the editor is saved or its state changed - * and the modified "attributes" must be committed (i.e. written) to the XML model. - */ - @Override - public void commit() { - UiElementNode parent = getUiParent(); - if (parent != null && isValid() && isDirty()) { - // Get (or create) the underlying XML element node that contains the value. - Node element = parent.prepareCommit(); - if (element != null) { - String value = getTextWidgetValue(); - - // Try to find an existing text child to update. - boolean updated = false; - - for (Node xml_child = element.getFirstChild(); - xml_child != null; - xml_child = xml_child.getNextSibling()) { - if (xml_child.getNodeType() == Node.TEXT_NODE) { - xml_child.setNodeValue(value); - updated = true; - break; - } - } - - // If we didn't find a text child to update, we need to create one. - if (!updated) { - Document doc = element.getOwnerDocument(); - if (doc != null) { - Text text = doc.createTextNode(value); - element.appendChild(text); - } - } - - setCurrentValue(value); - } - } - setDirty(false); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java deleted file mode 100644 index 39cfc58..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java +++ /dev/null @@ -1,1272 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier; -import com.android.ide.eclipse.editors.resources.configurations.LanguageQualifier; -import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier; -import com.android.ide.eclipse.editors.resources.configurations.NetworkCodeQualifier; -import com.android.ide.eclipse.editors.resources.configurations.PixelDensityQualifier; -import com.android.ide.eclipse.editors.resources.configurations.RegionQualifier; -import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; -import com.android.ide.eclipse.editors.resources.configurations.ScreenDimensionQualifier; -import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier; -import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier; -import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier; -import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier.KeyboardState; -import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier.NavigationMethod; -import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier.ScreenOrientation; -import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier.TextInputMethod; -import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier.TouchScreenType; -import com.android.ide.eclipse.editors.resources.manager.ResourceManager; - -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StackLayout; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.FocusAdapter; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; - -import java.util.HashMap; - -/** - * Custom UI widget to let user build a Folder configuration. - * <p/> - * To use this, instantiate somewhere in the UI and then: - * <ul> - * <li>Use {@link #setConfiguration(String)} or {@link #setConfiguration(FolderConfiguration)}. - * <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)} and - * test it using {@link FolderConfiguration#isValid()}. - * </ul> - */ -public class ConfigurationSelector extends Composite { - - public static final int WIDTH_HINT = 600; - public static final int HEIGHT_HINT = 250; - - private Runnable mOnChangeListener; - - private TableViewer mFullTableViewer; - private TableViewer mSelectionTableViewer; - private Button mAddButton; - private Button mRemoveButton; - private StackLayout mStackLayout; - - private boolean mOnRefresh = false; - - private final FolderConfiguration mBaseConfiguration = new FolderConfiguration(); - private final FolderConfiguration mSelectedConfiguration = new FolderConfiguration(); - - private final HashMap<Class<? extends ResourceQualifier>, QualifierEditBase> mUiMap = - new HashMap<Class<? extends ResourceQualifier>, QualifierEditBase>(); - private Composite mQualifierEditParent; - - /** - * Basic of {@link VerifyListener} to only accept digits. - */ - private static class DigitVerifier implements VerifyListener { - public void verifyText(VerifyEvent e) { - // check for digit only. - for (int i = 0 ; i < e.text.length(); i++) { - char letter = e.text.charAt(i); - if (letter < '0' || letter > '9') { - e.doit = false; - return; - } - } - } - } - - /** - * Implementation of {@link VerifyListener} for Country Code qualifiers. - */ - public static class MobileCodeVerifier extends DigitVerifier { - @Override - public void verifyText(VerifyEvent e) { - super.verifyText(e); - - // basic tests passed? - if (e.doit) { - // check the max 3 digits. - if (e.text.length() - e.end + e.start + - ((Text)e.getSource()).getText().length() > 3) { - e.doit = false; - } - } - } - } - - /** - * Implementation of {@link VerifyListener} for the Language and Region qualifiers. - */ - public static class LanguageRegionVerifier implements VerifyListener { - public void verifyText(VerifyEvent e) { - // check for length - if (e.text.length() - e.end + e.start + ((Combo)e.getSource()).getText().length() > 2) { - e.doit = false; - return; - } - - // check for lower case only. - for (int i = 0 ; i < e.text.length(); i++) { - char letter = e.text.charAt(i); - if ((letter < 'a' || letter > 'z') && (letter < 'A' || letter > 'Z')) { - e.doit = false; - return; - } - } - } - } - - /** - * Implementation of {@link VerifyListener} for the Pixel Density qualifier. - */ - public static class DensityVerifier extends DigitVerifier { } - - /** - * Implementation of {@link VerifyListener} for the Screen Dimension qualifier. - */ - public static class DimensionVerifier extends DigitVerifier { } - - /** - * Enum for the state of the configuration being created. - */ - public enum ConfigurationState { - OK, INVALID_CONFIG, REGION_WITHOUT_LANGUAGE; - } - - public ConfigurationSelector(Composite parent) { - super(parent, SWT.NONE); - - mBaseConfiguration.createDefault(); - - GridLayout gl = new GridLayout(4, false); - gl.marginWidth = gl.marginHeight = 0; - setLayout(gl); - - // first column is the first table - final Table fullTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); - fullTable.setLayoutData(new GridData(GridData.FILL_BOTH)); - fullTable.setHeaderVisible(true); - fullTable.setLinesVisible(true); - - // create the column - final TableColumn fullTableColumn = new TableColumn(fullTable, SWT.LEFT); - // set the header - fullTableColumn.setText("Available Qualifiers"); - - fullTable.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = fullTable.getClientArea(); - fullTableColumn.setWidth(r.width); - } - }); - - mFullTableViewer = new TableViewer(fullTable); - mFullTableViewer.setContentProvider(new QualifierContentProvider()); - mFullTableViewer.setLabelProvider(new QualifierLabelProvider( - false /* showQualifierValue */)); - mFullTableViewer.setInput(mBaseConfiguration); - mFullTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - ISelection selection = event.getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection structSelection = (IStructuredSelection)selection; - Object first = structSelection.getFirstElement(); - - if (first instanceof ResourceQualifier) { - mAddButton.setEnabled(true); - return; - } - } - - mAddButton.setEnabled(false); - } - }); - - // 2nd column is the left/right arrow button - Composite buttonComposite = new Composite(this, SWT.NONE); - gl = new GridLayout(1, false); - gl.marginWidth = gl.marginHeight = 0; - buttonComposite.setLayout(gl); - buttonComposite.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - - new Composite(buttonComposite, SWT.NONE); - mAddButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH); - mAddButton.setText("->"); - mAddButton.setEnabled(false); - mAddButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - IStructuredSelection selection = - (IStructuredSelection)mFullTableViewer.getSelection(); - - Object first = selection.getFirstElement(); - if (first instanceof ResourceQualifier) { - ResourceQualifier qualifier = (ResourceQualifier)first; - - mBaseConfiguration.removeQualifier(qualifier); - mSelectedConfiguration.addQualifier(qualifier); - - mFullTableViewer.refresh(); - mSelectionTableViewer.refresh(); - mSelectionTableViewer.setSelection(new StructuredSelection(qualifier), true); - - onChange(false /* keepSelection */); - } - } - }); - - mRemoveButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH); - mRemoveButton.setText("<-"); - mRemoveButton.setEnabled(false); - mRemoveButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - IStructuredSelection selection = - (IStructuredSelection)mSelectionTableViewer.getSelection(); - - Object first = selection.getFirstElement(); - if (first instanceof ResourceQualifier) { - ResourceQualifier qualifier = (ResourceQualifier)first; - - mSelectedConfiguration.removeQualifier(qualifier); - mBaseConfiguration.addQualifier(qualifier); - - mFullTableViewer.refresh(); - mSelectionTableViewer.refresh(); - - onChange(false /* keepSelection */); - } - } - }); - - // 3rd column is the selected config table - final Table selectionTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); - selectionTable.setLayoutData(new GridData(GridData.FILL_BOTH)); - selectionTable.setHeaderVisible(true); - selectionTable.setLinesVisible(true); - - // create the column - final TableColumn selectionTableColumn = new TableColumn(selectionTable, SWT.LEFT); - // set the header - selectionTableColumn.setText("Chosen Qualifiers"); - - selectionTable.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = selectionTable.getClientArea(); - selectionTableColumn.setWidth(r.width); - } - }); - mSelectionTableViewer = new TableViewer(selectionTable); - mSelectionTableViewer.setContentProvider(new QualifierContentProvider()); - mSelectionTableViewer.setLabelProvider(new QualifierLabelProvider( - true /* showQualifierValue */)); - mSelectionTableViewer.setInput(mSelectedConfiguration); - mSelectionTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - // ignore selection changes during resfreshes in some cases. - if (mOnRefresh) { - return; - } - - ISelection selection = event.getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection structSelection = (IStructuredSelection)selection; - - if (structSelection.isEmpty() == false) { - Object first = structSelection.getFirstElement(); - - if (first instanceof ResourceQualifier) { - mRemoveButton.setEnabled(true); - - QualifierEditBase composite = mUiMap.get(first.getClass()); - - if (composite != null) { - composite.setQualifier((ResourceQualifier)first); - } - - mStackLayout.topControl = composite; - mQualifierEditParent.layout(); - - return; - } - } else { - mStackLayout.topControl = null; - mQualifierEditParent.layout(); - } - } - - mRemoveButton.setEnabled(false); - } - }); - - // 4th column is the detail of the selected qualifier - mQualifierEditParent = new Composite(this, SWT.NONE); - mQualifierEditParent.setLayout(mStackLayout = new StackLayout()); - mQualifierEditParent.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - - // create the UI for all the qualifiers, and associate them to the ResourceQualifer class. - mUiMap.put(CountryCodeQualifier.class, new MCCEdit(mQualifierEditParent)); - mUiMap.put(NetworkCodeQualifier.class, new MNCEdit(mQualifierEditParent)); - mUiMap.put(LanguageQualifier.class, new LanguageEdit(mQualifierEditParent)); - mUiMap.put(RegionQualifier.class, new RegionEdit(mQualifierEditParent)); - mUiMap.put(ScreenOrientationQualifier.class, new OrientationEdit(mQualifierEditParent)); - mUiMap.put(PixelDensityQualifier.class, new PixelDensityEdit(mQualifierEditParent)); - mUiMap.put(TouchScreenQualifier.class, new TouchEdit(mQualifierEditParent)); - mUiMap.put(KeyboardStateQualifier.class, new KeyboardEdit(mQualifierEditParent)); - mUiMap.put(TextInputMethodQualifier.class, new TextInputEdit(mQualifierEditParent)); - mUiMap.put(NavigationMethodQualifier.class, new NavigationEdit(mQualifierEditParent)); - mUiMap.put(ScreenDimensionQualifier.class, new ScreenDimensionEdit(mQualifierEditParent)); - } - - /** - * Sets a listener to be notified when the configuration changes. - * @param listener A {@link Runnable} whose <code>run()</code> method is called when the - * configuration is changed. The method is called from the UI thread. - */ - public void setOnChangeListener(Runnable listener) { - mOnChangeListener = listener; - } - - /** - * Initialize the UI with a given {@link FolderConfiguration}. This must - * be called from the UI thread. - * @param config The configuration. - */ - public void setConfiguration(FolderConfiguration config) { - mSelectedConfiguration.set(config); - mSelectionTableViewer.refresh(); - - // create the base config, which is the default config minus the qualifiers - // in SelectedConfiguration - mBaseConfiguration.substract(mSelectedConfiguration); - mFullTableViewer.refresh(); - } - - /** - * Initialize the UI with the configuration represented by a resource folder name. - * This must be called from the UI thread. - * - * @param folderSegments the segments of the folder name, - * split using {@link FolderConfiguration#QUALIFIER_SEP}. - * @return true if success, or false if the folder name is not a valid name. - */ - public boolean setConfiguration(String[] folderSegments) { - FolderConfiguration config = ResourceManager.getInstance().getConfig(folderSegments); - - if (config == null) { - return false; - } - - setConfiguration(config); - - return true; - } - - /** - * Initialize the UI with the configuration represented by a resource folder name. - * This must be called from the UI thread. - * @param folderName the name of the folder. - * @return true if success, or false if the folder name is not a valid name. - */ - public boolean setConfiguration(String folderName) { - // split the name of the folder in segments. - String[] folderSegments = folderName.split(FolderConfiguration.QUALIFIER_SEP); - - return setConfiguration(folderSegments); - } - - /** - * Gets the configuration as setup by the widget. - * @param config the {@link FolderConfiguration} object to be filled with the information - * from the UI. - */ - public void getConfiguration(FolderConfiguration config) { - config.set(mSelectedConfiguration); - } - - /** - * Returns the state of the configuration being edited/created. - */ - public ConfigurationState getState() { - if (mSelectedConfiguration.getInvalidQualifier() != null) { - return ConfigurationState.INVALID_CONFIG; - } - - if (mSelectedConfiguration.checkRegion() == false) { - return ConfigurationState.REGION_WITHOUT_LANGUAGE; - } - - return ConfigurationState.OK; - } - - /** - * Returns the first invalid qualifier of the configuration being edited/created, - * or <code>null<code> if they are all valid (or if none exists). - * <p/>If {@link #getState()} return {@link ConfigurationState#INVALID_CONFIG} then this will - * not return <code>null</code>. - */ - public ResourceQualifier getInvalidQualifier() { - return mSelectedConfiguration.getInvalidQualifier(); - } - - /** - * Handle changes in the configuration. - * @param keepSelection if <code>true</code> attemps to avoid triggering selection change in - * {@link #mSelectedConfiguration}. - */ - private void onChange(boolean keepSelection) { - ISelection selection = null; - if (keepSelection) { - mOnRefresh = true; - selection = mSelectionTableViewer.getSelection(); - } - - mSelectionTableViewer.refresh(true); - - if (keepSelection) { - mSelectionTableViewer.setSelection(selection); - mOnRefresh = false; - } - - if (mOnChangeListener != null) { - mOnChangeListener.run(); - } - } - - /** - * Content provider around a {@link FolderConfiguration}. - */ - private static class QualifierContentProvider implements IStructuredContentProvider { - - private FolderConfiguration mInput; - - public QualifierContentProvider() { - } - - public void dispose() { - // pass - } - - public Object[] getElements(Object inputElement) { - return mInput.getQualifiers(); - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - mInput = null; - if (newInput instanceof FolderConfiguration) { - mInput = (FolderConfiguration)newInput; - } - } - } - - /** - * Label provider for {@link ResourceQualifier} objects. - */ - private static class QualifierLabelProvider implements ITableLabelProvider { - - private final boolean mShowQualifierValue; - - public QualifierLabelProvider(boolean showQualifierValue) { - mShowQualifierValue = showQualifierValue; - } - - public String getColumnText(Object element, int columnIndex) { - // only one column, so we can ignore columnIndex - if (element instanceof ResourceQualifier) { - if (mShowQualifierValue) { - String value = ((ResourceQualifier)element).getStringValue(); - if (value.length() == 0) { - return String.format("%1$s (?)", - ((ResourceQualifier)element).getShortName()); - } else { - return value; - } - - } else { - return ((ResourceQualifier)element).getShortName(); - } - } - - return null; - } - - public Image getColumnImage(Object element, int columnIndex) { - // only one column, so we can ignore columnIndex - if (element instanceof ResourceQualifier) { - return ((ResourceQualifier)element).getIcon(); - } - - return null; - } - - public void addListener(ILabelProviderListener listener) { - // pass - } - - public void dispose() { - // pass - } - - public boolean isLabelProperty(Object element, String property) { - // pass - return false; - } - - public void removeListener(ILabelProviderListener listener) { - // pass - } - } - - /** - * Base class for Edit widget for {@link ResourceQualifier}. - */ - private abstract static class QualifierEditBase extends Composite { - - public QualifierEditBase(Composite parent, String title) { - super(parent, SWT.NONE); - setLayout(new GridLayout(1, false)); - - new Label(this, SWT.NONE).setText(title); - } - - public abstract void setQualifier(ResourceQualifier qualifier); - } - - /** - * Edit widget for {@link CountryCodeQualifier}. - */ - private class MCCEdit extends QualifierEditBase { - - private Text mText; - - public MCCEdit(Composite parent) { - super(parent, CountryCodeQualifier.NAME); - - mText = new Text(this, SWT.BORDER); - mText.addVerifyListener(new MobileCodeVerifier()); - mText.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onTextChange(); - } - }); - - mText.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - onTextChange(); - } - }); - } - - private void onTextChange() { - String value = mText.getText(); - - if (value.length() == 0) { - // empty string, means a qualifier with no value. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); - } else { - try { - CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier( - CountryCodeQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mSelectedConfiguration.setCountryCodeQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong - // (for instance not exactly 3 digits). - mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); - } - } catch (NumberFormatException nfe) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - CountryCodeQualifier q = (CountryCodeQualifier)qualifier; - - mText.setText(Integer.toString(q.getCode())); - } - } - - /** - * Edit widget for {@link NetworkCodeQualifier}. - */ - private class MNCEdit extends QualifierEditBase { - private Text mText; - - public MNCEdit(Composite parent) { - super(parent, NetworkCodeQualifier.NAME); - - mText = new Text(this, SWT.BORDER); - mText.addVerifyListener(new MobileCodeVerifier()); - mText.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onTextChange(); - } - }); - mText.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - onTextChange(); - } - }); - } - - private void onTextChange() { - String value = mText.getText(); - - if (value.length() == 0) { - // empty string, means a qualifier with no value. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); - } else { - try { - NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier( - NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mSelectedConfiguration.setNetworkCodeQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong - // (for instance not exactly 3 digits). - mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); - } - } catch (NumberFormatException nfe) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - NetworkCodeQualifier q = (NetworkCodeQualifier)qualifier; - - mText.setText(Integer.toString(q.getCode())); - } - } - - /** - * Edit widget for {@link LanguageQualifier}. - */ - private class LanguageEdit extends QualifierEditBase { - private Combo mLanguage; - - public LanguageEdit(Composite parent) { - super(parent, LanguageQualifier.NAME); - - mLanguage = new Combo(this, SWT.DROP_DOWN); - mLanguage.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mLanguage.addVerifyListener(new LanguageRegionVerifier()); - mLanguage.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onLanguageChange(); - } - public void widgetSelected(SelectionEvent e) { - onLanguageChange(); - } - }); - mLanguage.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onLanguageChange(); - } - }); - } - - private void onLanguageChange() { - // update the current config - String value = mLanguage.getText(); - - if (value.length() == 0) { - // empty string, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier()); - } else { - LanguageQualifier qualifier = null; - String segment = LanguageQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = LanguageQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mSelectedConfiguration.setLanguageQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier()); - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - LanguageQualifier q = (LanguageQualifier)qualifier; - - String value = q.getValue(); - if (value != null) { - mLanguage.setText(value); - } - } - } - - /** - * Edit widget for {@link RegionQualifier}. - */ - private class RegionEdit extends QualifierEditBase { - private Combo mRegion; - - public RegionEdit(Composite parent) { - super(parent, RegionQualifier.NAME); - - mRegion = new Combo(this, SWT.DROP_DOWN); - mRegion.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mRegion.addVerifyListener(new LanguageRegionVerifier()); - mRegion.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onRegionChange(); - } - public void widgetSelected(SelectionEvent e) { - onRegionChange(); - } - }); - mRegion.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onRegionChange(); - } - }); - } - - private void onRegionChange() { - // update the current config - String value = mRegion.getText(); - - if (value.length() == 0) { - // empty string, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setRegionQualifier(new RegionQualifier()); - } else { - RegionQualifier qualifier = null; - String segment = RegionQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = RegionQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mSelectedConfiguration.setRegionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mSelectedConfiguration.setRegionQualifier(new RegionQualifier()); - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - RegionQualifier q = (RegionQualifier)qualifier; - - String value = q.getValue(); - if (value != null) { - mRegion.setText(q.getValue()); - } - } - } - - /** - * Edit widget for {@link ScreenOrientationQualifier}. - */ - private class OrientationEdit extends QualifierEditBase { - - private Combo mOrientation; - - public OrientationEdit(Composite parent) { - super(parent, ScreenOrientationQualifier.NAME); - - mOrientation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); - ScreenOrientation[] soValues = ScreenOrientation.values(); - for (ScreenOrientation value : soValues) { - mOrientation.add(value.getDisplayValue()); - } - - mOrientation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mOrientation.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onOrientationChange(); - } - public void widgetSelected(SelectionEvent e) { - onOrientationChange(); - } - }); - } - - protected void onOrientationChange() { - // update the current config - int index = mOrientation.getSelectionIndex(); - - if (index != -1) { - mSelectedConfiguration.setScreenOrientationQualifier(new ScreenOrientationQualifier( - ScreenOrientation.getByIndex(index))); - } else { - // empty selection, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setScreenOrientationQualifier( - new ScreenOrientationQualifier()); - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - ScreenOrientationQualifier q = (ScreenOrientationQualifier)qualifier; - - ScreenOrientation value = q.getValue(); - if (value == null) { - mOrientation.clearSelection(); - } else { - mOrientation.select(ScreenOrientation.getIndex(value)); - } - } - } - - /** - * Edit widget for {@link PixelDensityQualifier}. - */ - private class PixelDensityEdit extends QualifierEditBase { - private Text mText; - - public PixelDensityEdit(Composite parent) { - super(parent, PixelDensityQualifier.NAME); - - mText = new Text(this, SWT.BORDER); - mText.addVerifyListener(new DensityVerifier()); - mText.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onTextChange(); - } - }); - mText.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - onTextChange(); - } - }); - } - - private void onTextChange() { - String value = mText.getText(); - - if (value.length() == 0) { - // empty string, means a qualifier with no value. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setPixelDensityQualifier(new PixelDensityQualifier()); - } else { - try { - PixelDensityQualifier qualifier = PixelDensityQualifier.getQualifier( - PixelDensityQualifier.getFolderSegment(Integer.parseInt(value))); - if (qualifier != null) { - mSelectedConfiguration.setPixelDensityQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong - // (for instance a one letter string). - // We do nothing in this case. - return; - } - } catch (NumberFormatException nfe) { - // Looks like the code is not a number. This should not happen since the text - // field has a VerifyListener that prevents it. - // We do nothing in this case. - return; - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - PixelDensityQualifier q = (PixelDensityQualifier)qualifier; - - mText.setText(Integer.toString(q.getValue())); - } - } - - /** - * Edit widget for {@link TouchScreenQualifier}. - */ - private class TouchEdit extends QualifierEditBase { - - private Combo mTouchScreen; - - public TouchEdit(Composite parent) { - super(parent, TouchScreenQualifier.NAME); - - mTouchScreen = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); - TouchScreenType[] tstValues = TouchScreenType.values(); - for (TouchScreenType value : tstValues) { - mTouchScreen.add(value.getDisplayValue()); - } - - mTouchScreen.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTouchScreen.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onTouchChange(); - } - public void widgetSelected(SelectionEvent e) { - onTouchChange(); - } - }); - } - - protected void onTouchChange() { - // update the current config - int index = mTouchScreen.getSelectionIndex(); - - if (index != -1) { - mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier( - TouchScreenType.getByIndex(index))); - } else { - // empty selection, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier()); - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - TouchScreenQualifier q = (TouchScreenQualifier)qualifier; - - TouchScreenType value = q.getValue(); - if (value == null) { - mTouchScreen.clearSelection(); - } else { - mTouchScreen.select(TouchScreenType.getIndex(value)); - } - } - } - - /** - * Edit widget for {@link KeyboardStateQualifier}. - */ - private class KeyboardEdit extends QualifierEditBase { - - private Combo mKeyboard; - - public KeyboardEdit(Composite parent) { - super(parent, KeyboardStateQualifier.NAME); - - mKeyboard = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); - KeyboardState[] ksValues = KeyboardState.values(); - for (KeyboardState value : ksValues) { - mKeyboard.add(value.getDisplayValue()); - } - - mKeyboard.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mKeyboard.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onKeyboardChange(); - } - public void widgetSelected(SelectionEvent e) { - onKeyboardChange(); - } - }); - } - - protected void onKeyboardChange() { - // update the current config - int index = mKeyboard.getSelectionIndex(); - - if (index != -1) { - mSelectedConfiguration.setKeyboardStateQualifier(new KeyboardStateQualifier( - KeyboardState.getByIndex(index))); - } else { - // empty selection, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setKeyboardStateQualifier( - new KeyboardStateQualifier()); - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - KeyboardStateQualifier q = (KeyboardStateQualifier)qualifier; - - KeyboardState value = q.getValue(); - if (value == null) { - mKeyboard.clearSelection(); - } else { - mKeyboard.select(KeyboardState.getIndex(value)); - } - } - } - - /** - * Edit widget for {@link TextInputMethodQualifier}. - */ - private class TextInputEdit extends QualifierEditBase { - - private Combo mTextInput; - - public TextInputEdit(Composite parent) { - super(parent, TextInputMethodQualifier.NAME); - - mTextInput = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); - TextInputMethod[] timValues = TextInputMethod.values(); - for (TextInputMethod value : timValues) { - mTextInput.add(value.getDisplayValue()); - } - - mTextInput.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTextInput.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onTextInputChange(); - } - public void widgetSelected(SelectionEvent e) { - onTextInputChange(); - } - }); - } - - protected void onTextInputChange() { - // update the current config - int index = mTextInput.getSelectionIndex(); - - if (index != -1) { - mSelectedConfiguration.setTextInputMethodQualifier(new TextInputMethodQualifier( - TextInputMethod.getByIndex(index))); - } else { - // empty selection, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setTextInputMethodQualifier( - new TextInputMethodQualifier()); - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - TextInputMethodQualifier q = (TextInputMethodQualifier)qualifier; - - TextInputMethod value = q.getValue(); - if (value == null) { - mTextInput.clearSelection(); - } else { - mTextInput.select(TextInputMethod.getIndex(value)); - } - } - } - - /** - * Edit widget for {@link NavigationMethodQualifier}. - */ - private class NavigationEdit extends QualifierEditBase { - - private Combo mNavigation; - - public NavigationEdit(Composite parent) { - super(parent, NavigationMethodQualifier.NAME); - - mNavigation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); - NavigationMethod[] nmValues = NavigationMethod.values(); - for (NavigationMethod value : nmValues) { - mNavigation.add(value.getDisplayValue()); - } - - mNavigation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mNavigation.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onNavigationChange(); - } - public void widgetSelected(SelectionEvent e) { - onNavigationChange(); - } - }); - } - - protected void onNavigationChange() { - // update the current config - int index = mNavigation.getSelectionIndex(); - - if (index != -1) { - mSelectedConfiguration.setNavigationMethodQualifier(new NavigationMethodQualifier( - NavigationMethod.getByIndex(index))); - } else { - // empty selection, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setNavigationMethodQualifier( - new NavigationMethodQualifier()); - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - NavigationMethodQualifier q = (NavigationMethodQualifier)qualifier; - - NavigationMethod value = q.getValue(); - if (value == null) { - mNavigation.clearSelection(); - } else { - mNavigation.select(NavigationMethod.getIndex(value)); - } - } - } - - /** - * Edit widget for {@link ScreenDimensionQualifier}. - */ - private class ScreenDimensionEdit extends QualifierEditBase { - - private Text mSize1; - private Text mSize2; - - public ScreenDimensionEdit(Composite parent) { - super(parent, ScreenDimensionQualifier.NAME); - - ModifyListener modifyListener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - onSizeChange(); - } - }; - - FocusAdapter focusListener = new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - onSizeChange(); - } - }; - - mSize1 = new Text(this, SWT.BORDER); - mSize1.addVerifyListener(new DimensionVerifier()); - mSize1.addModifyListener(modifyListener); - mSize1.addFocusListener(focusListener); - - mSize2 = new Text(this, SWT.BORDER); - mSize2.addVerifyListener(new DimensionVerifier()); - mSize2.addModifyListener(modifyListener); - mSize2.addFocusListener(focusListener); - } - - private void onSizeChange() { - // update the current config - String size1 = mSize1.getText(); - String size2 = mSize2.getText(); - - // if only one of the strings is empty, do nothing - if ((size1.length() == 0) ^ (size2.length() == 0)) { - return; - } else if (size1.length() == 0 && size2.length() == 0) { - // empty size, means no qualifier. - // Since the qualifier classes are immutable, and we don't want to - // remove the qualifier from the configuration, we create a new default one. - mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier()); - } else { - ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1, - size2); - - if (qualifier != null) { - mSelectedConfiguration.setScreenDimensionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong. - // we do nothing in this case. - return; - } - } - - // notify of change - onChange(true /* keepSelection */); - } - - @Override - public void setQualifier(ResourceQualifier qualifier) { - ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier; - - mSize1.setText(Integer.toString(q.getValue1())); - mSize2.setText(Integer.toString(q.getValue2())); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java deleted file mode 100644 index 2f3209b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.ProjectChooserHelper; -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; -import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; -import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState; -import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; - -/** - * This is the single page of the {@link NewXmlFileWizard} which provides the ability to create - * skeleton XML resources files for Android projects. - * <p/> - * This page is used to select the project, the resource folder, resource type and file name. - */ -class NewXmlFileCreationPage extends WizardPage { - - /** - * Information on one type of resource that can be created (e.g. menu, pref, layout, etc.) - */ - static class TypeInfo { - private final String mUiName; - private final ResourceFolderType mResFolderType; - private final String mTooltip; - private final Object mRootSeed; - private Button mWidget; - private ArrayList<String> mRoots = new ArrayList<String>(); - private final String mXmlns; - private final String mDefaultAttrs; - private final String mDefaultRoot; - - public TypeInfo(String uiName, - String tooltip, - ResourceFolderType resFolderType, - Object rootSeed, - String defaultRoot, - String xmlns, - String defaultAttrs) { - mUiName = uiName; - mResFolderType = resFolderType; - mTooltip = tooltip; - mRootSeed = rootSeed; - mDefaultRoot = defaultRoot; - mXmlns = xmlns; - mDefaultAttrs = defaultAttrs; - } - - /** Returns the UI name for the resource type. Unique. Never null. */ - String getUiName() { - return mUiName; - } - - /** Returns the tooltip for the resource type. Can be null. */ - String getTooltip() { - return mTooltip; - } - - /** - * Returns the name of the {@link ResourceFolderType}. - * Never null but not necessarily unique, - * e.g. two types use {@link ResourceFolderType#XML}. - */ - String getResFolderName() { - return mResFolderType.getName(); - } - - /** - * Returns the matching {@link ResourceFolderType}. - * Never null but not necessarily unique, - * e.g. two types use {@link ResourceFolderType#XML}. - */ - ResourceFolderType getResFolderType() { - return mResFolderType; - } - - /** Sets the radio button associate with the resource type. Can be null. */ - void setWidget(Button widget) { - mWidget = widget; - } - - /** Returns the radio button associate with the resource type. Can be null. */ - Button getWidget() { - return mWidget; - } - - /** - * Returns the seed used to fill the root element values. - * The seed might be either a String, a String array, an {@link ElementDescriptor}, - * a {@link DocumentDescriptor} or null. - */ - Object getRootSeed() { - return mRootSeed; - } - - /** Returns the default root element that should be selected by default. Can be null. */ - String getDefaultRoot() { - return mDefaultRoot; - } - - /** - * Returns the list of all possible root elements for the resource type. - * This can be an empty ArrayList but not null. - * <p/> - * TODO: the root list SHOULD depend on the currently selected project, to include - * custom classes. - */ - ArrayList<String> getRoots() { - return mRoots; - } - - /** - * If the generated resource XML file requires an "android" XMLNS, this should be set - * to {@link AndroidConstants#NS_RESOURCES}. When it is null, no XMLNS is generated. - */ - String getXmlns() { - return mXmlns; - } - - /** - * When not null, this represent extra attributes that must be specified in the - * root element of the generated XML file. When null, no extra attributes are inserted. - */ - String getDefaultAttrs() { - return mDefaultAttrs; - } - } - - /** - * TypeInfo, information for each "type" of file that can be created. - */ - private static final TypeInfo[] sTypes = { - new TypeInfo( - "Layout", // UI name - "An XML file that describes a screen layout.", // tooltip - ResourceFolderType.LAYOUT, // folder type - LayoutDescriptors.getInstance().getDescriptor(), // root seed - "LinearLayout", // default root - AndroidConstants.NS_RESOURCES, // xmlns - "android:layout_width=\"wrap_content\"\n" + // default attributes - "android:layout_height=\"wrap_content\"" - ), - new TypeInfo("Values", // UI name - "An XML file with simple values: colors, strings, dimensions, etc.", // tooltip - ResourceFolderType.VALUES, // folder type - ResourcesDescriptors.ROOT_ELEMENT, // root seed - null, // default root - null, // xmlns - null // default attributes - ), - new TypeInfo("Menu", // UI name - "An XML file that describes an menu.", // tooltip - ResourceFolderType.MENU, // folder type - MenuDescriptors.MENU_ROOT_ELEMENT, // root seed - null, // default root - AndroidConstants.NS_RESOURCES, // xmlns - null // default attributes - ), - new TypeInfo("Preference", // UI name - "An XML file that describes preferences.", // tooltip - ResourceFolderType.XML, // folder type - XmlDescriptors.getInstance().getPreferencesDescriptor(), // root seed - AndroidConstants.CLASS_PREFERENCE_SCREEN, // default root - AndroidConstants.NS_RESOURCES, // xmlns - null // default attributes - ), - new TypeInfo("Searchable", // UI name - "An XML file that describes a searchable [TODO].", // tooltip - ResourceFolderType.XML, // folder type - XmlDescriptors.getInstance().getSearchableDescriptor(), // root seed - null, // default root - AndroidConstants.NS_RESOURCES, // xmlns - null // default attributes - ), - new TypeInfo("Animation", // UI name - "An XML file that describes an animation.", // tooltip - ResourceFolderType.ANIM, // folder type - // TODO reuse constants if we ever make an editor with descriptors for animations - new String[] { // root seed - "set", //$NON-NLS-1$ - "alpha", //$NON-NLS-1$ - "scale", //$NON-NLS-1$ - "translate", //$NON-NLS-1$ - "rotate" //$NON-NLS-1$ - }, - "set", //$NON-NLS-1$ // default root - null, // xmlns - null // default attributes - ), - }; - - /** Absolute destination folder root, e.g. "/res/" */ - private static String sResFolderAbs = AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP; - /** Relative destination folder root, e.g. "res/" */ - private static String sResFolderRel = AndroidConstants.FD_RESOURCES + AndroidConstants.WS_SEP; - - private IProject mProject; - private Text mProjectTextField; - private Button mProjectBrowseButton; - private Text mFileNameTextField; - private Text mWsFolderPathTextField; - private Combo mRootElementCombo; - private IStructuredSelection mInitialSelection; - private ConfigurationSelector mConfigSelector; - private FolderConfiguration mTempConfig = new FolderConfiguration(); - private boolean mInternalWsFolderPathUpdate; - private boolean mInternalTypeUpdate; - private boolean mInternalConfigSelectorUpdate; - private ProjectChooserHelper mProjectChooserHelper; - - - // --- UI creation --- - - /** - * Constructs a new {@link NewXmlFileCreationPage}. - * <p/> - * Called by {@link NewXmlFileWizard#createMainPage()}. - */ - protected NewXmlFileCreationPage(String pageName) { - super(pageName); - setPageComplete(false); - } - - public void setInitialSelection(IStructuredSelection initialSelection) { - mInitialSelection = initialSelection; - } - - /** - * Called by the parent Wizard to create the UI for this Wizard Page. - * - * {@inheritDoc} - * - * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) - */ - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NULL); - composite.setFont(parent.getFont()); - - initializeDialogUnits(parent); - - composite.setLayout(new GridLayout(3, false /*makeColumnsEqualWidth*/)); - composite.setLayoutData(new GridData(GridData.FILL_BOTH)); - - createProjectGroup(composite); - createTypeGroup(composite); - createRootGroup(composite); - - // Show description the first time - setErrorMessage(null); - setMessage(null); - setControl(composite); - - // Update state the first time - initializeRootValues(); - initializeFromSelection(mInitialSelection); - validatePage(); - } - - /** - * Returns the target project or null. - */ - public IProject getProject() { - return mProject; - } - - /** - * Returns the destination filename or an empty string. - */ - public String getFileName() { - return mFileNameTextField == null ? "" : mFileNameTextField.getText(); //$NON-NLS-1$ - } - - /** - * Returns the destination folder path relative to the project or an empty string. - */ - public String getWsFolderPath() { - return mWsFolderPathTextField == null ? "" : mWsFolderPathTextField.getText(); //$NON-NLS-1$ - } - - - /** - * Returns an {@link IFile} on the destination file. - * <p/> - * Uses {@link #getProject()}, {@link #getWsFolderPath()} and {@link #getFileName()}. - * <p/> - * Returns null if the project, filename or folder are invalid and the destination file - * cannot be determined. - * <p/> - * The {@link IFile} is a resource. There might or might not be an actual real file. - */ - public IFile getDestinationFile() { - IProject project = getProject(); - String wsFolderPath = getWsFolderPath(); - String fileName = getFileName(); - if (project != null && wsFolderPath.length() > 0 && fileName.length() > 0) { - IPath dest = new Path(wsFolderPath).append(fileName); - IFile file = project.getFile(dest); - return file; - } - return null; - } - - /** - * Returns the {@link TypeInfo} for the currently selected type radio button. - * Returns null if no radio button is selected. - * - * @return A {@link TypeInfo} or null. - */ - public TypeInfo getSelectedType() { - TypeInfo type = null; - for (TypeInfo ti : sTypes) { - if (ti.getWidget().getSelection()) { - type = ti; - break; - } - } - return type; - } - - /** - * Returns the selected root element string, if any. - * - * @return The selected root element string or null. - */ - public String getRootElement() { - int index = mRootElementCombo.getSelectionIndex(); - if (index >= 0) { - return mRootElementCombo.getItem(index); - } - return null; - } - - // --- UI creation --- - - /** - * Helper method to create a new GridData with an horizontal span. - * - * @param horizSpan The number of cells for the horizontal span. - * @return A new GridData with the horizontal span. - */ - private GridData newGridData(int horizSpan) { - GridData gd = new GridData(); - gd.horizontalSpan = horizSpan; - return gd; - } - - /** - * Helper method to create a new GridData with an horizontal span and a style. - * - * @param horizSpan The number of cells for the horizontal span. - * @param style The style, e.g. {@link GridData#FILL_HORIZONTAL} - * @return A new GridData with the horizontal span and the style. - */ - private GridData newGridData(int horizSpan, int style) { - GridData gd = new GridData(style); - gd.horizontalSpan = horizSpan; - return gd; - } - - /** - * Helper method that creates an empty cell in the parent composite. - * - * @param parent The parent composite. - */ - private void emptyCell(Composite parent) { - new Label(parent, SWT.NONE); - } - - /** - * Creates the project & filename fields. - * <p/> - * The parent must be a GridLayout with 3 colums. - */ - private void createProjectGroup(Composite parent) { - // project name - String tooltip = "The Android Project where the new resource file will be created."; - Label label = new Label(parent, SWT.NONE); - label.setText("Project"); - label.setToolTipText(tooltip); - - mProjectTextField = new Text(parent, SWT.BORDER); - mProjectTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mProjectTextField.setToolTipText(tooltip); - - mProjectBrowseButton = new Button(parent, SWT.NONE); - mProjectBrowseButton.setText("Browse..."); - mProjectBrowseButton.setToolTipText("Allows you to select the Android project to modify."); - mProjectBrowseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onProjectBrowse(); - } - }); - mProjectChooserHelper = new ProjectChooserHelper(parent.getShell()); - - // file name - tooltip = "The name of the resource file to create."; - label = new Label(parent, SWT.NONE); - label.setText("File"); - label.setToolTipText(tooltip); - - mFileNameTextField = new Text(parent, SWT.BORDER); - mFileNameTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mFileNameTextField.setToolTipText(tooltip); - mFileNameTextField.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - validatePage(); - } - }); - - emptyCell(parent); - } - - /** - * Creates the type field, {@link ConfigurationSelector} and the folder field. - * <p/> - * The parent must be a GridLayout with 3 colums. - */ - private void createTypeGroup(Composite parent) { - // separator - Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - label.setLayoutData(newGridData(3, GridData.GRAB_HORIZONTAL)); - - // label before type radios - label = new Label(parent, SWT.NONE); - label.setText("What type of resource would you like to create?"); - label.setLayoutData(newGridData(3)); - - // display the types on three columns of radio buttons. - emptyCell(parent); - Composite grid = new Composite(parent, SWT.NONE); - emptyCell(parent); - - grid.setLayout(new GridLayout(3, true /*makeColumnsEqualWidth*/)); - - SelectionListener radioListener = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // single-click. Only do something if activated. - if (e.getSource() instanceof Button) { - onRadioTypeUpdated((Button) e.getSource()); - } - } - }; - - int n = sTypes.length; - int num_lines = n/3; - for (int line = 0; line < num_lines; line++) { - for (int i = 0; i < 3; i++) { - TypeInfo type = sTypes[line * 3 + i]; - Button radio = new Button(grid, SWT.RADIO); - type.setWidget(radio); - radio.setSelection(false); - radio.setText(type.getUiName()); - radio.setToolTipText(type.getTooltip()); - radio.addSelectionListener(radioListener); - } - } - - // label before configuration selector - label = new Label(parent, SWT.NONE); - label.setText("What type of resource configuration would you like?"); - label.setLayoutData(newGridData(3)); - - // configuration selector - emptyCell(parent); - mConfigSelector = new ConfigurationSelector(parent); - GridData gd = newGridData(2, GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL); - gd.widthHint = ConfigurationSelector.WIDTH_HINT; - gd.heightHint = ConfigurationSelector.HEIGHT_HINT; - mConfigSelector.setLayoutData(gd); - mConfigSelector.setOnChangeListener(new onConfigSelectorUpdated()); - - // folder name - String tooltip = "The folder where the file will be generated, relative to the project."; - label = new Label(parent, SWT.NONE); - label.setText("Folder"); - label.setToolTipText(tooltip); - - mWsFolderPathTextField = new Text(parent, SWT.BORDER); - mWsFolderPathTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mWsFolderPathTextField.setToolTipText(tooltip); - mWsFolderPathTextField.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onWsFolderPathUpdated(); - } - }); - - emptyCell(parent); - } - - /** - * Creates the root element combo. - * <p/> - * The parent must be a GridLayout with 3 colums. - */ - private void createRootGroup(Composite parent) { - // separator - Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - label.setLayoutData(newGridData(3, GridData.GRAB_HORIZONTAL)); - - // label before the root combo - String tooltip = "The root element to create in the XML file."; - label = new Label(parent, SWT.NONE); - label.setText("Select the root element for the XML file:"); - label.setLayoutData(newGridData(3)); - label.setToolTipText(tooltip); - - // root combo - emptyCell(parent); - - mRootElementCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); - mRootElementCombo.setEnabled(false); - mRootElementCombo.select(0); - mRootElementCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mRootElementCombo.setToolTipText(tooltip); - - emptyCell(parent); - } - - /** - * Called by {@link NewXmlFileWizard} to initialize the page with the selection - * received by the wizard -- typically the current user workbench selection. - * <p/> - * Things we expect to find out from the selection: - * <ul> - * <li>The project name, valid if it's an android nature.</li> - * <li>The current folder, valid if it's a folder under /res</li> - * <li>An existing filename, in which case the user will be asked whether to override it.</li> - * <ul> - * - * @param selection The selection when the wizard was initiated. - */ - private void initializeFromSelection(IStructuredSelection selection) { - if (selection == null) { - return; - } - - - // Find the best match in the element list. In case there are multiple selected elements - // select the one that provides the most information and assign them a score, - // e.g. project=1 + folder=2 + file=4. - IProject targetProject = null; - String targetWsFolderPath = null; - String targetFileName = null; - int targetScore = 0; - for (Object element : selection.toList()) { - if (element instanceof IAdaptable) { - IResource res = (IResource) ((IAdaptable) element).getAdapter(IResource.class); - IProject project = res != null ? res.getProject() : null; - - // Is this an Android project? - try { - if (project == null || !project.hasNature(AndroidConstants.NATURE)) { - continue; - } - } catch (CoreException e) { - // checking the nature failed, ignore this resource - continue; - } - - int score = 1; // we have a valid project at least - - IPath wsFolderPath = null; - String fileName = null; - if (res.getType() == IResource.FOLDER) { - wsFolderPath = res.getProjectRelativePath(); - } else if (res.getType() == IResource.FILE) { - fileName = res.getName(); - wsFolderPath = res.getParent().getProjectRelativePath(); - } - - // Disregard this folder selection if it doesn't point to /res/something - if (wsFolderPath != null && - wsFolderPath.segmentCount() > 1 && - AndroidConstants.FD_RESOURCES.equals(wsFolderPath.segment(0))) { - score += 2; - } else { - wsFolderPath = null; - fileName = null; - } - - score += fileName != null ? 4 : 0; - - if (score > targetScore) { - targetScore = score; - targetProject = project; - targetWsFolderPath = wsFolderPath != null ? wsFolderPath.toString() : null; - targetFileName = fileName; - } - } - } - - // Now set the UI accordingly - if (targetScore > 0) { - mProject = targetProject; - mProjectTextField.setText(targetProject != null ? targetProject.getName() : ""); //$NON-NLS-1$ - mFileNameTextField.setText(targetFileName != null ? targetFileName : ""); //$NON-NLS-1$ - mWsFolderPathTextField.setText(targetWsFolderPath != null ? targetWsFolderPath : ""); //$NON-NLS-1$ - } - } - - /** - * Initialize the root values of the type infos based on the current framework values. - */ - private void initializeRootValues() { - for (TypeInfo type : sTypes) { - ArrayList<String> roots = type.getRoots(); - if (roots.size() > 0) { - continue; - } - - // depending of the type of the seed, initialize the root in different ways - Object rootSeed = type.getRootSeed(); - - if (rootSeed instanceof String) { - // The seed is a single string, Add it as-is. - roots.add((String) rootSeed); - } else if (rootSeed instanceof String[]) { - // The seed is an array of strings. Add them as-is. - for (String value : (String[]) rootSeed) { - roots.add(value); - } - } else if (rootSeed instanceof ElementDescriptor) { - // The seed is an element descriptor or a document descriptor. - // In this case add all the children element descriptors defined, recursively, - // and avoid infinite recursion by keeping track of what has already been added. - - HashSet<ElementDescriptor> visited = new HashSet<ElementDescriptor>(); - initRootElementDescriptor(roots, (ElementDescriptor) rootSeed, visited); - - // Sort alphabetically. - Collections.sort(roots); - } - } - } - - /** - * Helper method to recursively insert all XML names for the given {@link ElementDescriptor} - * into the roots array list. Keeps track of visited nodes to avoid infinite recursion. - * Also avoids inserting the top {@link DocumentDescriptor} which is generally synthetic - * and not a valid root element. - */ - private void initRootElementDescriptor(ArrayList<String> roots, - ElementDescriptor desc, HashSet<ElementDescriptor> visited) { - if (!(desc instanceof DocumentDescriptor)) { - String xmlName = desc.getXmlName(); - if (xmlName != null && xmlName.length() > 0) { - roots.add(xmlName); - } - } - - visited.add(desc); - - for (ElementDescriptor child : desc.getChildren()) { - if (!visited.contains(child)) { - initRootElementDescriptor(roots, child, visited); - } - } - } - - /** - * Callback called when the user uses the "Browse Projects" button. - */ - private void onProjectBrowse() { - IJavaProject p = mProjectChooserHelper.chooseJavaProject(mProjectTextField.getText()); - if (p != null) { - mProject = p.getProject(); - mProjectTextField.setText(mProject.getName()); - validatePage(); - } - } - - /** - * Callback called when the Folder text field is changed, either programmatically - * or by the user. - */ - private void onWsFolderPathUpdated() { - if (mInternalWsFolderPathUpdate) { - return; - } - - String wsFolderPath = mWsFolderPathTextField.getText(); - - // This is a custom path, we need to sanitize it. - // First it should start with "/res/". Then we need to make sure there are no - // relative paths, things like "../" or "./" or even "//". - wsFolderPath = wsFolderPath.replaceAll("/+\\.\\./+|/+\\./+|//+|\\\\+|^/+", "/"); //$NON-NLS-1$ //$NON-NLS-2$ - wsFolderPath = wsFolderPath.replaceAll("^\\.\\./+|^\\./+", ""); //$NON-NLS-1$ //$NON-NLS-2$ - wsFolderPath = wsFolderPath.replaceAll("/+\\.\\.$|/+\\.$|/+$", ""); //$NON-NLS-1$ //$NON-NLS-2$ - - ArrayList<TypeInfo> matches = new ArrayList<TypeInfo>(); - - // We get "res/foo" from selections relative to the project when we want a "/res/foo" path. - if (wsFolderPath.startsWith(sResFolderRel)) { - wsFolderPath = sResFolderAbs + wsFolderPath.substring(sResFolderRel.length()); - - mInternalWsFolderPathUpdate = true; - mWsFolderPathTextField.setText(wsFolderPath); - mInternalWsFolderPathUpdate = false; - } - - if (wsFolderPath.startsWith(sResFolderAbs)) { - wsFolderPath = wsFolderPath.substring(sResFolderAbs.length()); - - int pos = wsFolderPath.indexOf(AndroidConstants.WS_SEP_CHAR); - if (pos >= 0) { - wsFolderPath = wsFolderPath.substring(0, pos); - } - - String[] folderSegments = wsFolderPath.split(FolderConfiguration.QUALIFIER_SEP); - - if (folderSegments.length > 0) { - String folderName = folderSegments[0]; - - // update config selector - mInternalConfigSelectorUpdate = true; - mConfigSelector.setConfiguration(folderSegments); - mInternalConfigSelectorUpdate = false; - - boolean selected = false; - for (TypeInfo type : sTypes) { - if (type.getResFolderName().equals(folderName)) { - matches.add(type); - selected |= type.getWidget().getSelection(); - } - } - - if (matches.size() == 1) { - // If there's only one match, select it if it's not already selected - if (!selected) { - selectType(matches.get(0)); - } - } else if (matches.size() > 1) { - // There are multiple type candidates for this folder. This can happen - // for /res/xml for example. Check to see if one of them is currently - // selected. If yes, leave the selection unchanged. If not, deselect all type. - if (!selected) { - selectType(null); - } - } else { - // Nothing valid was selected. - selectType(null); - } - } - } - - validatePage(); - } - - /** - * Callback called when one of the type radio button is changed. - * - * @param typeWidget The type radio button that changed. - */ - private void onRadioTypeUpdated(Button typeWidget) { - // Do nothing if this is an internal modification or if the widget has been - // de-selected. - if (mInternalTypeUpdate || !typeWidget.getSelection()) { - return; - } - - // Find type info that has just been enabled. - TypeInfo type = null; - for (TypeInfo ti : sTypes) { - if (ti.getWidget() == typeWidget) { - type = ti; - break; - } - } - - if (type == null) { - return; - } - - // update the combo - - updateRootCombo(type); - - // update the folder path - - String wsFolderPath = mWsFolderPathTextField.getText(); - String newPath = null; - - mConfigSelector.getConfiguration(mTempConfig); - ResourceQualifier qual = mTempConfig.getInvalidQualifier(); - if (qual == null) { - // The configuration is valid. Reformat the folder path using the canonical - // value from the configuration. - - newPath = sResFolderAbs + mTempConfig.getFolderName(type.getResFolderType()); - } else { - // The configuration is invalid. We still update the path but this time - // do it manually on the string. - if (wsFolderPath.startsWith(sResFolderAbs)) { - wsFolderPath.replaceFirst( - "^(" + sResFolderAbs +")[^-]*(.*)", //$NON-NLS-1$ //$NON-NLS-2$ - "\\1" + type.getResFolderName() + "\\2"); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - newPath = sResFolderAbs + mTempConfig.getFolderName(type.getResFolderType()); - } - } - - if (newPath != null && !newPath.equals(wsFolderPath)) { - mInternalWsFolderPathUpdate = true; - mWsFolderPathTextField.setText(newPath); - mInternalWsFolderPathUpdate = false; - } - - validatePage(); - } - - /** - * Helper method that fills the values of the "root element" combo box based - * on the currently selected type radio button. Also disables the combo is there's - * only one choice. Always select the first root element for the given type. - * - * @param type The currently selected {@link TypeInfo}. Cannot be null. - */ - private void updateRootCombo(TypeInfo type) { - // reset all the values in the combo - mRootElementCombo.removeAll(); - - if (type != null) { - // get the list of roots. The list can be empty but not null. - ArrayList<String> roots = type.getRoots(); - - // enable the combo if there's more than one choice - mRootElementCombo.setEnabled(roots != null && roots.size() > 1); - - for (String root : roots) { - mRootElementCombo.add(root); - } - - int index = 0; // default is to select the first one - String defaultRoot = type.getDefaultRoot(); - if (defaultRoot != null) { - index = roots.indexOf(defaultRoot); - } - mRootElementCombo.select(index < 0 ? 0 : index); - } - } - - /** - * Callback called when the configuration has changed in the {@link ConfigurationSelector}. - */ - private class onConfigSelectorUpdated implements Runnable { - public void run() { - if (mInternalConfigSelectorUpdate) { - return; - } - - TypeInfo type = getSelectedType(); - - if (type != null) { - mConfigSelector.getConfiguration(mTempConfig); - StringBuffer sb = new StringBuffer(sResFolderAbs); - sb.append(mTempConfig.getFolderName(type.getResFolderType())); - - mInternalWsFolderPathUpdate = true; - mWsFolderPathTextField.setText(sb.toString()); - mInternalWsFolderPathUpdate = false; - - validatePage(); - } - } - } - - /** - * Helper method to select on of the type radio buttons. - * - * @param type The TypeInfo matching the radio button to selected or null to deselect them all. - */ - private void selectType(TypeInfo type) { - if (type == null || !type.getWidget().getSelection()) { - mInternalTypeUpdate = true; - for (TypeInfo type2 : sTypes) { - type2.getWidget().setSelection(type2 == type); - } - updateRootCombo(type); - mInternalTypeUpdate = false; - } - } - - /** - * Validates the fields, displays errors and warnings. - * Enables the finish button if there are no errors. - */ - private void validatePage() { - String error = null; - String warning = null; - - // -- validate project - if (getProject() == null) { - error = "Please select an Android project."; - } - - // -- validate filename - if (error == null) { - String fileName = getFileName(); - if (fileName == null || fileName.length() == 0) { - error = "A destination file name is required."; - } else if (fileName != null && !fileName.endsWith(AndroidConstants.DOT_XML)) { - error = String.format("The filename must end with %1$s.", AndroidConstants.DOT_XML); - } - } - - // -- validate type - if (error == null) { - TypeInfo type = getSelectedType(); - - if (type == null) { - error = "One of the types must be selected (e.g. layout, values, etc.)"; - } - } - - // -- validate folder configuration - if (error == null) { - ConfigurationState state = mConfigSelector.getState(); - if (state == ConfigurationState.INVALID_CONFIG) { - ResourceQualifier qual = mConfigSelector.getInvalidQualifier(); - if (qual != null) { - error = String.format("The qualifier '%1$s' is invalid in the folder configuration.", - qual.getName()); - } - } else if (state == ConfigurationState.REGION_WITHOUT_LANGUAGE) { - error = "The Region qualifier requires the Language qualifier."; - } - } - - // -- validate generated path - if (error == null) { - String wsFolderPath = getWsFolderPath(); - if (!wsFolderPath.startsWith(sResFolderAbs)) { - error = String.format("Target folder must start with %1$s.", sResFolderAbs); - } - } - - // -- validate destination file doesn't exist - if (error == null) { - IFile file = getDestinationFile(); - if (file != null && file.exists()) { - warning = "The destination file already exists"; - } - } - - // -- update UI & enable finish if there's no error - setPageComplete(error == null); - if (error != null) { - setMessage(error, WizardPage.ERROR); - } else if (warning != null) { - setMessage(warning, WizardPage.WARNING); - } else { - setErrorMessage(null); - setMessage(null); - } - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java deleted file mode 100644 index 8318e4b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.wizards.NewXmlFileCreationPage.TypeInfo; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.ui.INewWizard; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.ide.IDE; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; - -/** - * The "New Android XML File Wizard" provides the ability to create skeleton XML - * resources files for Android projects. - * <p/> - * The wizard has one page, {@link NewXmlFileCreationPage}, used to select the project, - * the resource folder, resource type and file name. It then creates the XML file. - */ -public class NewXmlFileWizard extends Wizard implements INewWizard { - - private static final String PROJECT_LOGO_LARGE = "android_large"; //$NON-NLS-1$ - - protected static final String MAIN_PAGE_NAME = "newAndroidXmlFilePage"; //$NON-NLS-1$ - - private NewXmlFileCreationPage mMainPage; - - public void init(IWorkbench workbench, IStructuredSelection selection) { - setHelpAvailable(false); // TODO have help - setWindowTitle("New Android XML File"); - setImageDescriptor(); - - mMainPage = createMainPage(); - mMainPage.setTitle("New Android XML File"); - mMainPage.setDescription("Creates a new Android XML file."); - mMainPage.setInitialSelection(selection); - } - - /** - * Creates the wizard page. - * <p/> - * Please do NOT override this method. - * <p/> - * This is protected so that it can be overridden by unit tests. - * However the contract of this class is private and NO ATTEMPT will be made - * to maintain compatibility between different versions of the plugin. - */ - protected NewXmlFileCreationPage createMainPage() { - return new NewXmlFileCreationPage(MAIN_PAGE_NAME); - } - - // -- Methods inherited from org.eclipse.jface.wizard.Wizard -- - // - // The Wizard class implements most defaults and boilerplate code needed by - // IWizard - - /** - * Adds pages to this wizard. - */ - @Override - public void addPages() { - addPage(mMainPage); - } - - /** - * Performs any actions appropriate in response to the user having pressed - * the Finish button, or refuse if finishing now is not permitted: here, it - * actually creates the workspace project and then switch to the Java - * perspective. - * - * @return True - */ - @Override - public boolean performFinish() { - IFile file = createXmlFile(); - if (file == null) { - return false; - } else { - // Open the file in an editor - IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (win != null) { - IWorkbenchPage page = win.getActivePage(); - if (page != null) { - try { - IDE.openEditor(page, file); - } catch (PartInitException e) { - EditorsPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$ - file.getFullPath().toString()); - } - } - } - return true; - } - } - - // -- Custom Methods -- - - private IFile createXmlFile() { - IFile file = mMainPage.getDestinationFile(); - String name = file.getFullPath().toString(); - boolean need_delete = false; - - if (file.exists()) { - if (!EditorsPlugin.displayPrompt("New Android XML File", - String.format("Do you want to overwrite the file %1$s ?", name))) { - // abort if user selects cancel. - return null; - } - need_delete = true; - } else { - createWsParentDirectory(file.getParent()); - } - - TypeInfo type = mMainPage.getSelectedType(); - if (type == null) { - // this is not expected to happen - EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name); //$NON-NLS-1$ - return null; - } - String xmlns = type.getXmlns(); - String root = mMainPage.getRootElement(); - if (root == null) { - // this is not expected to happen - EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$ - file.toString()); - return null; - } - - StringBuilder sb = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); //$NON-NLS-1$ - - sb.append('<').append(root); - if (xmlns != null) { - sb.append('\n').append(" xmlns:android=\"").append(xmlns).append("\""); //$NON-NLS-1$ //$NON-NLS-2$ - } - - String attrs = type.getDefaultAttrs(); - if (attrs != null) { - sb.append("\n "); //$NON-NLS-1$ - sb.append(attrs.replace("\n", "\n ")); //$NON-NLS-1$ //$NON-NLS-2$ - } - - sb.append(">\n"); //$NON-NLS-1$ - sb.append("</").append(root).append(">\n"); //$NON-NLS-1$ //$NON-NLS-2$ - - String result = sb.toString(); - String error = null; - try { - byte[] buf = result.getBytes("UTF8"); - InputStream stream = new ByteArrayInputStream(buf); - if (need_delete) { - file.delete(IFile.KEEP_HISTORY | IFile.FORCE, null /*monitor*/); - } - file.create(stream, true /*force*/, null /*progres*/); - return file; - } catch (UnsupportedEncodingException e) { - error = e.getMessage(); - } catch (CoreException e) { - error = e.getMessage(); - } - - error = String.format("Failed to generate %1$s: %2$s", name, error); - EditorsPlugin.displayError("New Android XML File", error); - return null; - } - - private boolean createWsParentDirectory(IContainer wsPath) { - if (wsPath.getType() == IContainer.FOLDER) { - if (wsPath == null || wsPath.exists()) { - return true; - } - - IFolder folder = (IFolder) wsPath; - try { - if (createWsParentDirectory(wsPath.getParent())) { - folder.create(true /* force */, true /* local */, null /* monitor */); - return true; - } - } catch (CoreException e) { - e.printStackTrace(); - } - } - - return false; - } - - /** - * Returns an image descriptor for the wizard logo. - */ - private void setImageDescriptor() { - ImageDescriptor desc = IconFactory.getInstance().getImageDescriptor(PROJECT_LOGO_LARGE); - setDefaultPageImageDescriptor(desc); - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java deleted file mode 100644 index 446cc14..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.IResourceRepository; -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.DialogSettings; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.ui.dialogs.FilteredTree; -import org.eclipse.ui.dialogs.PatternFilter; -import org.eclipse.ui.dialogs.SelectionStatusDialog; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A dialog to let the user choose a reference to a resource. - * - */ -public class ReferenceChooserDialog extends SelectionStatusDialog { - - private static Pattern sResourcePattern = Pattern.compile("@(.*)/(.+)"); //$NON-NLS-1$ - private static Pattern sInlineIdResourcePattern = Pattern.compile("@\\+id/(.+)"); //$NON-NLS-1$ - - private static IDialogSettings sDialogSettings = new DialogSettings(""); - - private IResourceRepository mResources; - private String mCurrentResource; - - private FilteredTree mFilteredTree; - - /** - * @param parent - */ - public ReferenceChooserDialog(IResourceRepository resources, Shell parent) { - super(parent); - - int shellStyle = getShellStyle(); - setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE); - - setTitle("Reference Dialog"); - setMessage(String.format("Choose a resource")); - mResources = resources; - - setDialogBoundsSettings(sDialogSettings, getDialogBoundsStrategy()); - } - - public void setCurrentResource(String resource) { - mCurrentResource = resource; - } - - public String getCurrentResource() { - return mCurrentResource; - } - - - /* (non-Javadoc) - * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult() - */ - @Override - protected void computeResult() { - // get the selection - TreePath treeSelection = getSelection(); - if (treeSelection != null) { - if (treeSelection.getSegmentCount() == 2) { - // get the resource type and the resource item - ResourceType resourceType = (ResourceType)treeSelection.getFirstSegment(); - ResourceItem resourceItem = (ResourceItem)treeSelection.getLastSegment(); - - mCurrentResource = resourceType.getXmlString(resourceItem, false /* system */); - } - } - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite top = (Composite)super.createDialogArea(parent); - - // create the standard message area - createMessageArea(top); - - // create the filtered tree - createFilteredTree(top); - - // setup the initial selection - setupInitialSelection(); - - return top; - } - - private void createFilteredTree(Composite parent) { - mFilteredTree = new FilteredTree(parent, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION, - new PatternFilter()); - - GridData data = new GridData(); - data.widthHint = convertWidthInCharsToPixels(60); - data.heightHint = convertHeightInCharsToPixels(18); - data.grabExcessVerticalSpace = true; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.FILL; - mFilteredTree.setLayoutData(data); - mFilteredTree.setFont(parent.getFont()); - - TreeViewer treeViewer = mFilteredTree.getViewer(); - Tree tree = treeViewer.getTree(); - - tree.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - handleDoubleClick(); - } - - public void widgetSelected(SelectionEvent e) { - handleSelection(); - } - }); - - treeViewer.setLabelProvider(new ResourceLabelProvider()); - treeViewer.setContentProvider(new ResourceContentProvider(false /* fullLevels */)); - treeViewer.setInput(mResources); - } - - protected void handleSelection() { - validateCurrentSelection(); - } - - protected void handleDoubleClick() { - if (validateCurrentSelection()) { - buttonPressed(IDialogConstants.OK_ID); - } - } - - /** - * Returns the selected item in the tree as a {@link TreePath} object. - * @return the <code>TreePath</code> object or <code>null</code> if there was no selection. - */ - private TreePath getSelection() { - ISelection selection = mFilteredTree.getViewer().getSelection(); - if (selection instanceof TreeSelection) { - TreeSelection treeSelection = (TreeSelection)selection; - TreePath[] treePaths = treeSelection.getPaths(); - - // the selection mode is SWT.SINGLE, so we just get the first one. - if (treePaths.length > 0) { - return treePaths[0]; - } - } - - return null; - } - - private boolean validateCurrentSelection() { - TreePath treeSelection = getSelection(); - - IStatus status; - if (treeSelection != null) { - if (treeSelection.getSegmentCount() == 2) { - status = new Status(IStatus.OK, AndroidConstants.EDITORS_PLUGIN_ID, - IStatus.OK, "", //$NON-NLS-1$ - null); - } else { - status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID, - IStatus.ERROR, "You must select a Resource Item", - null); - } - } else { - status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID, - IStatus.ERROR, "", //$NON-NLS-1$ - null); - } - - updateStatus(status); - - return status.isOK(); - } - - /** - * Sets up the initial selection. - * <p/> - * This parses {@link #mCurrentResource} to find out the resource type and the resource name. - */ - private void setupInitialSelection() { - // checks the inline id pattern first as it's more restrictive than the other one. - Matcher m = sInlineIdResourcePattern.matcher(mCurrentResource); - if (m.matches()) { - // get the matching name - String resourceName = m.group(1); - - // setup initial selection - setupInitialSelection(ResourceType.ID, resourceName); - } else { - // attempts the inline id pattern - m = sResourcePattern.matcher(mCurrentResource); - if (m.matches()) { - // get the resource type. - ResourceType resourceType = ResourceType.getEnum(m.group(1)); - if (resourceType != null) { - // get the matching name - String resourceName = m.group(2); - - // setup initial selection - setupInitialSelection(resourceType, resourceName); - } - } - } - } - - /** - * Sets up the initial selection based on a {@link ResourceType} and a resource name. - * @param resourceType the resource type. - * @param resourceName the resource name. - */ - private void setupInitialSelection(ResourceType resourceType, String resourceName) { - // get all the resources of this type - ResourceItem[] resourceItems = mResources.getResources(resourceType); - - for (ResourceItem resourceItem : resourceItems) { - if (resourceName.equals(resourceItem.getName())) { - // name of the resource match, we select it, - TreePath treePath = new TreePath(new Object[] { resourceType, resourceItem }); - mFilteredTree.getViewer().setSelection(new TreeSelection(treePath)); - - // and we're done. - return; - } - } - - // if we get here, the resource type is valid, but the resource is missing. - // we select and expand the resource type element. - TreePath treePath = new TreePath(new Object[] { resourceType }); - mFilteredTree.getViewer().setSelection(new TreeSelection(treePath)); - mFilteredTree.getViewer().setExpandedState(resourceType, true /* expanded */); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java deleted file mode 100644 index 60a627b..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.common.resources.IResourceRepository; -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A dialog to let the user select a resource based on a resource type. - */ -public class ResourceChooser extends AbstractElementListSelectionDialog { - - private Pattern mProjectResourcePattern; - - private ResourceType mResourceType; - - private IResourceRepository mProjectResources; - - // TODO: enable when we can display the system resources. - // private Pattern mSystemResourcePattern; - // private IResourceRepository mSystemResources; - // private Button mProjectButton; - // private Button mSystemButton; - - private String mCurrentResource; - - /** - * Creates a Resource Chooser dialog. - * @param type The type of the resource to choose - * @param project The repository for the project - * @param system The System resource repository - * @param parent the parent shell - */ - public ResourceChooser(ResourceType type, IResourceRepository project, - IResourceRepository system, Shell parent) { - super(parent, new ResourceLabelProvider()); - - mResourceType = type; - mProjectResources = project; - // TODO: enable when we can display the system resources. - // mSystemResources = system; - - mProjectResourcePattern = Pattern.compile( - "@" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$ - // TODO: enable when we can display the system resources. - // mSystemResourcePattern = Pattern.compile( - // "@android:" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$ - - setTitle("Resource Chooser"); - setMessage(String.format("Choose a %1$s resource", - mResourceType.getDisplayName().toLowerCase())); - } - - public void setCurrentResource(String resource) { - mCurrentResource = resource; - } - - public String getCurrentResource() { - return mCurrentResource; - } - - @Override - protected void computeResult() { - Object[] elements = getSelectedElements(); - if (elements.length == 1 && elements[0] instanceof ResourceItem) { - ResourceItem item = (ResourceItem)elements[0]; - - mCurrentResource = mResourceType.getXmlString(item, - // TODO: enable when we can display the system resources. - false /*mSystemButton.getSelection()*/); - } - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite top = (Composite)super.createDialogArea(parent); - - createMessageArea(top); - - // TODO: enable when we can display the system resources. - // createButtons(top); - - createFilterText(top); - createFilteredList(top); - - setupResourceListAndCurrent(); - - return top; - } - - /** - * Creates the radio button to switch between project and system resources. - * @param top the parent composite - */ - /* TODO: enable when we can display the system resources. - private void createButtons(Composite top) { - mProjectButton = new Button(top, SWT.RADIO); - mProjectButton.setText("Project Resources"); - mProjectButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - setListElements(mProjectResources.getResources(mResourceType)); - } - }); - mSystemButton = new Button(top, SWT.RADIO); - mSystemButton.setText("System Resources"); - mSystemButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - setListElements(mSystemResources.getResources(mResourceType)); - } - }); - } - */ - - /** - * Setups the current list based on the current resource. - */ - private void setupResourceListAndCurrent() { - if (setupInitialSelection(mProjectResourcePattern, mProjectResources) == false) { - // if we couldn't understand the current value, we default to the project resources - ResourceItem[] items = mProjectResources.getResources(mResourceType); - setListElements(items); - } - /* - * TODO: enable when we can display the system resources. - if (setupInitialSelection(mProjectResourcePattern, mProjectResources) == false) { - if (setupInitialSelection(mSystemResourcePattern, mSystemResources) == false) { - // if we couldn't understand the current value, we default to the project resources - IResourceItem[] items = mProjectResources.getResources(mResourceType); - setListElements(items); - mProjectButton.setSelection(true); - } else { - mSystemButton.setSelection(true); - } - } else { - mProjectButton.setSelection(true); - }*/ - } - - /** - * Attempts to setup the list of element from a repository if the current resource - * matches the provided pattern. - * @param pattern the pattern to test the current value - * @param repository the repository to use if the pattern matches. - * @return true if success. - */ - private boolean setupInitialSelection(Pattern pattern, IResourceRepository repository) { - Matcher m = pattern.matcher(mCurrentResource); - if (m.matches()) { - // we have a project resource, let's setup the list - ResourceItem[] items = repository.getResources(mResourceType); - setListElements(items); - - // and let's look for the item we found - String name = m.group(1); - - for (ResourceItem item : items) { - if (name.equals(item.getName())) { - setSelection(new Object[] { item }); - break; - } - } - return true; - } - return false; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java deleted file mode 100644 index 7c6a539..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.common.resources.IResourceRepository; -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.manager.ConfigurableResourceItem; -import com.android.ide.eclipse.editors.resources.manager.ResourceFile; - -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Content provider for the Resource Explorer TreeView. - * Each level of the tree is represented by a different class. - * <ul> - * <li>{@link ResourceType}. This represents the list of existing Resource Type present - * in the resources. This can be matched to the subclasses inside the class <code>R</code> - * </li> - * <ul> - * <li>{@link ResourceItem}. This represents one resource (which can existing in various alternate - * versions). This is similar to the resource Ids defined as <code>R.sometype.id</code>. - * </li> - * <ul> - * <li>{@link ResourceFile}. (optional) This represents a particular version of the - * {@link ResourceItem}. It is displayed as a list of resource qualifier. - * </li> - * </ul> - * </ul> - * </ul> - * - * @see ResourceLabelProvider - */ -public class ResourceContentProvider implements ITreeContentProvider { - - /** - * The current ProjectResources being displayed. - */ - private IResourceRepository mResources; - - private boolean mFullLevels; - - /** - * Constructs a new content providers for resource display. - * @param fullLevels if <code>true</code> the content provider will suppport all 3 levels. If - * <code>false</code>, only two levels are provided. - */ - public ResourceContentProvider(boolean fullLevels) { - mFullLevels = fullLevels; - } - - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof ResourceType) { - return mResources.getResources((ResourceType)parentElement); - } else if (mFullLevels && parentElement instanceof ConfigurableResourceItem) { - return ((ConfigurableResourceItem)parentElement).getSourceFileArray(); - } - return null; - } - - public Object getParent(Object element) { - // pass - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof ResourceType) { - return mResources.hasResources((ResourceType)element); - } else if (mFullLevels && element instanceof ConfigurableResourceItem) { - return ((ConfigurableResourceItem)element).hasAlternates(); - } - return false; - } - - public Object[] getElements(Object inputElement) { - if (inputElement instanceof IResourceRepository) { - if ((IResourceRepository)inputElement == mResources) { - // get the top level resources. - return mResources.getAvailableResourceTypes(); - } - } - - return new Object[0]; - } - - public void dispose() { - // pass - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (newInput instanceof IResourceRepository) { - mResources = (IResourceRepository)newInput; - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java deleted file mode 100644 index 024d084..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2007 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.eclipse.editors.wizards; - -import com.android.ide.eclipse.common.resources.IIdResourceItem; -import com.android.ide.eclipse.common.resources.ResourceItem; -import com.android.ide.eclipse.common.resources.ResourceType; -import com.android.ide.eclipse.editors.resources.manager.ConfigurableResourceItem; -import com.android.ide.eclipse.editors.resources.manager.IdResourceItem; -import com.android.ide.eclipse.editors.resources.manager.ResourceFile; - -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; - -/** - * Label provider for the Resource Explorer TreeView. - * Each level of the tree is represented by a different class. - * <ul> - * <li>{@link ResourceType}. This represents the list of existing Resource Type present - * in the resources. This can be matched to the subclasses inside the class <code>R</code> - * </li> - * <ul> - * <li>{@link ResourceItem}. This represents one resource. The actual type can be - * {@link ConfigurableResourceItem} (which can exist in various alternate versions), - * or {@link IdResourceItem}. - * This is similar to the resource Ids defined as <code>R.sometype.id</code>. - * </li> - * <ul> - * <li>{@link ResourceFile}. This represents a particular version of the {@link ResourceItem}. - * It is displayed as a list of resource qualifier. - * </li> - * </ul> - * </ul> - * </ul> - * - * @see ResourceContentProvider - */ -public class ResourceLabelProvider implements ILabelProvider, ITableLabelProvider { - private Image mWarningImage; - - public ResourceLabelProvider() { - mWarningImage = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( - ISharedImages.IMG_OBJS_WARN_TSK).createImage(); - } - - /** - * @see #getColumnImage(Object, int) - */ - public Image getImage(Object element) { - // pass - return null; - } - - /** - * @see #getColumnText(Object, int) - */ - public String getText(Object element) { - return getColumnText(element, 0); - } - - public void addListener(ILabelProviderListener listener) { - // pass - } - - public void dispose() { - mWarningImage.dispose(); - } - - public boolean isLabelProperty(Object element, String property) { - return false; - } - - public void removeListener(ILabelProviderListener listener) { - // pass - } - - public Image getColumnImage(Object element, int columnIndex) { - if (columnIndex == 1) { - if (element instanceof ConfigurableResourceItem) { - ConfigurableResourceItem item = (ConfigurableResourceItem)element; - if (item.hasDefault() == false) { - return mWarningImage; - } - } - } - return null; - } - - public String getColumnText(Object element, int columnIndex) { - switch (columnIndex) { - case 0: - if (element instanceof ResourceType) { - return ((ResourceType)element).getDisplayName(); - } else if (element instanceof ResourceItem) { - return ((ResourceItem)element).getName(); - } else if (element instanceof ResourceFile) { - return ((ResourceFile)element).getFolder().getConfiguration().toDisplayString(); - } - break; - case 1: - if (element instanceof ConfigurableResourceItem) { - ConfigurableResourceItem item = (ConfigurableResourceItem)element; - int count = item.getAlternateCount(); - if (count > 0) { - if (item.hasDefault()) { - count++; - } - return String.format("%1$d version(s)", count); - } - } else if (element instanceof IIdResourceItem) { - IIdResourceItem idResource = (IIdResourceItem)element; - if (idResource.isDeclaredInline()) { - return "Declared inline"; - } - } - return null; - } - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java deleted file mode 100644 index bb010e3..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.xml; - -import com.android.ide.eclipse.editors.AndroidContentAssist; -import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors; - -/** - * Content Assist Processor for /res/xml XML files - */ -class XmlContentAssist extends AndroidContentAssist { - - /** - * Constructor for LayoutContentAssist - */ - public XmlContentAssist() { - super(XmlDescriptors.getInstance().getDescriptor().getChildren()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java deleted file mode 100644 index 40d655a..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.xml; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.AndroidEditor; -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.FirstElementParser; -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors; - -import org.eclipse.core.resources.IFile; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.FileEditorInput; -import org.w3c.dom.Document; - -/** - * Multi-page form editor for /res/xml XML files. - */ -public class XmlEditor extends AndroidEditor { - - public static final String ID = "com.android.ide.eclipse.editors.xml.XmlEditor"; //$NON-NLS-1$ - - /** Root node of the UI element hierarchy */ - private UiDocumentNode mUiRootNode; - /** Listener to update the root node if the resource framework changes */ - private Runnable mResourceRefreshListener; - - /** - * Creates the form editor for resources XML files. - */ - public XmlEditor() { - super(); - initUiRootNode(); - } - - /** - * Returns the root node of the UI element hierarchy, which here - * is the document node. - */ - @Override - public UiDocumentNode getUiRootNode() { - return mUiRootNode; - } - - // ---- Static ---- - - /** - * Indicates if this is a file that this {@link XmlEditor} can handle. - * <p/> - * The {@link XmlEditor} can handle XML files that have a <searchable> or - * <Preferences> root XML element with the adequate xmlns:android attribute. - * - * @return True if the {@link XmlEditor} can handle that file. - */ - public static boolean canHandleFile(IFile file) { - - FirstElementParser.Result result = FirstElementParser.parse( - file.getLocation().toOSString(), - AndroidConstants.NS_RESOURCES); - - if (result != null) { - String name = result.getElement(); - if (name != null && result.getXmlnsPrefix() != null) { - DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor(); - for (ElementDescriptor elem : desc.getChildren()) { - if (elem.getXmlName().equals(name)) { - // This is an element that this document can handle - return true; - } - } - } - } - - return false; - } - - // ---- Base Class Overrides ---- - - @Override - public void dispose() { - if (mResourceRefreshListener != null) { - EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener = null; - } - super.dispose(); - } - - /** - * Returns whether the "save as" operation is supported by this editor. - * <p/> - * Save-As is a valid operation for the ManifestEditor since it acts on a - * single source file. - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return true; - } - - /** - * Create the various form pages. - */ - @Override - protected void createFormPages() { - try { - addPage(new XmlTreePage(this)); - } catch (PartInitException e) { - EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$ - } - - } - - /* (non-java doc) - * Change the tab/title name to include the project name. - */ - @Override - protected void setInput(IEditorInput input) { - super.setInput(input); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput) input; - IFile file = fileInput.getFile(); - setPartName(String.format("%1$s", file.getName())); - } - } - - /** - * Processes the new XML Model, which XML root node is given. - * - * @param xml_doc The XML document, if available, or null if none exists. - */ - @Override - protected void xmlModelChanged(Document xml_doc) { - mUiRootNode.loadFromXmlNode(xml_doc); - - super.xmlModelChanged(xml_doc); - } - - - // ---- Local Methods ---- - - /** - * Creates the initial UI Root Node, including the known mandatory elements. - */ - private void initUiRootNode() { - // The root UI node is always created, even if there's no corresponding XML node. - if (mUiRootNode == null) { - DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor(); - mUiRootNode = (UiDocumentNode) desc.createUiNode(); - mUiRootNode.setEditor(this); - - // Add a listener to refresh the root node if the resource framework changes - // by forcing it to parse its own XML - mResourceRefreshListener = new Runnable() { - public void run() { - commitPages(false /* onSave */); - - mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode()); - } - }; - EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener); - mResourceRefreshListener.run(); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java deleted file mode 100644 index d25c812..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.xml; - - -import com.android.ide.eclipse.editors.AndroidSourceViewerConfig; - -/** - * Source Viewer Configuration that calls in XmlContentAssist. - */ -public class XmlSourceViewerConfig extends AndroidSourceViewerConfig { - - public XmlSourceViewerConfig() { - super(new XmlContentAssist()); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java deleted file mode 100644 index 5bb0f72..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.xml; - -import com.android.ide.eclipse.editors.EditorsPlugin; -import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Page for the xml form editor. - */ -public final class XmlTreePage extends FormPage { - /** Page id used for switching tabs programmatically */ - public final static String PAGE_ID = "xml_tree_page"; //$NON-NLS-1$ - - /** Container editor */ - XmlEditor mEditor; - - public XmlTreePage(XmlEditor editor) { - super(editor, PAGE_ID, "Structure"); // tab's label, keep it short - mEditor = editor; - } - - /** - * Creates the content in the form hosted in this page. - * - * @param managedForm the form hosted in this page. - */ - @Override - protected void createFormContent(IManagedForm managedForm) { - super.createFormContent(managedForm); - ScrolledForm form = managedForm.getForm(); - form.setText("Android Xml"); - form.setImage(EditorsPlugin.getAndroidLogo()); - - UiElementNode rootNode = mEditor.getUiRootNode(); - UiTreeBlock block = new UiTreeBlock(mEditor, rootNode, - true /* autoCreateRoot */, - null /* no element filters */, - "Xml Elements", - "List of all xml elements in this XML file."); - block.createContent(managedForm); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java deleted file mode 100644 index 14cb9d6..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2008 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.eclipse.editors.xml.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo; -import com.android.ide.eclipse.common.resources.ViewClassInfo; -import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo; -import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; -import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; -import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; -import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor; - -import java.util.ArrayList; -import java.util.Map; - - -/** - * Description of the /res/xml structure. - * Currently supports the <searchable> and <preferences> root nodes. - */ -public class XmlDescriptors { - - /** Singleton instance */ - private static XmlDescriptors sThis; - - /** The root document descriptor for both searchable and preferences. */ - private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ - - /** The root document descriptor for searchable. */ - private DocumentDescriptor mSearchDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ - - /** The root document descriptor for preferences. */ - private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ - - /** Returns a singleton instance of the {@link XmlDescriptors}. */ - public static synchronized XmlDescriptors getInstance() { - if (sThis == null) { - sThis = new XmlDescriptors(); - } - return sThis; - } - - /** @return the root descriptor for both searchable and preferences. */ - public DocumentDescriptor getDescriptor() { - return mDescriptor; - } - - /** @return the root descriptor for searchable. */ - public DocumentDescriptor getSearchableDescriptor() { - return mSearchDescriptor; - } - - /** @return the root descriptor for preferences. */ - public DocumentDescriptor getPreferencesDescriptor() { - return mPrefDescriptor; - } - - /** - * Updates the document descriptor. - * <p/> - * It first computes the new children of the descriptor and then updates them - * all at once. - * - * @param searchableStyleMap The map style=>attributes for <searchable> from the attrs.xml file - * @param prefs The list of non-group preference descriptions - * @param prefGroups The list of preference group descriptions - */ - public synchronized void updateDescriptors( - Map<String, DeclareStyleableInfo> searchableStyleMap, - ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) { - - XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( - "android", //$NON-NLS-1$ - AndroidConstants.NS_RESOURCES); - - ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns); - ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns); - ArrayList<ElementDescriptor> list = new ArrayList<ElementDescriptor>(); - if (searchable != null) { - list.add(searchable); - mSearchDescriptor.setChildren(new ElementDescriptor[]{ searchable }); - } - if (preferences != null) { - list.add(preferences); - mPrefDescriptor.setChildren(new ElementDescriptor[]{ preferences }); - } - - if (list.size() > 0) { - mDescriptor.setChildren(list.toArray(new ElementDescriptor[list.size()])); - } - } - - //------------------------- - // Creation of <searchable> - //------------------------- - - /** - * Returns the new ElementDescriptor for <searchable> - */ - private ElementDescriptor createSearchable( - Map<String, DeclareStyleableInfo> searchableStyleMap, - XmlnsAttributeDescriptor xmlns) { - - ElementDescriptor action_key = createElement(searchableStyleMap, - "SearchableActionKey", //$NON-NLS-1$ styleName - "actionkey", //$NON-NLS-1$ xmlName - "Action Key", // uiName - null, // sdk url - null, // extraAttribute - null, // childrenElements - false /* mandatory */ ); - - ElementDescriptor searchable = createElement(searchableStyleMap, - "Searchable", //$NON-NLS-1$ styleName - "searchable", //$NON-NLS-1$ xmlName - "Searchable", // uiName - null, // sdk url - xmlns, // extraAttribute - new ElementDescriptor[] { action_key }, // childrenElements - false /* mandatory */ ); - return searchable; - } - - /** - * Returns a new ElementDescriptor constructed from the information given here - * and the javadoc & attributes extracted from the style map if any. - */ - private ElementDescriptor createElement( - Map<String, DeclareStyleableInfo> styleMap, String styleName, - String xmlName, String uiName, String sdkUrl, - AttributeDescriptor extraAttribute, - ElementDescriptor[] childrenElements, boolean mandatory) { - - ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl, - null, childrenElements, mandatory); - - return updateElement(element, styleMap, styleName, extraAttribute); - } - - /** - * Updates an ElementDescriptor with the javadoc & attributes extracted from the style - * map if any. - */ - private ElementDescriptor updateElement(ElementDescriptor element, - Map<String, DeclareStyleableInfo> styleMap, - String styleName, - AttributeDescriptor extraAttribute) { - ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>(); - - DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null; - if (style != null) { - DescriptorsUtils.appendAttributes(descs, - null, // elementName - AndroidConstants.NS_RESOURCES, - style.getAttributes(), - null, // requiredAttributes - null); // overrides - element.setTooltip(style.getJavaDoc()); - } - - if (extraAttribute != null) { - descs.add(extraAttribute); - } - - element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()])); - return element; - } - - //-------------------------- - // Creation of <Preferences> - //-------------------------- - - /** - * Returns the new ElementDescriptor for <Preferences> - */ - private ElementDescriptor createPreference(ViewClassInfo[] prefs, - ViewClassInfo[] prefGroups, XmlnsAttributeDescriptor xmlns) { - - ArrayList<ElementDescriptor> newPrefs = new ArrayList<ElementDescriptor>(); - if (prefs != null) { - for (ViewClassInfo info : prefs) { - ElementDescriptor desc = convertPref(info); - newPrefs.add(desc); - } - } - - ElementDescriptor topPreferences = null; - - ArrayList<ElementDescriptor> newGroups = new ArrayList<ElementDescriptor>(); - if (prefGroups != null) { - for (ViewClassInfo info : prefGroups) { - ElementDescriptor desc = convertPref(info); - newGroups.add(desc); - - if (info.getCanonicalClassName() == AndroidConstants.CLASS_PREFERENCES) { - topPreferences = desc; - } - } - } - - ArrayList<ElementDescriptor> everything = new ArrayList<ElementDescriptor>(); - everything.addAll(newGroups); - everything.addAll(newPrefs); - ElementDescriptor[] newArray = everything.toArray(new ElementDescriptor[everything.size()]); - - // Link all groups to everything else here.. recursively - for (ElementDescriptor layoutDesc : newGroups) { - layoutDesc.setChildren(newArray); - } - - // The "top" element to be returned corresponds to the class "Preferences". - // Its descriptor has already been created. However the root one also needs - // the hidden xmlns:android definition.. - if (topPreferences != null) { - AttributeDescriptor[] attrs = topPreferences.getAttributes(); - AttributeDescriptor[] newAttrs = new AttributeDescriptor[attrs.length + 1]; - System.arraycopy(attrs, 0, newAttrs, 0, attrs.length); - newAttrs[attrs.length] = xmlns; - return new ElementDescriptor( - topPreferences.getXmlName(), - topPreferences.getUiName(), - topPreferences.getTooltip(), - topPreferences.getSdkUrl(), - newAttrs, - topPreferences.getChildren(), - false /* mandatory */); - } else { - return null; - } - } - - /** - * Creates an element descriptor from a given {@link ViewClassInfo}. - */ - private ElementDescriptor convertPref(ViewClassInfo info) { - String xml_name = info.getShortClassName(); - String tooltip = info.getJavaDoc(); - - // Process all Preference attributes - ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); - DescriptorsUtils.appendAttributes(attributes, - null, // elementName - AndroidConstants.NS_RESOURCES, - info.getAttributes(), - null, // requiredAttributes - null); // overrides - - for (ViewClassInfo link = info.getSuperClass(); - link != null; - link = link.getSuperClass()) { - AttributeInfo[] attrList = link.getAttributes(); - if (attrList.length > 0) { - attributes.add(new SeparatorAttributeDescriptor( - String.format("Attributes from %1$s", link.getShortClassName()))); - DescriptorsUtils.appendAttributes(attributes, - null, // elementName - AndroidConstants.NS_RESOURCES, - attrList, - null, // requiredAttributes - null); // overrides - } - } - - return new ViewElementDescriptor(xml_name, - xml_name, // ui_name - info.getCanonicalClassName(), - tooltip, - null, // sdk_url - attributes.toArray(new AttributeDescriptor[attributes.size()]), - null, - null, // children - false /* mandatory */); - } -} |