/* * Copyright (c) 2007, 2011, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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.tools.visualvm.modules.tracer.impl.details; import com.sun.tools.visualvm.modules.tracer.impl.swing.HeaderPanel; import com.sun.tools.visualvm.modules.tracer.impl.swing.ScrollBar; import com.sun.tools.visualvm.modules.tracer.impl.timeline.TimelineSupport; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.Scrollable; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; /** * * @author Jiri Sedlacek */ public final class DetailsPanel extends JPanel { private JPanel noDataContainer; private JComponent dataContainer; private JScrollBar scrollBar; private DetailsTable table; private final TimelineSupport support; private boolean selectionAdjusting; private KeyStroke tableKeyStroke; public DetailsPanel(TimelineSupport support) { this.support = support; initComponents(); initListeners(); } public void setTableModel(TableModel model) { if (model == null) { table.clearSelection(); table.setModel(new DefaultTableModel()); removeAll(); add(noDataContainer, BorderLayout.CENTER); } else { int selectedRow = getSelectedRow(); table.setModel(model); if (selectedRow != -1) table.getSelectionModel().setSelectionInterval(selectedRow, selectedRow); removeAll(); add(dataContainer, BorderLayout.CENTER); } validate(); repaint(); } private void initListeners() { TableListener tableListener = new TableListener(); table.getSelectionModel().addListSelectionListener(tableListener); table.addKeyListener(tableListener); table.addMouseListener(tableListener); } private int getSelectedRow() { int selectedRow = table.getSelectedRow(); return selectedRow == -1 ? -1 : table.convertRowIndexToModel(selectedRow); } private boolean isTrackingEnd() { if (scrollBar == null) return false; return scrollBar.getValue() + scrollBar.getVisibleAmount() >= scrollBar.getMaximum(); } private boolean isSelectionChanging() { if (selectionAdjusting) return true; if (tableKeyStroke == null) return false; return table.getActionForKeyStroke(tableKeyStroke) != null; } private void initComponents() { table = new DetailsTable(); table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JViewport viewport = new Viewport(table); final JScrollPane tableScroll = new JScrollPane( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); tableScroll.setViewport(viewport); tableScroll.setBorder(BorderFactory.createEmptyBorder()); tableScroll.setViewportBorder(BorderFactory.createEmptyBorder()); tableScroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new HeaderPanel()); scrollBar = new ScrollBar(JScrollBar.VERTICAL) { public int getUnitIncrement(int direction) { JViewport vp = tableScroll.getViewport(); Scrollable view = (Scrollable)(vp.getView()); Rectangle vr = vp.getViewRect(); return view.getScrollableUnitIncrement(vr, getOrientation(), direction); } public int getBlockIncrement(int direction) { JViewport vp = tableScroll.getViewport(); Scrollable view = (Scrollable)(vp.getView()); Rectangle vr = vp.getViewRect(); return view.getScrollableBlockIncrement(vr, getOrientation(), direction); } public void setValues(int newValue, int newExtent, int newMin, int newMax) { setEnabled(newExtent < newMax); if (isEnabled() && !isSelectionChanging() && isTrackingEnd()) newValue = newMax - newExtent; super.setValues(newValue, newExtent, newMin, newMax); } }; tableScroll.setVerticalScrollBar(scrollBar); dataContainer = tableScroll; JLabel noDataLabel = new JLabel("<No probe selected>", JLabel.CENTER); noDataLabel.setEnabled(false); noDataContainer = new JPanel(new BorderLayout()); noDataContainer.setOpaque(false); noDataContainer.add(noDataLabel, BorderLayout.CENTER); setOpaque(false); setLayout(new BorderLayout()); add(noDataContainer, BorderLayout.CENTER); } private class TableListener extends MouseAdapter implements ListSelectionListener, KeyListener { public void valueChanged(ListSelectionEvent e) { selectionAdjusting = e.getValueIsAdjusting(); } public void keyPressed(KeyEvent e) { tableKeyStroke = KeyStroke.getKeyStrokeForEvent(e); } public void keyReleased(KeyEvent e) { tableKeyStroke = null; if (e.getKeyCode() == KeyEvent.VK_SPACE) support.scrollChartToIndex(getSelectedRow()); } public void keyTyped(KeyEvent e) {} public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) support.scrollChartToIndex(getSelectedRow()); } } private static class Viewport extends JViewport { private final DetailsTable view; private final Color background; Viewport(DetailsTable view) { super(); setView(view); this.view = view; setOpaque(true); background = view.getBackground(); setBackground(background); view.getColumnModel().addColumnModelListener(new TableColumnModelListener() { public void columnAdded(TableColumnModelEvent e) { repaint(); } public void columnMoved(TableColumnModelEvent e) { repaint(); } public void columnRemoved(TableColumnModelEvent e) { repaint(); } public void columnMarginChanged(ChangeEvent e) { repaint(); } public void columnSelectionChanged(ListSelectionEvent e) {} }); } protected void paintComponent(Graphics g) { super.paintComponent(g); paintVerticalLines(g); } private void paintVerticalLines(Graphics g) { int height = getHeight(); int viewHeight = view.getHeight(); if (viewHeight >= height) return; g.setColor(background); g.fillRect(0, viewHeight, getWidth(), getHeight() - viewHeight); int cellX = 0; int cellWidth; TableColumnModel model = view.getColumnModel(); int columnCount = model.getColumnCount(); g.setColor(DetailsTable.DEFAULT_GRID_COLOR); for (int i = 0; i < columnCount; i++) { cellWidth = model.getColumn(i).getWidth(); cellX += cellWidth; g.drawLine(cellX - 1, viewHeight, cellX - 1, height); } } } }