public boolean onInitialize(String fqcn) {
// This base rule can handle any class.
mFqcn = fqcn
+
+ // For debugging and as an example of how to use the injected _rules_engine property.
+ _rules_engine.debugPrintf("Initialize() of %s", _rules_engine.getFqcn());
+
return true;
}
--- /dev/null
+/*
+ * 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.eclipse.adt.editors.layout.gscripts;
+
+
+
+/**
+ * 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. Rules can access it via
+ * the property "_rules_engine" which is dynamically added to {@link IViewRule}
+ * instances on creation.
+ *
+ * @see IViewRule#RULES_ENGINE
+ */
+public interface IClientRulesEngine {
+
+ /**
+ * Returns the FQCN for which the rule was loaded.
+ */
+ 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);
+}
+
// -----------
- /** TODO: this is a hack. Shouldn't be here but instead part of some kind of helper
- * given to IViewRule implementations.
- */
- void debugPrintf(String msg, Object...params);
-
- // -----------
-
/**
* An XML attribute in an {@link INode}.
* <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/>
+ * When rules are instantiated, a property "_rules_engine" is dynamically added which references
+ * the {@link IClientRulesEngine} created for this rule.
*/
public interface IViewRule {
/**
+ * The name of the property that returns a {@link IClientRulesEngine} created for this
+ * rules. The instance lets rules use some methods from the rules engine, for example
+ * for accessing other rules.
+ */
+ final static String RULES_ENGINE = "_rules_engine";
+
+ /**
* This method is called by the rule engine when the script is first loaded.
* It gives the rule a chance to initialize itself.
*
}
}
- public void debugPrintf(String msg, Object...params) {
- AdtPlugin.printToConsole(
- mNode == null ? "Groovy" : mNode.getDescriptor().getXmlLocalName() + ".groovy",
- String.format(msg, params)
- );
- }
-
public Rect getBounds() {
return mBounds;
}
return null;
}
+ private void debugPrintf(String msg, Object...params) {
+ AdtPlugin.printToConsole(
+ mNode == null ? "Groovy" : mNode.getDescriptor().getXmlLocalName() + ".groovy",
+ String.format(msg, params)
+ );
+ }
+
}
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.editors.layout.gscripts.DropFeedback;
+import com.android.ide.eclipse.adt.editors.layout.gscripts.IClientRulesEngine;
import com.android.ide.eclipse.adt.editors.layout.gscripts.IDragElement;
import com.android.ide.eclipse.adt.editors.layout.gscripts.IGraphics;
import com.android.ide.eclipse.adt.editors.layout.gscripts.INode;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
+import groovy.lang.ExpandoMetaClass;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
+import groovy.lang.GroovyObject;
import groovy.lang.GroovyResourceLoader;
import java.io.InputStream;
private IViewRule initializeRule(IViewRule rule, String targetFqcn) {
try {
+ if (rule instanceof GroovyObject) {
+ initializeMetaClass((GroovyObject) rule, targetFqcn);
+ }
+
if (rule.onInitialize(targetFqcn)) {
// Add it to the cache and return it
mRulesCache.put(targetFqcn, rule);
}
/**
+ * Initializes a custom meta class for the given {@link GroovyObject}.
+ * This is used to add a meta "_rules_engine" property to the {@link IViewRule} instances.
+ *
+ * @param instance The {@link IViewRule} groovy object to modify.
+ * @param targetFqcn The FQCN for the new {@link IClientRulesEngine}.
+ */
+ private void initializeMetaClass(GroovyObject instance, final String targetFqcn) {
+
+ final ClientRulesEngineImpl mClient = new ClientRulesEngineImpl(targetFqcn);
+
+ ExpandoMetaClass mc = new ExpandoMetaClass(instance.getClass(), false) {
+ @Override
+ public Object getProperty(Object object, String name) {
+ if (IViewRule.RULES_ENGINE.equals(name)) {
+ return mClient;
+ }
+ return super.getProperty(object, name);
+ }
+ };
+ mc.initialize();
+
+ instance.setMetaClass(mc);
+ }
+
+ /**
* Actually load a groovy script and instantiate an {@link IViewRule} from it.
* On error, outputs (hopefully meaningful) groovy error messages.
*
}
}
+ /**
+ * Implementation of {@link IClientRulesEngine}. This provide {@link IViewRule} clients
+ * with a few methods they can use to use functionality from this {@link RulesEngine}.
+ */
+ private class ClientRulesEngineImpl implements IClientRulesEngine {
+
+ private final String mFqcn;
+
+ public ClientRulesEngineImpl(String fqcn) {
+ mFqcn = fqcn;
+ }
+
+ public String getFqcn() {
+ return mFqcn;
+ }
+
+ public void debugPrintf(String msg, Object... params) {
+ AdtPlugin.printToConsole(
+ mFqcn == null ? "Groovy" : mFqcn,
+ String.format(msg, params)
+ );
+ }
+
+ public IViewRule loadRule(String fqcn) {
+ return RulesEngine.this.loadRule(fqcn, fqcn);
+ }
+ }
+
}