IDEA-171027 IDEA-175146 Update Memory view manually by default

This commit is contained in:
Vitaliy.Bibaev
2018-01-18 19:15:00 +03:00
parent f4f2c92fe5
commit 0ac0ed2323
7 changed files with 154 additions and 91 deletions
@@ -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);
}
}
}
@@ -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);
}
@@ -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;
}
}
@@ -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();
}
}
}
}
}
@@ -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<ReferenceType> 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<ReferenceType, Long> 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
@@ -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
+5
View File
@@ -270,6 +270,11 @@
<action class="com.intellij.debugger.memory.action.EnableBackgroundTrackingAction"
id="MemoryView.EnableTrackingWithClosedWindow"
text="Enable Tracking With Hidden Memory View"/>
<action class="com.intellij.debugger.memory.action.SwitchUpdateModeAction"
id="MemoryView.SwitchUpdateMode"
text="Update Loaded Classes On Debugger Stop"
description="Load classes on debugger pause (may increase overhead on debugger stepping)"/>
</group>
<group id="MemoryView.ClassesPopupActionGroup">