/* * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.ins.debug; import static com.sun.max.tele.MaxThreadState.*; import java.awt.*; import java.awt.datatransfer.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import com.sun.max.ins.*; import com.sun.max.ins.gui.*; import com.sun.max.tele.*; /** * A table specialized for displaying the threads in the VM. */ public final class ThreadsTable extends InspectorTable { private final InspectorView view; private final ThreadsTableModel tableModel; ThreadsTable(Inspection inspection, InspectorView view, ThreadsViewPreferences viewPreferences) { super(inspection); this.view = view; tableModel = new ThreadsTableModel(inspection); ThreadsColumnModel columnModel = new ThreadsColumnModel(viewPreferences); configureDefaultTable(tableModel, columnModel); } @Override public void updateFocusSelection() { // Sets table selection to thread, if any, that is the current user focus. final MaxThread thread = focus().thread(); final int row = tableModel.findRow(thread); updateSelection(row); } @Override public void valueChanged(ListSelectionEvent listSelectionEvent) { // Row selection changed, perhaps by user mouse click or navigation; // update user focus to follow the selection. super.valueChanged(listSelectionEvent); if (!listSelectionEvent.getValueIsAdjusting()) { final int row = getSelectedRow(); if (row >= 0) { final MaxThread thread = (MaxThread) getValueAt(row, 0); focus().setThread(thread); } } } @Override protected Transferable getTransferable(int row, int col) { final MaxThread thread = tableModel.getThreadAt(row); assert thread != null; final MaxObject vmThreadObject = thread.teleVmThread(); if (vmThreadObject != null) { return new InspectorTransferable.TeleObjectTransferable(inspection(), vmThreadObject); } return null; } /** * {@inheritDoc}. * <br> * Color the text specially in the row where the thread is at a triggered watchpoint or breakpoint */ @Override public Color cellForegroundColor(int row, int col) { final MaxThread thread = (MaxThread) tableModel.getValueAt(row, 0); if (thread != null) { final MaxThreadState threadState = thread.state(); if (threadState == BREAKPOINT || threadState == WATCHPOINT) { return preference().style().debugIPTagColor(); } } return null; } public InspectorView getView() { return view; } private final class ThreadsColumnModel extends InspectorTableColumnModel<ThreadsColumnKind> { private ThreadsColumnModel(ThreadsViewPreferences viewPreferences) { super(inspection(), ThreadsColumnKind.values().length, viewPreferences); addColumnIfSupported(ThreadsColumnKind.ID, new IDCellRenderer(inspection()), null); addColumnIfSupported(ThreadsColumnKind.HANDLE, new HandleCellRenderer(inspection()), null); addColumnIfSupported(ThreadsColumnKind.LOCAL_HANDLE, new LocalHandleCellRenderer(inspection()), null); addColumnIfSupported(ThreadsColumnKind.KIND, new KindCellRenderer(inspection()), null); addColumnIfSupported(ThreadsColumnKind.NAME, new NameCellRenderer(inspection()), null); addColumnIfSupported(ThreadsColumnKind.STATUS, new StatusCellRenderer(inspection()), null); } } /** * A table data model wrapped around the thread list in the * current state of the VM. The list goes empty with the process dies. */ private final class ThreadsTableModel extends InspectorTableModel { public ThreadsTableModel(Inspection inspection) { super(inspection); // TODO Auto-generated constructor stub } public int getColumnCount() { return ThreadsColumnKind.values().length; } public int getRowCount() { return vm().state().threads().size(); } public Object getValueAt(int row, int col) { return getThreadAt(row); } @Override public Class< ? > getColumnClass(int c) { return MaxThread.class; } @Override public String getRowDescription(int row) { final MaxThread thread = getThreadAt(row); if (thread.id() < 0) { return "Non-VM thread"; } final String threadIdText = Long.toString(thread.id()); return "VM thread ID: " + threadIdText; } public int findRow(MaxThread findThread) { int row = 0; for (MaxThread thread : vm().state().threads()) { if (thread.equals(findThread)) { return row; } row++; } return -1; } public MaxThread getThreadAt(int row) { int count = 0; for (MaxThread thread : vm().state().threads()) { if (count == row) { return thread; } count++; } return null; } } private final class IDCellRenderer extends PlainLabel implements TableCellRenderer { IDCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } final int id = thread.id(); if (id < 0) { setText(""); setToolTipText("Not a VM thread"); } else { final String threadIdText = Long.toString(id); setText(threadIdText); setToolTipText("VM thread ID: " + threadIdText); } setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } private final class HandleCellRenderer extends PlainLabel implements TableCellRenderer { HandleCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } final String handleString = thread.handleString(); setText(handleString); setToolTipText("Thread handle: " + handleString); setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } private final class LocalHandleCellRenderer extends PlainLabel implements TableCellRenderer { LocalHandleCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } final String handleString = Long.toString(thread.localHandle()); setText(handleString); setToolTipText("Local thread handle: " + handleString); setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } private final class KindCellRenderer extends PlainLabel implements TableCellRenderer { KindCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } String kind; if (thread.isJava()) { kind = "Java"; } else { if (thread.isPrimordial()) { kind = "primordial"; } else { kind = "native"; } } setText(kind); setToolTipText("Thread kind: " + kind); setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } private final class NameCellRenderer extends JavaNameLabel implements TableCellRenderer { NameCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } setValue(inspection().nameDisplay().shortName(thread), "Thread name: " + inspection().nameDisplay().longName(thread)); setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } private final class StatusCellRenderer extends PlainLabel implements TableCellRenderer { StatusCellRenderer(Inspection inspection) { super(inspection, null); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final MaxThread thread = (MaxThread) value; if (thread == null) { return gui().getUnavailableDataTableCellRenderer(); } final MaxThreadState threadState = thread.state(); setText(threadState.toString()); String toolTipText = "Thread status: " + threadState; if (thread.breakpoint() != null) { toolTipText = toolTipText + "(" + thread.breakpoint().getDescription() + ")"; } setToolTipText(toolTipText); setForeground(cellForegroundColor(row, column)); setBackground(cellBackgroundColor()); return this; } } }