001: package com.tagtraum.perf.gcviewer;
002:
003: import javax.swing.*;
004: import javax.swing.event.ChangeEvent;
005: import javax.swing.event.ChangeListener;
006: import java.awt.*;
007: import java.awt.datatransfer.DataFlavor;
008: import java.awt.datatransfer.Transferable;
009: import java.awt.datatransfer.UnsupportedFlavorException;
010: import java.awt.dnd.*;
011: import java.beans.PropertyChangeEvent;
012: import java.beans.PropertyChangeListener;
013: import java.io.IOException;
014: import java.io.File;
015: import java.util.*;
016: import java.net.URL;
017:
018: /**
019: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
020: * Date: May 5, 2005
021: * Time: 10:25:16 AM
022: */
023: public class GCDocument extends JInternalFrame {
024:
025: private java.util.List chartPanelViews = new ArrayList();
026: private ModelChart modelChart;
027: private boolean showModelPanel = true;
028: private boolean watched;
029: private RefreshWatchDog refreshWatchDog;
030:
031: public GCDocument(final GCViewer gcViewer, String s) {
032: super (s, true, true, true, false);
033: this .refreshWatchDog = new RefreshWatchDog();
034: refreshWatchDog.setGcDocument(this );
035: modelChart = new MultiModelChartFacade();
036: GridBagLayout layout = new GridBagLayout();
037: getContentPane().setLayout(layout);
038: getContentPane().setDropTarget(
039: new DropTarget(this , DnDConstants.ACTION_COPY,
040: new DropTargetListener() {
041: public void dragEnter(DropTargetDragEvent e) {
042: if (e
043: .isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
044: e
045: .acceptDrag(DnDConstants.ACTION_COPY);
046: } else {
047: e.rejectDrag();
048: }
049: }
050:
051: public void dragOver(
052: DropTargetDragEvent dtde) {
053: }
054:
055: public void dropActionChanged(
056: DropTargetDragEvent dtde) {
057: }
058:
059: public void dragExit(DropTargetEvent dte) {
060: }
061:
062: public void drop(DropTargetDropEvent e) {
063: try {
064: Transferable tr = e
065: .getTransferable();
066: if (e
067: .isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
068: e
069: .acceptDrop(DnDConstants.ACTION_COPY);
070: java.util.List list = (java.util.List) tr
071: .getTransferData(DataFlavor.javaFileListFlavor);
072: File[] files = (File[]) list
073: .toArray(new File[list
074: .size()]);
075: gcViewer.add(files);
076: GCDocument.this
077: .getContentPane()
078: .invalidate();
079: e.dropComplete(true);
080: } else {
081: e.rejectDrop();
082: }
083: } catch (IOException ioe) {
084: e.rejectDrop();
085: ioe.printStackTrace();
086: } catch (UnsupportedFlavorException ufe) {
087: e.rejectDrop();
088: ufe.printStackTrace();
089: }
090: }
091: }));
092:
093: }
094:
095: public RefreshWatchDog getRefreshWatchDog() {
096: return refreshWatchDog;
097: }
098:
099: public boolean isShowModelPanel() {
100: return showModelPanel;
101: }
102:
103: public void setShowModelPanel(boolean showModelPanel) {
104: boolean mustRelayout = this .showModelPanel != showModelPanel;
105: this .showModelPanel = showModelPanel;
106: if (mustRelayout) {
107: relayout();
108: }
109: }
110:
111: /**
112: * @return true, if any of the files has been reloaded
113: * @throws IOException
114: */
115: public boolean reloadModels(boolean background) throws IOException {
116: boolean reloaded = false;
117: for (int i = 0; i < chartPanelViews.size(); i++) {
118: reloaded |= ((ChartPanelView) chartPanelViews.get(i))
119: .reloadModel();
120: }
121: if (!background) {
122: relayout();
123: }
124: return reloaded;
125: }
126:
127: public ModelChart getModelChart() {
128: return modelChart;
129: }
130:
131: public void add(final URL url) throws IOException {
132: ChartPanelView chartPanelView = new ChartPanelView(this , url);
133: chartPanelViews.add(chartPanelView);
134: chartPanelView
135: .addPropertyChangeListener(new PropertyChangeListener() {
136: public void propertyChange(PropertyChangeEvent event) {
137: if ("minimized".equals(event.getPropertyName()))
138: relayout();
139: }
140: });
141: // make sure all models in one document have the same display properties
142: if (chartPanelViews.size() > 1) {
143: modelChart.setScaleFactor(modelChart.getScaleFactor());
144: modelChart.setShowFullGCLines(modelChart
145: .isShowFullGCLines());
146: modelChart.setShowGCTimesLine(modelChart
147: .isShowGCTimesLine());
148: modelChart.setShowGCTimesRectangles(modelChart
149: .isShowGCTimesRectangles());
150: modelChart.setShowIncGCLines(modelChart.isShowIncGCLines());
151: modelChart.setShowTotalMemoryLine(modelChart
152: .isShowTotalMemoryLine());
153: modelChart.setShowUsedMemoryLine(modelChart
154: .isShowUsedMemoryLine());
155: }
156: relayout();
157: }
158:
159: public void removeChartPanelView(ChartPanelView chartPanelView) {
160: chartPanelViews.remove(chartPanelView);
161: relayout();
162: }
163:
164: public void relayout() {
165: getContentPane().removeAll();
166: if (chartPanelViews.size() > 1) {
167: StringBuffer sb = new StringBuffer();
168: for (int i = 0; i < chartPanelViews.size(); i++) {
169: sb.append(((ChartPanelView) chartPanelViews.get(i))
170: .getModel().getURL().getFile());
171: if (i + 1 < chartPanelViews.size())
172: sb.append(", ");
173: }
174: setTitle(sb.toString());
175: } else if (!chartPanelViews.isEmpty())
176: setTitle(((ChartPanelView) chartPanelViews.get(0))
177: .getModel().getURL().toString());
178: else
179: setTitle("");
180: int row = 0;
181: boolean noMaximizedChartPanelView = true;
182: ChartPanelView lastMaximizedChartPanelView = getLastMaximizedChartPanelView();
183: MasterViewPortChangeListener masterViewPortChangeListener = new MasterViewPortChangeListener();
184:
185: for (int i = 0; i < chartPanelViews.size(); i++) {
186: final ChartPanelView chartPanelView = (ChartPanelView) chartPanelViews
187: .get(i);
188: final ModelChartImpl modelChart = (ModelChartImpl) chartPanelView
189: .getModelChart();
190: final ModelPanel modelPanel = chartPanelView
191: .getModelPanel();
192: //final JComponent parseLog = new JScrollPane(chartPanelView.getParseLog());
193: modelChart.invalidate();
194: GridBagConstraints constraints = new GridBagConstraints();
195: constraints.fill = GridBagConstraints.HORIZONTAL;
196: constraints.anchor = GridBagConstraints.NORTH;
197:
198: constraints.gridy = row;
199: if (chartPanelViews.size() > 1
200: || (chartPanelView.isMinimized() && chartPanelViews
201: .size() == 1)) {
202: constraints.gridwidth = 2;
203: constraints.weightx = 2;
204: //constraints.weighty = 1;
205: getContentPane().add(chartPanelView.getViewBar(),
206: constraints);
207: row++;
208: }
209: constraints.fill = GridBagConstraints.BOTH;
210: constraints.gridy = row;
211: constraints.gridwidth = 1;
212: constraints.gridheight = 1; //2
213: constraints.gridx = 0;
214: constraints.weightx = 2;
215: constraints.weighty = 2;
216: modelChart.setPreferredSize(new Dimension(800, 600));
217: modelChart.setVisible(!chartPanelView.isMinimized());
218: getContentPane().add(modelChart, constraints);
219:
220: /*
221: constraints.gridheight = 1;
222: constraints.gridy = row;
223: constraints.gridx = 1;
224: constraints.weightx = 0;
225: constraints.weighty = 4;
226: constraints.fill = GridBagConstraints.BOTH;
227: constraints.anchor = GridBagConstraints.NORTH;
228: getContentPane().add(parseLog, constraints);
229: parseLog.setVisible(!chartPanelView.isMinimized());
230:
231: row++;
232: */
233:
234: constraints.gridy = row;
235: constraints.gridheight = 1;
236: constraints.gridx = 1;
237: constraints.weightx = 0;
238: constraints.weighty = 0;
239: constraints.fill = GridBagConstraints.HORIZONTAL;
240: constraints.anchor = GridBagConstraints.SOUTH;
241: getContentPane().add(modelPanel, constraints);
242: modelPanel.setVisible(showModelPanel
243: && (!chartPanelView.isMinimized()));
244:
245: if (!chartPanelView.isMinimized()) {
246: noMaximizedChartPanelView = false;
247: final boolean isLastMaximizedChartPanelView = lastMaximizedChartPanelView == chartPanelView;
248: // lock viewports with each other...
249: // remove old master listeners
250: final JViewport viewport = modelChart.getViewport();
251: lockChartsToOneScrollbar(viewport,
252: isLastMaximizedChartPanelView, modelChart,
253: masterViewPortChangeListener);
254:
255: final JScrollBar horizontalScrollBar = modelChart
256: .getHorizontalScrollBar();
257: // clean old change listeners
258: ChangeListener[] changeListeners = ((DefaultBoundedRangeModel) horizontalScrollBar
259: .getModel()).getChangeListeners();
260: for (int j = 0; j < changeListeners.length; j++) {
261: if (changeListeners[j] instanceof ScrollBarMaximumChangeListener) {
262: horizontalScrollBar.getModel()
263: .removeChangeListener(
264: changeListeners[j]);
265: }
266: }
267: if (isLastMaximizedChartPanelView && isWatched()) {
268: horizontalScrollBar.getModel().addChangeListener(
269: new ScrollBarMaximumChangeListener());
270: }
271: if (isLastMaximizedChartPanelView) {
272: horizontalScrollBar.setEnabled(!isWatched());
273: }
274: }
275: row++;
276: }
277: if (noMaximizedChartPanelView) {
278: // add dummy panel
279: GridBagConstraints constraints = new GridBagConstraints();
280: constraints.fill = GridBagConstraints.BOTH;
281: constraints.gridy = row;
282: constraints.weightx = 3;
283: constraints.weighty = 3;
284: getContentPane().add(new JPanel(), constraints);
285: }
286: scaleModelChart();
287: revalidate();
288: }
289:
290: private void lockChartsToOneScrollbar(final JViewport viewport,
291: final boolean lastMaximizedChartPanelView,
292: final ModelChartImpl modelChart,
293: MasterViewPortChangeListener masterViewPortChangeListener) {
294: ChangeListener[] changeListeners = viewport
295: .getChangeListeners();
296: for (int j = 0; j < changeListeners.length; j++) {
297: if (changeListeners[j] instanceof MasterViewPortChangeListener) {
298: viewport.removeChangeListener(changeListeners[j]);
299: }
300: }
301: if (lastMaximizedChartPanelView) {
302: modelChart
303: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
304: // add scrollbar listener
305: viewport.addChangeListener(masterViewPortChangeListener);
306: } else {
307: modelChart
308: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
309: masterViewPortChangeListener.addSlaveViewport(viewport);
310: }
311: }
312:
313: public int getChartPanelViewCount() {
314: return chartPanelViews.size();
315: }
316:
317: public ChartPanelView getChartPanelView(int i) {
318: return (ChartPanelView) chartPanelViews.get(i);
319: }
320:
321: public void setWatched(boolean watched) {
322: this .watched = watched;
323: final JScrollBar horizontalScrollBar = ((ModelChartImpl) getLastMaximizedChartPanelView()
324: .getModelChart()).getHorizontalScrollBar();
325: if (watched) {
326: horizontalScrollBar.setValue(horizontalScrollBar
327: .getMaximum());
328: }
329: horizontalScrollBar.setEnabled(!watched);
330: }
331:
332: public boolean isWatched() {
333: return watched;
334: }
335:
336: private static class MasterViewPortChangeListener implements
337: ChangeListener {
338: private java.util.List slaveViewPorts = new ArrayList();
339:
340: public void addSlaveViewport(JViewport viewPort) {
341: slaveViewPorts.add(viewPort);
342: }
343:
344: public void stateChanged(ChangeEvent e) {
345: JViewport master = (JViewport) e.getSource();
346: final int x = master.getViewPosition().x;
347: for (int i = 0; i < slaveViewPorts.size(); i++) {
348: JViewport slave = (JViewport) slaveViewPorts.get(i);
349: slave.setViewPosition(new Point(x, slave
350: .getViewPosition().y));
351: }
352: }
353: }
354:
355: public ChartPanelView getLastMaximizedChartPanelView() {
356: ChartPanelView lastMaximizedChartPanelView = null;
357: for (int i = 0; i < chartPanelViews.size(); i++) {
358: final ChartPanelView chartPanelView = (ChartPanelView) chartPanelViews
359: .get(i);
360: if (!chartPanelView.isMinimized())
361: lastMaximizedChartPanelView = chartPanelView;
362: }
363: return lastMaximizedChartPanelView;
364: }
365:
366: private void scaleModelChart() {
367: for (int i = 0; i < chartPanelViews.size(); i++) {
368: final ChartPanelView aChartPanelView = ((ChartPanelView) chartPanelViews
369: .get(i));
370: aChartPanelView.getModelChart().setFootprint(
371: getMaxFootprint());
372: aChartPanelView.getModelChart().setMaxPause(
373: getMaxMaxPause());
374: aChartPanelView.getModelChart().setRunningTime(
375: getMaxRunningTime());
376: }
377: }
378:
379: private double getMaxRunningTime() {
380: double max = 0;
381: for (int i = 0; i < chartPanelViews.size(); i++) {
382: max = Math.max(max, ((ChartPanelView) chartPanelViews
383: .get(i)).getModel().getRunningTime());
384: }
385: return max;
386: }
387:
388: private long getMaxFootprint() {
389: long max = 0;
390: for (int i = 0; i < chartPanelViews.size(); i++) {
391: max = Math.max(max, ((ChartPanelView) chartPanelViews
392: .get(i)).getModel().getFootprint());
393: }
394: return max;
395: }
396:
397: private double getMaxMaxPause() {
398: double max = 0;
399: for (int i = 0; i < chartPanelViews.size(); i++) {
400: max = Math.max(max, ((ChartPanelView) chartPanelViews
401: .get(i)).getModel().getPause().getMax());
402: }
403: return max;
404: }
405:
406: private class MultiModelChartFacade implements ModelChart {
407:
408: public boolean isAntiAlias() {
409: if (chartPanelViews.isEmpty())
410: return false;
411: return ((ChartPanelView) chartPanelViews.get(0))
412: .getModelChart().isAntiAlias();
413: }
414:
415: public void setAntiAlias(boolean antiAlias) {
416: for (int i = 0; i < chartPanelViews.size(); i++) {
417: ((ChartPanelView) chartPanelViews.get(i))
418: .getModelChart().setAntiAlias(antiAlias);
419: }
420: }
421:
422: public long getFootprint() {
423: if (chartPanelViews.isEmpty())
424: return 0;
425: return ((ChartPanelView) chartPanelViews.get(0))
426: .getModelChart().getFootprint();
427: }
428:
429: public double getMaxPause() {
430: if (chartPanelViews.isEmpty())
431: return 0;
432: return ((ChartPanelView) chartPanelViews.get(0))
433: .getModelChart().getMaxPause();
434: }
435:
436: public void setRunningTime(double runningTime) {
437: for (int i = 0; i < chartPanelViews.size(); i++) {
438: ((ChartPanelView) chartPanelViews.get(i))
439: .getModelChart().setRunningTime(runningTime);
440: }
441: }
442:
443: public void setFootprint(long footPrint) {
444: for (int i = 0; i < chartPanelViews.size(); i++) {
445: ((ChartPanelView) chartPanelViews.get(i))
446: .getModelChart().setFootprint(footPrint);
447: }
448: }
449:
450: public void setMaxPause(double maxPause) {
451: for (int i = 0; i < chartPanelViews.size(); i++) {
452: ((ChartPanelView) chartPanelViews.get(i))
453: .getModelChart().setMaxPause(maxPause);
454: }
455: }
456:
457: public void setScaleFactor(double scaleFactor) {
458: for (int i = 0; i < chartPanelViews.size(); i++) {
459: ((ChartPanelView) chartPanelViews.get(i))
460: .getModelChart().setScaleFactor(scaleFactor);
461: }
462: }
463:
464: public double getScaleFactor() {
465: if (chartPanelViews.isEmpty())
466: return 1;
467: return ((ChartPanelView) chartPanelViews.get(0))
468: .getModelChart().getScaleFactor();
469: }
470:
471: public boolean isShowGCTimesLine() {
472: if (chartPanelViews.isEmpty())
473: return false;
474: return ((ChartPanelView) chartPanelViews.get(0))
475: .getModelChart().isShowGCTimesLine();
476: }
477:
478: public void setShowGCTimesLine(boolean showGCTimesLine) {
479: for (int i = 0; i < chartPanelViews.size(); i++) {
480: ((ChartPanelView) chartPanelViews.get(i))
481: .getModelChart().setShowGCTimesLine(
482: showGCTimesLine);
483: }
484: }
485:
486: public boolean isShowGCTimesRectangles() {
487: if (chartPanelViews.isEmpty())
488: return false;
489: return ((ChartPanelView) chartPanelViews.get(0))
490: .getModelChart().isShowGCTimesRectangles();
491: }
492:
493: public void setShowGCTimesRectangles(
494: boolean showGCTimesRectangles) {
495: for (int i = 0; i < chartPanelViews.size(); i++) {
496: ((ChartPanelView) chartPanelViews.get(i))
497: .getModelChart().setShowGCTimesRectangles(
498: showGCTimesRectangles);
499: }
500: }
501:
502: public boolean isShowFullGCLines() {
503: if (chartPanelViews.isEmpty())
504: return false;
505: return ((ChartPanelView) chartPanelViews.get(0))
506: .getModelChart().isShowFullGCLines();
507: }
508:
509: public void setShowFullGCLines(boolean showFullGCLines) {
510: for (int i = 0; i < chartPanelViews.size(); i++) {
511: ((ChartPanelView) chartPanelViews.get(i))
512: .getModelChart().setShowFullGCLines(
513: showFullGCLines);
514: }
515: }
516:
517: public boolean isShowIncGCLines() {
518: if (chartPanelViews.isEmpty())
519: return false;
520: return ((ChartPanelView) chartPanelViews.get(0))
521: .getModelChart().isShowIncGCLines();
522: }
523:
524: public void setShowIncGCLines(boolean showIncGCLines) {
525: for (int i = 0; i < chartPanelViews.size(); i++) {
526: ((ChartPanelView) chartPanelViews.get(i))
527: .getModelChart().setShowIncGCLines(
528: showIncGCLines);
529: }
530: }
531:
532: public boolean isShowTotalMemoryLine() {
533: if (chartPanelViews.isEmpty())
534: return false;
535: return ((ChartPanelView) chartPanelViews.get(0))
536: .getModelChart().isShowTotalMemoryLine();
537: }
538:
539: public void setShowTotalMemoryLine(boolean showTotalMemoryLine) {
540: for (int i = 0; i < chartPanelViews.size(); i++) {
541: ((ChartPanelView) chartPanelViews.get(i))
542: .getModelChart().setShowTotalMemoryLine(
543: showTotalMemoryLine);
544: }
545: }
546:
547: public boolean isShowUsedMemoryLine() {
548: if (chartPanelViews.isEmpty())
549: return false;
550: return ((ChartPanelView) chartPanelViews.get(0))
551: .getModelChart().isShowUsedMemoryLine();
552: }
553:
554: public void setShowUsedMemoryLine(boolean showUsedMemoryLine) {
555: for (int i = 0; i < chartPanelViews.size(); i++) {
556: ((ChartPanelView) chartPanelViews.get(i))
557: .getModelChart().setShowUsedMemoryLine(
558: showUsedMemoryLine);
559: }
560: }
561:
562: public void setShowTenured(boolean showTenured) {
563: for (int i = 0; i < chartPanelViews.size(); i++) {
564: ((ChartPanelView) chartPanelViews.get(i))
565: .getModelChart().setShowTenured(showTenured);
566: }
567: }
568:
569: public boolean isShowTenured() {
570: if (chartPanelViews.isEmpty())
571: return false;
572: return ((ChartPanelView) chartPanelViews.get(0))
573: .getModelChart().isShowTenured();
574: }
575:
576: public void setShowYoung(boolean showYoung) {
577: for (int i = 0; i < chartPanelViews.size(); i++) {
578: ((ChartPanelView) chartPanelViews.get(i))
579: .getModelChart().setShowYoung(showYoung);
580: }
581: }
582:
583: public boolean isShowYoung() {
584: if (chartPanelViews.isEmpty())
585: return false;
586: return ((ChartPanelView) chartPanelViews.get(0))
587: .getModelChart().isShowYoung();
588: }
589:
590: }
591:
592: private class ScrollBarMaximumChangeListener implements
593: ChangeListener {
594:
595: public void stateChanged(ChangeEvent e) {
596: if (isWatched()) {
597: BoundedRangeModel model = (BoundedRangeModel) e
598: .getSource();
599: model.setValue(model.getMaximum());
600: }
601: }
602:
603: }
604: }
|