001: package tide.utils;
002:
003: import tide.editor.MainEditorFrame;
004: import snow.utils.gui.CustomEtchedBorder;
005: import javax.swing.*;
006: import javax.swing.event.*;
007: import javax.swing.border.*;
008: import java.awt.*;
009: import java.awt.event.*;
010: import javax.swing.table.*;
011: import java.awt.geom.*;
012: import snow.datatransfer.ClipboardUtils;
013:
014: public final class PackagesDependenciesViewer extends JDialog {
015: final private PackagesDependenciesAnalysis analysis;
016:
017: private final DepTableModel depTableModel;
018: private final JTable table;
019:
020: final private int[][] actualDisplayedMatrix;
021:
022: final private JCheckBox withoutCountCB = new JCheckBox(
023: "without count", true);
024: Font font = new Font("Dialog", Font.PLAIN, 10);
025:
026: int clickedCol = -1;
027: int clickedRow = -1;
028:
029: public PackagesDependenciesViewer(
030: final PackagesDependenciesAnalysis analysis, String title) {
031: super (MainEditorFrame.instance, title, false);
032: this .analysis = analysis;
033:
034: actualDisplayedMatrix = new int[analysis.getPackageNames().length][analysis
035: .getPackageNames().length];
036: resetMatrixToUsages();
037:
038: depTableModel = new DepTableModel();
039: table = new JTable(depTableModel);
040: table.setFont(font);
041:
042: JScrollPane pane = new JScrollPane(table);
043: add(pane, BorderLayout.CENTER);
044:
045: // Thank's Peter B. !
046: table.setRowHeight(15);
047: //table.setCellSelectionEnabled(true);
048: table.setRowSelectionAllowed(true);
049: table.setColumnSelectionAllowed(true);
050: table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
051: table.getTableHeader().setDefaultRenderer(
052: new VerticalTableCellRenderer(true, 270));
053: table.getTableHeader().setReorderingAllowed(false);
054: table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
055:
056: table.setDefaultRenderer(String.class, new TCRenderer());
057: table.setDefaultRenderer(Object.class, new TCRenderer());
058:
059: for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
060: table.getColumnModel().getColumn(i).setPreferredWidth(15);
061: }
062:
063: TableModel headerTM = new DefaultTableModel(new String[][] {},
064: new String[] { "line uses column" }) {
065: @Override
066: public boolean isCellEditable(int row, int column) {
067: return false;
068: }
069:
070: @Override
071: public Object getValueAt(int row, int col) {
072: return analysis.getPackageNames()[row];
073: }
074:
075: @Override
076: public int getColumnCount() {
077: return 1;
078: }
079:
080: @Override
081: public int getRowCount() {
082: return analysis.getPackageNames().length;
083: }
084: };
085: JTable headerTable = new JTable(headerTM);
086: headerTable.setFont(font);
087: headerTable.setRowHeight(table.getRowHeight());
088: headerTable.getTableHeader().setReorderingAllowed(false);
089: headerTable.setDefaultRenderer(Object.class,
090: new VerticalTableCellRenderer(false, 350));
091: headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
092: headerTable.getColumnModel().getColumn(0)
093: .setPreferredWidth(350);
094: headerTable.setPreferredScrollableViewportSize(headerTable
095: .getPreferredSize());
096: headerTable.setFocusable(false);
097: pane.setRowHeaderView(headerTable);
098: pane.setCorner(JScrollPane.UPPER_LEFT_CORNER, headerTable
099: .getTableHeader());
100:
101: /* table.addMouseMotionListener(new MouseMotionAdapter()
102: { @Override
103: public void mouseMoved(MouseEvent me)
104: {
105: }
106: }
107: );*/
108:
109: table.addMouseListener(new MouseAdapter() {
110: @Override
111: public void mousePressed(MouseEvent me) {
112: final int col = table.columnAtPoint(me.getPoint());
113: clickedCol = col;
114: final int row = table.rowAtPoint(me.getPoint());
115: clickedRow = row;
116: if (row >= 0 && col >= 0) {
117: EventQueue.invokeLater(new Runnable() {
118: public void run() {
119: // TODO: in a mouse Motion Listener
120: table.setRowSelectionInterval(row, row);
121: table.setColumnSelectionInterval(col, col);
122: if (table.getValueAt(row, col).toString()
123: .length() > 0) {
124: table
125: .setToolTipText("<html><body>"
126: + analysis
127: .getPackageNames()[row]
128: + "<br> uses<br>"
129: + analysis
130: .getPackageNames()[col]);
131: } else {
132: table.setToolTipText("");
133: }
134: //don't work: ToolTipManager.sharedInstance().showTipWindow();
135: table.repaint();
136: table.getTableHeader().repaint();
137: }
138: });
139: }
140: }
141: });
142:
143: JPanel ctrlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,
144: 2, 2));
145: add(ctrlPanel, BorderLayout.SOUTH);
146:
147: JButton exportToClipboard = new JButton(
148: "Export to clipboard (Tab separated)");
149: exportToClipboard.setMargin(new Insets(0, 2, 0, 2));
150: ctrlPanel.add(exportToClipboard);
151: exportToClipboard.addActionListener(new ActionListener() {
152: public void actionPerformed(ActionEvent ae) {
153: ClipboardUtils.copyToClipboard(analysis.toString());
154: }
155: });
156:
157: ctrlPanel.add(withoutCountCB);
158: withoutCountCB.addActionListener(new ActionListener() {
159: public void actionPerformed(ActionEvent ae) {
160: repaint();
161: }
162: });
163:
164: JButton resetBT = new JButton("Reset");
165: resetBT.setMargin(new Insets(0, 2, 0, 2));
166: ctrlPanel.add(resetBT);
167: resetBT.addActionListener(new ActionListener() {
168: public void actionPerformed(ActionEvent ae) {
169: resetMatrixToUsages();
170: repaint();
171: }
172: });
173:
174: JButton propagateBT = new JButton("Propagate");
175: propagateBT
176: .setToolTipText("<html><body>Shows the second generation of usages (usages of usages) and so on.");
177: propagateBT.setMargin(new Insets(0, 2, 0, 2));
178: ctrlPanel.add(propagateBT);
179: propagateBT.addActionListener(new ActionListener() {
180: public void actionPerformed(ActionEvent ae) {
181: propagate();
182: repaint();
183: }
184: });
185:
186: int screenH = (int) Toolkit.getDefaultToolkit().getScreenSize()
187: .getHeight();
188: int dim = Math.min(800, screenH);
189:
190: setSize(dim, dim);
191: this .setLocationRelativeTo(MainEditorFrame.instance);
192: setVisible(true);
193: }
194:
195: /** copy the analysis result
196: */
197: private void resetMatrixToUsages() {
198: for (int i = 0; i < actualDisplayedMatrix.length; i++) {
199: for (int j = 0; j < actualDisplayedMatrix.length; j++) {
200: actualDisplayedMatrix[i][j] = analysis
201: .getUsagesMatrix()[i][j];
202: }
203: }
204: }
205:
206: /** compute A.M
207: */
208: private void propagate() {
209: int[][] r = matrixMult(actualDisplayedMatrix, analysis
210: .getUsagesMatrix());
211: for (int i = 0; i < actualDisplayedMatrix.length; i++) {
212: for (int j = 0; j < actualDisplayedMatrix.length; j++) {
213: actualDisplayedMatrix[i][j] = (r[i][j] != 0 ? 1 : 0);
214: }
215: }
216: }
217:
218: private int[][] matrixMult(int[][] a, int[][] b) {
219: int[][] c = new int[a.length][a.length];
220: for (int i = 0; i < a.length; i++) {
221: for (int j = 0; j < a[i].length; j++) {
222: for (int k = 0; k < a.length; k++) {
223: c[i][j] += a[i][k] * b[k][j]; // line i of a dot col j of b
224: }
225: }
226: }
227: return c;
228: }
229:
230: private class DepTableModel extends AbstractTableModel {
231: public int getRowCount() {
232: return analysis.getUsagesMatrix().length;
233: }
234:
235: public int getColumnCount() {
236: return analysis.names.length;
237: }
238:
239: public Object getValueAt(int row, int col) {
240: //if(row==col) return "";
241: int nd = actualDisplayedMatrix[row][col];
242: if (nd == 0)
243: return "";
244: if (withoutCountCB.isSelected()) {
245: return "X";
246: }
247: return "" + nd;
248:
249: }
250:
251: @Override
252: public boolean isCellEditable(int row, int column) {
253: return false;
254: }
255:
256: /** used by the header renderer...
257: */
258: @Override
259: public String getColumnName(int col) {
260: //if(col==0) return "";
261: return analysis.getPackageNames()[col];
262: }
263:
264: }
265:
266: private class TCRenderer extends DefaultTableCellRenderer {
267:
268: Border hb = new LineBorder(new Color(30, 30, 120)); // light blue
269: Border hb2 = new LineBorder(new Color(30, 30, 220)); // light blue
270:
271: Border origBorder = null;
272:
273: public TCRenderer() {
274: super ();
275: origBorder = getBorder();
276: }
277:
278: @Override
279: public Component getTableCellRendererComponent(JTable table,
280: Object value, boolean isSelected, boolean hasFocus,
281: int row, int column) {
282: super .getTableCellRendererComponent(table, value,
283: isSelected, hasFocus, row, column);
284:
285: if (clickedRow == row || clickedCol == column) {
286: setBorder(hb);
287: } else {
288: setBorder(origBorder);
289: }
290:
291: if (clickedRow == column && clickedCol == row) {
292: // symmetric !
293: setBorder(hb2);
294: }
295:
296: return this ;
297: }
298:
299: }
300:
301: /** Thanks Peter B.
302: */
303: private class VerticalTableCellRenderer extends
304: DefaultTableCellRenderer {
305: private boolean rotate = true;
306: private int dim = 0;
307: Border hb = new LineBorder(new Color(30, 30, 120)); // light blue
308: Border origBorder = null;
309:
310: public VerticalTableCellRenderer(boolean _rotate,
311: int _headerTableWidth) {
312: super ();
313: origBorder = getBorder();
314: this .rotate = _rotate;
315: this .dim = _headerTableWidth;
316: this .setPreferredSize(_rotate ? new Dimension(this
317: .getPreferredSize().width, dim) : new Dimension(
318: dim, this .getPreferredSize().height));
319: this .setMinimumSize(_rotate ? new Dimension(this
320: .getPreferredSize().width, dim) : new Dimension(
321: dim, this .getPreferredSize().height));
322: this .setMaximumSize(_rotate ? new Dimension(this
323: .getPreferredSize().width, dim) : new Dimension(
324: dim, this .getPreferredSize().height));
325: }
326:
327: @Override
328: public Component getTableCellRendererComponent(JTable table,
329: Object value, boolean isSelected, boolean hasFocus,
330: int row, int column) {
331: if (clickedCol == column) {
332: hasFocus = true;
333: isSelected = true;
334: }
335:
336: super .getTableCellRendererComponent(table, value,
337: isSelected, hasFocus, row, column);
338:
339: if (this .rotate) {
340: int cw = table.getColumnModel().getColumn(column)
341: .getWidth();
342: setPreferredSize(new Dimension(cw, dim));
343: } else {
344: int rh = table.getRowHeight(row);
345: setPreferredSize(new Dimension(dim, rh));
346: }
347:
348: /* if(clickedCol==column)
349: {
350: setBorder(hb);
351: }
352: else
353: {
354: setBorder(origBorder);
355: }*/
356:
357: return this ;
358: }
359:
360: @Override
361: public void paintComponent(Graphics g) {
362: Graphics2D g2 = (Graphics2D) g;
363: g2.setColor(UIManager.getColor("Panel.background"));
364: g2.fill(new Rectangle2D.Double(0, 0, getPreferredSize()
365: .getWidth(), getPreferredSize().getHeight()));
366:
367: if (rotate) {
368: Border border = //BorderFactory.createLineBorder(Color.darkGray); // etched
369: new CustomEtchedBorder(false, false, false, true);
370: border.paintBorder(this , g, 0, 0,
371: getPreferredSize().width,
372: getPreferredSize().height);
373: }
374:
375: g2.setFont(font); //UIManager.getFont("Label.font"));
376: g2.setColor(UIManager.getColor("Label.foreground"));
377: if (rotate) {
378: g2.rotate(Math.PI + Math.PI / 2.0);
379: g2.drawString(getText(),
380: -getPreferredSize().height + 7,
381: getPreferredSize().width / 2 + 3);
382: } else {
383: // align right ?
384: g2.drawString(getText(), 7,
385: getPreferredSize().height / 2 + 3);
386: }
387: }
388: }
389:
390: }
|