aboutsummaryrefslogtreecommitdiffstats
path: root/rule_api
diff options
context:
space:
mode:
Diffstat (limited to 'rule_api')
-rw-r--r--rule_api/.classpath7
-rw-r--r--rule_api/.gitignore1
-rw-r--r--rule_api/.project17
-rw-r--r--rule_api/.settings/org.eclipse.jdt.core.prefs71
-rw-r--r--rule_api/Android.mk28
-rw-r--r--rule_api/NOTICE190
-rw-r--r--rule_api/README.txt10
-rw-r--r--rule_api/src/com/android/ide/common/api/DrawingStyle.java174
-rwxr-xr-xrule_api/src/com/android/ide/common/api/DropFeedback.java172
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IAttributeInfo.java84
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IClientRulesEngine.java246
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IColor.java28
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IDragElement.java99
-rw-r--r--rule_api/src/com/android/ide/common/api/IFeedbackPainter.java35
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IGraphics.java233
-rw-r--r--rule_api/src/com/android/ide/common/api/IMenuCallback.java44
-rwxr-xr-xrule_api/src/com/android/ide/common/api/INode.java249
-rw-r--r--rule_api/src/com/android/ide/common/api/INodeHandler.java35
-rw-r--r--rule_api/src/com/android/ide/common/api/IValidator.java39
-rw-r--r--rule_api/src/com/android/ide/common/api/IViewMetadata.java102
-rwxr-xr-xrule_api/src/com/android/ide/common/api/IViewRule.java301
-rw-r--r--rule_api/src/com/android/ide/common/api/InsertType.java56
-rw-r--r--rule_api/src/com/android/ide/common/api/MarginType.java51
-rw-r--r--rule_api/src/com/android/ide/common/api/Margins.java58
-rwxr-xr-xrule_api/src/com/android/ide/common/api/Point.java80
-rwxr-xr-xrule_api/src/com/android/ide/common/api/Rect.java210
-rw-r--r--rule_api/src/com/android/ide/common/api/ResizePolicy.java171
-rwxr-xr-xrule_api/src/com/android/ide/common/api/RuleAction.java656
-rw-r--r--rule_api/src/com/android/ide/common/api/Segment.java70
-rw-r--r--rule_api/src/com/android/ide/common/api/SegmentType.java93
30 files changed, 3610 insertions, 0 deletions
diff --git a/rule_api/.classpath b/rule_api/.classpath
new file mode 100644
index 0000000..f9c91e7
--- /dev/null
+++ b/rule_api/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/common"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/rule_api/.gitignore b/rule_api/.gitignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/rule_api/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/rule_api/.project b/rule_api/.project
new file mode 100644
index 0000000..2e2a12e
--- /dev/null
+++ b/rule_api/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>rule_api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/rule_api/.settings/org.eclipse.jdt.core.prefs b/rule_api/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e755df2
--- /dev/null
+++ b/rule_api/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,71 @@
+#Thu Jun 09 12:26:44 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
diff --git a/rule_api/Android.mk b/rule_api/Android.mk
new file mode 100644
index 0000000..6f5d034
--- /dev/null
+++ b/rule_api/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAVA_RESOURCE_DIRS := src
+
+LOCAL_JAVA_LIBRARIES := \
+ common
+
+LOCAL_MODULE := rule_api
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/rule_api/NOTICE b/rule_api/NOTICE
new file mode 100644
index 0000000..becc120
--- /dev/null
+++ b/rule_api/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2011, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) 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. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/rule_api/README.txt b/rule_api/README.txt
new file mode 100644
index 0000000..b094e60
--- /dev/null
+++ b/rule_api/README.txt
@@ -0,0 +1,10 @@
+The Rule API is a library intended for view authors to add designtime
+support for their custom views in Android layout editors.
+
+NOTE: The API is *not* final and will very likely continue to change
+incompatibly until we finish it and incorporate feedback.
+
+The rule API attempts to be IDE agnostic, so it should not have
+specific dependencies on any tools. IDE vendors building layout
+editors should provide IDE-side implementations of the rule interfaces
+such that they can interact with view rules.
diff --git a/rule_api/src/com/android/ide/common/api/DrawingStyle.java b/rule_api/src/com/android/ide/common/api/DrawingStyle.java
new file mode 100644
index 0000000..199608e
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/DrawingStyle.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Drawing styles are used to distinguish the visual appearance of selection,
+ * hovers, anchors, etc. Each style may have different colors, line thickness,
+ * dashing style, transparency, etc.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public enum DrawingStyle {
+ /**
+ * The style used to draw the selected views
+ */
+ SELECTION,
+
+ /**
+ * The style used to draw guidelines - overlay lines which indicate
+ * significant geometric positions.
+ */
+ GUIDELINE,
+
+ /**
+ * The style used to guideline shadows
+ */
+ GUIDELINE_SHADOW,
+
+ /**
+ * The style used to draw guidelines, in particular shared edges and center lines; this
+ * is a dashed edge.
+ */
+ GUIDELINE_DASHED,
+
+ /**
+ * The style used to draw distance annotations
+ */
+ DISTANCE,
+
+ /**
+ * The style used to draw grids
+ */
+ GRID,
+
+ /**
+ * The style used for hovered views (e.g. when the mouse is directly on top
+ * of the view)
+ */
+ HOVER,
+
+ /**
+ * The style used for hovered views (e.g. when the mouse is directly on top
+ * of the view), when the hover happens to be the same object as the selection
+ */
+ HOVER_SELECTION,
+
+ /**
+ * The style used to draw anchors (lines to the other views the given view
+ * is anchored to)
+ */
+ ANCHOR,
+
+ /**
+ * The style used to draw outlines (the structure of views)
+ */
+ OUTLINE,
+
+ /**
+ * The style used to draw the recipient/target View of a drop. This is
+ * typically going to be the bounding-box of the view into which you are
+ * adding a new child.
+ */
+ DROP_RECIPIENT,
+
+ /**
+ * The style used to draw a potential drop area <b>within</b> a
+ * {@link #DROP_RECIPIENT}. For example, if you are dragging into a view
+ * with a LinearLayout, the {@link #DROP_RECIPIENT} will be the view itself,
+ * whereas each possible insert position between two children will be a
+ * {@link #DROP_ZONE}. If the mouse is over a {@link #DROP_ZONE} it should
+ * be drawn using the style {@link #DROP_ZONE_ACTIVE}.
+ */
+ DROP_ZONE,
+
+ /**
+ * The style used to draw a currently active drop zone within a drop
+ * recipient. See the documentation for {@link #DROP_ZONE} for details on
+ * the distinction between {@link #DROP_RECIPIENT}, {@link #DROP_ZONE} and
+ * {@link #DROP_ZONE_ACTIVE}.
+ */
+ DROP_ZONE_ACTIVE,
+
+ /**
+ * The style used to draw a preview of where a dropped view would appear if
+ * it were to be dropped at a given location.
+ */
+ DROP_PREVIEW,
+
+ /**
+ * The style used to preview a resize operation. Similar to {@link #DROP_PREVIEW}
+ * but usually fainter to work better in combination with guidelines which
+ * are often overlaid during resize.
+ */
+ RESIZE_PREVIEW,
+
+ /**
+ * The style used to show a proposed resize bound which is being rejected (for example,
+ * because there is no near edge to attach to in a RelativeLayout).
+ */
+ RESIZE_FAIL,
+
+ /**
+ * The style used to draw help/hint text.
+ */
+ HELP,
+
+ /**
+ * The style used to draw illegal/error/invalid markers
+ */
+ INVALID,
+
+ /**
+ * The style used to highlight dependencies
+ */
+ DEPENDENCY,
+
+ /**
+ * The style used to draw an invalid cycle
+ */
+ CYCLE,
+
+ /**
+ * The style used to highlight the currently dragged views during a layout
+ * move (if they are not hidden)
+ */
+ DRAGGED,
+
+ /**
+ * The style used to draw empty containers of zero bounds (which are padded
+ * a bit to make them visible during a drag or selection).
+ */
+ EMPTY,
+
+ /**
+ * A style used for unspecified purposes; can be used by a client to have
+ * yet another color that is domain specific; using this color constant
+ * rather than your own hardcoded value means that you will be guaranteed to
+ * pick up a color that is themed properly and will look decent with the
+ * rest of the colors
+ */
+ CUSTOM1,
+
+ /**
+ * A second styled used for unspecified purposes; see {@link #CUSTOM1} for
+ * details.
+ */
+ CUSTOM2
+}
diff --git a/rule_api/src/com/android/ide/common/api/DropFeedback.java b/rule_api/src/com/android/ide/common/api/DropFeedback.java
new file mode 100755
index 0000000..4be9c9e
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/DropFeedback.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Structure returned by onDropEnter/Move and passed to over onDropXyz methods.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public class DropFeedback {
+ /**
+ * User data that the rule can use in any way it wants to carry state from one
+ * operation to another.
+ * <p/>
+ * Filled and owned by the view rule.
+ */
+ public Object userData;
+
+ /**
+ * If true the next screen update will invoke the paint callback.
+ * <p/>
+ * Filled by the view rule to request a paint, and reset by the canvas after
+ * the paint occurred.
+ */
+ public boolean requestPaint;
+
+ /**
+ * Set to false by the engine when entering a new view target.
+ * The view rule should set this to true if the current view target is not
+ * a valid drop zone.
+ * <p/>
+ * When set to true, the onDropped() method will not be called if the user releases
+ * the mouse button. Depending on the platform or implementation, the mouse cursor
+ * <em>may</em> reflect that the drop operation is invalid.
+ * <p/>
+ * Rationale: an operation like onDropEnter() is called each time the mouse enters
+ * a new view target and is supposed to return null when the drop cannot happen
+ * <em>at all</em> in that target. However a layout like RelativeLayout decorates
+ * potential targets with "hot spots" that are suitable drop zones, whereas some
+ * other parts of the view are not suitable drop zones. In this case the onDropEnter()
+ * or onDropMove() operation would return a {@link DropFeedback} with
+ * <code>invalidTarget=true</code>.
+ */
+ public boolean invalidTarget;
+
+ /**
+ * Painter invoked by the canvas to paint the feedback.
+ * Filled by the view rule, called by the engine.
+ * <p/>
+ */
+ public IFeedbackPainter painter;
+
+ /**
+ * When set to a non-null valid rectangle, this informs the engine that a drag'n'drop
+ * feedback wants to capture the mouse as long as it stays in the given area.
+ * <p/>
+ * When the mouse is captured, drop events will keep going to the rule that started the
+ * capture and the current INode proxy will not change.
+ * <p/>
+ * Filled by the view rule, read by the engine.
+ */
+ public Rect captureArea;
+
+ /**
+ * Set to true by the drag'n'drop engine when the current drag operation is a copy.
+ * When false the operation is a move and <em>after</em> a successful drop the source
+ * elements will be deleted.
+ * <p/>
+ * Filled by the engine, read by view rule.
+ */
+ public boolean isCopy;
+
+ /**
+ * The bounds of the drag, relative to the starting mouse position. For example, if
+ * you have a rectangular view of size 100x80, and you start dragging at position
+ * (15,20) from the top left corner of this rectangle, then the drag bounds would be
+ * (-15,-20, 100x80).
+ * <p>
+ * NOTE: The coordinate units will be in layout/view coordinates. In other words, they
+ * are unaffected by the canvas zoom.
+ */
+ public Rect dragBounds;
+
+ /**
+ * The baseline of the primary dragged view. -1 means that the view does not have a baseline.
+ */
+ public int dragBaseline = -1;
+
+ /**
+ * Set to true when the drag'n'drop starts and ends in the same canvas of the
+ * same Eclipse instance.
+ * <p/>
+ * Filled by the engine, read by view rule.
+ */
+ public boolean sameCanvas;
+
+ /**
+ * Density scale for pixels. To compute the dip (device independent pixel) in the
+ * view from a layout coordinate, apply this scale.
+ */
+ public double dipScale = 1.0;
+
+ /**
+ * Initializes the drop feedback with the given user data and paint
+ * callback. A paint is requested if the paint callback is non-null.
+ *
+ * @param userData Data stored for later retrieval by the client
+ * @param painter A callback invoked to paint the drop feedback
+ */
+ public DropFeedback(Object userData, IFeedbackPainter painter) {
+ this.userData = userData;
+ this.painter = painter;
+ this.requestPaint = painter != null;
+ this.captureArea = null;
+ }
+
+ /**
+ * A message to be displayed to the user, if any. Should not contain line separators.
+ */
+ public String message;
+
+ /**
+ * An error message to be displayed to the user, if any. Should not contain line
+ * separators.
+ */
+ public String errorMessage;
+
+ /**
+ * A message to be displayed in a tooltip to the user, which should be short, but
+ * can be multiple lines (use embedded newlines)
+ */
+ public String tooltip;
+
+ /**
+ * Horizontal alignment for the tooltip, or null if no preference
+ */
+ public SegmentType tooltipX;
+
+ /**
+ * Vertical alignment for the tooltip, or null if no preference
+ */
+ public SegmentType tooltipY;
+
+ /**
+ * A mask of the currently held keyboard modifier keys - some combination of
+ * {@link #MODIFIER1}, {@link #MODIFIER2}, {@link #MODIFIER3}, or none.
+ */
+ public int modifierMask;
+
+ /** Bitmask value for modifier key 1 (Control on Windows/Linux, Command on Mac, etc) */
+ public static final int MODIFIER1 = 1;
+ /** Bitmask value for modifier key 2 (Shift) */
+ public static final int MODIFIER2 = 2;
+ /** Bitmask value for modifier key 3 (Alt on Windows/Linux, Option on Mac, etc) */
+ public static final int MODIFIER3 = 4;
+}
diff --git a/rule_api/src/com/android/ide/common/api/IAttributeInfo.java b/rule_api/src/com/android/ide/common/api/IAttributeInfo.java
new file mode 100755
index 0000000..2a6ecd8
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IAttributeInfo.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Information about an attribute as gathered from the attrs.xml file where
+ * the attribute was declared. This must include a format (string, reference, float, etc.),
+ * possible flag or enum values, whether it's deprecated and its javadoc.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IAttributeInfo {
+
+ /** An attribute format, e.g. string, reference, float, etc. */
+ public enum Format {
+ STRING,
+ BOOLEAN,
+ INTEGER,
+ FLOAT,
+ REFERENCE,
+ COLOR,
+ DIMENSION,
+ FRACTION,
+ ENUM,
+ FLAG;
+
+ /**
+ * Returns true if and only if this format is in the given array of
+ * formats
+ *
+ * @param formats An array of formats, or null.
+ * @return True if and only if the given array (if any) contains this
+ * format.
+ */
+ public boolean in(Format[] formats) {
+ if (formats == null) {
+ return false;
+ }
+ for (Format f : formats) {
+ if (f == this) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /** Returns the XML Name of the attribute */
+ public String getName();
+
+ /** Returns the formats of the attribute. Cannot be null.
+ * Should have at least one format. */
+ public Format[] getFormats();
+
+ /** Returns the values for enums. null for other types. */
+ public String[] getEnumValues();
+
+ /** Returns the values for flags. null for other types. */
+ public String[] getFlagValues();
+
+ /** Returns a short javadoc, .i.e. the first sentence. */
+ public String getJavaDoc();
+
+ /** Returns the documentation for deprecated attributes. Null if not deprecated. */
+ public String getDeprecatedDoc();
+
+}
diff --git a/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java b/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java
new file mode 100755
index 0000000..0853378
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.ide.common.api;
+
+import com.android.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * A Client Rules Engine is a set of methods that {@link IViewRule}s can use to
+ * access the client public API of the Rules Engine.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IClientRulesEngine {
+
+ /**
+ * Returns the FQCN for which the rule was loaded.
+ *
+ * @return the fully qualified name of the rule
+ */
+ String getFqcn();
+
+ /**
+ * Prints a debug line in the Eclipse console using the ADT formatter.
+ *
+ * @param msg A String format message.
+ * @param params Optional parameters for the message.
+ */
+ void debugPrintf(String msg, Object...params);
+
+ /**
+ * Loads and returns an {@link IViewRule} for the given FQCN.
+ *
+ * @param fqcn A non-null, non-empty FQCN for the rule to load.
+ * @return The rule that best matches the given FQCN according to the
+ * inheritance chain. Rules are cached and requesting the same FQCN twice
+ * is fast and will return the same rule instance.
+ */
+ IViewRule loadRule(String fqcn);
+
+ /**
+ * Returns the metadata associated with the given fully qualified class name.
+ *
+ * @param fqcn a fully qualified class name for an Android view class
+ * @return the metadata associated with the given fully qualified class name.
+ */
+ IViewMetadata getMetadata(String fqcn);
+
+ /**
+ * Displays the given message string in an alert dialog with an "OK" button.
+ *
+ * @param message the message to be shown
+ */
+ void displayAlert(String message);
+
+ /**
+ * Displays a simple input alert dialog with an OK and Cancel buttons.
+ *
+ * @param message The message to display in the alert dialog.
+ * @param value The initial value to display in the input field. Can be null.
+ * @param filter An optional filter to validate the input. Specify null (or
+ * a validator which always returns true) if you do not want
+ * input validation.
+ * @return Null if canceled by the user. Otherwise the possibly-empty input string.
+ * @null Return value is null if dialog was canceled by the user.
+ */
+ @Nullable
+ String displayInput(String message, @Nullable String value, @Nullable IValidator filter);
+
+ /**
+ * Returns the minimum API level that the current Android project is targeting.
+ *
+ * @return the minimum API level to be supported, or -1 if it cannot be determined
+ */
+ int getMinApiLevel();
+
+ /**
+ * Returns a resource name validator for the current project
+ *
+ * @return an {@link IValidator} for validating new resource name in the current
+ * project
+ */
+ IValidator getResourceValidator();
+
+ /**
+ * Displays an input dialog where the user can enter an Android reference value
+ *
+ * @param currentValue the current reference to select
+ * @return the reference selected by the user, or null
+ */
+ String displayReferenceInput(String currentValue);
+
+ /**
+ * Displays an input dialog where the user can enter an Android resource name of the
+ * given resource type ("id", "string", "drawable", and so on.)
+ *
+ * @param currentValue the current reference to select
+ * @param resourceTypeName resource type, such as "id", "string", and so on (never
+ * null)
+ * @return the margins selected by the user in the same order as the input arguments,
+ * or null
+ */
+ String displayResourceInput(String resourceTypeName, String currentValue);
+
+ /**
+ * Displays an input dialog tailored for editing margin properties.
+ *
+ * @param all The current, initial value display for "all" margins (applied to all
+ * sides)
+ * @param left The current, initial value to display for the "left" margin
+ * @param right The current, initial value to display for the "right" margin
+ * @param top The current, initial value to display for the "top" margin
+ * @param bottom The current, initial value to display for the "bottom" margin
+ * @return an array of length 5 containing the user entered values for the all, left,
+ * right, top and bottom margins respectively
+ */
+ String[] displayMarginInput(String all, String left, String right, String top, String bottom);
+
+ /**
+ * Displays an input dialog tailored for inputing the source of an {@code <include>}
+ * layout tag. This is similar to {@link #displayResourceInput} for resource type
+ * "layout", but should also attempt to filter out layout resources that cannot be
+ * included from the current context (because it would result in a cyclic dependency).
+ *
+ * @return the layout resource to include
+ */
+ String displayIncludeSourceInput();
+
+ /**
+ * Displays an input dialog tailored for inputing the source of a {@code <fragment>}
+ * layout tag.
+ *
+ * @return the fully qualified class name of the fragment activity
+ */
+ String displayFragmentSourceInput();
+
+ /**
+ * Select the given nodes
+ *
+ * @param nodes the nodes to be selected, never null
+ */
+ void select(Collection<INode> nodes);
+
+ /**
+ * Triggers a redraw
+ */
+ void redraw();
+
+ /**
+ * Triggers a layout refresh and redraw
+ */
+ void layout();
+
+ /**
+ * Converts a pixel to a dp (device independent pixel) for the current screen density
+ *
+ * @param px the pixel dimension
+ * @return the corresponding dp dimension
+ */
+ public int pxToDp(int px);
+
+ /**
+ * Converts a device independent pixel to a screen pixel for the current screen density
+ *
+ * @param dp the device independent pixel dimension
+ * @return the corresponding pixel dimension
+ */
+ public int dpToPx(int dp);
+
+ /**
+ * Converts an IDE screen pixel distance to the corresponding layout distance. This
+ * can be used to draw annotations on the graphics object that should be unaffected by
+ * the zoom, or handle mouse events within a certain pixel distance regardless of the
+ * screen zoom.
+ *
+ * @param pixels the size in IDE screen pixels
+ * @return the corresponding pixel distance in the layout coordinate system
+ */
+ public int screenToLayout(int pixels);
+
+ /**
+ * Measure the preferred or actual ("wrap_content") size of the given nodes.
+ *
+ * @param parent the parent whose children should be measured
+ * @param filter a filter to change attributes in the process of measuring, for
+ * example forcing the layout_width to wrap_content or the layout_weight to
+ * unset
+ * @return the corresponding bounds of the nodes
+ */
+ Map<INode, Rect> measureChildren(INode parent, AttributeFilter filter);
+
+ /**
+ * The {@link AttributeFilter} allows a client of
+ * {@link IClientRulesEngine#measureChildren} to modify the actual XML values of the
+ * nodes being rendered, for example to force width and height values to wrap_content
+ * when measuring preferred size.
+ */
+ public interface AttributeFilter {
+ /**
+ * Returns the attribute value for the given node and attribute name. This filter
+ * allows a client to adjust the attribute values that a node presents to the
+ * layout library.
+ * <p>
+ * Return "" to unset an attribute. Return null to return the unfiltered value.
+ *
+ * @param node the node for which the attribute value should be returned
+ * @param namespace the attribute namespace
+ * @param localName the attribute local name
+ * @return an override value, or null to return the unfiltered value
+ */
+ String getAttribute(INode node, String namespace, String localName);
+ }
+
+ /**
+ * Given a UI root node and a potential XML node name, returns the first available id
+ * that matches the pattern "prefix%d".
+ * <p/>
+ * TabWidget is a special case and the method will always return "@android:id/tabs".
+ *
+ * @param fqcn The fully qualified class name of the view to generate a unique id for
+ * @return A suitable generated id in the attribute form needed by the XML id tag
+ * (e.g. "@+id/something")
+ */
+ public String getUniqueId(String fqcn);
+
+}
+
diff --git a/rule_api/src/com/android/ide/common/api/IColor.java b/rule_api/src/com/android/ide/common/api/IColor.java
new file mode 100755
index 0000000..f75d30a
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IColor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * A color, to be used with {@link IGraphics} draw operations.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IColor {
+ // pass
+}
diff --git a/rule_api/src/com/android/ide/common/api/IDragElement.java b/rule_api/src/com/android/ide/common/api/IDragElement.java
new file mode 100755
index 0000000..a5e339a
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IDragElement.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Represents an XML element with a name, attributes and inner elements.
+ * <p/>
+ * The semantic of the element name is to be a fully qualified class name of a View to inflate.
+ * The element name is not expected to have a namespace.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IDragElement {
+
+ /**
+ * Returns the element name, which must match a fully qualified class name of
+ * a View to inflate.
+ */
+ public abstract String getFqcn();
+
+ /**
+ * Returns the bounds of the element's node, if it originated from an existing
+ * canvas. The rectangle is invalid and non-null when the element originated
+ * from the object palette.
+ *
+ * The bounds are absolute for the canvas.
+ */
+ public abstract Rect getBounds();
+
+ /**
+ * Returns the fully qualified class name of the parent, if the element originated
+ * from an existing canvas. Returns null if the element has no parent, such as a top
+ * level element or an element originating from the object palette.
+ */
+ public abstract String getParentFqcn();
+
+ /**
+ * Returns the bounds of the element's parent, absolute for the canvas, or invalid if there
+ * is no suitable parent. This is generally invalid when {@link #getParentFqcn()} is null.
+ *
+ * The returned rectangle can be invalid. It is never null.
+ */
+ public abstract Rect getParentBounds();
+
+ /**
+ * Returns a list of attributes. The list can be empty but is never null.
+ */
+ public abstract IDragAttribute[] getAttributes();
+
+ /**
+ * Returns the requested attribute or null if not found.
+ */
+ public abstract IDragAttribute getAttribute(String uri, String localName);
+
+ /**
+ * Returns a list of inner elements. The list can be empty but is never null.
+ */
+ public abstract IDragElement[] getInnerElements();
+
+ /**
+ * An XML attribute in the {@link IDragElement}.
+ * <p/>
+ * The attribute is always represented by a namespace URI, a name and a value.
+ * The name cannot be empty.
+ * The namespace URI can be empty for an attribute without a namespace but is never null.
+ * The value can be empty but cannot be null.
+ */
+ public interface IDragAttribute {
+
+ /**
+ * Returns the namespace URI of the attribute.
+ * Can be empty for an attribute without a namespace but is never null.
+ */
+ public abstract String getUri();
+
+ /** Returns the XML local name of the attribute. Cannot be null nor empty. */
+ public abstract String getName();
+
+ /** Returns the value of the attribute. Cannot be null. Can be empty. */
+ public abstract String getValue();
+ }
+}
+
diff --git a/rule_api/src/com/android/ide/common/api/IFeedbackPainter.java b/rule_api/src/com/android/ide/common/api/IFeedbackPainter.java
new file mode 100644
index 0000000..7478f6b
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IFeedbackPainter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * A feedback painter paints drop feedback during a drag &amp; drop operation.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IFeedbackPainter {
+ /**
+ * Paints feedback for the given target node into the given graphics context.
+ *
+ * @param gc The graphics context to paint into
+ * @param targetNode The node being dragged
+ * @param feedback The feedback data
+ */
+ void paint(IGraphics gc, INode targetNode, DropFeedback feedback);
+}
diff --git a/rule_api/src/com/android/ide/common/api/IGraphics.java b/rule_api/src/com/android/ide/common/api/IGraphics.java
new file mode 100755
index 0000000..0ee2ef2
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IGraphics.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+import java.util.List;
+
+/**
+ * Represents a graphical context that rules can use to draw on the canvas.
+ * <p/>
+ * The wrapper GC is only valid during the context of a paint operation.
+ * This means {@link IViewRule}s should not cache this object and call it at
+ * just about any time, it is only valid during a call that actually receives
+ * the GC wrapper.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IGraphics {
+
+ /**
+ * Draws a line between 2 points, using the current foreground color and
+ * alpha.
+ */
+ void drawLine(int x1, int y1, int x2, int y2);
+
+ /**
+ * Draws a line between 2 points, using the current foreground color and
+ * alpha.
+ */
+ void drawLine(Point p1, Point p2);
+
+ /**
+ * Draws an arrow from (x1, y1) to (x2, y2).
+ *
+ * @param x1 The x coordinate of the beginning of the arrow
+ * @param y1 The y coordinate of the beginning of the arrow
+ * @param x2 The x coordinate of the end (point) of the arrow
+ * @param y2 The y coordinate of the end (point) of the arrow
+ * @param size The size of the arrowhead
+ */
+ void drawArrow(int x1, int y1, int x2, int y2, int size);
+
+ /**
+ * Draws a dot at the given position.
+ *
+ * @param x The x coordinate of the dot
+ * @param y The y coordinate of the dot
+ */
+ void drawPoint(int x, int y);
+
+ /**
+ * Draws a rectangle outline between 2 points, using the current foreground
+ * color and alpha.
+ */
+ void drawRect(int x1, int y1, int x2, int y2);
+
+ /**
+ * Draws a rectangle outline between 2 points, using the current foreground
+ * color and alpha.
+ */
+ void drawRect(Point p1, Point p2);
+
+ /**
+ * Draws a rectangle outline between 2 points, using the current foreground
+ * color and alpha.
+ */
+ void drawRect(Rect r);
+
+ /**
+ * Fills a rectangle outline between 2 points, using the current background
+ * color and alpha.
+ */
+ void fillRect(int x1, int y1, int x2, int y2);
+
+ /**
+ * Fills a rectangle outline between 2 points, using the current background
+ * color and alpha.
+ */
+ void fillRect(Point p1, Point p2);
+
+ /**
+ * Fills a rectangle outline between 2 points, using the current background
+ * color and alpha.
+ */
+ void fillRect(Rect r);
+
+ /**
+ * Draws the given string, using the current foreground color. No tab
+ * expansion or carriage return processing will be performed.
+ *
+ * @param string the string to be drawn.
+ * @param x the x coordinate of the top left corner of the text.
+ * @param y the y coordinate of the top left corner of the text.
+ */
+ void drawString(String string, int x, int y);
+
+ /**
+ * Draws the given string, using the current foreground color. No tab
+ * expansion or carriage return processing will be performed.
+ *
+ * @param string the string to be drawn.
+ * @param topLeft the top left corner of the text.
+ */
+ void drawString(String string, Point topLeft);
+
+ /**
+ * Draw the given strings, using the current stroke color and alpha for the
+ * text, and the current fill color and alpha for a rectangle behind the
+ * bounding box fitting all the lines of text. Each subsequent string is
+ * drawn on consecutive lines below the previous string.
+ *
+ * @param x The left edge to start each string at
+ * @param y The top position of the first string; subsequent strings are
+ * painted on lines below
+ * @param strings An array of labels to be displayed (should not be null).
+ * The actual String used is the {@link Object#toString()} value
+ * of each list item.
+ */
+ void drawBoxedStrings(int x, int y, List<?> strings);
+
+ /**
+ * Set up the graphics context to use the given style for subsequent drawing
+ * operations.
+ *
+ * @param style The drawing style to be used. May not be null.
+ */
+ void useStyle(DrawingStyle style);
+
+ /**
+ * Registers a color using 0x00rrggbb where each component is 0..0xFF.
+ * <p/>
+ * Transparency is handled separately using {@link #setAlpha(int)}.
+ * <p/>
+ * If the same color is registered twice, the same object will be returned.
+ * <p/>
+ * NOTE: It's preferable to use {@link #useStyle(DrawingStyle)} if possible
+ * to ensure that your colors work properly across multiple current and
+ * future themes.
+ */
+ IColor registerColor(int rgb);
+
+ /**
+ * Returns the height, in pixels, of the default font.
+ */
+ int getFontHeight();
+
+ /**
+ * Returns the current foreground color.
+ * The foreground color is used for drawing operations including when text is drawn.
+ */
+ IColor getForeground();
+
+ /**
+ * Sets the foreground color. The foreground color is used for drawing
+ * operations including when text is drawn.
+ */
+ void setForeground(IColor color);
+
+ /**
+ * Returns the current background color. The background color is used for
+ * fill operations.
+ */
+ IColor getBackground();
+
+ /**
+ * Sets the background color. The background color is used for fill
+ * operations.
+ */
+ void setBackground(IColor color);
+
+ /**
+ * Returns the current alpha value (varies between 0 for transparent and 255
+ * for opaque).
+ *
+ * @return The current alpha value in use
+ */
+ int getAlpha();
+
+ /**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * <p>
+ * TODO: Consider removing this method; it will usually be ignored because
+ * most graphics operations apply the alpha from the current drawing style
+ */
+ void setAlpha(int alpha);
+
+ /**
+ * A line style for {@link IGraphics#setLineStyle(LineStyle)}.
+ */
+ enum LineStyle {
+ /** Style for solid lines. */
+ LINE_SOLID,
+ /** Style for dashed lines. */
+ LINE_DASH,
+ /** Style for dotted lines. */
+ LINE_DOT,
+ /** Style for alternating dash-dot lines. */
+ LINE_DASHDOT,
+ /** Style for dash-dot-dot lines. */
+ LINE_DASHDOTDOT
+ }
+
+ /**
+ * Sets the current line style.
+ */
+ void setLineStyle(LineStyle style);
+
+ /**
+ * Sets the width that will be used when drawing lines.
+ * The operation is ignored if <var>width</var> is less than 1.
+ */
+ void setLineWidth(int width);
+}
diff --git a/rule_api/src/com/android/ide/common/api/IMenuCallback.java b/rule_api/src/com/android/ide/common/api/IMenuCallback.java
new file mode 100644
index 0000000..80f77b8
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IMenuCallback.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+import java.util.List;
+
+/**
+ * Callback interface for a {@link RuleAction}. The callback performs the actual
+ * work of the action, and this level of indirection allows multiple actions (which
+ * typically do not have their own class, only their own instances) to share a single
+ * implementation callback class.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IMenuCallback {
+ /**
+ * Performs the actual work promised by the {@link RuleAction}.
+ * @param action The action being applied.
+ * @param selectedNodes The nodes to apply the action to
+ * @param valueId For a Choices action, the string id of the selected choice
+ * @param newValue For a toggle or for a flag, true if the item is being
+ * checked, false if being unchecked. For enums this is not
+ * useful; however for flags it allows one to add or remove items
+ * to the flag's choices.
+ */
+ void action(RuleAction action, List<? extends INode> selectedNodes, String valueId,
+ Boolean newValue);
+}
diff --git a/rule_api/src/com/android/ide/common/api/INode.java b/rule_api/src/com/android/ide/common/api/INode.java
new file mode 100755
index 0000000..e3f34a9
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/INode.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.ide.common.api;
+
+import com.android.ide.common.api.IDragElement.IDragAttribute;
+
+
+/**
+ * Represents a view in the XML layout being edited.
+ * Each view or layout maps to exactly one XML node, thus the name.
+ * <p/>
+ * The primordial characteristic of a node is the fully qualified View class name that
+ * it represents (a.k.a FQCN), for example "android.view.View" or "android.widget.Button".
+ * <p/>
+ * There are 2 kind of nodes:
+ * - Nodes matching a view actually rendered in the layout canvas have a valid "bounds"
+ * rectangle that describe their position in pixels in the canvas. <br/>
+ * - Nodes created by IViewRule scripts but not yet rendered have an invalid bounds rectangle
+ * since they only exist in the uncommitted XML model and not yet in the rendered View model.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface INode {
+
+ /**
+ * Returns the FQCN of the view class represented by this node.
+ */
+ String getFqcn();
+
+ /**
+ * Returns the bounds of this node.
+ * <p/>
+ * The bounds are valid when this node maps a view that is already rendered.
+ * Typically, if the node is the target of a drag'n'drop operation then you can be
+ * guaranteed that its bounds are known and thus are valid.
+ * <p/>
+ * However the bounds are invalid (e.g. not known yet) for new XML elements
+ * that have just been created, e.g. by the {@link #appendChild(String)} method.
+ *
+ * @return A non-null rectangle, in canvas coordinates.
+ */
+ Rect getBounds();
+
+ /**
+ * Returns the margins for this node.
+ *
+ * @return the margins for this node, never null
+ */
+ Margins getMargins();
+
+ /**
+ * Returns the baseline of this node, or -1 if it has no baseline.
+ * The baseline is the distance from the top down to the baseline.
+ *
+ * @return the baseline, or -1 if not applicable
+ */
+ int getBaseline();
+
+ // ---- Hierarchy handling ----
+
+ /**
+ * Returns the root element of the view hierarchy.
+ * <p/>
+ * When a node is not attached to a hierarchy, it is its own root node.
+ * This may return null if the {@link INode} was not created using a correct UiNode,
+ * which is unlikely.
+ */
+ INode getRoot();
+
+ /**
+ * Returns the parent node of this node, corresponding to the parent view in the layout.
+ * The returned parent can be null when the node is the root element, or when the node is
+ * not yet or no longer attached to the hierarchy.
+ */
+ INode getParent();
+
+ /**
+ * Returns the list of valid children nodes. The list can be empty but not null.
+ */
+ INode[] getChildren();
+
+
+ // ---- XML Editing ---
+
+ /**
+ * Absolutely <em>all</em> calls that are going to edit the XML must be wrapped
+ * by an editXml() call. This call creates both an undo context wrapper and an
+ * edit-XML wrapper.
+ *
+ * @param undoName The UI name that will be given to the undo action.
+ * @param callback The code to execute.
+ */
+ void editXml(String undoName, final INodeHandler callback);
+
+ // TODO define an exception that methods below will throw if editXml() is not wrapping
+ // these calls.
+
+ /**
+ * Creates a new XML element as a child of this node's XML element.
+ * <p/>
+ * For this to work, the editor must have a descriptor for the given FQCN.
+ * <p/>
+ * This call must be done in the context of editXml().
+ *
+ * @param viewFqcn The FQCN of the element to create. The actual XML local name will
+ * depend on whether this is an Android view or a custom project view.
+ * @return The node for the newly created element. Can be null if we failed to create it.
+ */
+ INode appendChild(String viewFqcn);
+
+ /**
+ * Creates a new XML element as a child of this node's XML element and inserts
+ * it at the specified position in the children list.
+ * <p/>
+ * For this to work, the editor must have a descriptor for the given FQCN.
+ * <p/>
+ * This call must be done in the context of editXml().
+ *
+ * @param viewFqcn The FQCN of the element to create. The actual XML local name will
+ * depend on whether this is an Android view or a custom project view.
+ * @param index Index of the child to insert before. If the index is out of bounds
+ * (less than zero or larger that current last child), appends at the end.
+ * @return The node for the newly created element. Can be null if we failed to create it.
+ */
+ INode insertChildAt(String viewFqcn, int index);
+
+ /**
+ * Removes the given XML element child from this node's list of children.
+ * <p/>
+ * This call must be done in the context of editXml().
+ *
+ * @param node The child to be deleted.
+ */
+ void removeChild(INode node);
+
+ /**
+ * Sets an attribute for the underlying XML element.
+ * Attributes are not written immediately -- instead the XML editor batches edits and
+ * then commits them all together at once later.
+ * <p/>
+ * Custom attributes will be created on the fly.
+ * <p/>
+ * Passing an empty value actually <em>removes</em> an attribute from the XML.
+ * <p/>
+ * This call must be done in the context of editXml().
+ *
+ * @param uri The XML namespace URI of the attribute.
+ * @param localName The XML <em>local</em> name of the attribute to set.
+ * @param value It's value. Cannot be null. An empty value <em>removes</em> the attribute.
+ * @return Whether the attribute was actually set or not.
+ */
+ boolean setAttribute(String uri, String localName, String value);
+
+ /**
+ * Returns a given XML attribute.
+ * <p/>
+ * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
+ * That means that if called in the context of {@link #editXml(String, INodeHandler)}, the value
+ * returned here is not affected by {@link #setAttribute(String, String, String)} until
+ * the editXml closure is completed and the actual XML is updated.
+ *
+ * @param uri The XML name-space URI of the attribute.
+ * @param attrName The <em>local</em> name of the attribute.
+ * @return the attribute as a {@link String}, if it exists, or <code>null</code>.
+ */
+ String getStringAttr(String uri, String attrName);
+
+ /**
+ * Returns the {@link IAttributeInfo} for a given attribute.
+ * <p/>
+ * The information is useful to determine the format of an attribute (e.g. reference, string,
+ * float, enum, flag, etc.) and in the case of enums and flags also gives the possible values.
+ * <p/>
+ * Note: in Android resources, an enum can only take one of the possible values (e.g.
+ * "visibility" can be either "visible" or "none"), whereas a flag can accept one or more
+ * value (e.g. "align" can be "center_vertical|center_horizontal".)
+ * <p/>
+ * Note that this method does not handle custom non-android attributes. It may either
+ * return null for these or it may return a synthetic "string" format attribute depending
+ * on how the attribute was loaded.
+ *
+ * @param uri The XML name-space URI of the attribute.
+ * @param attrName The <em>local</em> name of the attribute.
+ * @return the {@link IAttributeInfo} if the attribute is known, or <code>null</code>.
+ */
+ public IAttributeInfo getAttributeInfo(String uri, String attrName);
+
+ /**
+ * Returns the list of all attributes declared by this node's descriptor.
+ * <p/>
+ * This returns a fixed list of all attributes known to the view or layout descriptor.
+ * This list does not depend on whether the attributes are actually used in the
+ * XML for this node.
+ * <p/>
+ * Note that for views, the list of attributes also includes the layout attributes
+ * inherited from the parent view. This means callers must not cache this list based
+ * solely on the type of the node, as its attribute list changes depending on the place
+ * of the view in the view hierarchy.
+ * <p/>
+ * If you want attributes actually written in the XML and their values, please use
+ * {@link #getStringAttr(String, String)} or {@link #getLiveAttributes()} instead.
+ *
+ * @return A non-null possible-empty list of {@link IAttributeInfo}.
+ */
+ public IAttributeInfo[] getDeclaredAttributes();
+
+ /**
+ * Returns the list of all attributes defined in the XML for this node.
+ * <p/>
+ * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
+ * That means that if called in the context of {@link #editXml(String, INodeHandler)}, the value
+ * returned here is not affected by {@link #setAttribute(String, String, String)} until
+ * the editXml closure is completed and the actual XML is updated.
+ * <p/>
+ * If you want a list of all possible attributes, whether used in the XML or not by
+ * this node, please see {@link #getDeclaredAttributes()} instead.
+ *
+ * @return A non-null possible-empty list of {@link IAttribute}.
+ */
+ public IAttribute[] getLiveAttributes();
+
+ // -----------
+
+ /**
+ * An XML attribute in an {@link INode} with a namespace URI, a name and its current value.
+ * <p/>
+ * The name cannot be empty.
+ * The namespace URI can be empty for an attribute without a namespace but is never null.
+ * The value can be empty but cannot be null.
+ */
+ public static interface IAttribute extends IDragAttribute { }
+}
diff --git a/rule_api/src/com/android/ide/common/api/INodeHandler.java b/rule_api/src/com/android/ide/common/api/INodeHandler.java
new file mode 100644
index 0000000..e261395
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/INodeHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * A node handler is a callback which operates on a Node, such as for example
+ * the implementation of an XML editing operation via
+ * {@link INode#editXml(String, INodeHandler)}.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface INodeHandler {
+ /**
+ * Operates on the given node.
+ *
+ * @param node The node to be operated on
+ */
+ void handle(INode node);
+}
diff --git a/rule_api/src/com/android/ide/common/api/IValidator.java b/rule_api/src/com/android/ide/common/api/IValidator.java
new file mode 100644
index 0000000..6ef44cd
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IValidator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * An IValidator can validate strings and return custom messages if validation
+ * fails.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IValidator {
+ /**
+ * Validates the given input string, and return null if the text is valid,
+ * and otherwise return a description for why the text is invalid. Returning
+ * an empty String ("") is acceptable (but should only be done when it is
+ * obvious to the user why the String is not valid.)
+ *
+ * @param text The input string to be validated
+ * @return Null if the text is valid, and otherwise a description (possibly
+ * empty) for why the text is not valid.
+ */
+ String validate(String text);
+}
diff --git a/rule_api/src/com/android/ide/common/api/IViewMetadata.java b/rule_api/src/com/android/ide/common/api/IViewMetadata.java
new file mode 100644
index 0000000..0687f30
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IViewMetadata.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Metadata about a particular view. The metadata for a View can be found by asking the
+ * {@link IClientRulesEngine} for the metadata for a given class via
+ * {@link IClientRulesEngine#getMetadata}.
+ */
+public interface IViewMetadata {
+ /**
+ * Returns the display name views of this type (a name suitable to display to the
+ * user, normally capitalized and usually but not necessarily tied to the
+ * implementation class). To be clear, a specific view may have an id attribute and a
+ * text attribute, <b>neither</b> of these is the display name. Instead, the class
+ * android.widget.ZoomControls may have the display name "Zoom Controls", and an
+ * individual view created into a layout can for example have the id "ZoomControl01".
+ *
+ * @return the user visible name of views of this type (never null)
+ */
+ public String getDisplayName();
+
+ /**
+ * Gets the insets for this view
+ *
+ * @return the insets for this view
+ */
+ public Margins getInsets();
+
+ /**
+ * Returns the {@link FillPreference} of this view
+ *
+ * @return the {@link FillPreference} of this view
+ */
+ public FillPreference getFillPreference();
+
+ /**
+ * Types of fill behavior that views can prefer.
+ * <p>
+ * TODO: Consider better names. FillPolicy? Stretchiness?
+ */
+ public enum FillPreference {
+ /** This view does not want to fill */
+ NONE,
+ /** This view wants to always fill both horizontal and vertical */
+ BOTH,
+ /** This view wants to fill horizontally but not vertically */
+ WIDTH,
+ /** This view wants to fill vertically but not horizontally */
+ HEIGHT,
+ /**
+ * This view wants to fill in the opposite dimension of the context, e.g. in a
+ * vertical context it wants to fill horizontally, and vice versa
+ */
+ OPPOSITE,
+ /** This view wants to fill horizontally, but only in a vertical context */
+ WIDTH_IN_VERTICAL,
+ /** This view wants to fill vertically, but only in a horizontal context */
+ HEIGHT_IN_HORIZONTAL;
+
+ /**
+ * Returns true if this view wants to fill horizontally, if the context is
+ * vertical or horizontal as indicated by the parameter.
+ *
+ * @param verticalContext If true, the context is vertical, otherwise it is
+ * horizontal.
+ * @return true if this view wants to fill horizontally
+ */
+ public boolean fillHorizontally(boolean verticalContext) {
+ return (this == BOTH || this == WIDTH ||
+ (verticalContext && (this == OPPOSITE || this == WIDTH_IN_VERTICAL)));
+ }
+
+ /**
+ * Returns true if this view wants to fill vertically, if the context is
+ * vertical or horizontal as indicated by the parameter.
+ *
+ * @param verticalContext If true, the context is vertical, otherwise it is
+ * horizontal.
+ * @return true if this view wants to fill vertically
+ */
+ public boolean fillVertically(boolean verticalContext) {
+ return (this == BOTH || this == HEIGHT ||
+ (!verticalContext && (this == OPPOSITE || this == HEIGHT_IN_HORIZONTAL)));
+ }
+ }
+
+}
diff --git a/rule_api/src/com/android/ide/common/api/IViewRule.java b/rule_api/src/com/android/ide/common/api/IViewRule.java
new file mode 100755
index 0000000..d29ef71
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/IViewRule.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+import java.util.List;
+
+
+/**
+ * An {@link IViewRule} describes the rules that apply to a given Layout or View object
+ * in the Graphical Layout Editor.
+ * <p/>
+ * Rules are implemented by builtin layout helpers, or 3rd party layout rule implementations
+ * provided with or for a given 3rd party widget.
+ * <p/>
+ * A 3rd party layout rule should use the same fully qualified class name as the layout it
+ * represents, plus "Rule" as a suffix. For example, the layout rule for the
+ * LinearLayout class is LinearLayoutRule, in the same package.
+ * <p/>
+ * Rule instances are stateless. They are created once per View class to handle and are shared
+ * across platforms or editor instances. As such, rules methods should never cache editor-specific
+ * arguments that they might receive.
+ * <p/>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public interface IViewRule {
+
+ /**
+ * This method is called by the rule engine when the script is first loaded.
+ * It gives the rule a chance to initialize itself.
+ *
+ * @param fqcn The fully qualified class name of the Layout or View that will be managed by
+ * this rule. This can be cached as it will never change for the lifetime of this rule
+ * instance. This may or may not match the script's filename as it may be the fqcn of a
+ * class derived from the one this rule can handle.
+ * @param engine The engine that is managing the rules. A rule can store a reference to
+ * the engine during initialization and then use it later to invoke some of the
+ * {@link IClientRulesEngine} methods for example to request user input.
+ * @return True if this rule can handle the given FQCN. False if the rule can't handle the
+ * given FQCN, in which case the rule engine will find another rule matching a parent class.
+ */
+ boolean onInitialize(String fqcn, IClientRulesEngine engine);
+
+ /**
+ * This method is called by the rules engine just before the script is unloaded.
+ */
+ void onDispose();
+
+ /**
+ * Returns the class name to display when an element is selected in the GLE.
+ * <p/>
+ * If null is returned, the GLE will automatically shorten the class name using its
+ * own heuristic, which is to keep the first 2 package components and the class name.
+ * The class name is the <code>fqcn</code> argument that was given
+ * to {@link #onInitialize(String,IClientRulesEngine)}.
+ *
+ * @return Null for the default behavior or a shortened string.
+ */
+ String getDisplayName();
+
+ /**
+ * Invoked by the Rules Engine to produce a set of actions to customize
+ * the context menu displayed for this view. The result is not cached and the
+ * method is invoked every time the context menu is about to be shown.
+ * <p>
+ * The order of the menu items is determined by the sort priority set on
+ * the actions.
+ * <p/>
+ * Most rules should consider calling super.{@link #addContextMenuActions(List, INode)}
+ * as well.
+ * <p/>
+ * Menu actions are either toggles or fixed lists with one currently-selected
+ * item. It is expected that the rule will need to recreate the actions with
+ * different selections when a menu is going to shown, which is why the result
+ * is not cached. However rules are encouraged to cache some or all of the result
+ * to speed up following calls if it makes sense.
+ *
+ * @param actions a list of actions to add new context menu actions into. The order
+ * of the actions in this list is not important; it will be sorted by
+ * {@link RuleAction#getSortPriority()} later.
+ * @param node the node to add actions for.
+ */
+ void addContextMenuActions(List<RuleAction> actions, INode node);
+
+ /**
+ * Invoked by the Rules Engine to ask the parent layout for the set of layout actions
+ * to display in the layout bar. The layout rule should add these into the provided
+ * list. The order the items are added in does not matter; the
+ * {@link RuleAction#getSortPriority()} values will be used to sort the actions prior
+ * to display, which makes it easier for parent rules and deriving rules to interleave
+ * their respective actions.
+ *
+ * @param actions the list of actions to add newly registered actions into
+ * @param parentNode the parent of the selection, or the selection itself if the root
+ * @param targets the targeted/selected nodes, if any
+ */
+ void addLayoutActions(List<RuleAction> actions,
+ INode parentNode, List<? extends INode> targets);
+
+ // ==== Selection ====
+
+ /**
+ * Returns a list of strings that will be displayed when a single child is being
+ * selected in a layout corresponding to this rule. This gives the container a chance
+ * to describe the child's layout attributes or other relevant information.
+ * <p/>
+ * Note that this is called only for single selections.
+ * <p/>
+ *
+ * @param parentNode The parent of the node selected. Never null.
+ * @param childNode The child node that was selected. Never null.
+ * @return a list of strings to be displayed, or null or empty to display nothing
+ */
+ List<String> getSelectionHint(INode parentNode, INode childNode);
+
+ /**
+ * Paints any layout-specific selection feedback for the given parent layout.
+ *
+ * @param graphics the graphics context to paint into
+ * @param parentNode the parent layout node
+ * @param childNodes the child nodes selected in the parent layout
+ */
+ void paintSelectionFeedback(IGraphics graphics, INode parentNode,
+ List<? extends INode> childNodes);
+
+ // ==== Drag'n'drop support ====
+
+ /**
+ * Called when the d'n'd starts dragging over the target node.
+ * If interested, returns a DropFeedback passed to onDrop/Move/Leave/Paint.
+ * If not interested in drop, return null.
+ * Followed by a paint.
+ */
+ DropFeedback onDropEnter(INode targetNode,
+ IDragElement[] elements);
+
+ /**
+ * Called after onDropEnter.
+ * Returns a DropFeedback passed to onDrop/Move/Leave/Paint (typically same
+ * as input one).
+ * Returning null will invalidate the drop workflow.
+ */
+ DropFeedback onDropMove(INode targetNode,
+ IDragElement[] elements,
+ DropFeedback feedback,
+ Point where);
+
+ /**
+ * Called when drop leaves the target without actually dropping.
+ * <p/>
+ * When switching between views, onDropLeave is called on the old node *after* onDropEnter
+ * is called after a new node that returned a non-null feedback. The feedback received here
+ * is the one given by the previous onDropEnter on the same target.
+ * <p/>
+ * E.g. call order is:
+ * <pre>
+ * - onDropEnter(node1) => feedback1
+ * <i>...user moves to new view...</i>
+ * - onDropEnter(node2) => feedback2
+ * - onDropLeave(node1, feedback1)
+ * <i>...user leaves canvas...</i>
+ * - onDropLeave(node2, feedback2)
+ * </pre>
+ */
+ void onDropLeave(INode targetNode,
+ IDragElement[] elements,
+ DropFeedback feedback);
+
+ /**
+ * Called when drop is released over the target to perform the actual drop.
+ * <p>
+ * TODO: Document that this method will be called under an edit lock so you can
+ * directly manipulate the nodes without wrapping it in an
+ * {@link INode#editXml(String, INodeHandler)} call
+ */
+ void onDropped(INode targetNode,
+ IDragElement[] elements,
+ DropFeedback feedback,
+ Point where);
+
+ /**
+ * Called when pasting elements in an existing document on the selected target.
+ *
+ * @param targetNode The first node selected.
+ * @param pastedElements The elements being pasted.
+ */
+ void onPaste(INode targetNode, IDragElement[] pastedElements);
+
+ // ==== XML Creation ====
+
+ /**
+ * Called when a view for this rule is being created. This allows for the rule to
+ * customize the newly created object. Note that this method is called not just when a
+ * view is created from a palette drag, but when views are constructed via a drag-move
+ * (where views are created in the destination and then deleted from the source), and
+ * even when views are constructed programmatically from other view rules. The
+ * {@link InsertType} parameter can be used to distinguish the context for the
+ * insertion. For example, the <code>DialerFilterRule</code> will insert EditText children
+ * when a DialerFilter is first created, but not during a copy/paste or a move.
+ *
+ * @param node the newly created node (which will always be a View that applies to
+ * this {@link IViewRule})
+ * @param parent the parent of the node (which may not yet contain the newly created
+ * node in its child list)
+ * @param insertType whether this node was created as part of a newly created view, or
+ * as a copy, or as a move, etc.
+ */
+ void onCreate(INode node, INode parent, InsertType insertType);
+
+ /**
+ * Called when a child for this view has been created and is being inserted into the
+ * view parent for which this {@link IViewRule} applies. Allows the parent to perform
+ * customizations of the object. As with {@link #onCreate}, the {@link InsertType}
+ * parameter can be used to handle new creation versus moves versus copy/paste
+ * operations differently.
+ *
+ * @param child the newly created node
+ * @param parent the parent of the newly created node (which may not yet contain the
+ * newly created node in its child list)
+ * @param insertType whether this node was created as part of a newly created view, or
+ * as a copy, or as a move, etc.
+ */
+ void onChildInserted(INode child, INode parent, InsertType insertType);
+
+ /**
+ * Called when one or more children are about to be deleted by the user. Note that
+ * children deleted programmatically from view rules (via
+ * {@link INode#removeChild(INode)}) will not notify about deletion.
+ * <p>
+ * Note that this method will be called under an edit lock, so rules can directly
+ * add/remove nodes and attributes as part of the deletion handling (and their
+ * actions will be part of the same undo-unit.)
+ *
+ * @param deleted a nonempty list of children about to be deleted
+ * @param parent the parent of the deleted children (which still contains the children
+ * since this method is called before the deletion is performed)
+ */
+ void onRemovingChildren(List<INode> deleted, INode parent);
+
+ /**
+ * Called by the IDE on the parent layout when a child widget is being resized. This
+ * is called once at the beginning of the resizing operation. A horizontal edge,
+ * or a vertical edge, or both, can be resized simultaneously.
+ *
+ * @param child the widget being resized
+ * @param parent the layout containing the child
+ * @param horizEdge The horizontal edge being resized, or null
+ * @param verticalEdge the vertical edge being resized, or null
+ * @return a {@link DropFeedback} object which performs an update painter callback
+ * etc.
+ */
+ DropFeedback onResizeBegin(INode child, INode parent,
+ SegmentType horizEdge, SegmentType verticalEdge);
+
+ /**
+ * Called by the IDE on the parent layout when a child widget is being resized. This
+ * is called repeatedly during the resize as the mouse is dragged to update the drag
+ * bounds, recompute guidelines, etc. The resize has not yet been "committed" so the
+ * XML should not be edited yet.
+ *
+ * @param feedback the {@link DropFeedback} object created in {@link #onResizeBegin}
+ * @param child the widget being resized
+ * @param parent the layout containing the child
+ * @param newBounds the new bounds the user has chosen to resize the widget to,
+ * in absolute coordinates
+ * @param modifierMask The modifier keys currently pressed by the user, as a bitmask
+ * of the constants {@link DropFeedback#MODIFIER1}, {@link DropFeedback#MODIFIER2}
+ * and {@link DropFeedback#MODIFIER3}.
+ */
+ void onResizeUpdate(DropFeedback feedback, INode child, INode parent, Rect newBounds,
+ int modifierMask);
+
+ /**
+ * Called by the IDE on the parent layout when a child widget is being resized. This
+ * is called once at the end of the resize operation, if it was not canceled.
+ * This method can call {@link INode#editXml} to update the node to reflect the
+ * new bounds.
+ *
+ * @param feedback the {@link DropFeedback} object created in {@link #onResizeBegin}
+ * @param child the widget being resized
+ * @param parent the layout containing the child
+ * @param newBounds the new bounds the user has chosen to resize the widget to,
+ * in absolute coordinates
+ */
+ void onResizeEnd(DropFeedback feedback, INode child, INode parent, Rect newBounds);
+}
diff --git a/rule_api/src/com/android/ide/common/api/InsertType.java b/rule_api/src/com/android/ide/common/api/InsertType.java
new file mode 100644
index 0000000..806b2bb
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/InsertType.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * An enumerated type of different insertion events, such as an insertion from a
+ * copy/paste operation or as the first half of a move operation.
+ */
+public enum InsertType {
+ /** The view is newly created (by for example a palette drag) */
+ CREATE,
+
+ /**
+ * Same as {@link #CREATE} but when the views are constructed for previewing, for
+ * example as part of a palette drag.
+ */
+ CREATE_PREVIEW,
+
+ /** The view is being inserted here because it was moved from somewhere else within
+ * the same layout */
+ MOVE_WITHIN,
+
+ /** The view is being inserted here because it was moved from some other layout */
+ MOVE_INTO,
+
+ /**
+ * The view is being inserted here as a result of a copy/paste from elsewhere
+ * (including drags, but not from the palette)
+ */
+ PASTE;
+
+ /**
+ * Returns true if this insert type is for a newly created view (for example a by
+ * palette drag). Note that this includes both normal create events as well as well as
+ * views created as part of previewing operations.
+ *
+ * @return true if this {@link InsertType} is for a newly created view
+ */
+ public boolean isCreate() {
+ return this == CREATE || this == CREATE_PREVIEW;
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/MarginType.java b/rule_api/src/com/android/ide/common/api/MarginType.java
new file mode 100644
index 0000000..d3a27a4
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/MarginType.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+
+/**
+ * A {@link MarginType} indicates whether a {@link Segment} corresponds to the visual edge
+ * of the node, or whether it is offset by a margin in the edge's direction, or whether
+ * it's both (which is the case when the margin is 0).
+ * <p>
+ * We need to keep track of the distinction because different constraints apply
+ * differently w.r.t. margins. Let's say you have a target node with a 50 dp margin in all
+ * directions. If you layout_alignTop with this node, the match will be on the visual
+ * bounds of the target node (ignoring the margin). If you layout_above this node, you
+ * will be offset by the margin on the target node. Therefore, we have to add <b>both</b>
+ * edges (the bounds of the target node with and without edges) and check for matches on
+ * each edge depending on the constraint being considered.
+ */
+public enum MarginType {
+ /**
+ * This margin type is used for nodes that have margins, and this segment includes the
+ * margin distance
+ */
+ WITH_MARGIN,
+
+ /**
+ * This margin type is used for nodes that have margins, and this segment does not
+ * include the margin distance
+ */
+ WITHOUT_MARGIN,
+
+ /**
+ * This margin type is used for nodes that do not have margins, so margin edges and
+ * non-margin edges are the same
+ */
+ NO_MARGIN;
+}
diff --git a/rule_api/src/com/android/ide/common/api/Margins.java b/rule_api/src/com/android/ide/common/api/Margins.java
new file mode 100644
index 0000000..40f44ce
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/Margins.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * Set of margins - distances to outer left, top, right and bottom edges. These objects
+ * can be used for both actual <b>margins</b> as well as insets - and in general any
+ * deltas to the bounds of a rectangle.
+ */
+public class Margins {
+ /** The left margin */
+ public final int left;
+
+ /** The right margin */
+ public final int right;
+
+ /** The top margin */
+ public final int top;
+
+ /** The bottom margin */
+ public final int bottom;
+
+ /**
+ * Creates a new {@link Margins} instance.
+ *
+ * @param left the left side margin
+ * @param right the right side margin
+ * @param top the top margin
+ * @param bottom the bottom margin
+ */
+ public Margins(int left, int right, int top, int bottom) {
+ super();
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
+ }
+
+ @Override
+ public String toString() {
+ return "Margins [left=" + left + ", right=" + right + ", top=" + top + ", bottom=" + bottom
+ + "]";
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/Point.java b/rule_api/src/com/android/ide/common/api/Point.java
new file mode 100755
index 0000000..67c41d3
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/Point.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+
+/**
+ * Mutable point.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public class Point {
+ public int x, y;
+
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Point(Point p) {
+ x = p.x;
+ y = p.y;
+ }
+
+ /** Sets the point to the given coordinates. */
+ public void set(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /** Returns a new instance of a point with the same values. */
+ public Point copy() {
+ return new Point(x, y);
+ }
+
+ /**
+ * Offsets this point by adding the given x,y deltas to the x,y coordinates.
+ * @return Returns self, for chaining.
+ */
+ public Point offsetBy(int x, int y) {
+ this.x += x;
+ this.y += y;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Point) {
+ Point rhs = (Point) obj;
+ return this.x == rhs.x && this.y == rhs.y;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = x ^ ((y >> 16) & 0x0FFFF) ^ ((y & 0x0FFFF) << 16);
+ return h;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Point [%dx%d]", x, y);
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/Rect.java b/rule_api/src/com/android/ide/common/api/Rect.java
new file mode 100755
index 0000000..f3922e2
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/Rect.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+
+
+/**
+ * Mutable rectangle bounds.
+ * <p/>
+ * To be valid, w >= 1 and h >= 1.
+ * By definition:
+ * - right side = x + w - 1.
+ * - bottom side = y + h - 1.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public class Rect {
+ public int x, y, w, h;
+
+ /** Initialize an invalid rectangle. */
+ public Rect() {
+ }
+
+ /** Initialize rectangle to the given values. They can be invalid. */
+ public Rect(int x, int y, int w, int h) {
+ set(x, y, w, h);
+ }
+
+ /** Initialize rectangle to the given values. They can be invalid. */
+ public Rect(Rect r) {
+ set(r);
+ }
+
+ /** Initialize rectangle to the given values. They can be invalid. */
+ public Rect set(int x, int y, int w, int h) {
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ return this;
+ }
+
+ /** Initialize rectangle to match the given one. */
+ public Rect set(Rect r) {
+ set(r.x, r.y, r.w, r.h);
+ return this;
+ }
+
+ /** Returns a new instance of a rectangle with the same values. */
+ public Rect copy() {
+ return new Rect(x, y, w, h);
+ }
+
+ /** Returns true if the rectangle has valid bounds, i.e. w>0 and h>0. */
+ public boolean isValid() {
+ return w > 0 && h > 0;
+ }
+
+ /** Returns true if the rectangle contains the x,y coordinates, borders included. */
+ public boolean contains(int x, int y) {
+ return isValid() &&
+ x >= this.x &&
+ y >= this.y &&
+ x < (this.x + this.w) &&
+ y < (this.y + this.h);
+ }
+
+ /** Returns true if the rectangle contains the x,y coordinates, borders included. */
+ public boolean contains(Point p) {
+ return p != null && contains(p.x, p.y);
+ }
+
+ /**
+ * Moves this rectangle by setting it's x,y coordinates to the new values.
+ * @return Returns self, for chaining.
+ */
+ public Rect moveTo(int x, int y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ }
+
+ /**
+ * Offsets this rectangle by adding the given x,y deltas to the x,y coordinates.
+ * @return Returns self, for chaining.
+ */
+ public Rect offsetBy(int x, int y) {
+ this.x += x;
+ this.y += y;
+ return this;
+ }
+
+ public Point getCenter() {
+ return new Point(x + (w > 0 ? w / 2 : 0),
+ y + (h > 0 ? h / 2 : 0));
+ }
+
+ public Point getTopLeft() {
+ return new Point(x, y);
+ }
+
+ public Point getBottomLeft() {
+ return new Point(x,
+ y + (h > 0 ? h : 0));
+ }
+
+ public Point getTopRight() {
+ return new Point(x + (w > 0 ? w : 0),
+ y);
+ }
+
+ public Point getBottomRight() {
+ return new Point(x + (w > 0 ? w : 0),
+ y + (h > 0 ? h : 0));
+ }
+
+ /**
+ * Returns the X coordinate of the right hand side of the rectangle
+ *
+ * @return the X coordinate of the right hand side of the rectangle
+ */
+ public int x2() {
+ return x + w;
+ }
+
+ /**
+ * Returns the Y coordinate of the bottom of the rectangle
+ *
+ * @return the Y coordinate of the bottom of the rectangle
+ */
+ public int y2() {
+ return y + h;
+ }
+
+ /**
+ * Returns the X coordinate of the center of the rectangle
+ *
+ * @return the X coordinate of the center of the rectangle
+ */
+ public int centerX() {
+ return x + w / 2;
+ }
+
+ /**
+ * Returns the Y coordinate of the center of the rectangle
+ *
+ * @return the Y coordinate of the center of the rectangle
+ */
+ public int centerY() {
+ return y + h / 2;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Rect [(%d,%d)-(%d,%d): %dx%d]", x, y, x + w, y + h, w, h);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Rect) {
+ Rect rhs = (Rect) obj;
+ // validity must be equal on both sides.
+ if (isValid() != rhs.isValid()) {
+ return false;
+ }
+ // an invalid rect is equal to any other invalid rect regardless of coordinates
+ if (!isValid() && !rhs.isValid()) {
+ return true;
+ }
+
+ return this.x == rhs.x && this.y == rhs.y && this.w == rhs.w && this.h == rhs.h;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hc = x;
+ hc ^= ((y >> 8) & 0x0FFFFFF) | ((y & 0x00000FF) << 24);
+ hc ^= ((w >> 16) & 0x000FFFF) | ((w & 0x000FFFF) << 16);
+ hc ^= ((h >> 24) & 0x00000FF) | ((h & 0x0FFFFFF) << 8);
+ return hc;
+ }
+
+ /**
+ * Returns the center point in the rectangle
+ *
+ * @return the center point in the rectangle
+ */
+ public Point center() {
+ return new Point(x + w / 2, y + h / 2);
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/ResizePolicy.java b/rule_api/src/com/android/ide/common/api/ResizePolicy.java
new file mode 100644
index 0000000..05ad81c
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/ResizePolicy.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.common.api;
+
+/**
+ * A {@link ResizePolicy} records state for whether a widget is resizable, and if so, in
+ * which directions
+ */
+public class ResizePolicy {
+ private static final int NONE = 0;
+ private static final int LEFT_EDGE = 1;
+ private static final int RIGHT_EDGE = 2;
+ private static final int TOP_EDGE = 4;
+ private static final int BOTTOM_EDGE = 8;
+ private static final int PRESERVE_RATIO = 16;
+
+ // Aliases
+ private static final int HORIZONTAL = LEFT_EDGE | RIGHT_EDGE;
+ private static final int VERTICAL = TOP_EDGE | BOTTOM_EDGE;
+ private static final int ANY = HORIZONTAL | VERTICAL;
+
+ // Shared objects for common policies
+
+ public static final ResizePolicy sAny = new ResizePolicy(ANY);
+ private static final ResizePolicy sNone = new ResizePolicy(NONE);
+ private static final ResizePolicy sHorizontal = new ResizePolicy(HORIZONTAL);
+ private static final ResizePolicy sVertical = new ResizePolicy(VERTICAL);
+ private static final ResizePolicy sScaled = new ResizePolicy(ANY | PRESERVE_RATIO);
+
+ private final int mFlags;
+
+
+ // Use factory methods to construct
+ private ResizePolicy(int flags) {
+ mFlags = flags;
+ }
+
+ /**
+ * Returns true if this policy allows resizing in at least one direction
+ *
+ * @return true if this policy allows resizing in at least one direction
+ */
+ public boolean isResizable() {
+ return (mFlags & ANY) != 0;
+ }
+
+ /**
+ * Returns true if this policy allows resizing the top edge
+ *
+ * @return true if this policy allows resizing the top edge
+ */
+ public boolean topAllowed() {
+ return (mFlags & TOP_EDGE) != 0;
+ }
+
+ /**
+ * Returns true if this policy allows resizing the right edge
+ *
+ * @return true if this policy allows resizing the right edge
+ */
+ public boolean rightAllowed() {
+ return (mFlags & RIGHT_EDGE) != 0;
+ }
+
+ /**
+ * Returns true if this policy allows resizing the bottom edge
+ *
+ * @return true if this policy allows resizing the bottom edge
+ */
+ public boolean bottomAllowed() {
+ return (mFlags & BOTTOM_EDGE) != 0;
+ }
+
+ /**
+ * Returns true if this policy allows resizing the left edge
+ *
+ * @return true if this policy allows resizing the left edge
+ */
+ public boolean leftAllowed() {
+ return (mFlags & LEFT_EDGE) != 0;
+ }
+
+ /**
+ * Returns true if this policy requires resizing in an aspect-ratio preserving manner
+ *
+ * @return true if this policy requires resizing in an aspect-ratio preserving manner
+ */
+ public boolean isAspectPreserving() {
+ return (mFlags & PRESERVE_RATIO) != 0;
+ }
+
+ /**
+ * Returns a resize policy allowing resizing in any direction
+ *
+ * @return a resize policy allowing resizing in any direction
+ */
+ public static ResizePolicy full() {
+ return sAny;
+ }
+
+ /**
+ * Returns a resize policy not allowing any resizing
+ *
+ * @return a policy which does not allow any resizing
+ */
+ public static ResizePolicy none() {
+ return sNone;
+ }
+
+ /**
+ * Returns a resize policy allowing horizontal resizing only
+ *
+ * @return a policy which allows horizontal resizing only
+ */
+ public static ResizePolicy horizontal() {
+ return sHorizontal;
+ }
+
+ /**
+ * Returns a resize policy allowing vertical resizing only
+ *
+ * @return a policy which allows vertical resizing only
+ */
+ public static ResizePolicy vertical() {
+ return sVertical;
+ }
+
+ /**
+ * Returns a resize policy allowing scaled / aspect-ratio preserving resizing only
+ *
+ * @return a resize policy allowing scaled / aspect-ratio preserving resizing only
+ */
+ public static ResizePolicy scaled() {
+ return sScaled;
+ }
+
+ /**
+ * Returns a resize policy with the specified resizability along the edges and the
+ * given aspect ratio behavior
+ * @param top whether the top edge is resizable
+ * @param right whether the right edge is resizable
+ * @param bottom whether the bottom edge is resizable
+ * @param left whether the left edge is resizable
+ * @param preserve whether the policy requires the aspect ratio to be preserved
+ * @return a resize policy recording the constraints required by the parameters
+ */
+ public static ResizePolicy create(boolean top, boolean right, boolean bottom, boolean left,
+ boolean preserve) {
+ int mask = NONE;
+ if (top) mask |= TOP_EDGE;
+ if (right) mask |= RIGHT_EDGE;
+ if (bottom) mask |= BOTTOM_EDGE;
+ if (left) mask |= LEFT_EDGE;
+ if (preserve) mask |= PRESERVE_RATIO;
+
+ return new ResizePolicy(mask);
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/RuleAction.java b/rule_api/src/com/android/ide/common/api/RuleAction.java
new file mode 100755
index 0000000..2ebab36
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/RuleAction.java
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+import com.android.util.Pair;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A {@link RuleAction} represents an action provided by an {@link IViewRule}, typically
+ * shown in a context menu or in the layout actions bar.
+ * <p/>
+ * Each action should have a reasonably unique ID. This is used when multiple nodes
+ * are selected to filter the actions down to just those actions that are supported
+ * across all selected nodes. If an action does not support multiple nodes, it can
+ * return false from {@link #supportsMultipleNodes()}.
+ * <p/>
+ * Actions can be grouped into a hierarchy of sub-menus using the {@link NestedAction} class,
+ * or into a flat submenu using the {@link Choices} class.
+ * <p/>
+ * Actions (including separators) all have a "sort priority", and this is used to
+ * sort the menu items or toolbar buttons into a specific order.
+ * <p>
+ * <b>NOTE: This is not a public or final API; if you rely on this be prepared
+ * to adjust your code for the next tools release.</b>
+ * </p>
+ */
+public class RuleAction implements Comparable<RuleAction> {
+ /**
+ * Character used to split multiple checked choices.
+ * The pipe character "|" is used, to natively match Android resource flag separators.
+ */
+ public final static String CHOICE_SEP = "|"; //$NON-NLS-1$
+
+ /**
+ * Same as {@link #CHOICE_SEP} but safe for use in regular expressions.
+ */
+ public final static String CHOICE_SEP_PATTERN = Pattern.quote(CHOICE_SEP);
+
+ /**
+ * The unique id of the action.
+ * @see #getId()
+ */
+ private final String mId;
+ /**
+ * The UI-visible title of the action.
+ */
+ private final String mTitle;
+
+ /** A URL pointing to an icon, or null */
+ private URL mIconUrl;
+
+ /**
+ * A callback executed when the action is selected in the context menu.
+ */
+ private final IMenuCallback mCallback;
+
+ /**
+ * The sorting priority of this item; actions can be sorted according to these
+ */
+ protected final int mSortPriority;
+
+ /**
+ * Whether this action supports multiple nodes, see
+ * {@link #supportsMultipleNodes()} for details.
+ */
+ private final boolean mSupportsMultipleNodes;
+
+ /**
+ * Special value which will insert a separator in the choices' submenu.
+ */
+ public final static String SEPARATOR = "----";
+
+ // Factories
+
+ /**
+ * Constructs a new separator which will be shown in places where separators
+ * are supported such as context menus
+ *
+ * @param sortPriority a priority used for sorting this action
+ * @return a new separator
+ */
+ public static Separator createSeparator(int sortPriority) {
+ return new Separator(sortPriority, true /* supportsMultipleNodes*/);
+ }
+
+ /**
+ * Constructs a new base {@link RuleAction} with its ID, title and action callback.
+ *
+ * @param id The unique ID of the action. Must not be null.
+ * @param title The title of the action. Must not be null.
+ * @param callback The callback executed when the action is selected.
+ * Must not be null.
+ * @param iconUrl a URL pointing to an icon to use for this action, or null
+ * @param sortPriority a priority used for sorting this action
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @return the new {@link RuleAction}
+ */
+ public static RuleAction createAction(String id, String title,
+ IMenuCallback callback, URL iconUrl, int sortPriority, boolean supportsMultipleNodes) {
+ RuleAction action = new RuleAction(id, title, callback, sortPriority,
+ supportsMultipleNodes);
+ action.setIconUrl(iconUrl);
+
+ return action;
+ }
+
+ /**
+ * Creates a new immutable toggle action.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The UI-visible title of the context menu item. Cannot be null.
+ * @param isChecked Whether the context menu item has a check mark.
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param iconUrl a URL pointing to an icon to use for this action, or null
+ * @param sortPriority a priority used for sorting this action
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @return the new {@link Toggle}
+ */
+ public static Toggle createToggle(String id, String title, boolean isChecked,
+ IMenuCallback callback, URL iconUrl, int sortPriority,
+ boolean supportsMultipleNodes) {
+ Toggle toggle = new Toggle(id, title, isChecked, callback, sortPriority,
+ supportsMultipleNodes);
+ toggle.setIconUrl(iconUrl);
+ return toggle;
+ }
+
+ /**
+ * Creates a new immutable multiple-choice action with a defined ordered set
+ * of action children.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The title of the action to be displayed to the user
+ * @param provider Provides the actions to be shown as children of this
+ * action
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param iconUrl the icon to use for the multiple choice action itself
+ * @param sortPriority the sorting priority to use for the multiple choice
+ * action itself
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @return the new {@link NestedAction}
+ */
+ public static NestedAction createChoices(String id, String title,
+ IMenuCallback callback, URL iconUrl,
+ int sortPriority, boolean supportsMultipleNodes, ActionProvider provider) {
+ NestedAction choices = new NestedAction(id, title, provider, callback,
+ sortPriority, supportsMultipleNodes);
+ choices.setIconUrl(iconUrl);
+ return choices;
+ }
+
+ /**
+ * Creates a new immutable multiple-choice action with a defined ordered set
+ * of children.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The title of the action to be displayed to the user
+ * @param iconUrls The icon urls for the children items (may be null)
+ * @param ids The internal ids for the children
+ * @param current The id(s) of the current choice(s) that will be check
+ * marked. Can be null. Can be an id not present in the choices
+ * map. There can be more than one id separated by
+ * {@link #CHOICE_SEP}.
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param titles The UI-visible titles of the children
+ * @param iconUrl the icon to use for the multiple choice action itself
+ * @param sortPriority the sorting priority to use for the multiple choice
+ * action itself
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @return the new {@link Choices}
+ */
+ public static Choices createChoices(String id, String title,
+ IMenuCallback callback, List<String> titles, List<URL> iconUrls, List<String> ids,
+ String current, URL iconUrl, int sortPriority, boolean supportsMultipleNodes) {
+ Choices choices = new Choices(id, title, callback, titles, iconUrls,
+ ids, current, sortPriority, supportsMultipleNodes);
+ choices.setIconUrl(iconUrl);
+
+ return choices;
+ }
+
+ /**
+ * Creates a new immutable multiple-choice action with a defined ordered set
+ * of children.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The title of the action to be displayed to the user
+ * @param iconUrls The icon urls for the children items (may be null)
+ * @param current The id(s) of the current choice(s) that will be check
+ * marked. Can be null. Can be an id not present in the choices
+ * map. There can be more than one id separated by
+ * {@link #CHOICE_SEP}.
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param iconUrl the icon to use for the multiple choice action itself
+ * @param sortPriority the sorting priority to use for the multiple choice
+ * action itself
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @param idsAndTitles a list of pairs (of ids and titles) to use for the
+ * menu items
+ * @return the new {@link Choices}
+ */
+ public static Choices createChoices(String id, String title,
+ IMenuCallback callback, List<URL> iconUrls,
+ String current, URL iconUrl, int sortPriority,
+ boolean supportsMultipleNodes, List<Pair<String, String>> idsAndTitles) {
+ int itemCount = idsAndTitles.size();
+ List<String> titles = new ArrayList<String>(itemCount);
+ List<String> ids = new ArrayList<String>(itemCount);
+ for (Pair<String, String> pair : idsAndTitles) {
+ ids.add(pair.getFirst());
+ titles.add(pair.getSecond());
+ }
+ Choices choices = new Choices(id, title, callback, titles, iconUrls,
+ ids, current, sortPriority, supportsMultipleNodes);
+ choices.setIconUrl(iconUrl);
+ return choices;
+ }
+
+ /**
+ * Creates a new immutable multiple-choice action with lazily computed children.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The title of the multiple-choice itself
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param provider the provider which provides choices lazily
+ * @param current The id(s) of the current choice(s) that will be check
+ * marked. Can be null. Can be an id not present in the choice
+ * alternatives. There can be more than one id separated by
+ * {@link #CHOICE_SEP}.
+ * @param iconUrl the icon to use for the multiple choice action itself
+ * @param sortPriority the sorting priority to use for the multiple choice
+ * action itself
+ * @param supportsMultipleNodes whether this action supports multiple nodes,
+ * see {@link #supportsMultipleNodes()} for details
+ * @return the new {@link Choices}
+ */
+ public static Choices createChoices(String id, String title,
+ IMenuCallback callback, ChoiceProvider provider,
+ String current, URL iconUrl, int sortPriority, boolean supportsMultipleNodes) {
+ Choices choices = new DelayedChoices(id, title, callback,
+ current, provider, sortPriority, supportsMultipleNodes);
+ choices.setIconUrl(iconUrl);
+ return choices;
+ }
+
+ /**
+ * Creates a new {@link RuleAction} with the given id and the given title.
+ * Actions which have the same id and the same title are deemed equivalent.
+ *
+ * @param id The unique id of the action, which must be similar for all actions that
+ * perform the same task. Cannot be null.
+ * @param title The UI-visible title of the action.
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ * @param sortPriority a priority used for sorting this action
+ * @param supportsMultipleNodes the new return value for
+ * {@link #supportsMultipleNodes()}
+ */
+ private RuleAction(String id, String title, IMenuCallback callback, int sortPriority,
+ boolean supportsMultipleNodes) {
+ mId = id;
+ mTitle = title;
+ mSortPriority = sortPriority;
+ mSupportsMultipleNodes = supportsMultipleNodes;
+ mCallback = callback;
+ }
+
+ /**
+ * Returns the unique id of the action. In the context of a multiple selection,
+ * actions which have the same id are collapsed together and must represent the same
+ * action. Cannot be null.
+ *
+ * @return the unique id of the action, never null
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the UI-visible title of the action, shown in the context menu.
+ * Cannot be null.
+ *
+ * @return the user name of the action, never null
+ */
+ public String getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Actions which have the same id and the same title are deemed equivalent.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RuleAction) {
+ RuleAction rhs = (RuleAction) obj;
+
+ if (mId != rhs.mId && !(mId != null && mId.equals(rhs.mId))) return false;
+ if (mTitle != rhs.mTitle &&
+ !(mTitle != null && mTitle.equals(rhs.mTitle))) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Whether this action supports multiple nodes. An action which supports
+ * multiple nodes can be applied to different nodes by passing in different
+ * nodes to its callback. Some actions are hardcoded for a specific node (typically
+ * one that isn't selected, such as an action which affects the parent of a selected
+ * node), and these actions will not be added to the context menu when more than
+ * one node is selected.
+ *
+ * @return true if this node supports multiple nodes
+ */
+ public boolean supportsMultipleNodes() {
+ return mSupportsMultipleNodes;
+ }
+
+ /**
+ * Actions which have the same id and the same title have the same hash code.
+ */
+ @Override
+ public int hashCode() {
+ int h = mId == null ? 0 : mId.hashCode();
+ h = h ^ (mTitle == null ? 0 : mTitle.hashCode());
+ return h;
+ }
+
+ /**
+ * Gets a URL pointing to an icon to use for this action, if any.
+ *
+ * @return a URL pointing to an icon to use for this action, or null
+ */
+ public URL getIconUrl() {
+ return mIconUrl;
+ }
+
+ /**
+ * Sets a URL pointing to an icon to use for this action, if any.
+ *
+ * @param iconUrl a URL pointing to an icon to use for this action, or null
+ * @return this action, to allow setter chaining
+ */
+ public RuleAction setIconUrl(URL iconUrl) {
+ mIconUrl = iconUrl;
+
+ return this;
+ }
+
+ /**
+ * Return a priority used for sorting this action
+ *
+ * @return a priority used for sorting this action
+ */
+ public int getSortPriority() {
+ return mSortPriority;
+ }
+
+ /**
+ * Returns the callback executed when the action is selected in the
+ * context menu. Cannot be null.
+ *
+ * @return the callback, never null
+ */
+ public IMenuCallback getCallback() {
+ return mCallback;
+ }
+
+ // Implements Comparable<MenuAciton>
+ public int compareTo(RuleAction other) {
+ if (mSortPriority != other.mSortPriority) {
+ return mSortPriority - other.mSortPriority;
+ }
+
+ return mTitle.compareTo(other.mTitle);
+ }
+
+ @Override
+ public String toString() {
+ return "RuleAction [id=" + mId + ", title=" + mTitle + ", priority=" + mSortPriority + "]";
+ }
+
+ /** A separator to display between actions */
+ public static class Separator extends RuleAction {
+ /** Construct using the factory {@link #createSeparator(int)} */
+ private Separator(int sortPriority, boolean supportsMultipleNodes) {
+ super("_separator", "", null, sortPriority, //$NON-NLS-1$ //$NON-NLS-2$
+ supportsMultipleNodes);
+ }
+ }
+
+ /**
+ * A toggle is a simple on/off action, displayed as an item in a context menu
+ * with a check mark if the item is checked.
+ * <p/>
+ * Two toggles are equal if they have the same id, title and group-id.
+ * It is expected for the checked state and action callback to be different.
+ */
+ public static class Toggle extends RuleAction {
+ /**
+ * True if the item is displayed with a check mark.
+ */
+ private final boolean mIsChecked;
+
+ /**
+ * Creates a new immutable toggle action.
+ *
+ * @param id The unique id of the action. Cannot be null.
+ * @param title The UI-visible title of the context menu item. Cannot be null.
+ * @param isChecked Whether the context menu item has a check mark.
+ * @param callback A callback to execute when the context menu item is
+ * selected.
+ */
+ private Toggle(String id, String title, boolean isChecked,
+ IMenuCallback callback, int sortPriority, boolean supportsMultipleNodes) {
+ super(id, title, callback, sortPriority, supportsMultipleNodes);
+ mIsChecked = isChecked;
+ }
+
+ /**
+ * Returns true if the item is displayed with a check mark.
+ *
+ * @return true if the item is displayed with a check mark.
+ */
+ public boolean isChecked() {
+ return mIsChecked;
+ }
+
+ /**
+ * Two toggles are equal if they have the same id and title.
+ * It is acceptable for the checked state and action callback to be different.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
+
+ /**
+ * Two toggles have the same hash code if they have the same id and title.
+ */
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+ }
+
+ /**
+ * An ordered list of choices the user can choose between. For choosing between
+ * actions, there is a {@link NestedAction} class.
+ */
+ public static class Choices extends RuleAction {
+ protected List<String> mTitles;
+ protected List<URL> mIconUrls;
+ protected List<String> mIds;
+ private boolean mRadio;
+
+ /**
+ * One or more id for the checked choice(s) that will be check marked.
+ * Can be null. Can be an id not present in the choices map.
+ */
+ protected final String mCurrent;
+
+ private Choices(String id, String title, IMenuCallback callback,
+ List<String> titles, List<URL> iconUrls, List<String> ids, String current,
+ int sortPriority, boolean supportsMultipleNodes) {
+ super(id, title, callback, sortPriority, supportsMultipleNodes);
+ mTitles = titles;
+ mIconUrls = iconUrls;
+ mIds = ids;
+ mCurrent = current;
+ }
+
+ /**
+ * Returns the list of urls to icons to display for each choice, or null
+ *
+ * @return the list of urls to icons to display for each choice, or null
+ */
+ public List<URL> getIconUrls() {
+ return mIconUrls;
+ }
+
+ /**
+ * Returns the list of ids for the menu choices, never null
+ *
+ * @return the list of ids for the menu choices, never null
+ */
+ public List<String> getIds() {
+ return mIds;
+ }
+
+ /**
+ * Returns the titles to be displayed for the menu choices, never null
+ *
+ * @return the titles to be displayed for the menu choices, never null
+ */
+ public List<String> getTitles() {
+ return mTitles;
+ }
+
+ /**
+ * Returns the current value of the choice
+ *
+ * @return the current value of the choice, possibly null
+ */
+ public String getCurrent() {
+ return mCurrent;
+ }
+
+ /**
+ * Set whether this choice list is best visualized as a radio group (instead of a
+ * dropdown)
+ *
+ * @param radio true if this choice list should be visualized as a radio group
+ */
+ public void setRadio(boolean radio) {
+ mRadio = radio;
+ }
+
+ /**
+ * Returns true if this choice list is best visualized as a radio group (instead
+ * of a dropdown)
+ *
+ * @return true if this choice list should be visualized as a radio group
+ */
+ public boolean isRadio() {
+ return mRadio;
+ }
+ }
+
+ /**
+ * An ordered list of actions the user can choose between. Similar to
+ * {@link Choices} but for actions instead.
+ */
+ public static class NestedAction extends RuleAction {
+ /** The provider to produce the list of nested actions when needed */
+ private final ActionProvider mProvider;
+
+ private NestedAction(String id, String title, ActionProvider provider,
+ IMenuCallback callback, int sortPriority,
+ boolean supportsMultipleNodes) {
+ super(id, title, callback, sortPriority, supportsMultipleNodes);
+ mProvider = provider;
+ }
+
+ /**
+ * Returns the nested actions available for the given node
+ *
+ * @param node the node to look up nested actions for
+ * @return a list of nested actions
+ */
+ public List<RuleAction> getNestedActions(INode node) {
+ return mProvider.getNestedActions(node);
+ }
+ }
+
+ /** Like {@link Choices}, but the set of choices is computed lazily */
+ private static class DelayedChoices extends Choices {
+ private final ChoiceProvider mProvider;
+
+ private DelayedChoices(String id, String title,
+ IMenuCallback callback, String current, ChoiceProvider provider,
+ int sortPriority, boolean supportsMultipleNodes) {
+ super(id, title, callback, null, null, null, current, sortPriority,
+ supportsMultipleNodes);
+ mProvider = provider;
+ }
+
+ private void ensureInitialized() {
+ if (mTitles == null) {
+ mTitles = new ArrayList<String>();
+ mIconUrls = new ArrayList<URL>();
+ mIds = new ArrayList<String>();
+
+ mProvider.addChoices(mTitles, mIconUrls, mIds);
+ }
+ }
+
+ @Override
+ public List<URL> getIconUrls() {
+ ensureInitialized();
+ return mIconUrls;
+ }
+
+ @Override
+ public List<String> getIds() {
+ ensureInitialized();
+ return mIds;
+ }
+
+ @Override
+ public List<String> getTitles() {
+ ensureInitialized();
+ return mTitles;
+ }
+ }
+
+ /**
+ * Provides the set of nested action choices associated with a {@link NestedAction}
+ * object when they are needed. Useful for lazy initialization of context
+ * menus and popup menus until they are actually needed.
+ */
+ public interface ActionProvider {
+ /**
+ * Returns the nested actions available for the given node
+ *
+ * @param node the node to look up nested actions for
+ * @return a list of nested actions
+ */
+ public List<RuleAction> getNestedActions(INode node);
+ }
+
+ /**
+ * Provides the set of choices associated with an {@link Choices}
+ * object when they are needed. Useful for lazy initialization of context
+ * menus and popup menus until they are actually needed.
+ */
+ public interface ChoiceProvider {
+ /**
+ * Adds in the needed titles, iconUrls (if any) and ids.
+ * Use {@link RuleAction#SEPARATOR} to create separators.
+ *
+ * @param titles a list of titles that the provider should append to
+ * @param iconUrls a list of icon URLs that the provider should append to
+ * @param ids a list of ids that the provider should append to
+ */
+ public void addChoices(List<String> titles, List<URL> iconUrls, List<String> ids);
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/Segment.java b/rule_api/src/com/android/ide/common/api/Segment.java
new file mode 100644
index 0000000..9668b54
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/Segment.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/**
+ * A segment is a straight horizontal or vertical line between two points, typically an
+ * edge of a node but also possibly some internal segment like a baseline or a center
+ * line, and it can be offset by a margin from the node's visible bounds.
+ */
+public class Segment {
+ /** For horizontal lines, the y coordinate; for vertical lines the x */
+ public final int at;
+
+ /** The starting coordinate along the line */
+ public final int from;
+
+ /** The ending coordinate along the line */
+ public final int to;
+
+ /** Whether the edge is a top edge, a baseline edge, a left edge, etc */
+ public final SegmentType edgeType;
+
+ /**
+ * Whether the edge is offset from the node by a margin or not, or whether it has no
+ * margin
+ */
+ public final MarginType marginType;
+
+ /** The node that contains this edge */
+ public final INode node;
+
+ /**
+ * The id of the node. May be null (in which case id should be generated when
+ * move/resize is completed
+ */
+ public final String id;
+
+ public Segment(int at, int from, int to, INode node, String id, SegmentType edgeType,
+ MarginType marginType) {
+ this.at = at;
+ this.from = from;
+ this.to = to;
+ this.node = node;
+ this.id = id;
+ this.edgeType = edgeType;
+ this.marginType = marginType;
+ }
+
+ @Override
+ public String toString() {
+ String nodeStr = node == null ? "null" : node.getFqcn().substring(
+ node.getFqcn().lastIndexOf(('.')) + 1);
+ return "Segment [edgeType=" + edgeType + ", node=" + nodeStr + ", at=" + at + ", id=" + id
+ + ", from=" + from + ", to=" + to + ", marginType=" + marginType + "]";
+ }
+}
diff --git a/rule_api/src/com/android/ide/common/api/SegmentType.java b/rule_api/src/com/android/ide/common/api/SegmentType.java
new file mode 100644
index 0000000..a21247d
--- /dev/null
+++ b/rule_api/src/com/android/ide/common/api/SegmentType.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.common.api;
+
+/** A segment type describes the different roles or positions a segment can have in a node */
+public enum SegmentType {
+ LEFT, TOP, RIGHT, BOTTOM, BASELINE, CENTER_VERTICAL, CENTER_HORIZONTAL, UNKNOWN;
+
+ public boolean isHorizontal() {
+ return this == TOP || this == BOTTOM || this == BASELINE || this == CENTER_HORIZONTAL;
+ }
+
+ /**
+ * Returns the X coordinate for an edge of this type given its bounds
+ *
+ * @param node the node containing the edge
+ * @param bounds the bounds of the node
+ * @return the X coordinate for an edge of this type given its bounds
+ */
+ public int getX(INode node, Rect bounds) {
+ // We pass in the bounds rather than look it up via node.getBounds() because
+ // during a resize or move operation, we call this method to look up proposed
+ // bounds rather than actual bounds
+ switch (this) {
+ case RIGHT:
+ return bounds.x + bounds.w;
+ case TOP:
+ case BOTTOM:
+ case CENTER_VERTICAL:
+ return bounds.x + bounds.w / 2;
+ case UNKNOWN:
+ assert false;
+ return bounds.x;
+ case LEFT:
+ case BASELINE:
+ default:
+ return bounds.x;
+ }
+ }
+
+ /**
+ * Returns the Y coordinate for an edge of this type given its bounds
+ *
+ * @param node the node containing the edge
+ * @param bounds the bounds of the node
+ * @return the Y coordinate for an edge of this type given its bounds
+ */
+ public int getY(INode node, Rect bounds) {
+ switch (this) {
+ case TOP:
+ return bounds.y;
+ case BOTTOM:
+ return bounds.y + bounds.h;
+ case BASELINE: {
+ int baseline = node != null ? node.getBaseline() : -1;
+ if (node == null) {
+ // This happens when you are dragging an element and we don't have
+ // a node (only an IDragElement) such as on a palette drag.
+ // For now just hack it.
+ baseline = (int) (bounds.h * 0.8f); // HACK
+ }
+ return bounds.y + baseline;
+ }
+ case UNKNOWN:
+ assert false;
+ return bounds.y;
+ case RIGHT:
+ case LEFT:
+ case CENTER_HORIZONTAL:
+ default:
+ return bounds.y + bounds.h / 2;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name();
+ }
+}