diff --git a/plugin/src/main/java/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java b/plugin/src/main/java/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java deleted file mode 100644 index 36b1395..0000000 --- a/plugin/src/main/java/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.jetbrains.plugins.gradle.config; - -import consulo.component.messagebus.MessageBusConnection; -import consulo.gradle.localize.GradleLocalize; -import consulo.project.Project; -import consulo.ui.ex.action.ActionGroup; -import consulo.ui.ex.action.ActionManager; -import consulo.ui.ex.action.ActionToolbar; -import consulo.ui.ex.awt.*; -import org.jetbrains.plugins.gradle.settings.GradleSettings; -import org.jetbrains.plugins.gradle.settings.GradleSettingsListener; -import org.jetbrains.plugins.gradle.ui.RichTextControlBuilder; - -import javax.annotation.Nonnull; -import javax.swing.*; -import java.awt.*; -import java.util.Collections; -import java.util.List; - -/** - * 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 Template Method pattern. The shared features are listed below: - *
- * 
- * 
- *

- * Not thread-safe. - * - * @author Denis Zhdanov - * @since 2011-12-26 - */ -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 TOOL_WINDOW_TOOLBAR_ID = "Gradle.ChangeActionsToolbar"; - - /** 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); - - private final Project myProject; - private final String myPlace; - - protected GradleToolWindowPanel(@Nonnull Project project, @Nonnull String place) { - super(true); - myProject = project; - myPlace = place; - setContent(myContent); - - MessageBusConnection connection = project.getMessageBus().connect(project); - connection.subscribe(GradleSettingsListener.TOPIC, new GradleSettingsListenerAdapter() { - // TODO den implement -// @Override public void onLinkedProjectConfigChange(@Nullable String oldPath, @Nullable String newPath) { -// if (StringUtil.isEmpty(newPath)) { -// myLayout.show(myContent, NON_LINKED_CARD_NAME); -// return; -// } -// if (StringUtil.isEmpty(oldPath) && !StringUtil.isEmpty(newPath)) { -// myLayout.show(myContent, CONTENT_CARD_NAME); -// } -// } - }); - } - - public void initContent() { - final ActionManager actionManager = ActionManager.getInstance(); - final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(TOOL_WINDOW_TOOLBAR_ID); - ActionToolbar actionToolbar = actionManager.createActionToolbar(myPlace, actionGroup, true); - JPanel toolbarControl = new JPanel(new GridBagLayout()); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.weightx = 1; - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.anchor = GridBagConstraints.WEST; - toolbarControl.add(actionToolbar.getComponent(), constraints); - for (JComponent component : getToolbarControls()) { - component.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); - toolbarControl.add(component, constraints); - } - setToolbar(toolbarControl); - - final JComponent payloadControl = buildContent(); - JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(payloadControl); - JScrollBar scrollBar = scrollPane.getVerticalScrollBar(); - scrollBar.setUnitIncrement(scrollBar.getUnitIncrement() * 7); - myContent.add(scrollPane, CONTENT_CARD_NAME); - RichTextControlBuilder builder = new RichTextControlBuilder(); - builder.setBackgroundColor(payloadControl.getBackground()); - builder.setForegroundColor(UIUtil.getInactiveTextColor()); - builder.setFont(payloadControl.getFont()); - builder.setText(GradleLocalize.gradleToolwindowTextNoLinkedProject().get()); - final JComponent noLinkedProjectControl = builder.build(); - myContent.add(noLinkedProjectControl, NON_LINKED_CARD_NAME); - update(); - } - - /** - * @return list of UI controls to be displayed vertically at the toolbar - */ - @Nonnull - protected List getToolbarControls() { - return Collections.emptyList(); - } - - /** - * Asks current control to update its state. - */ - public void update() { - final GradleSettings settings = GradleSettings.getInstance(myProject); - // TODO den implement - String cardToShow = "sf"; -// String cardToShow = StringUtil.isEmpty(settings.getLinkedExternalProjectPath()) ? NON_LINKED_CARD_NAME : CONTENT_CARD_NAME; - myLayout.show(myContent, cardToShow); - boolean showToolbar = cardToShow != NON_LINKED_CARD_NAME; - for (JComponent component : getToolbarControls()) { - component.setVisible(showToolbar); - } - } - - @Nonnull - public Project getProject() { - return myProject; - } - - /** - * @return GUI control to be displayed at the current tab - */ - @Nonnull - protected abstract JComponent buildContent(); - - /** - * Callback for asking content control to update its state. - */ - protected abstract void updateContent(); -} diff --git a/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java b/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java deleted file mode 100644 index efbcc0e..0000000 --- a/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.jetbrains.plugins.gradle.ui; - -import consulo.dataContext.DataContext; -import consulo.dataContext.DataManager; -import consulo.gradle.GradleConstants; -import consulo.ui.Size; -import consulo.ui.ex.action.*; -import consulo.ui.ex.awt.ClickListener; -import consulo.ui.ex.awt.UIUtil; -import consulo.util.concurrent.AsyncResult; - -import javax.annotation.Nonnull; -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; - -/** - * @author Denis Zhdanov - * @since 1/16/12 5:20 PM - */ -public class RichTextActionProcessor implements RichTextControlBuilder.RichTextProcessor { - - @Override - public JComponent process(@Nonnull String s) { - final ActionManager actionManager = ActionManager.getInstance(); - final AnAction action = actionManager.getAction(s); - if (action == null) { - return null; - } - final Presentation presentation = action.getTemplatePresentation(); - - if (presentation.getIcon() != null) { - return ActionButtonFactory.getInstance().create(action, presentation.clone(), GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE, new Size(0, 0)).getComponent(); - } - - final String text = action.getTemplatePresentation().getText(); - JLabel result = new JLabel(text) { - public void paint(Graphics g) { - super.paint(g); - final int y = g.getClipBounds().height - getFontMetrics(getFont()).getDescent() + 2; - final int width = getFontMetrics(getFont()).stringWidth(getText()); - g.drawLine(0, y, width, y); - } - }; - Color color = UIUtil.isUnderDarcula() ? Color.ORANGE : Color.BLUE; - result.setForeground(color); - result.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - - new ClickListener() { - @Override - public boolean onClick(MouseEvent e, int clickCount) { - final AsyncResult callback = DataManager.getInstance().getDataContextFromFocus(); - final DataContext context = callback.getResult(); - if (context == null) { - return false; - } - final Presentation presentation = new BasePresentationFactory().getPresentation(action); - action.actionPerformed(new AnActionEvent( - e, context, GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE, presentation, ActionManager.getInstance(), e.getModifiers() - )); - return true; - } - }.installOn(result); - return result; - } - - @Nonnull - @Override - public String getKey() { - return "action"; - } -} diff --git a/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextControlBuilder.java b/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextControlBuilder.java deleted file mode 100644 index 80fe7d8..0000000 --- a/plugin/src/main/java/org/jetbrains/plugins/gradle/ui/RichTextControlBuilder.java +++ /dev/null @@ -1,244 +0,0 @@ -package org.jetbrains.plugins.gradle.ui; - -import consulo.ui.ex.awt.MultiRowFlowPanel; -import consulo.util.lang.StringUtil; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.swing.*; -import java.awt.*; -import java.util.List; -import java.util.*; - -/** - * Allows to build controls that show target user text with 'reach info' (e.g. inline icon button). - *

- * Not thread-safe. - * - * @author Denis Zhdanov - * @since 1/16/12 5:06 PM - */ -public class RichTextControlBuilder { - - private static final String RICH_TEXT_TOKEN_START = "{@"; - private static final String RICH_TEXT_TOKEN_END = "}"; - - private final Map myProcessors = new HashMap(); - private final JPanel myResult = new JPanel(new GridBagLayout()); - private final Collection myComponents = new ArrayList(); - - private Color myForegroundColor; - private Color myBackgroundColor; - private Font myFont; - - public RichTextControlBuilder() { - myForegroundColor = myResult.getForeground(); - myBackgroundColor = myResult.getBackground(); - myFont = myResult.getFont(); - - registerProcessor(new RichTextActionProcessor()); - } - - /** - * Defines target text to show by the UI component built by the current builder. - *

- * The text can be 'reach', i.e. contain text like '{@value #RICH_TEXT_TOKEN_START}key data{@value #RICH_TEXT_TOKEN_END}'. - * Then 'data' will be delivered to the {@link RichTextProcessor} registered for the - * {@link RichTextProcessor#getKey() target key}. {@link RichTextProcessor#process(String) Returned component} (if any) will be - * shown within the resulting UI control. - *

- * For example, there is a predefined {@link RichTextActionProcessor} that resolves references to the actions (shows its icon at - * the resulting component). - * - * @param text target text to show by the resulting control - * @throws IllegalArgumentException if given text is malformed - */ - public void setText(@Nonnull String text) throws IllegalArgumentException { - myResult.removeAll(); - myComponents.clear(); - List rowComponents = new ArrayList(); - RichTextProcessor metaDataProcessor = null; - StringBuilder metaTokenData = new StringBuilder(); - boolean ignoreNext = false; - for (String s : StringUtil.tokenize(new StringTokenizer(text, " \n", true))) { - if (ignoreNext || s.isEmpty()) { - ignoreNext = false; - continue; - } - - if (metaDataProcessor != null) { - // Inside meta-token. - final int i = s.indexOf(RICH_TEXT_TOKEN_END); - if (i >= 0) { - // Meta-token ends within the current string. - metaTokenData.append(s.substring(0, i)); - final JComponent component = metaDataProcessor.process(metaTokenData.toString()); - if (component != null) { - rowComponents.add(component); - } - metaTokenData.setLength(0); - metaDataProcessor = null; - if (i + RICH_TEXT_TOKEN_END.length() < s.length()) { - s = s.substring(i + RICH_TEXT_TOKEN_END.length()); - } - else { - continue; - } - } - else { - // Meta-token data continues here. - metaTokenData.append(s); - continue; - } - } - - final int start = s.indexOf(RICH_TEXT_TOKEN_START); - - // Check if meta data starts here. - if (start >= 0) { - if (start + RICH_TEXT_TOKEN_START.length() >= s.length()) { - throw new IllegalArgumentException(String.format( - "Invalid rich text detected. Meta data key is assumed to directly follow '%s' (no white spaces between them). " - + "Given text: '%s'", RICH_TEXT_TOKEN_START, text)); - } - - // Define meta-key end offset. - int end = s.indexOf(RICH_TEXT_TOKEN_END); - boolean metaDataComplete = true; - if (end < start) { - end = s.length(); - metaDataComplete = false; - } - String metaKey = s.substring(start + RICH_TEXT_TOKEN_START.length(), end); - metaDataProcessor = myProcessors.get(metaKey); - if (metaDataProcessor == null) { - throw new IllegalArgumentException(String.format( - "No processor is registered for the meta-key '%s' (processors are available only for these keys - %s). Rich text: '%s'", - metaKey, myProcessors.keySet(), text - )); - } - - // There is a possible case like {@key}. We can complete meta-processing here than. - if (metaDataComplete) { - final JComponent component = metaDataProcessor.process(""); - if (component != null) { - rowComponents.add(component); - } - metaDataProcessor = null; - if (end < s.length()) { - // Handle situation like '{@key}text', i.e. there is no white space between the meta-data and the text that follows it. - s = s.substring(end); - } - else { - continue; - } - } - else { - ignoreNext = true; - continue; - } - } - if (s.contains("\n")) { - addRow(rowComponents); - rowComponents.clear(); - } - else { - final JLabel label = new JLabel(s); - label.setForeground(myForegroundColor); - label.setBackground(myBackgroundColor); - label.setFont(myFont); - rowComponents.add(label); - } - } - if (!rowComponents.isEmpty()) { - addRow(rowComponents); - } - } - - public void setForegroundColor(@Nonnull Color foregroundColor) { - myForegroundColor = foregroundColor; - } - - public void setBackgroundColor(@Nonnull Color backgroundColor) { - myBackgroundColor = backgroundColor; - } - - public void setFont(@Nonnull Font font) { - myFont = font; - } - - /** - * Registers given processor within the current builder, i.e. it will be - * {@link RichTextProcessor#process(String) asked to process} meta data for the - * {@link RichTextProcessor#getKey target key} (if any). - * - * @param processor processor to register - */ - public void registerProcessor(@Nonnull RichTextProcessor processor) { - myProcessors.put(processor.getKey(), processor); - } - - /** - * @return component built within the provided information - */ - @Nonnull - public JComponent build() { - for (JComponent component : myComponents) { - component.setForeground(myForegroundColor); - component.setBackground(myBackgroundColor); - component.setFont(myFont); - } - myResult.setForeground(myForegroundColor); - myResult.setBackground(myBackgroundColor); - myResult.setFont(myFont); - - GridBagConstraints constraints = new GridBagConstraints(); - constraints.weighty = 1; - constraints.fill = GridBagConstraints.VERTICAL; - myResult.add(Box.createVerticalStrut(1), constraints); - return myResult; - } - - private void addRow(@Nonnull Collection rowComponents) { - JPanel row = new MultiRowFlowPanel(FlowLayout.CENTER, 0, 3); - row.setBackground(myBackgroundColor); - myComponents.add(row); - 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; - myResult.add(row, constraints); - } - - /** - * Encapsulates functionality for showing particular {@link RichTextControlBuilder#setText(String) rich text}. - */ - public interface RichTextProcessor { - - /** - * @return flavor of the rich text that can be managed by the current processor - */ - @Nonnull - String getKey(); - - /** - * Callback that receives target rich text data and returns UI control that represents it. - *

- * For example, it can receive action id and return action's icon button. - * - * @param text target rich text - * @return UI control that represents given rich text in a way specific to the current processor (if any) - */ - @Nullable - JComponent process(@Nonnull String text); - } -} diff --git a/plugin/src/test/jav_/org/jetbrains/plugins/gradle/util/RichTextControlBuilderTest.java b/plugin/src/test/jav_/org/jetbrains/plugins/gradle/util/RichTextControlBuilderTest.java deleted file mode 100644 index ed52a1b..0000000 --- a/plugin/src/test/jav_/org/jetbrains/plugins/gradle/util/RichTextControlBuilderTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.jetbrains.plugins.gradle.util; - -import com.intellij.testFramework.SkipInHeadlessEnvironment; -import org.jetbrains.plugins.gradle.ui.RichTextControlBuilder; -import org.jmock.Expectations; -import org.jmock.Mockery; -import org.jmock.integration.junit4.JMock; -import org.jmock.integration.junit4.JUnit4Mockery; -import org.jmock.lib.legacy.ClassImposteriser; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import javax.swing.*; - -/** - * @author Denis Zhdanov - * @since 01/17/2012 - */ -@RunWith(JMock.class) -@SkipInHeadlessEnvironment -public class RichTextControlBuilderTest { - - private static final String META_KEY = "my-key"; - - private RichTextControlBuilder myBuilder; - private Mockery myMockery; - private RichTextControlBuilder.RichTextProcessor myProcessor; - - @Before - public void setUp() { - myBuilder = new RichTextControlBuilder(); - myMockery = new JUnit4Mockery() {{ - setImposteriser(ClassImposteriser.INSTANCE); - }}; - - myProcessor = myMockery.mock(RichTextControlBuilder.RichTextProcessor.class); - myMockery.checking(new Expectations() {{ - allowing(myProcessor).getKey(); will(returnValue(META_KEY)); - }}); - myBuilder.registerProcessor(myProcessor); - } - - @After - public void checkExpectations() { - myMockery.assertIsSatisfied(); - } - - @Test(expected = IllegalArgumentException.class) - public void invalidMetaKeyDefinition() { - myBuilder.setText("test {@ invalid-key data}"); - } - - @Test(expected = IllegalArgumentException.class) - public void noProcessorForMetaKey() { - myBuilder.setText("{@key data}"); - } - - @Test - public void completeMetaInfo() { - String text = String.format("this is a test text with two inline meta-datas: {@%s meta \t text} and {@%s}", META_KEY, META_KEY); - myMockery.checking(new Expectations() {{ - one(myProcessor).process("meta \t text"); will(returnValue(new JLabel(""))); - one(myProcessor).process(""); will(returnValue(new JLabel(""))); - }}); - myBuilder.setText(text); - } -}