< prev index next >
application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/ThreadsPage.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
--- 1,8 ----
/*
! * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
! * Copyright (c) 2019, Red Hat Inc. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at http://oss.oracle.com/licenses/upl
*** 42,53 ****
--- 43,60 ----
import java.util.stream.Stream;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
+ import org.eclipse.jface.viewers.StructuredSelection;
+ import org.eclipse.jface.viewers.TableViewer;
+ import org.eclipse.jface.wizard.WizardPage;
+ import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
+ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
+ import org.eclipse.swt.widgets.Item;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.openjdk.jmc.common.IMCThread;
import org.openjdk.jmc.common.IState;
import org.openjdk.jmc.common.IWritableState;
import org.openjdk.jmc.common.item.Aggregators;
*** 67,92 ****
--- 74,105 ----
import org.openjdk.jmc.flightrecorder.ui.IPageContainer;
import org.openjdk.jmc.flightrecorder.ui.IPageDefinition;
import org.openjdk.jmc.flightrecorder.ui.IPageUI;
import org.openjdk.jmc.flightrecorder.ui.StreamModel;
import org.openjdk.jmc.flightrecorder.ui.common.AbstractDataPage;
+ import org.openjdk.jmc.flightrecorder.ui.common.FilterComponent;
import org.openjdk.jmc.flightrecorder.ui.common.FlavorSelector.FlavorSelectorState;
import org.openjdk.jmc.flightrecorder.ui.common.ImageConstants;
import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram;
import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram.HistogramSelection;
import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram.ItemHistogramBuilder;
import org.openjdk.jmc.flightrecorder.ui.common.ItemRow;
+ import org.openjdk.jmc.flightrecorder.ui.common.DropdownLaneFilter;
import org.openjdk.jmc.flightrecorder.ui.common.ThreadGraphLanes;
import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages;
+ import org.openjdk.jmc.flightrecorder.ui.selection.SelectionStoreActionToolkit;
import org.openjdk.jmc.ui.UIPlugin;
import org.openjdk.jmc.ui.charts.IXDataRenderer;
import org.openjdk.jmc.ui.charts.QuantitySpanRenderer;
import org.openjdk.jmc.ui.charts.RendererToolkit;
import org.openjdk.jmc.ui.column.ColumnManager.SelectionState;
+ import org.openjdk.jmc.ui.column.ColumnMenusFactory;
import org.openjdk.jmc.ui.column.TableSettings;
import org.openjdk.jmc.ui.handlers.ActionToolkit;
import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
+ import org.openjdk.jmc.ui.wizards.IPerformFinishable;
+ import org.openjdk.jmc.ui.wizards.OnePageWizardDialog;
public class ThreadsPage extends AbstractDataPage {
public static class ThreadsPageFactory implements IDataPageFactory {
*** 151,194 ****
return null;
}, Messages.JavaApplicationPage_COLUMN_THREAD_DURATION,
Messages.JavaApplicationPage_COLUMN_THREAD_DURATION_DESC);
}
! private class ThreadsPageUi extends ChartAndTableUI {
private static final String THREADS_TABLE_FILTER = "threadsTableFilter"; //$NON-NLS-1$
private static final String HIDE_THREAD = "hideThread"; //$NON-NLS-1$
private static final String RESET_CHART = "resetChart"; //$NON-NLS-1$
private Boolean isChartMenuActionsInit;
private Boolean isChartModified;
private Boolean reloadThreads;
private IAction hideThreadAction;
private IAction resetChartAction;
private List<IXDataRenderer> threadRows;
private MCContextMenuManager mm;
private ThreadGraphLanes lanes;
ThreadsPageUi(Composite parent, FormToolkit toolkit, IPageContainer editor, IState state) {
super(pageFilter, getDataSource(), parent, toolkit, editor, state, getName(), pageFilter, getIcon(),
flavorSelectorState);
mm = (MCContextMenuManager) chartCanvas.getContextMenu();
sash.setOrientation(SWT.HORIZONTAL);
addActionsToContextMenu(mm);
// FIXME: The lanes field is initialized by initializeChartConfiguration which is called by the super constructor. This is too indirect for SpotBugs to resolve and should be simplified.
lanes.updateContextMenu(mm, false);
-
form.getToolBarManager()
.add(ActionToolkit.action(() -> lanes.openEditLanesDialog(mm, false), Messages.ThreadsPage_EDIT_LANES,
FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.ICON_LANES_EDIT)));
form.getToolBarManager().update(true);
chartLegend.getControl().dispose();
buildChart();
- table.getManager().setSelectionState(histogramSelectionState);
- tableFilterComponent.loadState(state.getChild(THREADS_TABLE_FILTER));
chart.setVisibleRange(visibleRange.getStart(), visibleRange.getEnd());
onFilterChange(tableFilter);
}
/**
* Hides a thread from the chart and rebuilds the chart
*/
private void hideThread(Object thread) {
if (this.threadRows != null && this.threadRows.size() > 0 && thread instanceof IMCThread) {
--- 164,217 ----
return null;
}, Messages.JavaApplicationPage_COLUMN_THREAD_DURATION,
Messages.JavaApplicationPage_COLUMN_THREAD_DURATION_DESC);
}
! private class ThreadsPageUi extends ChartAndPopupTableUI {
private static final String THREADS_TABLE_FILTER = "threadsTableFilter"; //$NON-NLS-1$
private static final String HIDE_THREAD = "hideThread"; //$NON-NLS-1$
private static final String RESET_CHART = "resetChart"; //$NON-NLS-1$
+ private static final String TABLE = "table"; //$NON-NLS-1$
private Boolean isChartMenuActionsInit;
private Boolean isChartModified;
private Boolean reloadThreads;
private IAction hideThreadAction;
private IAction resetChartAction;
private List<IXDataRenderer> threadRows;
private MCContextMenuManager mm;
private ThreadGraphLanes lanes;
+ private DropdownLaneFilter laneFilter;
ThreadsPageUi(Composite parent, FormToolkit toolkit, IPageContainer editor, IState state) {
super(pageFilter, getDataSource(), parent, toolkit, editor, state, getName(), pageFilter, getIcon(),
flavorSelectorState);
mm = (MCContextMenuManager) chartCanvas.getContextMenu();
sash.setOrientation(SWT.HORIZONTAL);
addActionsToContextMenu(mm);
// FIXME: The lanes field is initialized by initializeChartConfiguration which is called by the super constructor. This is too indirect for SpotBugs to resolve and should be simplified.
lanes.updateContextMenu(mm, false);
form.getToolBarManager()
.add(ActionToolkit.action(() -> lanes.openEditLanesDialog(mm, false), Messages.ThreadsPage_EDIT_LANES,
FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.ICON_LANES_EDIT)));
+ form.getToolBarManager()
+ .add(ActionToolkit.action(() -> openViewThreadDetailsDialog(state), Messages.ThreadsPage_VIEW_THREAD_DETAILS,
+ FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.ICON_TABLE)));
form.getToolBarManager().update(true);
chartLegend.getControl().dispose();
+ setupFilterBar();
buildChart();
chart.setVisibleRange(visibleRange.getStart(), visibleRange.getEnd());
onFilterChange(tableFilter);
}
+ private void setupFilterBar() {
+ laneFilter = new DropdownLaneFilter(filterBar, lanes, mm);
+ laneFilter.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+ filterBar.setChart(chart);
+ filterBar.setChartCanvas(chartCanvas);
+ }
+
/**
* Hides a thread from the chart and rebuilds the chart
*/
private void hideThread(Object thread) {
if (this.threadRows != null && this.threadRows.size() > 0 && thread instanceof IMCThread) {
*** 275,300 ****
}
@Override
protected IXDataRenderer getChartRenderer(IItemCollection itemsInTable, HistogramSelection tableSelection) {
List<IXDataRenderer> rows = new ArrayList<>();
!
IItemCollection selectedItems;
HistogramSelection selection;
if (tableSelection.getRowCount() == 0) {
selectedItems = itemsInTable;
! selection = table.getAllRows();
} else {
selectedItems = tableSelection.getItems();
selection = tableSelection;
}
boolean useDefaultSelection = rows.size() > 1;
if (lanes.getLaneDefinitions().stream().anyMatch(a -> a.isEnabled()) && selection.getRowCount() > 0) {
if (this.reloadThreads) {
this.threadRows = selection
.getSelectedRows((object, items) -> lanes.buildThreadRenderer(object, items))
.collect(Collectors.toList());
this.isChartModified = false;
if (this.isChartMenuActionsInit) {
setResetChartActionEnablement(false);
setHideThreadActionEnablement(true);
}
--- 298,325 ----
}
@Override
protected IXDataRenderer getChartRenderer(IItemCollection itemsInTable, HistogramSelection tableSelection) {
List<IXDataRenderer> rows = new ArrayList<>();
! ItemHistogram histogram = getUndisposedTable();
IItemCollection selectedItems;
HistogramSelection selection;
if (tableSelection.getRowCount() == 0) {
selectedItems = itemsInTable;
! selection = histogram.getAllRows();
} else {
selectedItems = tableSelection.getItems();
selection = tableSelection;
}
boolean useDefaultSelection = rows.size() > 1;
if (lanes.getLaneDefinitions().stream().anyMatch(a -> a.isEnabled()) && selection.getRowCount() > 0) {
if (this.reloadThreads) {
this.threadRows = selection
.getSelectedRows((object, items) -> lanes.buildThreadRenderer(object, items))
.collect(Collectors.toList());
+ chartCanvas.setNumItems(this.threadRows.size());
+ textCanvas.setNumItems(this.threadRows.size());
this.isChartModified = false;
if (this.isChartMenuActionsInit) {
setResetChartActionEnablement(false);
setHideThreadActionEnablement(true);
}
*** 323,339 ****
}
@Override
public void saveTo(IWritableState state) {
super.saveTo(state);
- tableFilterComponent.saveState(state.createChild(THREADS_TABLE_FILTER));
saveToLocal();
}
private void saveToLocal() {
flavorSelectorState = flavorSelector.getFlavorSelectorState();
! histogramSelectionState = table.getManager().getSelectionState();
visibleRange = chart.getVisibleRange();
}
@Override
protected List<IAction> initializeChartConfiguration(IState state) {
--- 348,363 ----
}
@Override
public void saveTo(IWritableState state) {
super.saveTo(state);
saveToLocal();
}
private void saveToLocal() {
flavorSelectorState = flavorSelector.getFlavorSelectorState();
! histogramSelectionState = getUndisposedTable().getManager().getSelectionState();
visibleRange = chart.getVisibleRange();
}
@Override
protected List<IAction> initializeChartConfiguration(IState state) {
*** 341,352 ****
--- 365,444 ----
this.isChartModified = false;
this.reloadThreads = true;
lanes = new ThreadGraphLanes(() -> getDataSource(), () -> buildChart());
return lanes.initializeChartConfiguration(Stream.of(state.getChildren(THREAD_LANE)));
}
+
+ private TablePopup tablePopup;
+ public void openViewThreadDetailsDialog(IState state) {
+ tablePopup = new TablePopup(state);
+ OnePageWizardDialog.openAndHideCancelButton(tablePopup, 500, 600);
+ }
+
+ private class TablePopup extends WizardPage implements IPerformFinishable {
+
+ private IState state;
+
+ protected TablePopup(IState state) {
+ super("ThreadDetailsPage"); //$NON-NLS-1$
+ this.state = state;
+ setTitle(Messages.ThreadsPage_TABLE_POPUP_TITLE);
+ setDescription(Messages.ThreadsPage_TABLE_POPUP_DESCRIPTION);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ table = buildHistogram(parent, state.getChild(TABLE));
+ MCContextMenuManager mm = MCContextMenuManager.create(table.getManager().getViewer().getControl());
+ ColumnMenusFactory.addDefaultMenus(table.getManager(), mm);
+ table.getManager().getViewer().addSelectionChangedListener(e -> buildChart());
+ table.getManager().getViewer()
+ .addSelectionChangedListener(e -> pageContainer.showSelection(table.getSelection().getItems()));
+ SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), table,
+ NLS.bind(Messages.ChartAndTableUI_HISTOGRAM_SELECTION, getName()), mm);
+ tableFilterComponent = FilterComponent.createFilterComponent(table.getManager().getViewer().getControl(),
+ table.getManager(), tableFilter, model.getItems().apply(pageFilter),
+ pageContainer.getSelectionStore()::getSelections, this::onFilterChangeHelper);
+ mm.add(tableFilterComponent.getShowFilterAction());
+ mm.add(tableFilterComponent.getShowSearchAction());
+ table.getManager().setSelectionState(histogramSelectionState);
+ tableFilterComponent.loadState(state.getChild(THREADS_TABLE_FILTER));
+ onFilterChange(tableFilter);
+
+ if (selectionInput != null) {
+ table.getManager().getViewer().setSelection(new StructuredSelection(selectionInput));
+ }
+
+ Item[] columnWidgets = ((TableViewer) table.getManager().getViewer()).getTable().getColumns();
+ for (Item columWidget : columnWidgets) {
+ columWidget.addListener(SWT.Selection, e -> columnSortChanged());
+ }
+
+ setControl(parent);
+ }
+
+ private void columnSortChanged() {
+ if (!table.getSelection().getItems().hasItems()) {
+ buildChart();
+ }
+ }
+
+ private void onFilterChangeHelper(IItemFilter filter) {
+ onFilterChange(filter);
+ }
+
+ @Override
+ public boolean performFinish() {
+ IItemCollection lastSelection = table.getSelection().getItems();
+ table.show(lastSelection);
+ selectionInput = (Object[]) table.getManager().getViewer().getInput();
+ return true;
+ }
+ }
}
+ private Object[] selectionInput;
private FlavorSelectorState flavorSelectorState;
private SelectionState histogramSelectionState;
private IItemFilter tableFilter;
private IRange<IQuantity> visibleRange;
< prev index next >