IDEA-76142 Gradle support - cannot update IDEA projects once one of build.gradle files changes

1. Added basic infrastructure for the gradle tool window GUI controls;
2. Minor refactoring;
This commit is contained in:
Denis.Zhdanov
2011-12-29 10:58:01 +04:00
parent 49166128a1
commit 2aa76b0407
9 changed files with 284 additions and 7 deletions
@@ -285,7 +285,7 @@ public final class Presentation implements Cloneable {
myChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
public Object clone(){
public Presentation clone(){
try{
Presentation presentation = (Presentation)super.clone();
presentation.myChangeSupport = new PropertyChangeSupport(presentation);
@@ -1104,7 +1104,7 @@ public class StringUtil {
}
@NotNull
public static Iterable<String> tokenize(@NotNull String s, final StringTokenizer tokenizer) {
public static Iterable<String> tokenize(final StringTokenizer tokenizer) {
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
@@ -55,4 +55,9 @@ gradle.generic.text.error.sdk.undefined=Gradle installation is unknown
gradle.home.setting.type.deduced=Gradle location is deduced
gradle.home.setting.type.unknown=Gradle location is unknown
gradle.home.setting.type.explicit.correct=Gradle location is defined
gradle.home.setting.type.explicit.incorrect=Gradle location is incorrect
gradle.home.setting.type.explicit.incorrect=Gradle location is incorrect
gradle.toolwindow.text.no.linked.project=\nThere is no linked Gradle project\nYou may use {link} to add the one.
gradle.action.link.project.text=Link gradle project
gradle.action.link.project.description=Allows to link any gradle project to the current IDE project
+7
View File
@@ -58,4 +58,11 @@
</component>
</project-components>
<actions>
<action id="Gradle.LinkToProject" class="org.jetbrains.plugins.gradle.config.GradleLinkToProjectAction" icon="/general/add.png"/>
<group id="Gradle.ChangeActionsToolbar">
<reference id="Gradle.LinkToProject"/>
</group>
</actions>
</idea-plugin>
@@ -0,0 +1,28 @@
package org.jetbrains.plugins.gradle.config;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.plugins.gradle.util.GradleBundle;
/**
* Allows to link gradle project to the current IntelliJ IDEA project.
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 12/26/11 5:09 PM
*/
public class GradleLinkToProjectAction extends AnAction implements DumbAware {
public GradleLinkToProjectAction() {
getTemplatePresentation().setText(GradleBundle.message("gradle.action.link.project.text"));
getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.link.project.description"));
}
@Override
public void actionPerformed(AnActionEvent e) {
// TODO den implement
System.out.println("action performed");
}
}
@@ -0,0 +1,141 @@
package org.jetbrains.plugins.gradle.config;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.ex.ActionButtonLook;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ScrollPaneFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
/**
* Base class for high-level Gradle GUI controls used at the Gradle tool window. The basic idea is to encapsulate the same features in
* this class and allow to extend it via <code>Template Method</code> pattern. The shared features are listed below:
* <pre>
* <ul>
* <li>provide common actions at the toolbar;</li>
* <li>show info control when no gradle project is linked to the current IntelliJ IDEA project;</li>
* </ul>
* </pre>
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 12/26/11 5:19 PM
*/
public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel {
private static final String NON_LINKED_CARD_NAME = "NON_LINKED";
private static final String CONTENT_CARD_NAME = "CONTENT";
private static final String LINK_BUTTON_MARKER = "{link}";
private static final String TOOL_WINDOW_TOOLBAR_ID = "Gradle.ChangeActionsToolbar";
private static final String LINK_PROJECT_ACTION_ID = "Gradle.LinkToProject";
/** Show info control when no gradle project is linked, using {@link CardLayout} for that. */
private final CardLayout myLayout = new CardLayout();
/** Top-level container, managed by the card layout. */
private final JPanel myContent = new JPanel(myLayout);
/** Control to show when no gradle project is linked to the current IntelliJ IDEA project. */
private final JPanel myNonLinkedInfoPanel = new JPanel();
protected GradleToolWindowPanel(@NotNull String place) {
super(true);
final ActionManager actionManager = ActionManager.getInstance();
final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(TOOL_WINDOW_TOOLBAR_ID);
ActionToolbar actionToolbar = actionManager.createActionToolbar(place, actionGroup, true);
setToolbar(actionToolbar.getComponent());
initContent();
setContent(myContent);
}
private void initContent() {
final JComponent payloadControl = buildContent();
myContent.add(ScrollPaneFactory.createScrollPane(payloadControl), CONTENT_CARD_NAME);
myNonLinkedInfoPanel.setLayout(new GridBagLayout());
final Color background = payloadControl.getBackground();
myNonLinkedInfoPanel.setBackground(background);
List<JComponent> rowComponents = new ArrayList<JComponent>();
final String sentence = GradleBundle.message("gradle.toolwindow.text.no.linked.project");
for (String s : StringUtil.tokenize(new StringTokenizer(sentence, " \n", true))) {
if (s.isEmpty()) {
continue;
}
if (LINK_BUTTON_MARKER.equals(s)) {
final ActionManager actionManager = ActionManager.getInstance();
final AnAction action = actionManager.getAction(LINK_PROJECT_ACTION_ID);
ActionButton button= new ActionButton(
action, action.getTemplatePresentation().clone(), GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE, new Dimension(0, 0))
{
@Override
protected void paintButtonLook(Graphics g) {
// Don't draw border at the inline button.
ActionButtonLook look = getButtonLook();
look.paintBackground(g, this);
look.paintIcon(g, this, getIcon());
}
};
rowComponents.add(button);
}
else if (s.contains("\n")) {
addRow(rowComponents, background);
rowComponents.clear();
}
else {
final JLabel label = new JLabel(s);
label.setForeground(payloadControl.getForeground());
label.setBackground(background);
label.setFont(payloadControl.getFont());
rowComponents.add(label);
}
}
if (!rowComponents.isEmpty()) {
addRow(rowComponents, background);
}
GridBagConstraints constraints = new GridBagConstraints();
constraints.weighty = 1;
constraints.fill = GridBagConstraints.VERTICAL;
myNonLinkedInfoPanel.add(Box.createVerticalStrut(1), constraints);
myContent.add(myNonLinkedInfoPanel, NON_LINKED_CARD_NAME);
myLayout.show(myContent, NON_LINKED_CARD_NAME);
}
private void addRow(@NotNull Collection<JComponent> rowComponents, @NotNull Color backgroundColor) {
JPanel row = new MultiRowFlowPanel(FlowLayout.CENTER, 0, 3);
row.setBackground(backgroundColor);
if (rowComponents.isEmpty()) {
row.add(new JLabel(" "));
}
else {
for (JComponent component : rowComponents) {
row.add(component);
}
}
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets.top = 3;
myNonLinkedInfoPanel.add(row, constraints);
}
/**
* @return GUI control to be displayed at the current tab
*/
@NotNull
protected abstract JComponent buildContent();
}
@@ -0,0 +1,83 @@
package org.jetbrains.plugins.gradle.config;
import javax.swing.*;
import java.awt.*;
/**
* Flow layout calculates necessary size assuming that all components are layed out within a single row.
* That may cause troubles during initial space calculation, i.e. panel with flow layout is represented as a
* single wide row inside a scroll pane. This panel fixes that by calculating necessary size on its own.
* It fixes the width to use as a minimum between a width offered by default flow layout and customizable value
* and calculates the height. If the user has an ability to manually change panel size (e.g. indirectly via changing
* size of the dialog that serves as a container for the panel), that width is used as a maximum width.
*
* @author: Denis Zhdanov
* @since: Jul 28, 2008
*/
public class MultiRowFlowPanel extends JPanel {
private int maximumWidth = Toolkit.getDefaultToolkit().getScreenSize().width / 2;
public MultiRowFlowPanel(int align, int hGap, int vGap) {
super(new FlowLayout(align, hGap, vGap));
}
/**
* Calculates a preferred size assuming that the maximum row width is a value returned from
* {@link #getMaxRowWidth()}.
*/
@Override
public Dimension getPreferredSize() {
return calculateSize(getMaxRowWidth());
}
/**
* Calculates a preferred size assuming that the maximum row width is a value returned from
* {@link #getMaxRowWidth()}.
*/
@Override
public Dimension getMinimumSize() {
return calculateSize(getMaxRowWidth());
}
/**
* @return current representation width if the component is already showed; minimum of default preferred
* width (when all components are layed in a single row) and half screen width
*/
private int getMaxRowWidth() {
int result = getSize().width;
if (result == 0) {
result = Math.min(super.getPreferredSize().width, maximumWidth);
}
return result;
}
/**
* Iterates all child components and calculates the space enough to keep all of them assuming that the width is
* fixed.
*/
private Dimension calculateSize(int maxRowWidth) {
FlowLayout layout = (FlowLayout)getLayout();
int height = 0;
int currentRowWidth = 0;
int currentRowHeight = 0;
for (int i = 0, count = getComponentCount(); i < count; ++i) {
Component comp = getComponent(i);
Dimension bounds = comp.getPreferredSize();
if (!comp.isVisible()) {
continue;
}
currentRowHeight = Math.max(currentRowHeight, bounds.height);
if (currentRowWidth + layout.getHgap() + bounds.width <= maxRowWidth) {
if (bounds.width != 0) {
currentRowWidth += bounds.width + layout.getHgap();
}
continue;
}
height += currentRowHeight + layout.getVgap();
currentRowWidth = bounds.width;
currentRowHeight = bounds.height;
}
return new Dimension(maxRowWidth, height + currentRowHeight + 2 * layout.getVgap());
}
}
@@ -1,6 +1,9 @@
package org.jetbrains.plugins.gradle.sync;
import com.intellij.ui.treeStructure.SimpleTree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
@@ -10,11 +13,20 @@ import javax.swing.*;
* @author Denis Zhdanov
* @since 11/3/11 3:58 PM
*/
public class GradleProjectStructureChangesPanel extends JPanel {
public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
private final GradleProjectStructureChangesModel myModel;
public GradleProjectStructureChangesPanel(@NotNull GradleProjectStructureChangesModel model) {
super(GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE);
myModel = model;
}
@NotNull
@Override
protected JComponent buildContent() {
// TODO den implement
return new SimpleTree();
//return new JLabel("project-structure-change-content");
}
}
@@ -13,9 +13,10 @@ import javax.swing.*;
*/
public class GradleConstants {
public static final Icon GRADLE_ICON = IconLoader.getIcon("/icons/gradle.png");
@NonNls public static final String EXTENSION = "gradle";
@NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
public static final Icon GRADLE_ICON = IconLoader.getIcon("/icons/gradle.png");
@NonNls public static final String EXTENSION = "gradle";
@NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
@NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR";
private GradleConstants() {
}