blob: 388907a466bfb727f0c288caa8dd3e88295c74c1 [file] [log] [blame]
/*
* 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.eclipse.adt.internal.editors.layout.gre;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.AUTO_URI;
import static com.android.SdkConstants.CLASS_FRAGMENT;
import static com.android.SdkConstants.CLASS_V4_FRAGMENT;
import static com.android.SdkConstants.CLASS_VIEW;
import static com.android.SdkConstants.NEW_ID_PREFIX;
import static com.android.SdkConstants.URI_PREFIX;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.api.IClientRulesEngine;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.IValidator;
import com.android.ide.common.api.IViewMetadata;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.common.layout.BaseViewRule;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutCanvas;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionManager;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.refactorings.core.RenameResult;
import com.android.ide.eclipse.adt.internal.resources.CyclicDependencyValidator;
import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.ui.MarginChooser;
import com.android.ide.eclipse.adt.internal.ui.ReferenceChooserDialog;
import com.android.ide.eclipse.adt.internal.ui.ResourceChooser;
import com.android.ide.eclipse.adt.internal.ui.ResourcePreviewHelper;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.actions.OpenNewClassWizardAction;
import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension;
import org.eclipse.jdt.ui.dialogs.ITypeInfoRequestor;
import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;
import org.eclipse.jdt.ui.wizards.NewClassWizardPage;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* Implementation of {@link IClientRulesEngine}. This provides {@link IViewRule} clients
* with a few methods they can use to access functionality from this {@link RulesEngine}.
*/
class ClientRulesEngine implements IClientRulesEngine {
/** The return code from the dialog for the user choosing "Clear" */
public static final int CLEAR_RETURN_CODE = -5;
/** The dialog button ID for the user choosing "Clear" */
private static final int CLEAR_BUTTON_ID = CLEAR_RETURN_CODE;
private final RulesEngine mRulesEngine;
private final String mFqcn;
public ClientRulesEngine(RulesEngine rulesEngine, String fqcn) {
mRulesEngine = rulesEngine;
mFqcn = fqcn;
}
@Override
public @NonNull String getFqcn() {
return mFqcn;
}
@Override
public void debugPrintf(@NonNull String msg, Object... params) {
AdtPlugin.printToConsole(
mFqcn == null ? "<unknown>" : mFqcn,
String.format(msg, params)
);
}
@Override
public IViewRule loadRule(@NonNull String fqcn) {
return mRulesEngine.loadRule(fqcn, fqcn);
}
@Override
public void displayAlert(@NonNull String message) {
MessageDialog.openInformation(
AdtPlugin.getShell(),
mFqcn, // title
message);
}
@Override
public boolean rename(INode node) {
GraphicalEditorPart editor = mRulesEngine.getEditor();
SelectionManager manager = editor.getCanvasControl().getSelectionManager();
RenameResult result = manager.performRename(node, null);
return !result.isCanceled() && !result.isUnavailable();
}
@Override
public String displayInput(@NonNull String message, @Nullable String value,
final @Nullable IValidator filter) {
IInputValidator validator = null;
if (filter != null) {
validator = new IInputValidator() {
@Override
public String isValid(String newText) {
// IValidator has the same interface as SWT's IInputValidator
try {
return filter.validate(newText);
} catch (Exception e) {
AdtPlugin.log(e, "Custom validator failed: %s", e.toString());
return ""; //$NON-NLS-1$
}
}
};
}
InputDialog d = new InputDialog(
AdtPlugin.getShell(),
mFqcn, // title
message,
value == null ? "" : value, //$NON-NLS-1$
validator) {
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, CLEAR_BUTTON_ID, "Clear", false /*defaultButton*/);
super.createButtonsForButtonBar(parent);
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
if (buttonId == CLEAR_BUTTON_ID) {
assert CLEAR_RETURN_CODE != Window.OK && CLEAR_RETURN_CODE != Window.CANCEL;
setReturnCode(CLEAR_RETURN_CODE);
close();
}
}
};
int result = d.open();
if (result == ResourceChooser.CLEAR_RETURN_CODE) {
return "";
} else if (result == Window.OK) {
return d.getValue();
}
return null;
}
@Override
@Nullable
public Object getViewObject(@NonNull INode node) {
ViewHierarchy views = mRulesEngine.getEditor().getCanvasControl().getViewHierarchy();
CanvasViewInfo vi = views.findViewInfoFor(node);
if (vi != null) {
return vi.getViewObject();
}
return null;
}
@Override
public @NonNull IViewMetadata getMetadata(final @NonNull String fqcn) {
return new IViewMetadata() {
@Override
public @NonNull String getDisplayName() {
// This also works when there is no "."
return fqcn.substring(fqcn.lastIndexOf('.') + 1);
}
@Override
public @NonNull FillPreference getFillPreference() {
return ViewMetadataRepository.get().getFillPreference(fqcn);
}
@Override
public @NonNull Margins getInsets() {
return mRulesEngine.getEditor().getCanvasControl().getInsets(fqcn);
}
@Override
public @NonNull List<String> getTopAttributes() {
return ViewMetadataRepository.get().getTopAttributes(fqcn);
}
};
}
@Override
public int getMinApiLevel() {
Sdk currentSdk = Sdk.getCurrent();
if (currentSdk != null) {
IAndroidTarget target = currentSdk.getTarget(mRulesEngine.getEditor().getProject());
if (target != null) {
return target.getVersion().getApiLevel();
}
}
return -1;
}
@Override
public IValidator getResourceValidator(
@NonNull final String resourceTypeName, final boolean uniqueInProject,
final boolean uniqueInLayout, final boolean exists, final String... allowed) {
return new IValidator() {
private ResourceNameValidator mValidator;
@Override
public String validate(@NonNull String text) {
if (mValidator == null) {
ResourceType type = ResourceType.getEnum(resourceTypeName);
if (uniqueInLayout) {
assert !uniqueInProject;
assert !exists;
Set<String> existing = new HashSet<String>();
Document doc = mRulesEngine.getEditor().getModel().getXmlDocument();
if (doc != null) {
addIds(doc, existing);
}
for (String s : allowed) {
existing.remove(s);
}
mValidator = ResourceNameValidator.create(false, existing, type);
} else {
assert allowed.length == 0;
IProject project = mRulesEngine.getEditor().getProject();
mValidator = ResourceNameValidator.create(false, project, type);
if (uniqueInProject) {
mValidator.unique();
}
}
if (exists) {
mValidator.exist();
}
}
return mValidator.isValid(text);
}
};
}
/** Find declared ids under the given DOM node */
private static void addIds(Node node, Set<String> ids) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
if (id != null && id.startsWith(NEW_ID_PREFIX)) {
ids.add(BaseViewRule.stripIdPrefix(id));
}
}
NodeList children = node.getChildNodes();
for (int i = 0, n = children.getLength(); i < n; i++) {
Node child = children.item(i);
addIds(child, ids);
}
}
@Override
public String displayReferenceInput(@Nullable String currentValue) {
GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor();
LayoutEditorDelegate delegate = graphicalEditor.getEditorDelegate();
IProject project = delegate.getEditor().getProject();
if (project != null) {
// get the resource repository for this project and the system resources.
ResourceRepository projectRepository =
ResourceManager.getInstance().getProjectResources(project);
Shell shell = AdtPlugin.getShell();
if (shell == null) {
return null;
}
ReferenceChooserDialog dlg = new ReferenceChooserDialog(
project,
projectRepository,
shell);
dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor));
dlg.setCurrentResource(currentValue);
if (dlg.open() == Window.OK) {
return dlg.getCurrentResource();
}
}
return null;
}
@Override
public String displayResourceInput(@NonNull String resourceTypeName,
@Nullable String currentValue) {
return displayResourceInput(resourceTypeName, currentValue, null);
}
private String displayResourceInput(String resourceTypeName, String currentValue,
IInputValidator validator) {
ResourceType type = ResourceType.getEnum(resourceTypeName);
GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor();
return ResourceChooser.chooseResource(graphicalEditor, type, currentValue, validator);
}
@Override
public String[] displayMarginInput(@Nullable String all, @Nullable String left,
@Nullable String right, @Nullable String top, @Nullable String bottom) {
GraphicalEditorPart editor = mRulesEngine.getEditor();
IProject project = editor.getProject();
if (project != null) {
Shell shell = AdtPlugin.getShell();
if (shell == null) {
return null;
}
AndroidTargetData data = editor.getEditorDelegate().getEditor().getTargetData();
MarginChooser dialog = new MarginChooser(shell, editor, data, all, left, right,
top, bottom);
if (dialog.open() == Window.OK) {
return dialog.getMargins();
}
}
return null;
}
@Override
public String displayIncludeSourceInput() {
AndroidXmlEditor editor = mRulesEngine.getEditor().getEditorDelegate().getEditor();
IInputValidator validator = CyclicDependencyValidator.create(editor.getInputFile());
return displayResourceInput(ResourceType.LAYOUT.getName(), null, validator);
}
@Override
public void select(final @NonNull Collection<INode> nodes) {
LayoutCanvas layoutCanvas = mRulesEngine.getEditor().getCanvasControl();
final SelectionManager selectionManager = layoutCanvas.getSelectionManager();
selectionManager.select(nodes);
// ALSO run an async select since immediately after nodes are created they
// may not be selectable. We can't ONLY run an async exec since
// code may depend on operating on the selection.
layoutCanvas.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
selectionManager.select(nodes);
}
});
}
@Override
public String displayFragmentSourceInput() {
try {
// Compute a search scope: We need to merge all the subclasses
// android.app.Fragment and android.support.v4.app.Fragment
IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
IProject project = mRulesEngine.getProject();
final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
if (javaProject != null) {
IType oldFragmentType = javaProject.findType(CLASS_V4_FRAGMENT);
// First check to make sure fragments are available, and if not,
// warn the user.
IAndroidTarget target = Sdk.getCurrent().getTarget(project);
// No, this should be using the min SDK instead!
if (target.getVersion().getApiLevel() < 11 && oldFragmentType == null) {
// Compatibility library must be present
MessageDialog dialog =
new MessageDialog(
Display.getCurrent().getActiveShell(),
"Fragment Warning",
null,
"Fragments require API level 11 or higher, or a compatibility "
+ "library for older versions.\n\n"
+ " Do you want to install the compatibility library?",
MessageDialog.QUESTION,
new String[] { "Install", "Cancel" },
1 /* default button: Cancel */);
int answer = dialog.open();
if (answer == 0) {
if (!AddSupportJarAction.install(project)) {
return null;
}
} else {
return null;
}
}
// Look up sub-types of each (new fragment class and compatibility fragment
// class, if any) and merge the two arrays - then create a scope from these
// elements.
IType[] fragmentTypes = new IType[0];
IType[] oldFragmentTypes = new IType[0];
if (oldFragmentType != null) {
ITypeHierarchy hierarchy =
oldFragmentType.newTypeHierarchy(new NullProgressMonitor());
oldFragmentTypes = hierarchy.getAllSubtypes(oldFragmentType);
}
IType fragmentType = javaProject.findType(CLASS_FRAGMENT);
if (fragmentType != null) {
ITypeHierarchy hierarchy =
fragmentType.newTypeHierarchy(new NullProgressMonitor());
fragmentTypes = hierarchy.getAllSubtypes(fragmentType);
}
IType[] subTypes = new IType[fragmentTypes.length + oldFragmentTypes.length];
System.arraycopy(fragmentTypes, 0, subTypes, 0, fragmentTypes.length);
System.arraycopy(oldFragmentTypes, 0, subTypes, fragmentTypes.length,
oldFragmentTypes.length);
scope = SearchEngine.createJavaSearchScope(subTypes, IJavaSearchScope.SOURCES);
}
Shell parent = AdtPlugin.getShell();
final AtomicReference<String> returnValue =
new AtomicReference<String>();
final AtomicReference<SelectionDialog> dialogHolder =
new AtomicReference<SelectionDialog>();
final SelectionDialog dialog = JavaUI.createTypeDialog(
parent,
new ProgressMonitorDialog(parent),
scope,
IJavaElementSearchConstants.CONSIDER_CLASSES, false,
// Use ? as a default filter to fill dialog with matches
"?", //$NON-NLS-1$
new TypeSelectionExtension() {
@Override
public Control createContentArea(Composite parentComposite) {
Composite composite = new Composite(parentComposite, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
Button button = new Button(composite, SWT.PUSH);
button.setText("Create New...");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String fqcn = createNewFragmentClass(javaProject);
if (fqcn != null) {
returnValue.set(fqcn);
dialogHolder.get().close();
}
}
});
return composite;
}
@Override
public ITypeInfoFilterExtension getFilterExtension() {
return new ITypeInfoFilterExtension() {
@Override
public boolean select(ITypeInfoRequestor typeInfoRequestor) {
int modifiers = typeInfoRequestor.getModifiers();
if (!Flags.isPublic(modifiers)
|| Flags.isInterface(modifiers)
|| Flags.isEnum(modifiers)
|| Flags.isAbstract(modifiers)) {
return false;
}
return true;
}
};
}
});
dialogHolder.set(dialog);
dialog.setTitle("Choose Fragment Class");
dialog.setMessage("Select a Fragment class (? = any character, * = any string):");
if (dialog.open() == IDialogConstants.CANCEL_ID) {
return null;
}
if (returnValue.get() != null) {
return returnValue.get();
}
Object[] types = dialog.getResult();
if (types != null && types.length > 0) {
return ((IType) types[0]).getFullyQualifiedName();
}
} catch (JavaModelException e) {
AdtPlugin.log(e, null);
} catch (CoreException e) {
AdtPlugin.log(e, null);
}
return null;
}
@Override
public String displayCustomViewClassInput() {
try {
IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
IProject project = mRulesEngine.getProject();
final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
if (javaProject != null) {
// Look up sub-types of each (new fragment class and compatibility fragment
// class, if any) and merge the two arrays - then create a scope from these
// elements.
IType[] viewTypes = new IType[0];
IType fragmentType = javaProject.findType(CLASS_VIEW);
if (fragmentType != null) {
ITypeHierarchy hierarchy =
fragmentType.newTypeHierarchy(new NullProgressMonitor());
viewTypes = hierarchy.getAllSubtypes(fragmentType);
}
scope = SearchEngine.createJavaSearchScope(viewTypes, IJavaSearchScope.SOURCES);
}
Shell parent = AdtPlugin.getShell();
final AtomicReference<String> returnValue =
new AtomicReference<String>();
final AtomicReference<SelectionDialog> dialogHolder =
new AtomicReference<SelectionDialog>();
final SelectionDialog dialog = JavaUI.createTypeDialog(
parent,
new ProgressMonitorDialog(parent),
scope,
IJavaElementSearchConstants.CONSIDER_CLASSES, false,
// Use ? as a default filter to fill dialog with matches
"?", //$NON-NLS-1$
new TypeSelectionExtension() {
@Override
public Control createContentArea(Composite parentComposite) {
Composite composite = new Composite(parentComposite, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
Button button = new Button(composite, SWT.PUSH);
button.setText("Create New...");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String fqcn = createNewCustomViewClass(javaProject);
if (fqcn != null) {
returnValue.set(fqcn);
dialogHolder.get().close();
}
}
});
return composite;
}
@Override
public ITypeInfoFilterExtension getFilterExtension() {
return new ITypeInfoFilterExtension() {
@Override
public boolean select(ITypeInfoRequestor typeInfoRequestor) {
int modifiers = typeInfoRequestor.getModifiers();
if (!Flags.isPublic(modifiers)
|| Flags.isInterface(modifiers)
|| Flags.isEnum(modifiers)
|| Flags.isAbstract(modifiers)) {
return false;
}
return true;
}
};
}
});
dialogHolder.set(dialog);
dialog.setTitle("Choose Custom View Class");
dialog.setMessage("Select a Custom View class (? = any character, * = any string):");
if (dialog.open() == IDialogConstants.CANCEL_ID) {
return null;
}
if (returnValue.get() != null) {
return returnValue.get();
}
Object[] types = dialog.getResult();
if (types != null && types.length > 0) {
return ((IType) types[0]).getFullyQualifiedName();
}
} catch (JavaModelException e) {
AdtPlugin.log(e, null);
} catch (CoreException e) {
AdtPlugin.log(e, null);
}
return null;
}
@Override
public void redraw() {
mRulesEngine.getEditor().getCanvasControl().redraw();
}
@Override
public void layout() {
mRulesEngine.getEditor().recomputeLayout();
}
@Override
public Map<INode, Rect> measureChildren(@NonNull INode parent,
@Nullable IClientRulesEngine.AttributeFilter filter) {
RenderService renderService = RenderService.create(mRulesEngine.getEditor());
Map<INode, Rect> map = renderService.measureChildren(parent, filter);
if (map == null) {
map = Collections.emptyMap();
}
return map;
}
@Override
public int pxToDp(int px) {
ConfigurationChooser chooser = mRulesEngine.getEditor().getConfigurationChooser();
float dpi = chooser.getConfiguration().getDensity().getDpiValue();
return (int) (px * 160 / dpi);
}
@Override
public int dpToPx(int dp) {
ConfigurationChooser chooser = mRulesEngine.getEditor().getConfigurationChooser();
float dpi = chooser.getConfiguration().getDensity().getDpiValue();
return (int) (dp * dpi / 160);
}
@Override
public int screenToLayout(int pixels) {
return (int) (pixels / mRulesEngine.getEditor().getCanvasControl().getScale());
}
private String createNewFragmentClass(IJavaProject javaProject) {
NewClassWizardPage page = new NewClassWizardPage();
IProject project = mRulesEngine.getProject();
Sdk sdk = Sdk.getCurrent();
if (sdk == null) {
return null;
}
IAndroidTarget target = sdk.getTarget(project);
String superClass;
if (target == null || target.getVersion().getApiLevel() < 11) {
superClass = CLASS_V4_FRAGMENT;
} else {
superClass = CLASS_FRAGMENT;
}
page.setSuperClass(superClass, true /* canBeModified */);
IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject);
if (root != null) {
page.setPackageFragmentRoot(root, true /* canBeModified */);
}
ManifestInfo manifestInfo = ManifestInfo.get(project);
IPackageFragment pkg = manifestInfo.getPackageFragment();
if (pkg != null) {
page.setPackageFragment(pkg, true /* canBeModified */);
}
OpenNewClassWizardAction action = new OpenNewClassWizardAction();
action.setConfiguredWizardPage(page);
action.run();
IType createdType = page.getCreatedType();
if (createdType != null) {
return createdType.getFullyQualifiedName();
} else {
return null;
}
}
private String createNewCustomViewClass(IJavaProject javaProject) {
NewClassWizardPage page = new NewClassWizardPage();
IProject project = mRulesEngine.getProject();
String superClass = CLASS_VIEW;
page.setSuperClass(superClass, true /* canBeModified */);
IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject);
if (root != null) {
page.setPackageFragmentRoot(root, true /* canBeModified */);
}
ManifestInfo manifestInfo = ManifestInfo.get(project);
IPackageFragment pkg = manifestInfo.getPackageFragment();
if (pkg != null) {
page.setPackageFragment(pkg, true /* canBeModified */);
}
OpenNewClassWizardAction action = new OpenNewClassWizardAction();
action.setConfiguredWizardPage(page);
action.run();
IType createdType = page.getCreatedType();
if (createdType != null) {
return createdType.getFullyQualifiedName();
} else {
return null;
}
}
@Override
public @NonNull String getUniqueId(@NonNull String fqcn) {
UiDocumentNode root = mRulesEngine.getEditor().getModel();
String prefix = fqcn.substring(fqcn.lastIndexOf('.') + 1);
prefix = Character.toLowerCase(prefix.charAt(0)) + prefix.substring(1);
return DescriptorsUtils.getFreeWidgetId(root, prefix);
}
@Override
public @NonNull String getAppNameSpace() {
IProject project = mRulesEngine.getEditor().getProject();
ProjectState projectState = Sdk.getProjectState(project);
if (projectState != null && projectState.isLibrary()) {
return AUTO_URI;
}
ManifestInfo info = ManifestInfo.get(project);
return URI_PREFIX + info.getPackage();
}
}