diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/action/SwitchUpdateModeAction.java b/java/debugger/impl/src/com/intellij/debugger/memory/action/SwitchUpdateModeAction.java new file mode 100644 index 000000000000..e5300752d649 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/memory/action/SwitchUpdateModeAction.java @@ -0,0 +1,25 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.memory.action; + +import com.intellij.debugger.memory.component.MemoryViewManager; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.project.Project; + +/** + * @author Vitaliy.Bibaev + */ +public class SwitchUpdateModeAction extends ToggleAction { + @Override + public boolean isSelected(AnActionEvent e) { + return MemoryViewManager.getInstance().isAutoUpdateModeEnabled(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + Project project = e.getProject(); + if (project != null) { + MemoryViewManager.getInstance().setAutoUpdate(state); + } + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManager.java b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManager.java index 217a66b29984..582394dab0c2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManager.java @@ -32,11 +32,7 @@ public class MemoryViewManager implements ApplicationComponent, PersistentStateC } @Override - public void loadState(MemoryViewManagerState state) { - if (state == null) { - state = new MemoryViewManagerState(); - } - + public void loadState(@NotNull MemoryViewManagerState state) { myState = state; fireStateChanged(); } @@ -62,6 +58,13 @@ public class MemoryViewManager implements ApplicationComponent, PersistentStateC } } + public void setAutoUpdate(boolean value) { + if (myState.isAutoUpdateModeOn != value) { + myState.isAutoUpdateModeOn = value; + fireStateChanged(); + } + } + public boolean isNeedShowDiffOnly() { return myState.isShowWithDiffOnly; } @@ -74,6 +77,10 @@ public class MemoryViewManager implements ApplicationComponent, PersistentStateC return myState.isShowTrackedOnly; } + public boolean isAutoUpdateModeEnabled() { + return myState.isAutoUpdateModeOn; + } + public void addMemoryViewManagerListener(MemoryViewManagerListener listener, @NotNull Disposable parentDisposable) { myDispatcher.addListener(listener, parentDisposable); } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManagerState.java b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManagerState.java index 678b84e3cb9b..38effff9a435 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManagerState.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/component/MemoryViewManagerState.java @@ -1,24 +1,11 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.memory.component; public final class MemoryViewManagerState { public boolean isShowWithInstancesOnly = true; public boolean isShowWithDiffOnly = false; public boolean isShowTrackedOnly = false; + public boolean isAutoUpdateModeOn = false; MemoryViewManagerState() { } @@ -27,5 +14,6 @@ public final class MemoryViewManagerState { isShowWithInstancesOnly = other.isShowWithInstancesOnly; isShowWithDiffOnly = other.isShowWithDiffOnly; isShowTrackedOnly = other.isShowTrackedOnly; + isAutoUpdateModeOn = other.isAutoUpdateModeOn; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java index 3fb5b948ceac..f2949ba9147d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesFilteredView.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.memory.ui; import com.intellij.debugger.DebuggerManager; @@ -79,8 +65,8 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable private static final double MAX_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(2); private static final int DEFAULT_BATCH_SIZE = Integer.MAX_VALUE; private static final String EMPTY_TABLE_CONTENT_WHEN_RUNNING = "The application is running"; - private static final String EMPTY_TABLE_CONTENT_WHEN_SUSPENDED = "Nothing to show"; private static final String EMPTY_TABLE_CONTENT_WHEN_STOPPED = "Classes are not available"; + private static final String CLICKABLE_TABLE_CONTENT = "Click to load the classes list"; private final Project myProject; private final SingleAlarmWithMutableDelay mySingleAlarm; @@ -257,6 +243,9 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable myTable.setFilteringByDiffNonZero(state.isShowWithDiffOnly); myTable.setFilteringByInstanceExists(state.isShowWithInstancesOnly); myTable.setFilteringByTrackingState(state.isShowTrackedOnly); + if (state.isAutoUpdateModeOn && myTable.isInClickableMode()) { + updateClassesAndCounts(true); + } }; MemoryViewManager.getInstance().addMemoryViewManagerListener(memoryViewManagerListener, this); @@ -343,7 +332,7 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable myConstructorTrackedClasses.values().forEach(ConstructorInstancesTracker::commitTracked); } - private void updateClassesAndCounts() { + private void updateClassesAndCounts(boolean immediate) { ApplicationManager.getApplication().invokeLater(() -> { final XDebugSession debugSession = XDebuggerManager.getInstance(myProject).getCurrentSession(); if (debugSession != null) { @@ -353,7 +342,12 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable final DebugProcessImpl process = (DebugProcessImpl)debugProcess; final SuspendContextImpl context = process.getDebuggerContext().getSuspendContext(); if (context != null) { - mySingleAlarm.cancelAndRequest(context); + if (immediate) { + mySingleAlarm.cancelAndRequestImmediate(context); + } + else { + mySingleAlarm.cancelAndRequest(context); + } } } } @@ -395,10 +389,20 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable myConstructorTrackedClasses.values().forEach(x -> x.setBackgroundMode(false)); if (isNeedUpdateView()) { - updateClassesAndCounts(); + if (MemoryViewManager.getInstance().isAutoUpdateModeEnabled()) { + updateClassesAndCounts(true); + } + else { + makeTableClickable(); + } } } + private void makeTableClickable() { + ApplicationManager.getApplication().invokeLater( + () -> myTable.makeClickable(CLICKABLE_TABLE_CONTENT, () -> updateClassesAndCounts(true))); + } + private void doPause() { myDebugSessionListener.setActive(false); mySingleAlarm.cancelAllRequests(); @@ -542,6 +546,8 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable @Override public void mouseMoved(MouseEvent e) { + if (myTable.isInClickableMode()) return; + if (isShowNewInstancesEvent(e)) { myTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } @@ -577,10 +583,7 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable public void sessionResumed() { if (myIsActive) { myConstructorTrackedClasses.values().forEach(ConstructorInstancesTracker::obsolete); - ApplicationManager.getApplication().invokeLater(() -> { - myTable.getEmptyText().setText(EMPTY_TABLE_CONTENT_WHEN_RUNNING); - myTable.hideContent(); - }); + ApplicationManager.getApplication().invokeLater(() -> myTable.hideContent(EMPTY_TABLE_CONTENT_WHEN_RUNNING)); mySingleAlarm.cancelAllRequests(); } @@ -591,20 +594,20 @@ public class ClassesFilteredView extends BorderLayoutPanel implements Disposable myConstructorTrackedClasses.values().forEach(Disposer::dispose); myConstructorTrackedClasses.clear(); mySingleAlarm.cancelAllRequests(); - ApplicationManager.getApplication().invokeLater(() -> { - myTable.getEmptyText().setText(EMPTY_TABLE_CONTENT_WHEN_STOPPED); - myTable.clean(); - }); + ApplicationManager.getApplication().invokeLater(() -> myTable.clean(EMPTY_TABLE_CONTENT_WHEN_STOPPED)); } @Override public void sessionPaused() { - if (myIsActive) { - ApplicationManager.getApplication().invokeLater(() -> myTable.getEmptyText().setText(EMPTY_TABLE_CONTENT_WHEN_SUSPENDED)); - updateClassesAndCounts(); - } - myTime.incrementAndGet(); + if (myIsActive) { + if (MemoryViewManager.getInstance().isAutoUpdateModeEnabled()) { + updateClassesAndCounts(false); + } + else { + makeTableClickable(); + } + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java index 2c7782849ae5..6de5c7142b70 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/ui/ClassesTable.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.memory.ui; import com.intellij.debugger.memory.component.InstancesTracker; @@ -48,7 +34,12 @@ import javax.swing.border.Border; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableRowSorter; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; public class ClassesTable extends JBTable implements DataProvider, Disposable { @@ -59,6 +50,8 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { DataKey.create("ClassesTable.ReferenceCountProvider"); private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(); + private static final JBColor CLICKABLE_COLOR = new JBColor(new Color(250, 251, 252), new Color(62, 66, 69)); + private static final String DEFAULT_EMPTY_TEXT = "Nothing to show"; private static final int CLASSES_COLUMN_PREFERRED_WIDTH = 250; private static final int COUNT_COLUMN_MIN_WIDTH = 80; @@ -79,6 +72,7 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { private volatile List myItems = Collections.unmodifiableList(new ArrayList<>()); private boolean myIsShowCounts = true; + private MouseListener myMouseListener = null; public ClassesTable(@NotNull InstancesTracker tracker, @NotNull ClassesFilteredView parent, boolean onlyWithDiff, boolean onlyWithInstances, @@ -184,6 +178,49 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { return null; } + boolean isInClickableMode() { + return myMouseListener != null; + } + + void makeClickable(@NotNull String text, @NotNull Runnable onClick) { + releaseMouseListener(); + getEmptyText().setText(text); + + if (getMousePosition() != null) { + setBackground(CLICKABLE_COLOR); + } + + myMouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + onClick.run(); + } + + @Override + public void mouseEntered(MouseEvent e) { + setBackground(CLICKABLE_COLOR); + } + + @Override + public void mouseExited(MouseEvent e) { + setBackground(JBColor.background()); + } + }; + + addMouseListener(myMouseListener); + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + + private void releaseMouseListener() { + ApplicationManager.getApplication().assertIsDispatchThread(); + if (isInClickableMode()) { + removeMouseListener(myMouseListener); + myMouseListener = null; + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + setBackground(JBColor.background()); + } + } + void setBusy(boolean value) { setPaintBusy(value); } @@ -232,7 +269,10 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { updateCountsInternal(class2Count); } - void hideContent() { + void hideContent(@NotNull String emptyText) { + releaseMouseListener(); + getEmptyText().setText(emptyText); + myModel.hide(); } @@ -241,6 +281,9 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { } private void updateCountsInternal(@NotNull Map class2Count) { + releaseMouseListener(); + getEmptyText().setText(DEFAULT_EMPTY_TEXT); + final ReferenceType selectedClass = myModel.getSelectedClassBeforeHide(); int newSelectedIndex = -1; final boolean isInitialized = !myItems.isEmpty(); @@ -295,8 +338,10 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { return null; } - public void clean() { + public void clean(@NotNull String emptyText) { clearSelection(); + releaseMouseListener(); + getEmptyText().setText(emptyText); myItems = Collections.emptyList(); myCounts.clear(); myModel.mySelectedClassWhenHidden = null; @@ -305,7 +350,7 @@ public class ClassesTable extends JBTable implements DataProvider, Disposable { @Override public void dispose() { - ApplicationManager.getApplication().invokeLater(this::clean); + ApplicationManager.getApplication().invokeLater(() -> clean("")); } @Nullable diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/utils/SingleAlarmWithMutableDelay.java b/java/debugger/impl/src/com/intellij/debugger/memory/utils/SingleAlarmWithMutableDelay.java index 036ba7faf904..99534dd3c70f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/utils/SingleAlarmWithMutableDelay.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/utils/SingleAlarmWithMutableDelay.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.memory.utils; import com.intellij.debugger.engine.SuspendContextImpl; @@ -36,18 +22,22 @@ public class SingleAlarmWithMutableDelay { } public void cancelAndRequest(@NotNull SuspendContextImpl suspendContext) { - if (!myAlarm.isDisposed()) { - cancelAllRequests(); - addRequest(() -> myTask.run(suspendContext)); - } + cancelAndAddRequest(suspendContext, myDelayMillis); + } + + public void cancelAndRequestImmediate(@NotNull SuspendContextImpl suspendContext) { + cancelAndAddRequest(suspendContext, 0); } public void cancelAllRequests() { myAlarm.cancelAllRequests(); } - private void addRequest(@NotNull Runnable runnable) { - myAlarm.addRequest(runnable, myDelayMillis); + private void cancelAndAddRequest(@NotNull SuspendContextImpl suspendContext, int delayMillis) { + if (!myAlarm.isDisposed()) { + cancelAllRequests(); + myAlarm.addRequest(() -> myTask.run(suspendContext), delayMillis); + } } @FunctionalInterface diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index bb86aab1acb7..73ab7e95743b 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -270,6 +270,11 @@ + +