< prev index next >

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/ThreadsPage.java

Print this page

        

*** 74,84 **** --- 74,86 ---- 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.ThreadGraphLanes; import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages; + 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.TableSettings; import org.openjdk.jmc.ui.handlers.ActionToolkit; import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
*** 150,168 **** Messages.JavaApplicationPage_COLUMN_THREAD_DURATION_DESC); } private class ThreadsPageUi extends ChartAndTableUI { private static final String THREADS_TABLE_FILTER = "threadsTableFilter"; //$NON-NLS-1$ private ThreadGraphLanes lanes; private MCContextMenuManager mm; 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); ! mm.add(new Separator()); // 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, --- 152,178 ---- 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 IAction hideThreadAction; + private IAction resetChartAction; private ThreadGraphLanes lanes; private MCContextMenuManager mm; + private List<IXDataRenderer> threadRows; + private Boolean reloadThreads; + private Boolean isChartModified; + private Boolean isChartMenuActionsInit; 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,
*** 174,183 **** --- 184,273 ---- 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(String threadName) { + if (this.threadRows != null && this.threadRows.size() > 0) { + int index = indexOfThreadName(threadName); + if (index != -1) { + this.threadRows.remove(index); + this.reloadThreads = false; + buildChart(); + if (!this.isChartModified) { + this.isChartModified = true; + setResetChartActionEnablement(true); + } + } + if (this.threadRows.size() == 0) { + setHideThreadActionEnablement(false); + } + } + } + + /** + * Locates the index of the target Thread (by name) in the current selection list + * + * @param name + * the name of the Thread of interest + * @return the index of the Thread in the current selection, or -1 if not found + */ + private int indexOfThreadName(String name) { + for (int i = 0; i < this.threadRows.size() && name != null; i++) { + if (this.threadRows.get(i) instanceof QuantitySpanRenderer) { + if (name.equals(((QuantitySpanRenderer) this.threadRows.get(i)).getName())) { + return i; + } + } + } + return -1; + } + + /** + * Adds the hide thread and reset chart actions to the context menu + */ + private void addActionsToContextMenu(MCContextMenuManager mm) { + mm.add(new Separator()); + + IAction hideThreadAction = ActionToolkit.action(() -> this.hideThread(chartCanvas.getActiveScopeName()), + Messages.ThreadsPage_HIDE_THREAD_ACTION, + UIPlugin.getDefault().getMCImageDescriptor(UIPlugin.ICON_DELETE)); + hideThreadAction.setId(HIDE_THREAD); + this.hideThreadAction = hideThreadAction; + mm.add(hideThreadAction); + + IAction resetChartAction = ActionToolkit.action(() -> this.resetChartToSelection(), + Messages.ThreadsPage_RESET_CHART_TO_SELECTION_ACTION, + UIPlugin.getDefault().getMCImageDescriptor(UIPlugin.ICON_REFRESH)); + resetChartAction.setId(RESET_CHART); + resetChartAction.setEnabled(this.isChartModified); + this.resetChartAction = resetChartAction; + mm.add(resetChartAction); + + this.isChartMenuActionsInit = true; + } + + /** + * Redraws the chart, and disables the reset chart menu action + */ + private void resetChartToSelection() { + buildChart(); + this.isChartModified = false; + setResetChartActionEnablement(false); + setHideThreadActionEnablement(true); + } + + private void setHideThreadActionEnablement(Boolean enabled) { + this.hideThreadAction.setEnabled(enabled); + } + private void setResetChartActionEnablement(Boolean enabled) { + this.resetChartAction.setEnabled(enabled); + } + @Override protected ItemHistogram buildHistogram(Composite parent, IState state) { ItemHistogram build = HISTOGRAM.buildWithoutBorder(parent, JfrAttributes.EVENT_THREAD, TableSettings.forState(state)); return build;
*** 196,214 **** selectedItems = tableSelection.getItems(); selection = tableSelection; } boolean useDefaultSelection = rows.size() > 1; if (lanes.getLaneDefinitions().stream().anyMatch(a -> a.isEnabled()) && selection.getRowCount() > 0) { ! List<IXDataRenderer> threadRows = selection .getSelectedRows((object, items) -> lanes.buildThreadRenderer(object, items)) .collect(Collectors.toList()); double threadsWeight = Math.sqrt(threadRows.size()) * 0.15; double otherRowWeight = Math.max(threadsWeight * 0.1, (1 - threadsWeight) / rows.size()); List<Double> weights = Stream .concat(Stream.generate(() -> otherRowWeight).limit(rows.size()), Stream.of(threadsWeight)) .collect(Collectors.toList()); ! rows.add(RendererToolkit.uniformRows(threadRows)); useDefaultSelection = true; rows = Arrays.asList(RendererToolkit.weightedRows(rows, weights)); } IXDataRenderer root = rows.size() == 1 ? rows.get(0) : RendererToolkit.uniformRows(rows); // We don't use the default selection when there is only one row. This is to get the correct payload. --- 286,314 ---- 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); + } + } else { + this.reloadThreads = true; + } + double threadsWeight = Math.sqrt(threadRows.size()) * 0.15; double otherRowWeight = Math.max(threadsWeight * 0.1, (1 - threadsWeight) / rows.size()); List<Double> weights = Stream .concat(Stream.generate(() -> otherRowWeight).limit(rows.size()), Stream.of(threadsWeight)) .collect(Collectors.toList()); ! rows.add(RendererToolkit.uniformRows(this.threadRows)); useDefaultSelection = true; rows = Arrays.asList(RendererToolkit.weightedRows(rows, weights)); } IXDataRenderer root = rows.size() == 1 ? rows.get(0) : RendererToolkit.uniformRows(rows); // We don't use the default selection when there is only one row. This is to get the correct payload.
*** 234,243 **** --- 334,346 ---- visibleRange = chart.getVisibleRange(); } @Override protected List<IAction> initializeChartConfiguration(IState state) { + this.reloadThreads = true; + this.isChartModified = false; + this.isChartMenuActionsInit = false; lanes = new ThreadGraphLanes(() -> getDataSource(), () -> buildChart()); return lanes.initializeChartConfiguration(Stream.of(state.getChildren(THREAD_LANE))); } }
< prev index next >