mvc run target in community

This commit is contained in:
peter
2011-06-20 16:17:44 +02:00
parent 1687610e45
commit 945e95606a
5 changed files with 514 additions and 0 deletions
@@ -0,0 +1,88 @@
package org.jetbrains.plugins.groovy.mvc;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class MvcActionBase extends DumbAwareAction {
protected abstract void actionPerformed(@NotNull AnActionEvent e, @NotNull Module module, @NotNull MvcFramework framework);
@Override
public final void actionPerformed(AnActionEvent e) {
Pair<MvcFramework, Module> pair = guessFramework(e);
if (pair != null && isSupportFramework(pair.getFirst())) {
actionPerformed(e, pair.getSecond(), pair.getFirst());
}
}
protected boolean isSupportFramework(@NotNull MvcFramework framework) {
return true;
}
@Nullable
public static Pair<MvcFramework, Module> guessFramework(AnActionEvent event) {
final Module module = event.getData(event.getPlace() == ActionPlaces.MAIN_MENU ? DataKeys.MODULE : DataKeys.MODULE_CONTEXT);
if (module != null) {
MvcFramework commonPluginModuleFramework = MvcFramework.findCommonPluginModuleFramework(module);
if (commonPluginModuleFramework != null) {
for (Module mod : ModuleManager.getInstance(module.getProject()).getModules()) {
if (commonPluginModuleFramework.getCommonPluginsModuleName(mod).equals(module.getName())) {
if (commonPluginModuleFramework.hasSupport(mod)) {
return new Pair<MvcFramework, Module>(commonPluginModuleFramework, mod);
}
return null;
}
}
}
MvcFramework framework = MvcModuleStructureSynchronizer.getFramework(module);
if (framework != null) {
return Pair.create(framework, module);
}
}
final Project project = DataKeys.PROJECT.getData(event.getDataContext());
if (project == null) {
return null;
}
Pair<MvcFramework, Module> result = null;
for (Module mod : ModuleManager.getInstance(project).getModules()) {
final MvcFramework framework = MvcModuleStructureSynchronizer.getFramework(mod);
if (framework != null) {
if (result != null) {
return null;
}
result = Pair.create(framework, mod);
}
}
return result;
}
public final void update(AnActionEvent event) {
Pair<MvcFramework, Module> pair = guessFramework(event);
if (pair != null && isSupportFramework(pair.getFirst())) {
event.getPresentation().setVisible(true);
updateView(event, pair.getFirst(), pair.getSecond());
}
else {
event.getPresentation().setVisible(false);
}
}
protected void updateView(AnActionEvent event, @NotNull MvcFramework framework, @NotNull Module module) {
}
}
@@ -0,0 +1,33 @@
package org.jetbrains.plugins.groovy.mvc;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
/**
* @author ilyas
*/
public class MvcRunTarget extends MvcActionBase {
@Override
protected void actionPerformed(@NotNull AnActionEvent e, @NotNull Module module, @NotNull MvcFramework framework) {
MvcRunTargetDialog dialog = new MvcRunTargetDialog(module, framework);
dialog.show();
if (!dialog.isOK()) {
return;
}
Module selectedModule = dialog.getSelectedModule();
String[] targetArgs = dialog.getTargetArguments();
Pair<String, String[]> parsedCmd = MvcFramework.parsedCmd(targetArgs);
ProcessBuilder pb = framework.createCommandAndShowErrors(dialog.getVmOptions(), selectedModule, parsedCmd.first, parsedCmd.second);
if (pb == null) return;
MvcConsole.getInstance(selectedModule.getProject()).executeProcess(selectedModule, pb, null, false);
}
}
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.mvc.MvcRunTargetDialog">
<grid id="cbd77" binding="contentPane" layout-manager="BorderLayout" hgap="10" vgap="10">
<constraints>
<xy x="48" y="54" width="436" height="297"/>
</constraints>
<properties/>
<border type="none">
<font/>
</border>
<children>
<grid id="34d93" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints border-constraint="North"/>
<properties/>
<border type="none"/>
<children>
<component id="5abd7" class="javax.swing.JLabel" binding="myTargetLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Command line:" noi18n="true"/>
</properties>
</component>
<grid id="ca827" binding="myFakePanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="400" height="-1"/>
</grid>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</grid>
<grid id="2a188" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints border-constraint="Center"/>
<properties/>
<border type="etched" title="Options"/>
<children>
<grid id="e3588" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="2805d" class="javax.swing.JLabel" binding="myVmOptionLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="VM parameters:"/>
</properties>
</component>
<component id="8904c" class="javax.swing.JTextField" binding="myVmOptionsField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b107f" class="javax.swing.JLabel" binding="myModuleLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Module:"/>
</properties>
</component>
<component id="cf36f" class="javax.swing.JComboBox" binding="myModuleBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
</children>
</grid>
</form>
@@ -0,0 +1,212 @@
package org.jetbrains.plugins.groovy.mvc;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.TextFieldCompletionProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.mvc.util.ModuleCellRenderer;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MvcRunTargetDialog extends DialogWrapper {
private JPanel contentPane;
private JLabel myTargetLabel;
@SuppressWarnings({"UnusedDeclaration"}) private JPanel myFakePanel;
private JTextField myVmOptionsField;
private JComboBox myModuleBox;
private JLabel myModuleLabel;
private JLabel myVmOptionLabel;
private ComboBox myTargetField;
private Module myModule;
private final MvcFramework myFramework;
private Set<String> myCompletionVariantCache = null;
public MvcRunTargetDialog(@NotNull Module module, MvcFramework framework) {
super(module.getProject(), true);
myModule = module;
myFramework = framework;
setTitle("Run " + framework.getDisplayName() + " target");
setUpDialog();
setModal(true);
init();
}
private void setUpDialog() {
myTargetLabel.setLabelFor(myTargetField);
myTargetField.setFocusable(true);
myVmOptionLabel.setLabelFor(myVmOptionsField);
myVmOptionsField.setText(MvcRunTargetHistoryService.getInstance().getVmOptions());
List<Module> mvcModules = new ArrayList<Module>();
for (Module module : ModuleManager.getInstance(myModule.getProject()).getModules()) {
if (module == myModule || MvcModuleStructureSynchronizer.getFramework(module) != null) {
mvcModules.add(module);
}
}
assert mvcModules.contains(myModule);
myModuleLabel.setLabelFor(myModuleBox);
myModuleBox.setModel(new CollectionComboBoxModel(mvcModules, myModule));
myModuleBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
myModule = (Module)myModuleBox.getSelectedItem();
myCompletionVariantCache = null;
}
});
myModuleBox.setRenderer(new ModuleCellRenderer());
}
@NotNull
public Module getSelectedModule() {
return myModule;
}
@Override
protected void doOKAction() {
super.doOKAction();
MvcRunTargetHistoryService.getInstance().addCommand(getSelectedText(), getVmOptions());
}
public String getVmOptions() {
return myVmOptionsField.getText();
}
public String getSelectedText() {
return (String)myTargetField.getEditor().getItem();
}
public String[] getTargetArguments() {
String text = getSelectedText();
Iterable<String> iterable = StringUtil.tokenize(text, " ");
ArrayList<String> args = new ArrayList<String>();
for (String s : iterable) {
args.add(s);
}
return ArrayUtil.toStringArray(args);
}
protected JComponent createCenterPanel() {
return contentPane;
}
public JComponent getPreferredFocusedComponent() {
return myTargetField;
}
private void createUIComponents() {
myTargetField = new ComboBox(MvcRunTargetHistoryService.getInstance().getHistory(), -1);
myTargetField.setLightWeightPopupEnabled(false);
EditorComboBoxEditor editor = new StringComboboxEditor(myModule.getProject(), PlainTextFileType.INSTANCE, myTargetField);
myTargetField.setRenderer(new EditorComboBoxRenderer(editor));
myTargetField.setEditable(true);
myTargetField.setEditor(editor);
EditorTextField editorTextField = (EditorTextField)editor.getEditorComponent();
myFakePanel = new JPanel(new BorderLayout());
myFakePanel.add(myTargetField, BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@NotNull
@Override
protected String getPrefix(@NotNull String currentTextPrefix) {
return currentTextPrefix.substring(currentTextPrefix.lastIndexOf(' ') + 1);
}
@Override
protected void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, @NotNull CompletionResultSet result) {
if (myCompletionVariantCache == null) {
myCompletionVariantCache = getAllTargetNames(myModule);
}
for (String completionVariant : myCompletionVariantCache) {
result.addElement(LookupElementBuilder.create(completionVariant));
}
}
}.apply(editorTextField);
editorTextField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
setOKActionEnabled(!StringUtil.isEmptyOrSpaces(e.getDocument().getText()));
}
});
setOKActionEnabled(false);
}
private Set<String> getAllTargetNames(@NotNull Module module) {
final Set<String> result = new HashSet<String>();
MvcFramework.addAvailableSystemScripts(result, module);
final VirtualFile root = myFramework.findAppRoot(module);
if (root != null) {
MvcFramework.addAvailableScripts(result, root);
}
for (VirtualFile pluginRoot : myFramework.getAllPluginRoots(module, false)) {
MvcFramework.addAvailableScripts(result, pluginRoot);
}
addScriptsFromUserHome(result);
return result;
}
private static void addScriptsFromUserHome(Set<String> result) {
String userHome = SystemProperties.getUserHome();
if (userHome == null) return;
File scriptFolder = new File(userHome, ".grails/scripts");
File[] files = scriptFolder.listFiles();
if (files == null) return;
for (File file : files) {
if (isScriptFile(file)) {
String name = file.getName();
int idx = name.lastIndexOf('.');
if (idx != -1) {
name = name.substring(0, idx);
}
result.add(GroovyNamesUtil.camelToSnake(name));
}
}
}
public static boolean isScriptFile(File file) {
return file.isFile() && MvcFramework.isScriptFileName(file.getName());
}
}
@@ -0,0 +1,92 @@
package org.jetbrains.plugins.groovy.mvc;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.LinkedList;
/**
* @author Sergey Evdokimov
*/
@State(
name = "mvcRunTargetHistory",
storages = @Storage(
id ="other",
file = "$APP_CONFIG$/other.xml"
)
)
public class MvcRunTargetHistoryService implements PersistentStateComponent<String[]> {
private static final int MAX_HISTORY_LENGTH = 20;
private final LinkedList<String> myHistory = new LinkedList<String>();
private String myVmOptions = "";
@Override
public String[] getState() {
synchronized (myHistory) {
String[] res = new String[myHistory.size() + 1];
res[0] = '#' + myVmOptions;
int i = 1;
for (String s : myHistory) {
res[i++] = s;
}
return res;
}
}
@NotNull
public String getVmOptions() {
synchronized (myHistory) {
return myVmOptions;
}
}
@Override
public void loadState(String[] state) {
synchronized (myHistory) {
myHistory.clear();
int start = 0;
if (state.length > 0 && state[0].charAt(0) == '#') {
myVmOptions = state[0].substring(1);
start = 1;
}
else {
myVmOptions = "";
}
for (int i = start; i < state.length; i++) {
myHistory.add(state[i]);
}
}
}
public String[] getHistory() {
synchronized (myHistory) {
return ArrayUtil.toStringArray(myHistory);
}
}
public static MvcRunTargetHistoryService getInstance() {
return ServiceManager.getService(MvcRunTargetHistoryService.class);
}
public void addCommand(@NotNull String command, @NotNull String vmOptions) {
synchronized (myHistory) {
myVmOptions = vmOptions;
myHistory.remove(command);
myHistory.addFirst(command);
if (myHistory.size() > MAX_HISTORY_LENGTH) {
myHistory.removeLast();
}
}
}
}