Tycho compilation changes for SVN version also.
[simantics/platform.git] / bundles / org.simantics.threadlog / src / org / simantics / threadlog / ui / ThreadLogVisualizer.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.threadlog.ui;\r
13 \r
14 import gnu.trove.TLongObjectHashMap;\r
15 import gnu.trove.TObjectProcedure;\r
16 \r
17 import java.awt.BorderLayout;\r
18 import java.awt.event.ActionEvent;\r
19 import java.awt.event.KeyEvent;\r
20 import java.io.IOException;\r
21 import java.util.ArrayList;\r
22 import java.util.Collections;\r
23 \r
24 import javax.swing.AbstractAction;\r
25 import javax.swing.JButton;\r
26 import javax.swing.JFileChooser;\r
27 import javax.swing.JFrame;\r
28 import javax.swing.JToolBar;\r
29 import javax.swing.filechooser.FileNameExtensionFilter;\r
30 \r
31 import org.simantics.threadlog.Task;\r
32 import org.simantics.threadlog.ThreadLog;\r
33 \r
34 public class ThreadLogVisualizer extends JFrame {\r
35 \r
36     private static final long serialVersionUID = 6250996509358338304L;\r
37     \r
38     TimeLineViewer viewer = new TimeLineViewer();\r
39     JToolBar toolbar = new JToolBar("Thread Log Visualizer Tools");\r
40     JButton saveButton = new JButton(new SaveAction());\r
41 \r
42     ThreadLog currentLog;\r
43 \r
44     public ThreadLogVisualizer() {\r
45         super("Thread log visualizer");\r
46         setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);\r
47         setSize(800, 600);\r
48 \r
49         getContentPane().setLayout(new BorderLayout());\r
50         getContentPane().add(toolbar, BorderLayout.NORTH);\r
51         getContentPane().add(viewer, BorderLayout.CENTER);\r
52 \r
53         toolbar.add(saveButton);\r
54     }\r
55 \r
56     class SaveAction extends AbstractAction {\r
57         private static final long serialVersionUID = 1L;\r
58 \r
59         public SaveAction() {\r
60             super("Save");\r
61             putValue(SHORT_DESCRIPTION, "Save the Current Log");\r
62             putValue(MNEMONIC_KEY, KeyEvent.VK_S);\r
63         }\r
64 \r
65         @Override\r
66         public void actionPerformed(ActionEvent e) {\r
67             JFileChooser chooser = new JFileChooser();\r
68             FileNameExtensionFilter filter = new FileNameExtensionFilter(\r
69                     "Thread Logs (*.tlog)", "tlog", "tlog");\r
70             chooser.setFileFilter(filter);\r
71             int returnVal = chooser.showSaveDialog(ThreadLogVisualizer.this);\r
72             if (returnVal != JFileChooser.APPROVE_OPTION)\r
73                 return;\r
74 \r
75             try {\r
76                 currentLog.serialize(chooser.getSelectedFile());\r
77             } catch (IOException ex) {\r
78                 ex.printStackTrace();\r
79             }\r
80         }\r
81     }\r
82 \r
83     public void setLog(ThreadLog log) {\r
84         this.currentLog = log;\r
85 \r
86         String[] tasks = log.getTasks();\r
87         double[] times = log.getTimes();\r
88 \r
89         // Relativize to the first task\r
90         double minTime = Double.POSITIVE_INFINITY;\r
91         double maxTime = Double.NEGATIVE_INFINITY;\r
92 \r
93         for(int i=0;i<times.length;i+=2) {\r
94             double temp = times[i];\r
95             if(temp < minTime)\r
96                 minTime = temp;\r
97 \r
98             temp = times[i+1];\r
99             if(temp > maxTime)\r
100                 maxTime = temp;\r
101         }\r
102         for(int i=0;i<times.length;++i)\r
103             times[i] -= minTime;\r
104         maxTime -= minTime;\r
105 \r
106         // Group intervals by thread\r
107         TLongObjectHashMap<ArrayList<Interval>> intervals = new TLongObjectHashMap<ArrayList<Interval>>();\r
108         long[] threads = log.getThreads();\r
109         for(int i=0;i<tasks.length;++i) {\r
110             long thread = threads[i];\r
111             ArrayList<Interval> in = intervals.get(thread);\r
112             if(in == null) {\r
113                 in = new ArrayList<Interval>();\r
114                 intervals.put(thread, in);\r
115             }\r
116             in.add(new Interval(tasks[i], times[i*2], times[i*2+1]));\r
117         }\r
118 \r
119         // Create lanes\r
120         viewer.clear();\r
121         intervals.forEachValue(new TObjectProcedure<ArrayList<Interval>>() {\r
122 \r
123             @Override\r
124             public boolean execute(ArrayList<Interval> intervals) {\r
125                 Collections.sort(intervals);\r
126                 ArrayList<Lane> lanes = new ArrayList<Lane>();\r
127 \r
128                 int curLaneId = -1;\r
129                 Lane curLane = null;\r
130                 for(Interval in : intervals) {\r
131                     if(curLane == null || in.begin < curLane.getEnd()) {\r
132                         ++curLaneId;\r
133                         if(curLaneId < lanes.size())\r
134                             curLane = lanes.get(curLaneId);\r
135                         else {\r
136                             curLane = new Lane();\r
137                             lanes.add(curLane);\r
138                         }\r
139                     }\r
140                     else {\r
141                         while(curLaneId > 0) {\r
142                             Lane prevLane = lanes.get(curLaneId-1);\r
143                             if(prevLane.getEnd() > in.begin)\r
144                                 break;\r
145                             --curLaneId;\r
146                             curLane = prevLane;\r
147                         }\r
148                     }\r
149                     curLane.addInterval(in);\r
150                 }\r
151 \r
152                 for(Lane lane : lanes)\r
153                     viewer.addLane(lane);\r
154                 return true;\r
155             }\r
156 \r
157         });\r
158 \r
159         // update viewer\r
160         viewer.repaint();\r
161     }\r
162 \r
163     public void saveImage() {\r
164 \r
165     }\r
166 \r
167     public static void main(String[] args) throws Exception {\r
168         ThreadLog.setDefaultThreadLog(new ThreadLog());\r
169 \r
170         {\r
171             Task A = ThreadLog.BEGIN("A");\r
172             Thread.sleep(200);\r
173             Task B = ThreadLog.BEGIN("B");\r
174             Thread.sleep(100);\r
175             B.end();\r
176             Thread.sleep(100);\r
177             Task C = ThreadLog.BEGIN("C");\r
178             Thread.sleep(100);\r
179             C.end();\r
180             A.end();\r
181         }\r
182 \r
183         ThreadLogVisualizer vis = new ThreadLogVisualizer();\r
184         vis.setLog(ThreadLog.setDefaultThreadLog(null));\r
185         vis.setVisible(true);\r
186     }\r
187 }\r