diff --git a/debugger/impl/com/intellij/debugger/ui/DebuggerSessionTab.java b/debugger/impl/com/intellij/debugger/ui/DebuggerSessionTab.java index 1cdcdca8c2bc..a155ecf8a784 100644 --- a/debugger/impl/com/intellij/debugger/ui/DebuggerSessionTab.java +++ b/debugger/impl/com/intellij/debugger/ui/DebuggerSessionTab.java @@ -34,6 +34,7 @@ import com.intellij.execution.ui.layout.RunnerLayoutUi; import com.intellij.ide.CommonActionsManager; import com.intellij.ide.actions.ContextHelpAction; import com.intellij.openapi.Disposable; +import com.intellij.openapi.ui.ComponentWithActions; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -290,7 +291,7 @@ public class DebuggerSessionTab implements LogConsoleManager, Disposable { public void addLogConsole(final String name, final String path, final long skippedContent) { final Ref content = new Ref(); - final LogConsole log = new LogConsole(myProject, new File(path), skippedContent, name) { + final LogConsole log = new LogConsole(myProject, new File(path), skippedContent, name, false) { public boolean isActive() { final Content logContent = content.get(); return logContent != null && logContent.isSelected(); @@ -447,7 +448,7 @@ public class DebuggerSessionTab implements LogConsoleManager, Disposable { private Content addLogComponent(final AdditionalTabComponent tabComponent) { @NonNls final String id = "Log-" + tabComponent.getTabTitle(); - final Content logContent = myUi.createContent(id, tabComponent.getComponent(), tabComponent.getTabTitle(), + final Content logContent = myUi.createContent(id, (ComponentWithActions)tabComponent, tabComponent.getTabTitle(), IconLoader.getIcon("/fileTypes/text.png"), tabComponent.getPreferredFocusableComponent()); logContent.setDescription(tabComponent.getTooltip()); myAdditionalContent.put(tabComponent, logContent); diff --git a/execution/impl/com/intellij/execution/impl/ConsoleViewImpl.java b/execution/impl/com/intellij/execution/impl/ConsoleViewImpl.java index a6d101f469be..bec81a72e92f 100644 --- a/execution/impl/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/execution/impl/com/intellij/execution/impl/ConsoleViewImpl.java @@ -859,6 +859,8 @@ public final class ConsoleViewImpl extends JPanel implements ConsoleView, Observ } public JComponent getPreferredFocusableComponent() { + //ensure editor created + final JComponent component = getComponent(); return myEditor.getContentComponent(); } diff --git a/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java b/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java index 1586f40be531..6a40c34cf1ba 100644 --- a/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java +++ b/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java @@ -17,6 +17,7 @@ package com.intellij.diagnostic.logging; import com.intellij.openapi.ui.ComponentContainer; +import com.intellij.openapi.ui.ComponentWithActions; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -26,7 +27,7 @@ import java.awt.*; * User: anna * Date: 22-Mar-2006 */ -public abstract class AdditionalTabComponent extends JPanel implements ComponentContainer { +public abstract class AdditionalTabComponent extends JPanel implements ComponentContainer, ComponentWithActions { protected AdditionalTabComponent(LayoutManager layout) { super(layout); } diff --git a/lang-api/src/com/intellij/execution/ui/layout/RunnerLayoutUi.java b/lang-api/src/com/intellij/execution/ui/layout/RunnerLayoutUi.java index 9faec324e9e8..f634749cf8fb 100644 --- a/lang-api/src/com/intellij/execution/ui/layout/RunnerLayoutUi.java +++ b/lang-api/src/com/intellij/execution/ui/layout/RunnerLayoutUi.java @@ -4,6 +4,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComponentWithActions; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManagerListener; import org.jetbrains.annotations.NotNull; @@ -32,6 +33,9 @@ public interface RunnerLayoutUi { @NotNull Content createContent(@NotNull String contentId, @NotNull JComponent component, @NotNull String displayName, @Nullable Icon icon, @Nullable JComponent toFocus); + @NotNull + Content createContent(@NotNull String contentId, @NotNull ComponentWithActions contentWithActions, @NotNull String displayName, @Nullable Icon icon, @Nullable JComponent toFocus); + boolean removeContent(@Nullable Content content, boolean dispose); @Nullable diff --git a/lang-impl/src/com/intellij/diagnostic/logging/LogConsole.java b/lang-impl/src/com/intellij/diagnostic/logging/LogConsole.java index 5b95a421568e..ae491d83d38d 100644 --- a/lang-impl/src/com/intellij/diagnostic/logging/LogConsole.java +++ b/lang-impl/src/com/intellij/diagnostic/logging/LogConsole.java @@ -56,13 +56,17 @@ public abstract class LogConsole extends AdditionalTabComponent implements Chang private Project myProject; private String myPath; private boolean myWasInitialized; + private JPanel myTopComponent = new JPanel(new BorderLayout()); + private ActionGroup myActions; + private boolean myBuildInActions; - public LogConsole(Project project, File file, long skippedContents, String title) { + public LogConsole(Project project, File file, long skippedContents, String title, final boolean buildInActions) { super(new BorderLayout()); mySkippedContents = skippedContents; myTitle = title; myProject = project; myPath = file.getAbsolutePath(); + myBuildInActions = buildInActions; myReaderThread = new ReaderThread(file); TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project); myConsole = builder.getConsole(); @@ -72,42 +76,10 @@ public abstract class LogConsole extends AdditionalTabComponent implements Chang @SuppressWarnings({"NonStaticInitializer"}) private JComponent createToolbar(){ - DefaultActionGroup group = new DefaultActionGroup(); final LogConsolePreferences registrar = getPreferences(); - final ArrayList filters = new ArrayList(); - filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.INFO), IconLoader.getIcon("/ant/filterInfo.png")){ - public boolean isAcceptable(String line) { - return registrar.isApplicable(line, myPrevType); - } - }); - filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.WARNING), IconLoader.getIcon("/ant/filterWarning.png")){ - public boolean isAcceptable(String line) { - return registrar.isApplicable(line, myPrevType); - } - }); - filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.ERROR), IconLoader.getIcon("/ant/filterError.png")){ - public boolean isAcceptable(String line) { - return registrar.isApplicable(line, myPrevType); - } - }); - filters.addAll(registrar.getRegisteredLogFilters()); - for (final LogFilter filter : filters) { - group.add(new ToggleAction(filter.getName(), filter.getName(), filter.getIcon()){ - public boolean isSelected(AnActionEvent e) { - return registrar.isFilterSelected(filter); - } - public void setSelected(AnActionEvent e, boolean state) { - registrar.setFilterSelected(filter, state); - } - }); - } - final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true); - JPanel panel = new JPanel(new BorderLayout()); - panel.add(actionToolbar.getComponent(), BorderLayout.WEST); myFilter.reset(); myFilter.setSelectedItem(registrar.CUSTOM_FILTER != null ? registrar.CUSTOM_FILTER : ""); - panel.add(myFilter, BorderLayout.EAST); new AnAction(){ { registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)), LogConsole.this); @@ -116,9 +88,67 @@ public abstract class LogConsole extends AdditionalTabComponent implements Chang myFilter.requestFocusInWindow(); } }; - return panel; + + if (myBuildInActions) { + final JComponent tbComp = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, getOrCreateActions(), true).getComponent(); + myTopComponent.add(tbComp, BorderLayout.CENTER); + myTopComponent.add(myFilter, BorderLayout.EAST); + } + + + return myTopComponent; } + public ActionGroup getOrCreateActions() { + if (myActions != null) return myActions; + + final LogConsolePreferences prefs = getPreferences(); + + DefaultActionGroup group = new DefaultActionGroup(); + + final AnAction[] actions = myConsole.createUpDownStacktraceActions(); + for (AnAction action : actions) { + group.add(action); + } + + group.addSeparator(); + + final ArrayList filters = new ArrayList(); + filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.INFO), IconLoader.getIcon("/ant/filterInfo.png")){ + public boolean isAcceptable(String line) { + return prefs.isApplicable(line, myPrevType); + } + }); + filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.WARNING), IconLoader.getIcon("/ant/filterWarning.png")){ + public boolean isAcceptable(String line) { + return prefs.isApplicable(line, myPrevType); + } + }); + filters.add(new LogFilter(DiagnosticBundle.message("log.console.filter.by.type", LogConsolePreferences.ERROR), IconLoader.getIcon("/ant/filterError.png")){ + public boolean isAcceptable(String line) { + return prefs.isApplicable(line, myPrevType); + } + }); + filters.addAll(prefs.getRegisteredLogFilters()); + + for (final LogFilter filter : filters) { + group.add(new ToggleAction(filter.getName(), filter.getName(), filter.getIcon()){ + public boolean isSelected(AnActionEvent e) { + return prefs.isFilterSelected(filter); + } + + public void setSelected(AnActionEvent e, boolean state) { + prefs.setFilterSelected(filter, state); + } + }); + } + + myActions = group; + + return myActions; + } + + public void onFilterStateChange(final LogFilter filter) { filterConsoleOutput(new Condition() { public boolean value(final String line) { @@ -138,12 +168,6 @@ public abstract class LogConsole extends AdditionalTabComponent implements Chang public JComponent getComponent() { if (!myWasInitialized) { myWasInitialized = true; - final DefaultActionGroup group = new DefaultActionGroup(); - final AnAction[] actions = myConsole.createUpDownStacktraceActions(); - for (AnAction action : actions) { - group.add(action); - } - add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, false).getComponent(), BorderLayout.WEST); add(myConsole.getComponent(), BorderLayout.CENTER); add(createToolbar(), BorderLayout.NORTH); } @@ -383,8 +407,27 @@ public abstract class LogConsole extends AdditionalTabComponent implements Chang } } + public ActionGroup getToolbarActions() { + return getOrCreateActions(); + } + + public String getToolbarPlace() { + return ActionPlaces.UNKNOWN; + } + + public JComponent getToolbarContextComponent() { + return myConsole.getComponent(); + } public JComponent getPreferredFocusableComponent() { return myConsole.getPreferredFocusableComponent(); } + + public JComponent getSearchComponent() { + return myFilter; + } + + public boolean isContentBuiltIn() { + return myBuildInActions; + } } diff --git a/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java b/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java index 5fad498f907e..f6b9fd00d995 100644 --- a/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java +++ b/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java @@ -22,6 +22,7 @@ import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.execution.ui.layout.RunnerLayoutUi; import com.intellij.ide.actions.ContextHelpAction; import com.intellij.openapi.Disposable; +import com.intellij.openapi.ui.ComponentWithActions; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; @@ -140,7 +141,7 @@ public class RunContentBuilder implements LogConsoleManager, Disposable { } public void addLogConsole(final String name, final String path, final long skippedContent) { - final LogConsole log = new LogConsole(myProject, new File(path), skippedContent, name){ + final LogConsole log = new LogConsole(myProject, new File(path), skippedContent, name, false){ public boolean isActive() { final Content content = myUi.findContent(path); return content != null && content.isSelected(); @@ -210,7 +211,7 @@ public class RunContentBuilder implements LogConsoleManager, Disposable { } public void addAdditionalTabComponent(final AdditionalTabComponent tabComponent, final String id) { - final Content content = myUi.createContent(id, tabComponent.getComponent(), tabComponent.getTabTitle(), + final Content content = myUi.createContent(id, (ComponentWithActions)tabComponent, tabComponent.getTabTitle(), IconLoader.getIcon("/debugger/console.png"), tabComponent.getPreferredFocusableComponent()); diff --git a/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index ef54b796af4e..e40592f3c674 100644 --- a/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -1,7 +1,7 @@ package com.intellij.execution.ui.layout.impl; -import com.intellij.execution.ui.layout.actions.RestoreViewAction; import com.intellij.execution.ui.layout.RunnerLayoutUi; +import com.intellij.execution.ui.layout.actions.RestoreViewAction; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; @@ -224,19 +224,26 @@ public class RunnerContentUi TabInfo tab = new TabInfo(grid).setObject(getStateFor(content).getTab()).setText("Tab"); - Wrapper leftWrapper = new Wrapper(); - myCommonActionsPlaceholder.put(grid, leftWrapper); + Wrapper left = new Wrapper(); + myCommonActionsPlaceholder.put(grid, left); - Wrapper rightWrapper = new Wrapper(); - myMinimizedButtonsPlaceholder.put(grid, rightWrapper); - NonOpaquePanel sideComponent = new NonOpaquePanel(new CommonToolbarLayout(leftWrapper, rightWrapper)); + Wrapper minimizedToolbar = new Wrapper(); + myMinimizedButtonsPlaceholder.put(grid, minimizedToolbar); + + + final Wrapper searchComponent = new Wrapper(); + if (content.getSearchComponent() != null) { + searchComponent.setContent(content.getSearchComponent()); + } + + TwoSideComponent right = new TwoSideComponent(searchComponent, minimizedToolbar); + + + NonOpaquePanel sideComponent = new TwoSideComponent(left, right); tab.setSideComponent(sideComponent); - sideComponent.add(leftWrapper); - sideComponent.add(rightWrapper); - tab.setTabLabelActions((ActionGroup)myActionManager.getAction(VIEW_TOOLBAR), TAB_TOOLBAR_PLACE); myTabs.addTab(tab); @@ -757,6 +764,14 @@ public class RunnerContentUi }); } + private class TwoSideComponent extends NonOpaquePanel { + private TwoSideComponent(JComponent left, JComponent right) { + setLayout(new CommonToolbarLayout(left, right)); + add(left); + add(right); + } + } + private static class CommonToolbarLayout extends AbstractLayoutManager { private final JComponent myLeft; private final JComponent myRight; @@ -805,6 +820,23 @@ public class RunnerContentUi myRight.setBounds((int)myLeft.getBounds().getMaxX(), 0, parent.getWidth() - myLeft.getWidth(), parent.getHeight()); } + + toMakeVerticallyInCenter(myLeft, parent); + toMakeVerticallyInCenter(myRight, parent); + + } + + private void toMakeVerticallyInCenter(JComponent comp, Container parent) { + final Rectangle compBounds = comp.getBounds(); + int compHeight = comp.getPreferredSize().height; + final int parentHeight = parent.getHeight(); + if (compHeight > parentHeight) { + compHeight = parentHeight; + } + + int y = (int)Math.floor(parentHeight / 2.0 - compHeight / 2.0); + comp.setBounds(compBounds.x, y, compBounds.width, compHeight); + } } diff --git a/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java b/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java index 8bb37b122c45..228ce8f1cf12 100644 --- a/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java +++ b/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java @@ -2,6 +2,7 @@ package com.intellij.execution.ui.layout.impl; import com.intellij.execution.ui.layout.RunnerLayoutUi; import com.intellij.openapi.Disposable; +import com.intellij.openapi.ui.ComponentWithActions; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; @@ -84,16 +85,28 @@ public class RunnerLayoutUiImpl implements Disposable, RunnerLayoutUi { @NotNull public Content createContent(@NotNull String id, @NotNull JComponent component, @NotNull String displayName, @Nullable Icon icon, @Nullable JComponent focusable) { - final Content content = getContentFactory().createContent(component, displayName, false); - content.putUserData(CONTENT_TYPE, id); - content.putUserData(View.ID, id); - content.setIcon(icon); - if (focusable != null) { - content.setPreferredFocusableComponent(focusable); - } - return content; + return createContent(id, new ComponentWithActions.Impl(component), displayName, icon, focusable); } + @NotNull + public Content createContent(@NotNull final String contentId, @NotNull final ComponentWithActions withActions, @NotNull final String displayName, + @Nullable final Icon icon, + @Nullable final JComponent toFocus) { + final Content content = getContentFactory().createContent(withActions.getComponent(), displayName, false); + content.putUserData(CONTENT_TYPE, contentId); + content.putUserData(View.ID, contentId); + content.setIcon(icon); + if (toFocus != null) { + content.setPreferredFocusableComponent(toFocus); + } + + if (!withActions.isContentBuiltIn()) { + content.setSearchComponent(withActions.getSearchComponent()); + content.setActions(withActions.getToolbarActions(), withActions.getToolbarPlace(), withActions.getToolbarContextComponent()); + } + + return content; + } @NotNull public JComponent getComponent() { diff --git a/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java b/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java new file mode 100644 index 000000000000..49fc4a699811 --- /dev/null +++ b/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java @@ -0,0 +1,74 @@ +package com.intellij.openapi.ui; + +import com.intellij.openapi.actionSystem.ActionGroup; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public interface ComponentWithActions { + + @Nullable + ActionGroup getToolbarActions(); + + @Nullable + JComponent getSearchComponent(); + + @Nullable + String getToolbarPlace(); + + @Nullable + JComponent getToolbarContextComponent(); + + @NotNull + JComponent getComponent(); + + boolean isContentBuiltIn(); + + class Impl implements ComponentWithActions { + private ActionGroup myToolbar; + private String myToolbarPlace; + private JComponent myToolbarContext; + private JComponent mySearchComponent; + private JComponent myComponent; + + public Impl(final ActionGroup toolbar, final String toolbarPlace, final JComponent toolbarContext, + final JComponent searchComponent, + final JComponent component) { + myToolbar = toolbar; + myToolbarPlace = toolbarPlace; + myToolbarContext = toolbarContext; + mySearchComponent = searchComponent; + myComponent = component; + } + + public boolean isContentBuiltIn() { + return false; + } + + public Impl(final JComponent component) { + this(null, null, null, null, component); + } + + public ActionGroup getToolbarActions() { + return myToolbar; + } + + public JComponent getSearchComponent() { + return mySearchComponent; + } + + public String getToolbarPlace() { + return myToolbarPlace; + } + + public JComponent getToolbarContextComponent() { + return myToolbarContext; + } + + @NotNull + public JComponent getComponent() { + return myComponent; + } + } +} diff --git a/platform-api/src/com/intellij/ui/content/Content.java b/platform-api/src/com/intellij/ui/content/Content.java index 777e2ecdb722..3d1716d8dea9 100644 --- a/platform-api/src/com/intellij/ui/content/Content.java +++ b/platform-api/src/com/intellij/ui/content/Content.java @@ -87,8 +87,10 @@ public interface Content extends UserDataHolder, ComponentContainer { void setCloseable(boolean closeable); void setActions(ActionGroup actions, String place, @Nullable JComponent contextComponent); + void setSearchComponent(@Nullable JComponent comp); ActionGroup getActions(); + @Nullable JComponent getSearchComponent(); String getPlace(); JComponent getActionsContextComponent(); diff --git a/platform-api/src/com/intellij/ui/tabs/JBTabs.java b/platform-api/src/com/intellij/ui/tabs/JBTabs.java index 2dca1041cbb2..d7901cc01851 100644 --- a/platform-api/src/com/intellij/ui/tabs/JBTabs.java +++ b/platform-api/src/com/intellij/ui/tabs/JBTabs.java @@ -268,6 +268,8 @@ public class JBTabs extends JComponent implements PropertyChangeListener, TimerL private JComponent getToFocus() { final TabInfo info = getSelectedInfo(); + if (info == null) return null; + JComponent toFocus = null; if (isRequestFocusOnLastFocusedComponent() && info.getLastFocusOwner() != null && !isMyChildIsFocusedNow()) { diff --git a/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java b/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java index 6f9719f9f354..ebb08f313237 100644 --- a/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java +++ b/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java @@ -41,6 +41,7 @@ public class ContentImpl extends UserDataHolderBase implements Content { private boolean myAlerting = false; private JComponent myActionsContextComponent; + private JComponent mySearchComponent; public ContentImpl(JComponent component, String displayName, boolean isPinnable) { myComponent = component; @@ -229,4 +230,12 @@ public class ContentImpl extends UserDataHolderBase implements Content { public void fireAlert() { myChangeSupport.firePropertyChange(PROP_ALERT, null, true); } + + public void setSearchComponent(@Nullable final JComponent comp) { + mySearchComponent = comp; + } + + public JComponent getSearchComponent() { + return mySearchComponent; + } }