package jdepend.client.report.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import jdepend.framework.ui.component.JDependFrame; import jdepend.framework.ui.component.TableMouseMotionAdapter; import jdepend.framework.ui.component.TableSorter; import jdepend.framework.ui.util.JTableUtil; import jdepend.framework.util.BundleUtil; import jdepend.metadata.CandidateUtil; import jdepend.metadata.util.JavaClassUtil; import jdepend.model.JDependUnitMgr; import jdepend.model.JavaClassUnit; import jdepend.model.MetricsMgr; import jdepend.model.result.AnalysisResult; import jdepend.client.report.model.ReportJavaClassUnit; import jdepend.client.report.model.ReportJavaClassUnitUtil; import jdepend.client.report.util.ReportConstant; public class ClassListPanel extends JPanel { private DefaultTableModel classListModel; protected JTable classListTable; protected String current; protected List<String> selectedJavaClassId; // 外部JavaClass名称 protected List<String> extendUnits = new ArrayList<String>(); private Collection<ReportJavaClassUnit> javaClasses; protected JDependFrame frame; public ClassListPanel(JDependFrame frame) { super(); this.frame = frame; setLayout(new BorderLayout()); this.initClassList(); JScrollPane pane = new JScrollPane(classListTable); pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); this.add(pane); } private AnalysisResult getAnalysisResult(){ return JDependUnitMgr.getInstance().getResult(); } public int showClassList(Collection<JavaClassUnit> javaClasses) { clearClassList(); this.javaClasses = ReportJavaClassUnitUtil.convert(javaClasses); this.loadClassList(); this.fitCol(); return classListModel.getRowCount(); } public int showClassList(jdepend.model.Component component) { clearClassList(); this.javaClasses = ReportJavaClassUnitUtil.convert(component.getClasses()); this.loadClassList(); this.fitCol(); return classListModel.getRowCount(); } public int showAllClassList() { clearClassList(); this.javaClasses = ReportJavaClassUnitUtil.convert(getAnalysisResult().getClasses()); this.loadClassList(); this.fitCol(); return classListModel.getRowCount(); } public int filterClassList(String nameFilter, String callerFilter, String calleeFilter) { clearClassList(); this.inFilterClassList(nameFilter, callerFilter, calleeFilter); this.fitCol(); return classListModel.getRowCount(); } public void clearClassList() { classListModel.setRowCount(0); this.extendUnits = new ArrayList<String>(); } public void initPopupMenu(JavaClassMoveToDialogListener listener) { final JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(this.createCasItem()); popupMenu.add(this.createCesItem()); popupMenu.addSeparator(); popupMenu.add(this.createMoveToItem(listener)); popupMenu.add(this.createSaveAsItem()); this.getClassListTable().addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); if (e.getButton() == 3) { popupMenu.show(getClassListTable(), e.getX(), e.getY()); } } }); } private void fitCol() { List<String> fitColNames = new ArrayList<String>(); fitColNames.add(ReportConstant.Name); JTableUtil.fitTableColumns(classListTable, fitColNames); } private void loadClassList() { Object[] row; String metrics = null; for (JavaClassUnit javaClass : this.javaClasses) { row = new Object[classListTable.getColumnCount()]; for (int i = 0; i < classListTable.getColumnCount(); i++) { metrics = ReportConstant.toMetrics(classListTable.getColumnName(i)); row[i] = javaClass.getValue(metrics); } classListModel.addRow(row); if (!javaClass.isInner()) { this.extendUnits.add(javaClass.getId()); } } } private void inFilterClassList(String nameFilter, String callerFilter, String calleeFilter) { Object[] row; String metrics = null; for (JavaClassUnit javaClass : this.javaClasses) { if ((nameFilter == null || nameFilter.length() == 0 || JavaClassUtil.match(nameFilter, javaClass.getJavaClass())) && (callerFilter == null || callerFilter.length() == 0 || this.matchCallerFilter(callerFilter, javaClass)) && (calleeFilter == null || calleeFilter.length() == 0 || this.matchCalleeFilter(calleeFilter, javaClass))) { row = new Object[classListTable.getColumnCount()]; for (int i = 0; i < classListTable.getColumnCount(); i++) { metrics = ReportConstant.toMetrics(classListTable.getColumnName(i)); row[i] = javaClass.getValue(metrics); } classListModel.addRow(row); if (!javaClass.isInner()) { this.extendUnits.add(javaClass.getId()); } } } } private boolean matchCallerFilter(String callerFilter, JavaClassUnit javaClass) { for (JavaClassUnit caClass : javaClass.getCaList()) { if (JavaClassUtil.match(callerFilter, caClass.getJavaClass())) { return true; } } return false; } private boolean matchCalleeFilter(String calleeFilter, JavaClassUnit javaClass) { for (JavaClassUnit ceClass : javaClass.getCeList()) { if (JavaClassUtil.match(calleeFilter, ceClass.getJavaClass())) { return true; } } return false; } protected void initClassList() { classListModel = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; TableSorter sorter = new TableSorter(classListModel) { @Override protected Comparator getComparator(int column) { String currentCol = (String) classListTable.getColumnModel().getColumn(column).getHeaderValue(); if (currentCol.equals(ReportConstant.Ca) || currentCol.equals(ReportConstant.Ce)) { return new CaCeComparator(); } else { return super.getComparator(column); } } }; classListTable = new JTable(sorter); classListTable.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { JTable table = (JTable) e.getSource(); Point p = new Point(e.getX(), e.getY()); int col = table.columnAtPoint(p); int row = table.rowAtPoint(p); current = CandidateUtil.getId((String) table.getValueAt(row, 0), (String) table.getValueAt(row, 1)); String currentCol = (String) table.getColumnModel().getColumn(col).getHeaderValue(); selectedJavaClassId = new ArrayList<String>(); for (int rowNumber : table.getSelectedRows()) { selectedJavaClassId.add(CandidateUtil.getId((String) table.getValueAt(rowNumber, 0), (String) table.getValueAt(rowNumber, 1))); } if (e.getClickCount() == 2) { JavaClassUnit currentClass = getAnalysisResult().getTheClass(current); if (currentCol.equals(ReportConstant.Ca) || currentCol.equals(ReportConstant.Ce)) { Rectangle rec = table.getCellRect(row, col, false); Component comp = table.getComponentAt(p); int x = rec.x; String value = (String) table.getValueAt(row, col); int pos = value.indexOf('|'); String preValue = value.substring(0, pos); int width = x + comp.getFontMetrics(comp.getFont()).stringWidth(preValue); int pos1; if (currentCol.equals(ReportConstant.Ca)) { pos1 = value.indexOf('<'); } else { pos1 = value.indexOf('>'); } String preValue1 = value.substring(0, pos1); int width1 = x + comp.getFontMetrics(comp.getFont()).stringWidth(preValue1); if (p.x > x && p.x < width) { JavaClassCaCeDetailDialog d = new JavaClassCaCeDetailDialog(currentClass, currentCol, false); d.setModal(true); d.setVisible(true); } else if (p.x > width && p.x < width1) { JavaClassCaCeDetailDialog d = new JavaClassCaCeDetailDialog(currentClass, currentCol, true); d.setModal(true); d.setVisible(true); } else { if (currentCol.equals(ReportConstant.Ca)) { JavaClassCaGraphDialog d = new JavaClassCaGraphDialog(currentClass); d.setModal(true); d.setVisible(true); } else { JavaClassCeGraphDialog d = new JavaClassCeGraphDialog(currentClass); d.setModal(true); d.setVisible(true); } } } else if (currentCol.equals(ReportConstant.Name)) { JavaClassDetailDialog d = new JavaClassDetailDialog(currentClass); d.setModal(true); d.setVisible(true); } else if (currentCol.equals(ReportConstant.Cycle)) { if (MetricsMgr.Cyclic.equals(table.getModel().getValueAt(table.rowAtPoint(e.getPoint()), table.columnAtPoint(e.getPoint())))) { CycleDialog d = new CycleDialog(currentClass); d.setModal(true); d.setVisible(true); } } else if (currentCol.equals(ReportConstant.Cohesion)) { CohesionDialog d = new CohesionDialog(currentClass); d.setModal(true); d.setVisible(true); } else if (currentCol.equals(ReportConstant.Coupling)) { CouplingDialog d = new CouplingDialog(currentClass); d.setModal(true); d.setVisible(true); } } } }); sorter.setTableHeader(classListTable.getTableHeader()); classListModel.addColumn(ReportConstant.JavaClass_Place); classListModel.addColumn(ReportConstant.Name); classListModel.addColumn(ReportConstant.LC); classListModel.addColumn(ReportConstant.AC); classListModel.addColumn(ReportConstant.Ca); classListModel.addColumn(ReportConstant.Ce); classListModel.addColumn(ReportConstant.Coupling); classListModel.addColumn(ReportConstant.Cohesion); classListModel.addColumn(ReportConstant.Cycle); classListModel.addColumn(ReportConstant.JavaClass_State); classListModel.addColumn(ReportConstant.JavaClass_Stable); classListModel.addColumn(ReportConstant.JavaClass_isPrivateElement); classListModel.addColumn(ReportConstant.JavaClass_ClassType); // 增加点击图标 List<String> colNames = new ArrayList<String>(); colNames.add(ReportConstant.Name); colNames.add(ReportConstant.Ca); colNames.add(ReportConstant.Ce); colNames.add(ReportConstant.Coupling); colNames.add(ReportConstant.Cohesion); colNames.add(ReportConstant.Cycle); classListTable.addMouseMotionListener(new TableMouseMotionAdapter(classListTable, colNames)); sorter.setSortingStatus(1, TableSorter.ASCENDING); classListTable.getColumnModel().getColumn(0).setMinWidth(0); classListTable.getColumnModel().getColumn(0).setMaxWidth(0); JavaClassTableRenderer renderer = new JavaClassTableRenderer(); for (int i = 0; i < classListTable.getColumnCount(); i++) { classListTable.getColumn(classListTable.getColumnName(i)).setCellRenderer(renderer); } } protected JTable getClassListTable() { return classListTable; } protected JMenuItem createMoveToItem(final JavaClassMoveToDialogListener listener) { JMenuItem moveToItem = new JMenuItem(BundleUtil.getString(BundleUtil.Command_Move)); moveToItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (selectedJavaClassId.size() > 0) { moveTo(listener); } else { JOptionPane.showMessageDialog(frame, "请选择至少一个JavaClass.", "alert", JOptionPane.WARNING_MESSAGE); } } }); return moveToItem; } private void moveTo(JavaClassMoveToDialogListener listener) { Collection<JavaClassUnit> javaClasses = new ArrayList<JavaClassUnit>(); for (String javaClassId : selectedJavaClassId) { javaClasses.add(getAnalysisResult().getTheClass(javaClassId)); } JavaClassMoveToDialog d = new JavaClassMoveToDialog(frame, javaClasses); if (listener != null) { d.setListener(listener); } d.setModal(true); d.setVisible(true); } protected JMenuItem createSaveAsItem() { JMenuItem saveAsItem = new JMenuItem(BundleUtil.getString(BundleUtil.Command_SaveAs)); saveAsItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JTableUtil.exportTableToExcel(classListTable); } }); return saveAsItem; } protected JMenuItem createCasItem() { JMenuItem casItem = new JMenuItem(BundleUtil.getString(BundleUtil.Command_Ca)); casItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Collection<JavaClassUnit> javaClasses = new HashSet<JavaClassUnit>(); for (String javaClassId : selectedJavaClassId) { javaClasses.add(getAnalysisResult().getTheClass(javaClassId)); } JavaClassCaCeDetailDialog d = new JavaClassCaCeDetailDialog(javaClasses, ReportConstant.Ca); d.setModal(true); d.setVisible(true); } }); return casItem; } protected JMenuItem createCesItem() { JMenuItem cesItem = new JMenuItem(BundleUtil.getString(BundleUtil.Command_Ce)); cesItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Collection<JavaClassUnit> javaClasses = new HashSet<JavaClassUnit>(); for (String javaClassId : selectedJavaClassId) { javaClasses.add(getAnalysisResult().getTheClass(javaClassId)); } JavaClassCaCeDetailDialog d = new JavaClassCaCeDetailDialog(javaClasses, ReportConstant.Ce); d.setModal(true); d.setVisible(true); } }); return cesItem; } class JavaClassTableRenderer extends JPanel implements TableCellRenderer { public JavaClassTableRenderer() { this.setLayout(new BorderLayout()); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { this.removeAll(); if (value != null) { JLabel labelValue = new JLabel(); labelValue.setFont(table.getFont()); if (extendUnits.contains(CandidateUtil.getId((String) table.getValueAt(row, 0), (String) table.getValueAt(row, 1)))) { labelValue.setForeground(Color.GRAY); } String strValue = String.valueOf(value); labelValue.setText(strValue); this.add(labelValue); } if (isSelected) { this.setBackground(table.getSelectionBackground()); } else { this.setBackground(table.getBackground()); } return this; } } class CaCeComparator implements Comparator { @Override public int compare(Object o1, Object o2) { if (o1 instanceof String && o2 instanceof String) { String s1 = (String) o1; String s2 = (String) o2; if (s1.indexOf('|') != -1 && s2.indexOf('|') != -1) { return getValue(s1).compareTo(getValue(s2)); } else if (o1 instanceof Integer && o2 instanceof Integer) { return ((Integer) o1).compareTo((Integer) o2); } else if (o1 instanceof Float && o2 instanceof Float) { return ((Float) o1).compareTo((Float) o2); } else { return 0; } } else if (o1 instanceof Integer && o2 instanceof Integer) { return ((Integer) o1).compareTo((Integer) o2); } else if (o1 instanceof Float && o2 instanceof Float) { return ((Float) o1).compareTo((Float) o2); } else { return 0; } } private Integer getValue(String data) { return Integer.valueOf(data.substring(0, data.indexOf('|'))); } } }