From 53348aaeda7b5db163528c3797469b1a50831799 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 1 Nov 2012 19:26:55 +0400 Subject: [PATCH] IDEA-85676 add logcat to debugger session tab --- .../diagnostic/logging/LogConsoleBase.java | 22 ++- .../android/logcat/AndroidLogFilterModel.java | 50 +++--- .../AndroidLogcatToolWindowFactory.java | 2 +- .../logcat/AndroidLogcatToolWindowView.form | 16 +- .../logcat/AndroidLogcatToolWindowView.java | 130 ++++++++++----- .../android/run/AndroidDebugRunner.java | 151 +++++++++++++++++- .../run/AndroidRunConfigurationBase.java | 34 +--- .../android/run/AndroidRunningState.java | 15 +- 8 files changed, 291 insertions(+), 129 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java index 5ad8b6a6224e..96f05fbacf94 100644 --- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java +++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java @@ -79,6 +79,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L private LogFilterModel myModel; private final List myListeners = new ArrayList(); + private final List myFilters; private FilterComponent myFilter = new FilterComponent("LOG_FILTER_HISTORY", 5) { public void filter() { @@ -100,6 +101,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L myProject = project; myTitle = title; myModel = model; + myFilters = myModel.getLogFilters(); myReaderThread = new ReaderThread(reader); myBuildInActions = buildInActions; TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project); @@ -215,6 +217,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L return; } if (isActive() && !readerThread.myRunning) { + resetLogFilter(); myFilter.setSelectedItem(myModel.getCustomFilter()); readerThread.startRunning(); ApplicationManager.getApplication().executeOnPooledThread(readerThread); @@ -476,14 +479,8 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L } public JComponent getSearchComponent() { - List filters = myModel.getLogFilters(); - myLogFilterCombo.setModel(new DefaultComboBoxModel(filters.toArray(new LogFilter[filters.size()]))); - for (LogFilter filter : filters) { - if (myModel.isFilterSelected(filter)) { - myLogFilterCombo.setSelectedItem(filter); - break; - } - } + myLogFilterCombo.setModel(new DefaultComboBoxModel(myFilters.toArray(new LogFilter[myFilters.size()]))); + resetLogFilter(); myLogFilterCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { final LogFilter filter = (LogFilter)myLogFilterCombo.getSelectedItem(); @@ -501,6 +498,15 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L return mySearchComponent; } + private void resetLogFilter() { + for (LogFilter filter : myFilters) { + if (myModel.isFilterSelected(filter)) { + myLogFilterCombo.setSelectedItem(filter); + break; + } + } + } + @NotNull protected Component getTextFilterComponent() { return myFilter; diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogFilterModel.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogFilterModel.java index a10f21305f27..df562ed5fa8b 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogFilterModel.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogFilterModel.java @@ -21,6 +21,7 @@ import com.intellij.diagnostic.logging.LogFilter; import com.intellij.diagnostic.logging.LogFilterListener; import com.intellij.diagnostic.logging.LogFilterModel; import com.intellij.execution.process.ProcessOutputTypes; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; @@ -47,19 +48,15 @@ public abstract class AndroidLogFilterModel extends LogFilterModel { private boolean myFullMessageApplicableByCustomFilter = false; private StringBuilder myMessageBuilder = new StringBuilder(); - private LogFilter mySelectedLogFilter; - private List myLogFilters = new ArrayList(); + protected List myLogFilters = new ArrayList(); - public AndroidLogFilterModel(String initialLogLevelName) { + public AndroidLogFilterModel() { for (Log.LogLevel logLevel : Log.LogLevel.values()) { - AndroidLogFilter filter = new AndroidLogFilter(logLevel); - if (logLevel.name().equals(initialLogLevelName)) { - mySelectedLogFilter = filter; - } - myLogFilters.add(filter); + myLogFilters.add(new AndroidLogFilter(logLevel)); } } + public void updateCustomFilter(String filter) { super.updateCustomFilter(filter); setCustomFilter(filter); @@ -81,7 +78,7 @@ public abstract class AndroidLogFilterModel extends LogFilterModel { return null; } - protected abstract void saveLogLevel(Log.LogLevel logLevel); + protected abstract void saveLogLevel(String logLevelName); public void addFilterListener(LogFilterListener listener) { myListeners.add(listener); @@ -124,11 +121,8 @@ public abstract class AndroidLogFilterModel extends LogFilterModel { @Override public boolean isApplicable(String text) { if (!super.isApplicable(text)) return false; - - if (!(mySelectedLogFilter == null || mySelectedLogFilter.isAcceptable(text))) { - return false; - } - return true; + final LogFilter selectedLogLevelFilter = getSelectedLogLevelFilter(); + return selectedLogLevelFilter == null || selectedLogLevelFilter.isAcceptable(text); } public boolean isApplicableByCustomFilter(String text) { @@ -207,7 +201,7 @@ public abstract class AndroidLogFilterModel extends LogFilterModel { } @Nullable - private static Log.LogLevel getLogLevel(@NotNull String name) { + protected static Log.LogLevel getLogLevel(@NotNull String name) { for (Log.LogLevel level : Log.LogLevel.values()) { if (name.equals(level.name())) { return level; @@ -216,14 +210,32 @@ public abstract class AndroidLogFilterModel extends LogFilterModel { return null; } + public abstract String getSelectedLogLevelName(); + + @Nullable + private LogFilter getSelectedLogLevelFilter() { + final String filterName = getSelectedLogLevelName(); + if (filterName != null) { + for (AndroidLogFilter logFilter : myLogFilters) { + if (filterName.equals(logFilter.myLogLevel.name())) { + return logFilter; + } + } + } + return null; + } + public boolean isFilterSelected(LogFilter filter) { - return mySelectedLogFilter == filter; + return filter == getSelectedLogLevelFilter(); } public void selectFilter(LogFilter filter) { - if (filter != mySelectedLogFilter && filter instanceof AndroidLogFilter) { - mySelectedLogFilter = filter; - saveLogLevel(((AndroidLogFilter)filter).myLogLevel); + if (!(filter instanceof AndroidLogFilter)) { + return; + } + String newFilterName = ((AndroidLogFilter)filter).myLogLevel.name(); + if (!Comparing.equal(newFilterName, getSelectedLogLevelName())) { + saveLogLevel(newFilterName); fireFilterChange(filter); } } diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java index a58fce395583..94fc99a294cd 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java @@ -62,7 +62,7 @@ public class AndroidLogcatToolWindowFactory implements ToolWindowFactory { toolWindow.setToHideOnEmptyContent(true); toolWindow.setTitle(TOOL_WINDOW_ID); - final AndroidLogcatToolWindowView view = new AndroidLogcatToolWindowView(project) { + final AndroidLogcatToolWindowView view = new AndroidLogcatToolWindowView(project, null, false) { @Override protected boolean isActive() { ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(TOOL_WINDOW_ID); diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.form b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.form index 612ade05a828..30ca9e5c42f1 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.form +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.form @@ -25,7 +25,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -93,8 +93,8 @@ - - + + @@ -122,14 +122,6 @@ - - - - - - - - diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java index 6b6b6d6de598..50d036cc8e86 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java @@ -36,8 +36,10 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.ui.CollectionListModel; +import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBList; +import com.intellij.ui.components.JBScrollPane; import com.intellij.util.IconUtil; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.sdk.AndroidPlatform; @@ -71,13 +73,14 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { private JComboBox myDeviceCombo; private JPanel myConsoleWrapper; private final Splitter mySplitter; - private JButton myClearLogButton; private JPanel mySearchComponentWrapper; private JPanel myFiltersToolbarPanel; private JBList myFiltersList; private JPanel myLeftPanel; private JPanel myRightPanel; + private JPanel myTopPanel; + private JBScrollPane myFiltersListScrollPane; private volatile IDevice myDevice; private final Object myLock = new Object(); @@ -86,6 +89,8 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { private volatile Reader myCurrentReader; private volatile Writer myCurrentWriter; + private final IDevice myPreselectedDevice; + private final AndroidDebugBridge.IDeviceChangeListener myDeviceChangeListener = new AndroidDebugBridge.IDeviceChangeListener() { public void deviceConnected(IDevice device) { updateInUIThread(); @@ -139,8 +144,9 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } @SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"}) - public AndroidLogcatToolWindowView(final Project project) { + public AndroidLogcatToolWindowView(final Project project, @Nullable IDevice preselectedDevice, boolean addBorderToScrollPane) { myProject = project; + myPreselectedDevice = preselectedDevice; Disposer.register(myProject, this); mySplitter = new Splitter(); @@ -148,26 +154,36 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { mySplitter.setSecondComponent(myRightPanel); mySplitter.setProportion(0.2f); - myFiltersList.setBorder(BorderFactory.createEmptyBorder()); + if (addBorderToScrollPane) { + myFiltersListScrollPane.setViewportBorder(IdeBorderFactory.createBorder()); + } + else { + myFiltersList.setBorder(BorderFactory.createEmptyBorder()); + } - myDeviceCombo.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - updateLogConsole(); - } - }); - myDeviceCombo.setRenderer(new ListCellRendererWrapper() { - @Override - public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value == null) { - setText("[none]"); + if (preselectedDevice == null) { + myDeviceCombo.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + updateLogConsole(); } - else if (value instanceof IDevice) { - setText(((IDevice)value).getSerialNumber()); + }); + myDeviceCombo.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { + if (value == null) { + setText("[none]"); + } + else if (value instanceof IDevice) { + setText(((IDevice)value).getSerialNumber()); + } } - } - }); + }); + } + else { + myTopPanel.setVisible(false); + } final AndroidLogFilterModel logFilterModel = - new AndroidLogFilterModel(AndroidLogcatFiltersPreferences.getInstance(project).TOOL_WINDOW_LOG_LEVEL) { + new AndroidLogFilterModel() { private ConfiguredFilter myConfiguredFilter; @Override @@ -176,8 +192,13 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } @Override - protected void saveLogLevel(Log.LogLevel logLevel) { - AndroidLogcatFiltersPreferences.getInstance(project).TOOL_WINDOW_LOG_LEVEL = logLevel.name(); + protected void saveLogLevel(String logLevelName) { + AndroidLogcatFiltersPreferences.getInstance(project).TOOL_WINDOW_LOG_LEVEL = logLevelName; + } + + @Override + public String getSelectedLogLevelName() { + return AndroidLogcatFiltersPreferences.getInstance(project).TOOL_WINDOW_LOG_LEVEL; } @Override @@ -215,7 +236,9 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } } }); - mySearchComponentWrapper.add(myLogConsole.getSearchComponent()); + if (preselectedDevice == null) { + mySearchComponentWrapper.add(createSearchComponent(project)); + } JComponent consoleComponent = myLogConsole.getComponent(); final DefaultActionGroup group1 = new DefaultActionGroup(); @@ -233,7 +256,6 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group2, true).getComponent(); myFiltersToolbarPanel.add(tbComp2, BorderLayout.CENTER); - final String savedConfiguredFilterName = AndroidLogcatFiltersPreferences.getInstance(project).TOOL_WINDOW_CONFIGURED_FILTER; myFiltersList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { @@ -242,7 +264,10 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } final String filterName = (String)myFiltersList.getSelectedValue(); - final ConfiguredFilter filter = filterName != null ? compileConfiguredFilter(filterName) : null; + if (filterName == null) { + return; + } + final ConfiguredFilter filter = compileConfiguredFilter(filterName); ProgressManager.getInstance().run(new Task.Backgroundable(myProject, LogConsoleBase.APPLYING_FILTER_TITLE) { @Override @@ -255,7 +280,22 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { myConsoleWrapper.add(consoleComponent, BorderLayout.CENTER); Disposer.register(this, myLogConsole); - myClearLogButton.addActionListener(new ActionListener() { + + AndroidDebugBridge.addDeviceChangeListener(myDeviceChangeListener); + + updateDevices(); + updateLogConsole(); + updateConfiguredFilters(AndroidLogcatFiltersPreferences.getInstance(myProject).TOOL_WINDOW_CONFIGURED_FILTER); + if (myFiltersList.getSelectedValue() == null && myFiltersList.getItemsCount() > 0) { + myFiltersList.setSelectedIndex(0); + } + } + + @NotNull + public JPanel createSearchComponent(final Project project) { + final JPanel searchComponent = new JPanel(new BorderLayout()); + final JButton clearLogButton = new JButton(AndroidBundle.message("android.logcat.clear.log.button.title")); + clearLogButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { IDevice device = getSelectedDevice(); if (device != null) { @@ -264,17 +304,9 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } } }); - - AndroidDebugBridge.addDeviceChangeListener(myDeviceChangeListener); - - updateDevices(); - updateLogConsole(); - updateConfiguredFilters(); - - myFiltersList.setSelectedValue(savedConfiguredFilterName, true); - if (myFiltersList.getSelectedValue() == null && myFiltersList.getItemsCount() > 0) { - myFiltersList.setSelectedIndex(0); - } + searchComponent.add(myLogConsole.getSearchComponent(), BorderLayout.CENTER); + searchComponent.add(clearLogButton, BorderLayout.EAST); + return searchComponent; } protected abstract boolean isActive(); @@ -325,8 +357,14 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { } public void activate() { - updateDevices(); - updateLogConsole(); + if (isActive()) { + updateDevices(); + updateLogConsole(); + updateConfiguredFilters(AndroidLogcatFiltersPreferences.getInstance(myProject).TOOL_WINDOW_CONFIGURED_FILTER); + if (myFiltersList.getSelectedValue() == null && myFiltersList.getItemsCount() > 0) { + myFiltersList.setSelectedIndex(0); + } + } if (myLogConsole != null) { myLogConsole.activate(); } @@ -371,7 +409,7 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { @Nullable public IDevice getSelectedDevice() { - return (IDevice)myDeviceCombo.getSelectedItem(); + return myPreselectedDevice != null ? myPreselectedDevice : (IDevice)myDeviceCombo.getSelectedItem(); } @Nullable @@ -386,8 +424,10 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { return null; } - private void updateConfiguredFilters() { - final String selectedFilterName = (String)myFiltersList.getSelectedValue(); + private void updateConfiguredFilters(String defaultSelection) { + final String selectedFilterName = defaultSelection != null + ? defaultSelection + : (String)myFiltersList.getSelectedValue(); final AndroidConfiguredLogFilters filters = AndroidConfiguredLogFilters.getInstance(myProject); final List entries = filters.getFilterEntries(); @@ -425,7 +465,9 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { if (devices.length > 0 && temp == null) { temp = devices[0]; } - myDeviceCombo.setSelectedItem(temp); + if (temp != null) { + myDeviceCombo.setSelectedItem(temp); + } } } else { @@ -502,7 +544,7 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { entries.add(newEntry); configuredLogFilters.setFilterEntries(entries); - updateConfiguredFilters(); + updateConfiguredFilters(null); myFiltersList.setSelectedValue(newEntry.getName(), true); } } @@ -534,7 +576,7 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { entries.remove(filterEntry); configuredLogFilters.setFilterEntries(entries); - updateConfiguredFilters(); + updateConfiguredFilters(null); final int index = selectedIndex < myFiltersList.getItemsCount() ? selectedIndex : myFiltersList.getItemsCount() - 1; @@ -567,7 +609,7 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { if (dialog.isOK()) { final String newName = filterEntry.getName(); - updateConfiguredFilters(); + updateConfiguredFilters(null); myFiltersList.setSelectedValue(newName, true); } } diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidDebugRunner.java b/plugins/android/src/org/jetbrains/android/run/AndroidDebugRunner.java index 9d51584f12ee..acaca2cdf6ca 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidDebugRunner.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidDebugRunner.java @@ -17,6 +17,7 @@ package org.jetbrains.android.run; import com.android.ddmlib.IDevice; import com.intellij.debugger.engine.RemoteDebugProcessHandler; +import com.intellij.debugger.ui.DebuggerContentInfo; import com.intellij.debugger.ui.DebuggerPanelsManager; import com.intellij.debugger.ui.DebuggerSessionTab; import com.intellij.execution.*; @@ -28,21 +29,32 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.DefaultProgramRunner; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; -import com.intellij.execution.ui.ConsoleView; -import com.intellij.execution.ui.RunContentDescriptor; -import com.intellij.execution.ui.RunContentManager; +import com.intellij.execution.ui.*; +import com.intellij.execution.ui.layout.PlaceInGrid; +import com.intellij.icons.AllIcons; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiClass; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentManagerAdapter; +import com.intellij.ui.content.ContentManagerEvent; +import com.intellij.xdebugger.XDebuggerBundle; +import icons.AndroidIcons; import org.jetbrains.android.dom.manifest.Instrumentation; import org.jetbrains.android.dom.manifest.Manifest; +import org.jetbrains.android.logcat.AndroidLogcatToolWindowView; import org.jetbrains.android.run.testing.AndroidTestRunConfiguration; import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; + import static com.intellij.execution.process.ProcessOutputTypes.STDERR; /** @@ -55,6 +67,8 @@ public class AndroidDebugRunner extends DefaultProgramRunner { private static final Object myReaderLock = new Object(); private static final Object myDebugLock = new Object(); + @NonNls private static final String ANDROID_DEBUG_SELECTED_TAB_PROPERTY = "ANDROID_DEBUG_SELECTED_TAB"; + public static final String ANDROID_LOGCAT_CONTENT_ID = "Android Logcat"; private static void tryToCloseOldSessions(final Executor executor, Project project) { final ExecutionManager manager = ExecutionManager.getInstance(project); @@ -133,17 +147,20 @@ public class AndroidDebugRunner extends DefaultProgramRunner { private final RunnerSettings myRunnerSettings; private final ConfigurationPerRunnerSettings myConfigurationSettings; private final AndroidRunningState myState; + private final IDevice myDevice; public AndroidDebugState(Project project, RemoteConnection connection, RunnerSettings runnerSettings, ConfigurationPerRunnerSettings configurationSettings, - AndroidRunningState state) { + AndroidRunningState state, + IDevice device) { myProject = project; myConnection = connection; myRunnerSettings = runnerSettings; myConfigurationSettings = configurationSettings; myState = state; + myDevice = device; } public RunnerSettings getRunnerSettings() { @@ -157,7 +174,9 @@ public class AndroidDebugRunner extends DefaultProgramRunner { public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException { RemoteDebugProcessHandler process = new RemoteDebugProcessHandler(myProject); myState.setProcessHandler(process); - ConsoleView console = myState.attachConsole(); + final ConsoleView c = myState.getConfiguration().attachConsole(myState, executor); + final boolean resetSelectedTab = myState.getConfiguration() instanceof AndroidRunConfiguration; + final MyLogcatExecutionConsole console = new MyLogcatExecutionConsole(myProject, myDevice, process, c, resetSelectedTab); return new DefaultExecutionResult(console, process); } @@ -175,6 +194,107 @@ public class AndroidDebugRunner extends DefaultProgramRunner { return DefaultDebugExecutor.EXECUTOR_ID.equals(executorId) && profile instanceof AndroidRunConfigurationBase; } + private static class MyLogcatExecutionConsole implements ExecutionConsoleEx { + private final Project myProject; + private final AndroidLogcatToolWindowView myToolWindowView; + private final ConsoleView myConsoleView; + private final boolean myResetSelectedTab; + + private MyLogcatExecutionConsole(Project project, + IDevice device, + RemoteDebugProcessHandler process, + ConsoleView consoleView, + boolean resetSelectedTab) { + myProject = project; + myConsoleView = consoleView; + myResetSelectedTab = resetSelectedTab; + myToolWindowView = new AndroidLogcatToolWindowView(project, device, true) { + @Override + protected boolean isActive() { + final DebuggerSessionTab sessionTab = DebuggerPanelsManager.getInstance(myProject).getSessionTab(); + if (sessionTab == null) { + return false; + } + final Content content = sessionTab.getUi().findContent(ANDROID_LOGCAT_CONTENT_ID); + return content != null && content.isSelected(); + } + }; + Disposer.register(this, myToolWindowView); + myToolWindowView.getLogConsole().attachStopLogConsoleTrackingListener(process); + } + + @Override + public void buildUi(final RunnerLayoutUi layoutUi) { + final Content consoleContent = layoutUi.createContent(DebuggerContentInfo.CONSOLE_CONTENT, getComponent(), + XDebuggerBundle.message("debugger.session.tab.console.content.name"), + AllIcons.Debugger.Console, getPreferredFocusableComponent()); + + consoleContent.setCloseable(false); + layoutUi.addContent(consoleContent, 1, PlaceInGrid.bottom, false); + + // todo: provide other icon + final Content logcatContent = layoutUi.createContent(ANDROID_LOGCAT_CONTENT_ID, myToolWindowView.getContentPanel(), "Logcat", + AndroidIcons.Android, getPreferredFocusableComponent()); + logcatContent.setCloseable(false); + logcatContent.setSearchComponent(myToolWindowView.createSearchComponent(myProject)); + layoutUi.addContent(logcatContent, 2, PlaceInGrid.bottom, false); + + if (myResetSelectedTab) { + final String tabName = PropertiesComponent.getInstance().getValue(ANDROID_DEBUG_SELECTED_TAB_PROPERTY); + Content selectedContent = logcatContent; + + if (tabName != null) { + for (Content content : layoutUi.getContents()) { + if (tabName.equals(content.getDisplayName())) { + selectedContent = content; + } + } + } + layoutUi.getContentManager().setSelectedContent(selectedContent); + } + + layoutUi.addListener(new ContentManagerAdapter() { + public void selectionChanged(final ContentManagerEvent event) { + if (myResetSelectedTab) { + final Content content = event.getContent(); + + if (content.isSelected()) { + PropertiesComponent.getInstance().setValue(ANDROID_DEBUG_SELECTED_TAB_PROPERTY, content.getDisplayName()); + } + } + myToolWindowView.activate(); + } + }, myToolWindowView); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + myToolWindowView.activate(); + } + }); + } + + @Nullable + @Override + public String getExecutionConsoleId() { + return "ANDROID_LOGCAT"; + } + + @Override + public JComponent getComponent() { + return myConsoleView.getComponent(); + } + + @Override + public JComponent getPreferredFocusableComponent() { + return myConsoleView.getPreferredFocusableComponent(); + } + + @Override + public void dispose() { + } + } + private class MyDebugLauncher implements DebugLauncher { private final Project myProject; private final Executor myExecutor; @@ -203,7 +323,7 @@ public class AndroidDebugRunner extends DefaultProgramRunner { final DebuggerPanelsManager manager = DebuggerPanelsManager.getInstance(myProject); RemoteState st = new AndroidDebugState(myProject, new RemoteConnection(true, "localhost", debugPort, false), myEnvironment.getRunnerSettings(), - myEnvironment.getConfigurationSettings(), myRunningState); + myEnvironment.getConfigurationSettings(), myRunningState, device); RunContentDescriptor debugDescriptor = null; final ProcessHandler processHandler = myRunningState.getProcessHandler(); try { @@ -227,9 +347,26 @@ public class AndroidDebugRunner extends DefaultProgramRunner { myRunningState.getProcessHandler().putUserData(ANDROID_PROCESS_HANDLER, debugDescriptor); - DebuggerSessionTab sessionTab = manager.getSessionTab(); + final DebuggerSessionTab sessionTab = manager.getSessionTab(); assert sessionTab != null; sessionTab.setEnvironment(myEnvironment); + + /*final String contentId = "Android Logcat"; + final AndroidLogcatTabComponent component = new AndroidLogcatTabComponent(myProject, device) { + @Override + public boolean isActivte() { + final Content content = sessionTab.getUi().findContent(contentId); + return content != null && content.isSelected(); + } + }; + sessionTab.getUi().addListener(new ContentManagerAdapter() { + public void selectionChanged(final ContentManagerEvent event) { + component.activate(); + } + }, component); + component.getToolWindowView().getLogConsole().attachStopLogConsoleTrackingListener(newProcessHandler); + sessionTab.addAdditionalTabComponent(component, contentId, AllIcons.Debugger.Console);*/ + RunProfile profile = myEnvironment.getRunProfile(); assert profile instanceof AndroidRunConfigurationBase; RunContentManager runContentManager = ExecutionManager.getInstance(myProject).getContentManager(); diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java index 822ed2849ff7..18793c4615eb 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java @@ -17,11 +17,9 @@ package org.jetbrains.android.run; import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.Log; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; import com.intellij.CommonBundle; -import com.intellij.diagnostic.logging.LogConsole; import com.intellij.execution.ExecutionException; import com.intellij.execution.Executor; import com.intellij.execution.configurations.*; @@ -50,8 +48,6 @@ import org.jdom.Element; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidFacetConfiguration; -import org.jetbrains.android.logcat.AndroidLogFilterModel; -import org.jetbrains.android.logcat.AndroidLogcatFiltersPreferences; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.sdk.AndroidSdkUtils; import org.jetbrains.android.util.AndroidBundle; @@ -238,14 +234,7 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati AndroidApplicationLauncher applicationLauncher = getApplicationLauncher(facet); if (applicationLauncher != null) { return new AndroidRunningState(env, facet, targetChooser, computeCommandLine(), aPackage, applicationLauncher, - depModule2PackageName, supportMultipleDevices(), CLEAR_LOGCAT) { - - @NotNull - @Override - protected ConsoleView attachConsole() throws ExecutionException { - return AndroidRunConfigurationBase.this.attachConsole(this, executor); - } - }; + depModule2PackageName, supportMultipleDevices(), CLEAR_LOGCAT, this); } return null; } @@ -298,27 +287,6 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati protected abstract boolean supportMultipleDevices(); - @Override - public void customizeLogConsole(LogConsole console) { - final Project project = getProject(); - console.setFilterModel(new AndroidLogFilterModel(AndroidLogcatFiltersPreferences.getInstance(project).TAB_LOG_LEVEL) { - @Override - protected void setCustomFilter(String filter) { - AndroidLogcatFiltersPreferences.getInstance(project).TAB_CUSTOM_FILTER = filter; - } - - @Override - protected void saveLogLevel(Log.LogLevel logLevel) { - AndroidLogcatFiltersPreferences.getInstance(project).TAB_LOG_LEVEL = logLevel.name(); - } - - @Override - public String getCustomFilter() { - return AndroidLogcatFiltersPreferences.getInstance(project).TAB_CUSTOM_FILTER; - } - }); - } - public void readExternal(Element element) throws InvalidDataException { super.readExternal(element); readModule(element); diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java index 7c836cce736c..df1c47642b7f 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java @@ -84,7 +84,7 @@ import static com.intellij.execution.process.ProcessOutputTypes.STDOUT; /** * @author coyote */ -public abstract class AndroidRunningState implements RunProfileState, AndroidDebugBridge.IClientChangeListener { +public class AndroidRunningState implements RunProfileState, AndroidDebugBridge.IClientChangeListener { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.run.AndroidRunningState"); @NonNls private static final String ANDROID_TARGET_DEVICES_PROPERTY = "AndroidTargetDevices"; @@ -105,6 +105,7 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb private final String myCommandLine; private final AndroidApplicationLauncher myApplicationLauncher; private final Map myAdditionalFacet2PackageName; + private final AndroidRunConfigurationBase myConfiguration; private final Object myDebugLock = new Object(); @@ -173,7 +174,7 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb } } else { - console = attachConsole(); + console = myConfiguration.attachConsole(this, executor); } myConsole = console; @@ -211,7 +212,9 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb } @NotNull - protected abstract ConsoleView attachConsole() throws ExecutionException; + public AndroidRunConfigurationBase getConfiguration() { + return myConfiguration; + } @Nullable public RunnerSettings getRunnerSettings() { @@ -287,10 +290,12 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb AndroidApplicationLauncher applicationLauncher, Map additionalFacet2PackageName, boolean supportMultipleDevices, - boolean clearLogcatBeforeStart) throws ExecutionException { + boolean clearLogcatBeforeStart, + @NotNull AndroidRunConfigurationBase configuration) throws ExecutionException { myFacet = facet; myCommandLine = commandLine; - + myConfiguration = configuration; + myTargetChooser = targetChooser; mySupportMultipleDevices = supportMultipleDevices;