Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Maxim Medvedev
2011-02-04 12:15:40 +03:00
23 changed files with 140 additions and 1394 deletions
+7 -2
View File
@@ -7,11 +7,15 @@ class LibraryLicense {
List<LibraryLicense> licensesList = []
List<String> jetbrainsLibraries = ["tcServiceMessages"]
Map<String, String> predefinedLicenseUrls = ["Apache 2.0": "http://www.apache.org/licenses/LICENSE-2.0"]
binding.setVariable("libraryLicense", {Map args ->
if (args.libraryName == null) {
args.libraryName = args.name;
}
if (args.licenseUrl == null) {
args.licenseUrl = predefinedLicenseUrls[args.license]
}
licensesList << new LibraryLicense(args)
})
@@ -84,7 +88,7 @@ binding.setVariable("generateLicensesTable", {String filePath ->
def license = lib.licenseUrl != null ? "[$lib.license|$lib.licenseUrl]" : lib.license
return "|$name| $lib.version|$license|".toString()
}
lines.sort {String.CASE_INSENSITIVE_ORDER}
lines.sort(String.CASE_INSENSITIVE_ORDER)
FileWriter out = new FileWriter(filePath)
out.println("|| Software || Version || License ||")
@@ -108,7 +112,8 @@ libraryLicense(name: "Automaton", libraryName: "automaton.jar", version: "1.11",
libraryLicense(name: "DTDParser", version: "1.13", license: "LGPL", url: "http://sourceforge.net/projects/dtdparser/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1")
libraryLicense(name: "Ganymed", version: "bundled with SVNKit", license: "BSD", url: "http://www.ganymed.ethz.ch/ssh2/", licenseUrl: "http://www.ganymed.ethz.ch/ssh2/LICENSE.txt")
libraryLicense(name: "Guava", version: "R6", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html")
libraryLicense(name: "Groovy", version: "1.7.3", license: "Apache 2.0", url: "http://groovy.codehaus.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.html")
libraryLicense(name: "Gradle API", libraryName: "gradle-open-api-0.8.jar", version: "0.8", license: "Apache 2.0", url: "http://www.gradle.org/")
libraryLicense(name: "Groovy", version: "1.7.3", license: "Apache 2.0", url: "http://groovy.codehaus.org/")
libraryLicense(name: "JavaCVS", version: "no version number available (with patches by JetBrains)", license: "Sun Public License", url: "http://javacvs.netbeans.org/library/", licenseUrl: "http://www.netbeans.org/about/legal/spl.html")
libraryLicense(name: "Jaxen", version: "", license: "modified Apache", url: "http://www.jaxen.org/", licenseUrl: "http://www.jaxen.org/license.html")
libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as license/javahelp_license.html in IntelliJ IDEA distribution", url: "http://java.sun.com/products/javahelp/")
@@ -64,10 +64,19 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent {
super();
myProject = project;
myProjectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
MasterDetailsStateService.getInstance(project).register("ProjectJDKs.UI", this);
initTree();
}
@Override
protected String getComponentStateKey() {
return "ProjectJDKs.UI";
}
@Override
protected MasterDetailsStateService getStateService() {
return MasterDetailsStateService.getInstance(myProject);
}
protected void initTree() {
super.initTree();
new TreeSpeedSearch(myTree, new Convertor<TreePath, String>() {
@@ -34,7 +34,6 @@ import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorLi
import com.intellij.openapi.roots.ui.configuration.projectRoot.*;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.MasterDetailsState;
import com.intellij.openapi.ui.MasterDetailsStateService;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.packaging.artifacts.*;
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
@@ -61,7 +60,11 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
public ArtifactsStructureConfigurable(@NotNull Project project) {
super(project, new ArtifactStructureConfigurableState());
MasterDetailsStateService.getInstance(project).register("ArtifactsStructureConfigurable.UI", this);
}
@Override
protected String getComponentStateKey() {
return "ArtifactsStructureConfigurable.UI";
}
public void init(StructureConfigurableContext context, ModuleStructureConfigurable moduleStructureConfigurable,
@@ -160,7 +163,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
}
@Override
public MasterDetailsState getState() {
protected MasterDetailsState getState() {
((ArtifactStructureConfigurableState)myState).setDefaultArtifactSettings(myDefaultSettings.getState());
return super.getState();
}
@@ -209,6 +212,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
@Override
public void reset() {
loadComponentState();
myPackagingEditorContext.resetModifiableModel();
super.reset();
}
@@ -32,6 +32,7 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.MasterDetailsState;
import com.intellij.openapi.ui.MasterDetailsStateService;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Condition;
@@ -100,6 +101,10 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
});
}
@Override
protected MasterDetailsStateService getStateService() {
return MasterDetailsStateService.getInstance(myProject);
}
public ActionCallback navigateTo(@Nullable final Place place, final boolean requestFocus) {
if (place == null) return new ActionCallback.Done();
@@ -37,7 +37,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.MasterDetailsStateService;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
@@ -59,10 +58,14 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
public FacetStructureConfigurable(final Project project, ModuleManager moduleManager) {
super(project);
MasterDetailsStateService.getInstance(project).register("FacetStructureConfigurable.UI", this);
myModuleManager = moduleManager;
}
@Override
protected String getComponentStateKey() {
return "FacetStructureConfigurable.UI";
}
public static FacetStructureConfigurable getInstance(final @NotNull Project project) {
return ServiceManager.getService(project, FacetStructureConfigurable.class);
}
@@ -19,7 +19,6 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.ui.MasterDetailsStateService;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -31,10 +30,14 @@ public class GlobalLibrariesConfigurable extends BaseLibrariesConfigurable {
public GlobalLibrariesConfigurable(final Project project) {
super(project);
MasterDetailsStateService.getInstance(project).register("GlobalLibrariesConfigurable.UI", this);
myLevel = LibraryTablesRegistrar.APPLICATION_LEVEL;
}
@Override
protected String getComponentStateKey() {
return "GlobalLibrariesConfigurable.UI";
}
@Nls
public String getDisplayName() {
return "Global Libraries";
@@ -30,7 +30,6 @@ import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.MasterDetailsStateService;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nls;
@@ -75,10 +74,15 @@ public class JdkListConfigurable extends BaseStructureConfigurable {
public JdkListConfigurable(final Project project, ProjectStructureConfigurable root) {
super(project);
MasterDetailsStateService.getInstance(project).register("JdkListConfigurable.UI", this);
myJdksTreeModel = root.getProjectJdksModel();
myJdksTreeModel.addListener(myListener);
}
@Override
protected String getComponentStateKey() {
return "JdkListConfigurable.UI";
}
protected void processRemovedItems() {
}
@@ -50,7 +50,6 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProj
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MasterDetailsStateService;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.Comparing;
@@ -96,10 +95,13 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
public ModuleStructureConfigurable(Project project, ModuleManager manager) {
super(project);
MasterDetailsStateService.getInstance(project).register("ModuleStructureConfigurable.UI", this);
myModuleManager = manager;
}
@Override
protected String getComponentStateKey() {
return "ModuleStructureConfigurable.UI";
}
protected void initTree() {
super.initTree();
@@ -19,7 +19,6 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.ui.MasterDetailsStateService;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,10 +29,14 @@ import javax.swing.*;
public class ProjectLibrariesConfigurable extends BaseLibrariesConfigurable {
public ProjectLibrariesConfigurable(final Project project) {
super(project);
MasterDetailsStateService.getInstance(project).register("ProjectLibrariesConfigurable.UI", this);
myLevel = LibraryTablesRegistrar.PROJECT_LEVEL;
}
@Override
protected String getComponentStateKey() {
return "ProjectLibrariesConfigurable.UI";
}
@Nls
public String getDisplayName() {
return "Libraries";
@@ -61,6 +61,7 @@ import java.util.*;
public class ScopeChooserConfigurable extends MasterDetailsComponent implements NonDefaultProjectConfigurable, SearchableConfigurable {
private static final Icon SCOPES = IconLoader.getIcon("/ide/scopeConfigurable.png");
private static final Icon SAVE_ICON = IconLoader.getIcon("/runConfigurations/saveTempConfig.png");
@NonNls public static final String SCOPE_CHOOSER_CONFIGURABLE_UI_KEY = "ScopeChooserConfigurable.UI";
private final NamedScopesHolder myLocalScopesManager;
private final NamedScopesHolder mySharedScopesManager;
@@ -81,10 +82,19 @@ public class ScopeChooserConfigurable extends MasterDetailsComponent implements
mySharedScopesManager = DependencyValidationManager.getInstance(project);
myProject = project;
MasterDetailsStateService.getInstance(project).register("ScopeChooserConfigurable.UI", this);
initTree();
}
@Override
protected String getComponentStateKey() {
return SCOPE_CHOOSER_CONFIGURABLE_UI_KEY;
}
@Override
protected MasterDetailsStateService getStateService() {
return MasterDetailsStateService.getInstance(myProject);
}
protected ArrayList<AnAction> createActions(final boolean fromPopup) {
final ArrayList<AnAction> result = new ArrayList<AnAction>();
result.add(new MyAddAction(fromPopup));
@@ -323,6 +323,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected abstract boolean wasObjectStored(Object editableObject);
public void reset() {
loadComponentState();
myHasDeletedItems = false;
((DefaultTreeModel)myTree.getModel()).reload();
//myTree.requestFocus();
@@ -345,6 +346,17 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
updateSelectionFromTree();
}
protected void loadComponentState() {
final String key = getComponentStateKey();
final MasterDetailsStateService stateService = getStateService();
if (key != null && stateService != null) {
final MasterDetailsState state = stateService.getComponentState(key, myState.getClass());
if (state != null) {
loadState(state);
}
}
}
private static String getNodePathString(final MyNode node) {
StringBuilder path = new StringBuilder();
MyNode current = node;
@@ -365,11 +377,22 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
return path.toString();
}
public MasterDetailsState getState() {
@Nullable
@NonNls
protected String getComponentStateKey() {
return null;
}
@Nullable
protected MasterDetailsStateService getStateService() {
return null;
}
protected MasterDetailsState getState() {
return myState;
}
public void loadState(final MasterDetailsState object) {
protected void loadState(final MasterDetailsState object) {
XmlSerializerUtil.copyBean(object, myState);
}
@@ -391,6 +414,11 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
});
myRoot.removeAllChildren();
final String key = getComponentStateKey();
final MasterDetailsStateService stateService = getStateService();
if (key != null && stateService != null) {
stateService.setComponentState(key, getState());
}
myCurrentConfigurable = null;
}
@@ -33,6 +33,7 @@ import com.intellij.util.xmlb.annotations.Tag;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -46,57 +47,53 @@ import java.util.*;
)
public class MasterDetailsStateService implements PersistentStateComponent<MasterDetailsStateService.States>{
private final SkipDefaultValuesSerializationFilters mySerializationFilter = new SkipDefaultValuesSerializationFilters();
private final Map<String, MasterDetailsComponent> myComponents = new HashMap<String, MasterDetailsComponent>();
private final States myStates = new States();
private final Map<String, ComponentState> myStates = new HashMap<String, ComponentState>();
public static MasterDetailsStateService getInstance(@NotNull Project project) {
return ServiceManager.getService(project, MasterDetailsStateService.class);
}
public void register(@NotNull @NonNls String key, MasterDetailsComponent masterDetailsComponent) {
myComponents.put(key, masterDetailsComponent);
for (ComponentState state : myStates.getStates()) {
if (key.equals(state.myKey)) {
final Element element = state.mySettings;
if (element != null) {
loadComponentState(masterDetailsComponent, element);
}
}
}
/**
* @deprecated override {@link MasterDetailsComponent#getComponentStateKey()} and {@link MasterDetailsComponent#getStateService()} instead
*/
public void register(String key, MasterDetailsComponent component) {
}
private static void loadComponentState(MasterDetailsComponent masterDetailsComponent, Element element) {
final MasterDetailsState loadedState = XmlSerializer.deserialize(element, masterDetailsComponent.getState().getClass());
masterDetailsComponent.loadState(loadedState);
@Nullable
public MasterDetailsState getComponentState(@NotNull @NonNls String key, Class<? extends MasterDetailsState> stateClass) {
ComponentState state = myStates.get(key);
return state != null ? XmlSerializer.deserialize(state.mySettings, stateClass) : null;
}
public void setComponentState(@NotNull @NonNls String key, @NotNull MasterDetailsState state) {
final Element element = XmlSerializer.serialize(state, mySerializationFilter);
if (element == null) {
myStates.remove(key);
}
else {
final ComponentState componentState = new ComponentState();
componentState.myKey = key;
componentState.mySettings = element;
myStates.put(key, componentState);
}
}
public States getState() {
myStates.getStates().clear();
for (Map.Entry<String, MasterDetailsComponent> entry : myComponents.entrySet()) {
final Element element = XmlSerializer.serialize(entry.getValue().getState(), mySerializationFilter);
if (element != null) {
final ComponentState state = new ComponentState();
state.myKey = entry.getKey();
state.mySettings = element;
myStates.getStates().add(state);
}
}
Collections.sort(myStates.getStates(), new Comparator<ComponentState>() {
States states = new States();
states.myStates.addAll(myStates.values());
Collections.sort(states.getStates(), new Comparator<ComponentState>() {
@Override
public int compare(ComponentState o1, ComponentState o2) {
return o1.myKey.compareTo(o2.myKey);
}
});
return myStates;
return states;
}
public void loadState(States states) {
myStates.setStates(states.getStates());
for (ComponentState state : myStates.getStates()) {
final MasterDetailsComponent component = myComponents.get(state.myKey);
if (component != null) {
loadComponentState(component, state.mySettings);
}
myStates.clear();
for (ComponentState state : states.getStates()) {
myStates.put(state.myKey, state);
}
}
@@ -60,13 +60,22 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se
private final AtomicBoolean myInitialized = new AtomicBoolean(false);
public CopyrightProfilesPanel(Project project) {
MasterDetailsStateService.getInstance(project).register("Copyright.UI", this);
myProject = project;
myManager = CopyrightManager.getInstance(project);
initTree();
}
myProject = project;
myManager = CopyrightManager.getInstance(project);
initTree();
}
protected void processRemovedItems() {
@Override
protected MasterDetailsStateService getStateService() {
return MasterDetailsStateService.getInstance(myProject);
}
@Override
protected String getComponentStateKey() {
return "Copyright.UI";
}
protected void processRemovedItems() {
Map<String, CopyrightProfile> profiles = getAllProfiles();
final List<CopyrightProfile> deleted = new ArrayList<CopyrightProfile>();
for (CopyrightProfile profile : myManager.getCopyrights()) {
-9
View File
@@ -21,15 +21,6 @@
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/gradle-open-api-0.8.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="copyright" />
<orderEntry type="module" module-name="IntelliLang" />
Binary file not shown.
-13
View File
@@ -594,18 +594,5 @@
</component>
</project-components>
<actions>
<!-- Add your actions here -->
<action id="show-gradle" class="org.jetbrains.plugins.groovy.gradle.ui.ShowGradleUIAction"
text="Gradle UI" description="Run native Gradle UI for current project" icon="/icons/gradle/gradle.png">
<add-to-group group-id="ViewMenu" anchor="after" relative-to-action="HierarchyGroup"/>
<keyboard-shortcut keymap="$default" first-keystroke="shift ctrl G"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
<projectService serviceInterface="org.jetbrains.plugins.groovy.gradle.ui.GradleUISettings"
serviceImplementation="org.jetbrains.plugins.groovy.gradle.ui.GradleUISettings"/>
</extensions>
</idea-plugin>
@@ -1,286 +0,0 @@
/*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import org.gradle.openapi.external.ui.SettingsNodeVersion1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**<!=========================================================================>
This is our Idea-side implementation of a settings node. We'll store them in
a hashmap and then write them out to the Idea project file using its
serialization mechanism. The settings are actually a hiearchy of nodes
similar to xml, but without attributes.
@author mhunsicker
<!==========================================================================>*/
public class GradleIdeaSettingsNode implements SettingsNodeVersion1
{
public List<SettingsNodeVersion1> children = new ArrayList<SettingsNodeVersion1>();
public String name;
public String value;
public GradleIdeaSettingsNode parent;
public GradleIdeaSettingsNode( String name, GradleIdeaSettingsNode parent )
{
this.name = name;
this.parent = parent;
}
public void setName( String name )
{
this.name = name;
}
public String getName()
{
return name;
}
public void setValue( String value )
{
this.value = value;
}
public String getValue()
{
return value;
}
public List<SettingsNodeVersion1> getChildNodes()
{
return Collections.unmodifiableList( children );
}
public List<SettingsNodeVersion1> getChildNodes( String name )
{
List<SettingsNodeVersion1> matchingChildren = new ArrayList<SettingsNodeVersion1>( );
Iterator<SettingsNodeVersion1> iterator = children.iterator();
while( iterator.hasNext() )
{
SettingsNodeVersion1 settingsNodeVersion1 = iterator.next();
if( name.equals( settingsNodeVersion1.getName() ) )
matchingChildren.add( settingsNodeVersion1 );
}
return matchingChildren;
}
public SettingsNodeVersion1 getChildNode( String name )
{
Iterator<SettingsNodeVersion1> iterator = children.iterator();
while( iterator.hasNext() )
{
SettingsNodeVersion1 settingsNodeVersion1 = iterator.next();
if( name.equals( settingsNodeVersion1.getName() ) )
return settingsNodeVersion1;
}
return null;
}
public SettingsNodeVersion1 addChild( String name )
{
GradleIdeaSettingsNode node = new GradleIdeaSettingsNode( name, this );
children.add( node );
return node;
}
public SettingsNodeVersion1 addChildIfNotPresent( String name )
{
SettingsNodeVersion1 child = getChildNode( name );
if( child == null )
child = addChild( name );
return child;
}
public SettingsNodeVersion1 getNodeAtPath( String ... pathPortions )
{
if( pathPortions == null || pathPortions.length == 0 )
return null;
String firstPathPortion = pathPortions[ 0 ];
SettingsNodeVersion1 currentNode = getChildNode( firstPathPortion );
int index = 1;//Skip the first one. we've already used that one.
while( index < pathPortions.length && currentNode != null )
{
String pathPortion = pathPortions[ index ];
currentNode = currentNode.getChildNode( pathPortion );
index++;
}
return currentNode;
}
private SettingsNodeVersion1 getNodeAtPathCreateIfNotFound( String ... pathPortions )
{
if( pathPortions == null || pathPortions.length == 0 )
return null;
String firstPathPortion = pathPortions[ 0 ];
SettingsNodeVersion1 currentNode = getChildNode( firstPathPortion );
if( currentNode == null )
currentNode = addChild( firstPathPortion );
int index = 1;
while( index < pathPortions.length )
{
String pathPortion = pathPortions[ index ];
currentNode = currentNode.getChildNode( pathPortion );
if( currentNode == null )
currentNode = addChild( firstPathPortion );
index++;
}
return currentNode;
}
public void removeAllChildren()
{
children.clear();
}
public void removeFromParent()
{
if( parent != null )
{
if( parent.removeChild( this ) )
parent = null;
}
}
private boolean removeChild( GradleIdeaSettingsNode node )
{
return children.remove( node );
}
public void setValueOfChild( String name, String value )
{
SettingsNodeVersion1 settingsNode = addChildIfNotPresent( name );
settingsNode.setValue( value );
}
public String getValueOfChild( String name, String defaultValue )
{
SettingsNodeVersion1 settingsNode = getChildNode( name );
if( settingsNode == null )
return defaultValue;
return settingsNode.getValue();
}
public int getValueOfChildAsInt( String name, int defaultValue )
{
SettingsNodeVersion1 settingsNode = getChildNode( name );
if( settingsNode != null )
{
String value = settingsNode.getValue();
try
{
if( value != null )
return Integer.parseInt( value );
}
catch( NumberFormatException e )
{
//we couldn't parse it. Just return the default.
}
}
return defaultValue;
}
public void setValueOfChildAsInt( String name, int value )
{
setValueOfChild( name, Integer.toString( value ) );
}
public long getValueOfChildAsLong( String name, long defaultValue )
{
SettingsNodeVersion1 settingsNode = getChildNode( name );
if( settingsNode != null )
{
String value = settingsNode.getValue();
try
{
if( value != null )
return Long.parseLong( value );
}
catch( NumberFormatException e )
{
//we couldn't parse it. Just return the default.
}
}
return defaultValue;
}
public void setValueOfChildAsLong( String name, long value )
{
setValueOfChild( name, Long.toString( value ) );
}
public boolean getValueOfChildAsBoolean( String name, boolean defaultValue )
{
SettingsNodeVersion1 settingsNode = getChildNode( name );
if( settingsNode != null )
{
String value = settingsNode.getValue();
//I'm not calling 'Boolean.parseBoolean( value )' because it will return false if the value isn't true/false
//and we want it to return whatever the default is if its not a boolean. This is how the Int and Long functions
//behave.
if( value != null )
{
if( "true".equalsIgnoreCase( value ) )
return true;
if( "false".equalsIgnoreCase( value ) )
return false;
}
}
return defaultValue;
}
public void setValueOfChildAsBoolean( String name, boolean value )
{
setValueOfChild( name, Boolean.toString( value ) );
}
@Override
public String toString()
{
return getName() + "='" + getValue() + "' " + children.size() + " children";
}
//this should only be called by the serializer
public void setChildren( List<GradleIdeaSettingsNode> newChildren )
{
children.clear();
children.addAll( newChildren );
}
}
@@ -1,384 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.gradle.openapi.external.ui.*;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.gradle.GradleLibraryPresentationProvider;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
<!=========================================================================>
This shows a self-contained gradle UI inside a panel. It may also show a
gradle setup panel if gradle hasn't been configured or was unable to load.
The gradle UI is loaded dynamically from an external gradle installation.
There is a gradle open API jar that does the real work (and is part of gradle).
The gradle UI implementation uses versioned interfaces and wrappers to interact
with us. This allows us to be forward and backward compatible with gradle
(although certain major changes will break us). This allows the gradle UI to
change and gain new features that we don't have to know about (new features that
require our interaction obviously won't work, but the wrappers provide an
appropriate default behavior that is defined inside gradle).
You get the SinglePaneUIVersion1 here as well as add some custom panels to it.
@author mhunsicker
<!==========================================================================> */
public class GradlePanelWrapper
{
private final JPanel mainPanel = new JPanel( new BorderLayout() );
private Project myProject;
private GradleUISettings settings;
private SinglePaneUIVersion1 singlePaneUIVersion1;
private GradleSetupPanel gradleSetupPanel;
private final List<GradleTabVersion1> additionalTabs = new ArrayList<GradleTabVersion1>();
private final ObserverLord<GradleUIAvailabilityObserver> observerLord = new ObserverLord<GradleUIAvailabilityObserver>();
public void initalize(@Nullable Module module, Project myProject)
{
this.myProject = myProject;
this.settings = GradleUISettings.getInstance(myProject);
File gradleHomeDirectory = new File( GradleLibraryPresentationProvider.getSdkHome( module, myProject ).getPath() );
//this will either load the UI from gradle or display the gradle setup panel.
setupUI( gradleHomeDirectory );
}
public Project getProject() { return myProject; }
private boolean setupUI( final File gradleHomeDirectory )
{
try
{
if( gradleHomeDirectory == null )
{
addGradleSetupPanel( "Gradle not configured", (String) null );
return false;
}
if( !gradleHomeDirectory.exists() )
{
addGradleSetupPanel( "Gradle directory does not exist.", gradleHomeDirectory.getAbsolutePath() );
return false;
}
//Since this is Swing-related we want to make sure its always executed in the EDT.
//When called by Idea, we're not in the EDT. When called from out setup panel, we
//ARE in the EDT. If this fails, it will add the gradle setup panel.
if( SwingUtilities.isEventDispatchThread() )
loadUIFromGradle( gradleHomeDirectory );
else
SwingUtilities.invokeAndWait( new Runnable()
{
public void run()
{
loadUIFromGradle( gradleHomeDirectory );
}
} );
if( singlePaneUIVersion1 != null )
{
//by default, we'll set it to your project's directory, but this will probably be overridden when its settings are loaded in aboutToShow.
singlePaneUIVersion1.setCurrentDirectory( new File( myProject.getBaseDir().getPath() ) );
addAdditionalTabs();
setMainPanelContents( singlePaneUIVersion1.getComponent() );
singlePaneUIVersion1.aboutToShow();
return true;
}
}
catch( Exception e )
{
singlePaneUIVersion1 = null;
notifyGradleUIUnloaded();
addGradleSetupPanel( "Failed to load the gradle library.", e );
}
return false;
}
/**<!===== loadUIFromGradle ===============================================>
This dynamically loads the UI from a gradle installation. We call into
a function inside the gradle open API jar that handles all the reflection
of loading the classes. If this fails, we show the gradle setup panel.
<! Name Description>
@param gradleHomeDirectory where gradle resides
@author mhunsicker
<!=======================================================================>*/
private void loadUIFromGradle( File gradleHomeDirectory )
{
try
{
singlePaneUIVersion1 = UIFactory.createUI( GradlePanelWrapper.class.getClassLoader(), gradleHomeDirectory, new IdeaUIInteraction(), false );
final SinglePaneUIVersion1 singlePaneUIVersion1 = getSinglePaneUIVersion1();
final Project project = getProject();
observerLord.notifyObservers( new ObserverLord.ObserverNotification<GradleUIAvailabilityObserver>()
{
public void notify( GradleUIAvailabilityObserver observer )
{
observer.gradleUILoaded( singlePaneUIVersion1, project );
}
} );
}
catch( Throwable e )
{
singlePaneUIVersion1 = null;
notifyGradleUIUnloaded();
e.printStackTrace();
addGradleSetupPanel( "Failed to load the gradle library.", e );
}
}
/*package*/ void notifyGradleUIUnloaded()
{
observerLord.notifyObservers( new ObserverLord.ObserverNotification<GradleUIAvailabilityObserver>()
{
public void notify( GradleUIAvailabilityObserver observer )
{
observer.gradleUIUnloaded();
}
} );
}
public JPanel getComponent()
{
return mainPanel;
}
/**<!===== addGradleSetupPanel ============================================>
This sets the main panel to the gradle setup panel. This is used when
we could not load gradle either because of an error or lack of setup.
<! Name Description>
@param message a message of why we're displaying this.
@param messageDetails detailed information about why we're not displaying this.
this will only be visible if the user chooses to show it.
@author mhunsicker
<!=======================================================================>*/
private void addGradleSetupPanel( String message, String messageDetails )
{
if( gradleSetupPanel == null )
gradleSetupPanel = new GradleSetupPanel();
gradleSetupPanel.setMessage( message, messageDetails );
setMainPanelContents( gradleSetupPanel.getComponent() );
}
private void addGradleSetupPanel( String message, Throwable throwable )
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
addGradleSetupPanel( message, throwable.getMessage() + "\n" + sw.toString() );
}
/**<!===== setMainPanelContents ===========================================>
This replaces the main panel's contents with the specified new component.
@author mhunsicker
<!=======================================================================>*/
private void setMainPanelContents( Component newComponent )
{
mainPanel.removeAll();
mainPanel.invalidate();
mainPanel.add( newComponent, BorderLayout.CENTER );
mainPanel.validate();
mainPanel.repaint();
}
//
/**<!=========================================================================>
This class is how we interact with Gradle, specifically how to specify
what we use to interact with it. The purpose of SinglePaneUIInteractionVersion1
is to aid forward/backward compatibility.
@author mhunsicker
<!==========================================================================>*/
private class IdeaUIInteraction implements SinglePaneUIInteractionVersion1
{
private IdeaUIInteraction()
{
}
/**<!===== instantiateAlternateUIInteraction ==============================>
This is only called once and is how we get ahold of the AlternateUIInteraction.
@return an AlternateUIInteraction object. This cannot be null.
@author mhunsicker
<!=======================================================================>*/
public AlternateUIInteractionVersion1 instantiateAlternateUIInteraction()
{
return new IdeaAlternateUIInteraction();
}
/**<!===== instantiateSettings ============================================>
This is only called once and is how we get ahold of how the owner wants
to store preferences.
@return a settings object. This cannot be null.
@author mhunsicker
<!=======================================================================>*/
public SettingsNodeVersion1 instantiateSettings()
{
return settings.getRootNode();
}
}
//
/**<!=========================================================================>
@author mhunsicker
<!==========================================================================>*/
private class IdeaAlternateUIInteraction implements AlternateUIInteractionVersion1
{
/**<!===== editFiles ======================================================>
This is called when we should edit the specified files. Open them in the
current IDE or some external editor.
<! Name Description>
@param files the files to open
@author mhunsicker
<!=======================================================================>*/
public void editFiles( List<File> files )
{
Iterator<File> iterator = files.iterator();
while( iterator.hasNext() )
{
File file = iterator.next();
editFile( file );
}
}
/**<!===== doesSupportEditingFiles ========================================>
Determines if we can call editFiles. This is not a dynamic answer and
should always return either true of false. If you want to change the
answer, return true and then handle the files differently in editFiles.
@return true if support editing files, false otherwise.
@author mhunsicker
<!=======================================================================>*/
public boolean doesSupportEditingFiles()
{
return true;
}
}
/**<!===== editFile =======================================================>
Opens a single file in Idea.
<! Name Description>
@param file the file to open
@author mhunsicker
<!=======================================================================>*/
private void editFile( File file )
{
if( file != null && file.exists() )
{
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile( file );
if( virtualFile != null )
FileEditorManager.getInstance( myProject ).openFile( virtualFile, true );
}
}
public void close()
{
if( singlePaneUIVersion1 != null )
{
singlePaneUIVersion1.close();
//I'm going to clear this out because I think this is being called multiple times.
setMainPanelContents( new JLabel( "Closing" ) );
singlePaneUIVersion1 = null;
notifyGradleUIUnloaded();
}
}
/**<!===== canClose =======================================================>
Call this to determine if we can close. We'll just ask the .
@return .
@author mhunsicker
<!=======================================================================>*/
public boolean canClose()
{
if( singlePaneUIVersion1 != null )
return singlePaneUIVersion1.canClose( new SinglePaneUIVersion1.CloseInteraction()
{
public boolean promptUserToConfirmClosingWhileBusy()
{
int result = JOptionPane.showConfirmDialog( SwingUtilities.getWindowAncestor( mainPanel ), "Gradle tasks are being currently being executed. Exit anyway?", "Exit While Busy?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE );
return result == JOptionPane.YES_OPTION;
}
} );
return true;
}
/**<!===== addTab =========================================================>
This adds a tab. You'll want to add tabs using this rather than calling
SinglePaneUIVersion1.addTab directly. Why? Because this removes the timing
issues. That is, whether or not we've loaded the gradle UI, you can call
this and we'll show the tabs whenever we do display the UI.
<! Name Description>
@param tab the tab to add
@author mhunsicker
<!=======================================================================>*/
public void addTab( GradleTabVersion1 tab )
{
additionalTabs.add( tab );
if( singlePaneUIVersion1 != null )
singlePaneUIVersion1.addTab( singlePaneUIVersion1.getGradleTabCount() + 1, tab );
}
public void removeTab( GradleTabVersion1 tab )
{
additionalTabs.remove( tab );
if( singlePaneUIVersion1 != null )
singlePaneUIVersion1.removeTab( tab );
}
private void addAdditionalTabs()
{
Iterator<GradleTabVersion1> iterator = additionalTabs.iterator();
while( iterator.hasNext() )
{
GradleTabVersion1 gradleTab = iterator.next();
singlePaneUIVersion1.addTab( singlePaneUIVersion1.getGradleTabCount() + 1, gradleTab );
}
}
/**<!===== getSinglePaneUIVersion1 ========================================>
@return the single pane UI version1. Note: this is very likely to return
null if this hasn't been setup yet or hasn't loaded yet.
@author mhunsicker
<!=======================================================================>*/
public SinglePaneUIVersion1 getSinglePaneUIVersion1()
{
return singlePaneUIVersion1;
}
}
@@ -1,126 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import com.intellij.ui.ScrollPaneFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
/**
<!=========================================================================>
This panel is shown when gradle has not been configured or when an error
occurs trying to locate the gradle installation. It was intended to be a place
where the user could specify a gradle installation. Now, it appears to just
be a placeholder as well as a place to show error message.
@author mhunsicker
<!==========================================================================> */
public class GradleSetupPanel
{
private JPanel mainPanel;
private JPanel messagePanel;
private JLabel messageLabel;
private String messageDetails;
private String message;
private JButton detailsButton;
public GradleSetupPanel()
{
setupUI();
}
public Component getComponent() { return mainPanel; }
private void setupUI()
{
mainPanel = new JPanel( new BorderLayout() );
JPanel innerPanel = new JPanel( );
innerPanel.setLayout( new BoxLayout( innerPanel, BoxLayout.Y_AXIS ) );
innerPanel.add( createMessageComponent() );
mainPanel.add( innerPanel, BorderLayout.NORTH ); //this pushes things up. Glue doesn't work in this situation.
mainPanel.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10 ) );
}
private Component createMessageComponent()
{
messagePanel = new JPanel();
messagePanel.setLayout( new BoxLayout( messagePanel, BoxLayout.X_AXIS ) );
messageLabel = new JLabel();
detailsButton = new JButton( new AbstractAction( "Details...")
{
public void actionPerformed( ActionEvent e )
{
showDetails();
}
});
messagePanel.add( messageLabel );
messagePanel.add( Box.createHorizontalStrut( 10 ) );
messagePanel.add( detailsButton );
messagePanel.setVisible( false ); //hidden by default.
return messagePanel;
}
private void showDetails()
{
JTextArea detailsTextArea = new JTextArea( );
detailsTextArea.setOpaque( true );
detailsTextArea.setEditable( false );
detailsTextArea.setBorder( null );
detailsTextArea.setLineWrap( false );
detailsTextArea.setWrapStyleWord( true );
detailsTextArea.setText( message + "\n" + messageDetails );
detailsTextArea.setCaretPosition( 0 ); //put the caret at the front.
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(detailsTextArea);
scrollPane.setPreferredSize( new Dimension( 400, 500 ) );
JOptionPane.showMessageDialog( mainPanel, scrollPane );
}
public void setMessage( String message, String messageDetails )
{
this.messageDetails = messageDetails;
this.message = message;
messageLabel.setText( message );
detailsButton.setVisible( messageDetails != null ); //only show the 'details' button if there are details
messagePanel.setVisible( true );
}
public void hideMessage()
{
messagePanel.setVisible( false );
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import com.intellij.openapi.project.Project;
import org.gradle.openapi.external.ui.SinglePaneUIVersion1;
/**
<!=========================================================================>
This allows you to listen for the gradle UI coming and going.
@author mhunsicker
<!==========================================================================>*/
public interface GradleUIAvailabilityObserver
{
/**<!===== gradleUILoaded =================================================>
Notification that the gradle UI has been loaded.
<! Name Description>
@param singlePaneUIVersion1 the main gradle UI object.
@param ideaProject
@author mhunsicker
<!=======================================================================>*/
public void gradleUILoaded( SinglePaneUIVersion1 singlePaneUIVersion1, Project ideaProject );
/**<!===== gradleUIUnloaded ===============================================>
Notification that the gradle UI has been unloaded.
@author mhunsicker
<!=======================================================================>*/
public void gradleUIUnloaded();
}
@@ -1,125 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
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.openapi.components.StorageScheme;
import com.intellij.openapi.project.Project;
import org.gradle.openapi.external.ui.SettingsNodeVersion1;
import org.jdom.Element;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**<!=========================================================================>
This is our Idea-side implementation of settings. We'll store them in
a hashmap and then write them out to the Idea project file using its
serialization mechanism.
The actual settings are a hiearchy and are stored in instances of
GradleIdeaSettingsNode. This class basically holds onto the root node and
handles the serialization to/from Idea's project files.
@author mhunsicker
<!==========================================================================>*/
@State(
name = "GradleUISettings",
storages = {
@Storage(id = "default", file = "$PROJECT_FILE$"),
@Storage(id = "dir", file = "$PROJECT_CONFIG_DIR$/gradle_config.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
)
public class GradleUISettings implements PersistentStateComponent<Element>
{
private GradleIdeaSettingsNode rootNode = new GradleIdeaSettingsNode( "root", null );
private static final String SETTING = "setting";
private static final String NAME = "name";
private static final String VALUE = "value";
public GradleIdeaSettingsNode getRootNode() { return rootNode; }
public Element getState()
{
Element e = new Element( SETTING );
writeOutSetting(e, rootNode);
return e;
}
public void loadState(Element element)
{
List<GradleIdeaSettingsNode> settingsNodes = readInSetting( element, null );
if( !settingsNodes.isEmpty() ) //this should have either 1 or none in it.
rootNode = settingsNodes.get( 0 );
}
public static GradleUISettings getInstance(final Project project)
{
return ServiceManager.getService(project, GradleUISettings.class);
}
private void writeOutSetting( Element parentElement, GradleIdeaSettingsNode node )
{
Element element = new Element( SETTING );
parentElement.addContent( element );
element.setAttribute( NAME, node.getName() );
if( node.getValue() != null )
element.setAttribute( VALUE, node.getValue() );
for ( SettingsNodeVersion1 settingsNode : node.getChildNodes())
writeOutSetting( element, (GradleIdeaSettingsNode)settingsNode );
}
/**<!===== readInSetting ==================================================>
This does the real work of reading in settings. This recursively reads
them and because both the parent and children know about each other, we
have to track the children as we read them in.
@author mhunsicker
<!=======================================================================>*/
private List<GradleIdeaSettingsNode> readInSetting( Element parentElement, GradleIdeaSettingsNode parentNode )
{
List<GradleIdeaSettingsNode> nodesReadIn = new ArrayList<GradleIdeaSettingsNode>();
Iterator iterator = parentElement.getChildren( SETTING ).iterator();
while( iterator.hasNext() )
{
Element element = (Element) iterator.next();
String name = element.getAttributeValue( NAME );
GradleIdeaSettingsNode node = new GradleIdeaSettingsNode( name, parentNode );
String value = element.getAttributeValue( VALUE );
if( value != null )
node.setValue( value );
//read in our children
List<GradleIdeaSettingsNode> myChildren = readInSetting( element, node );
//and store them
node.setChildren( myChildren );
nodesReadIn.add( node );
}
return nodesReadIn;
}
}
@@ -1,210 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import javax.swing.SwingUtilities;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.EventQueue;
/**<!=========================================================================>
This is a Swing-friendly observer manager class. Swing-friendly, but can be
used by non-Swing classes. Its meant to abstract the fact that you probably
need to be in the Event Dispatch Thread when receiving notifications inside
Swing-related classes.
To use this class, add it as a member variable (don't derive from this!)
of a class that you want to be observered. You can have multiple instances
of this if you want to allow for a finer granularity of observing (similar
to components having mouse move listeners and mouse (click) listeners).
Next, create an interface for the observers. Now implement add and remove
observer functions that call the add and remove functions here. Lastly,
implement ObserverNotification and have it call the aforementioned observer
interface appropriately. Note: you should actually implement ObserverNotification
for each "message" you want to send. Example: One that would tell a view
a node was added. One that would tell a view a node was deleted, etc.
While you have multiple notification classes, you only need 1 (or few)
actual observer interfaces, containing all the possible functions called
by all notifications.
@author mhunsicker
<!==========================================================================>*/
public class ObserverLord<E>
{
////////////////////////////////////////////////////////////////////////////
//////////////////////////// member variables //////////////////////////////
////////////////////////////////////////////////////////////////////////////
private final List<E> regularObservers = new ArrayList<E>();
private final List<E> eventQueueObservers = new ArrayList<E>();
//
/**<!=========================================================================>
Implement this for each call to ObserverLord.notifyObservers. The notify
function usually just has a single call to a function on the observer.
Example:
public void notify( MyObserver observer )
{
observer.myfunction();
}
@author mhunsicker
<!==========================================================================>*/
public interface ObserverNotification<E>
{
public void notify( E observer );
}
////////////////////////////////////////////////////////////////////////////
///////////////////////////////// methods //////////////////////////////////
////////////////////////////////////////////////////////////////////////////
/**<!===== addObserver =============================================>
Adds an observer to our messaging system.
<! Name Description >
@param observer observer to add.
@param inEventQueue true to notify this observer only in the event queue,
false to notify it immediately.
@author mhunsicker
<!=======================================================================>*/
public void addObserver( E observer, boolean inEventQueue )
{
if( !inEventQueue )
addIfNew( observer, regularObservers );
else
addIfNew( observer, eventQueueObservers );
}
private void addIfNew( E observer, List<E> destinationList )
{
if( !destinationList.contains( observer ) )
destinationList.add( observer );
}
/**<!===== removeObserver ==========================================>
Deletes an observer in our messaging system.
<! Name Dir Description >
@param observer in,
@author mhunsicker
<!=======================================================================>*/
public void removeObserver( E observer )
{
regularObservers.remove( observer );
eventQueueObservers.remove( observer );
}
public void removeAllObservers()
{
regularObservers.clear();
eventQueueObservers.clear();
}
/**<!===== notifyObservers ================================================>
Messaging method that handles telling each observer that something
happen to the observable.
<! Name Dir Description >
@param notification in, notification sent to the observer
@author mhunsicker
<!=======================================================================>*/
public void notifyObservers( ObserverNotification<E> notification )
{
//notify all the non-event queue observers now.
notifyObserversInternal( regularObservers, notification );
notifyObserversInEventQueueThread( notification );
}
/**<!===== notifyObserversInEventQueueThread ====================================>
Here is where we notify all the event queue observers. To notify the event
queue observers we have to make sure it occurs in the event queue thread. If
we're not in the event queue, we'll wrap it in an invoke and wait.
<! Name Dir Description >
<! Name Dir Description >
@param notification in, notification sent to the observer
@author mhunsicker
<!=======================================================================>*/
private void notifyObserversInEventQueueThread( final ObserverNotification notification )
{
if( eventQueueObservers.size() == 0 ) //if we have no event queue observsers, we're done
return;
if( EventQueue.isDispatchThread() )
notifyObserversInternal( eventQueueObservers, notification );
else
{
try
{
SwingUtilities.invokeAndWait( new Runnable()
{
public void run()
{
notifyObserversInternal( eventQueueObservers, notification );
}
} );
}
catch( Exception e )
{
//System.out.println( "notifyObservers exception: " + e.toString() );
e.printStackTrace();
}
}
}
/**<!===== notifyObserversInternal ========================================>
The internal mechanism that actually notifies the observers. We just
iterate though each observer and pass it to the notification mechanism.
<! Name Dir Description >
@param observers in, objects that changed (observable)
@param notification in, notification sent to the observer
@author mhunsicker
<!=======================================================================>*/
private void notifyObserversInternal( List<E> observers, ObserverNotification notification )
{
Iterator<E> iterator = observers.iterator();
while( iterator.hasNext() )
{
E observer = iterator.next();
try
{
notification.notify( observer );
}
catch( Exception e ) //this is so an error in the notification doesn't stop the entire process.
{
e.printStackTrace();
}
}
}
public String toString()
{
return regularObservers.size() + " regular observers, " + eventQueueObservers.size() + " event queue observers";
}
}
@@ -1,139 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.gradle.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Disposer;
import org.gradle.openapi.external.ui.SettingsNodeVersion1;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.gradle.GradleLibraryPresentationProvider;
import javax.swing.*;
import java.awt.*;
//this shows the gradle UI if its not already visible
public class ShowGradleUIAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
new GradleUiDialog(e.getData(DataKeys.PROJECT), e.getData(DataKeys.MODULE)).show();
}
@Override
public void update(AnActionEvent e) {
boolean enabled = isEnabled(e);
e.getPresentation().setEnabled(enabled);
e.getPresentation().setVisible(enabled);
}
private static boolean isEnabled(AnActionEvent e) {
if (!"true".equals(System.getProperty("gradle.ui.action"))) {
return false;
}
Project project = e.getData(DataKeys.PROJECT);
return project != null && GradleLibraryPresentationProvider.getSdkHome(e.getData(DataKeys.MODULE), project) != null;
}
private static class GradleUiDialog extends DialogWrapper {
private static final String MAIN_COMPONENT_AS_DIALOG = "main-component-as-dialog";
private static final String LOCATION_Y = "location-y";
private static final String LOCATION_X = "location-x";
private static final String HEIGHT = "height";
private static final String WIDTH = "width";
private final GradlePanelWrapper myGradlePanelWrapper;
private Boolean canClose;
private final Project myProject;
public GradleUiDialog(final Project project, @Nullable final Module module) {
super(project);
myProject = project;
myGradlePanelWrapper = new GradlePanelWrapper();
myGradlePanelWrapper.initalize(module, project);
Disposer.register(getDisposable(), new Disposable() {
public void dispose() {
saveSettings(project);
myGradlePanelWrapper.close();
}
});
setModal(false);
setSize(400, 700);
setTitle("Gradle");
ProjectManager.getInstance().addProjectManagerListener(project, new ProjectManagerAdapter() {
public boolean canCloseProject(Project project) {
if (canClose == null) {
canClose = myGradlePanelWrapper.canClose();
}
return canClose;
}
});
init();
}
@Override
public void show() {
super.show();
restoreSettings(myProject);
}
@Override
protected JComponent createCenterPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(myGradlePanelWrapper.getComponent());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
return panel;
}
//this restores the location and size of the dialog
private void restoreSettings(Project project) {
GradleUISettings gradleUISettings = GradleUISettings.getInstance(project);
SettingsNodeVersion1 settingsNode = gradleUISettings.getRootNode().getChildNode(MAIN_COMPONENT_AS_DIALOG);
if (settingsNode != null) {
int x = settingsNode.getValueOfChildAsInt(LOCATION_X, getLocation().x);
int y = settingsNode.getValueOfChildAsInt(LOCATION_Y, getLocation().y);
int width = settingsNode.getValueOfChildAsInt(WIDTH, getSize().width);
int height = settingsNode.getValueOfChildAsInt(HEIGHT, getSize().height);
setLocation(x, y);
setSize(width, height);
}
}
//this restores the location and size of the dialog
private void saveSettings(Project project) {
GradleUISettings gradleUISettings = GradleUISettings.getInstance(project);
SettingsNodeVersion1 settingsNode = gradleUISettings.getRootNode().addChildIfNotPresent(MAIN_COMPONENT_AS_DIALOG);
settingsNode.setValueOfChildAsInt(LOCATION_X, getLocation().x);
settingsNode.setValueOfChildAsInt(LOCATION_Y, getLocation().y);
settingsNode.setValueOfChildAsInt(WIDTH, getSize().width);
settingsNode.setValueOfChildAsInt(HEIGHT, getSize().height);
}
}
}