001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Nov 30, 2002
005     * Time: 2:13:56 PM
006     */
007    
008    package EVolve.visualization.XYViz.ValValViz;
009    
010    import java.awt.*;
011    import java.awt.event.*;
012    import java.util.*;
013    import javax.swing.*;
014    import EVolve.Scene;
015    import EVolve.data.Element;
016    import EVolve.data.Entity;
017    import EVolve.util.ThreadChooser;
018    import EVolve.util.xmlutils.datastructures.SerializedVisualization;
019    import EVolve.util.painters.RandomPainter;
020    import EVolve.visualization.Dimension;
021    import EVolve.visualization.*;
022    
023    public class StackViz extends ValueValueVisualization{
024        private ArrayList menuList;
025        private JMenuItem itemChangeThread;
026        private HashMap methodStacks;
027        private ThreadChooser td;
028        private JTextField textBegin, textEnd;
029        private Stack stack;
030        private int event;
031        private JCheckBox chkSelectTimeFrame, chkSelectOccurredEntities;
032        private static JCheckBox selectionOptions[] = null;
033        private String selected;
034        protected static int SELECT_OPTION = 0x0011;
035        private JLabel toEventNo;
036    
037    
038        public StackViz() {
039            super();
040    
041            menuList = new ArrayList();
042            imageMap = new HashMap();
043            methodStacks = new HashMap();
044            td = new ThreadChooser(imageMap,false);
045    
046            interval = 1;
047            beginCall = 0;
048            endCall = 300;
049        }
050    
051        public Dimension[] createDimension() {
052            Dimension [] returnDimension = new Dimension[3];
053    
054            xAxis = new ValueDimension();
055            entityIdFilter = new ReferenceDimension();
056            filter2 = new ReferenceDimension();
057    
058            returnDimension[0] = xAxis;
059            returnDimension[1] = entityIdFilter;
060            returnDimension[2] = filter2;
061    
062            return returnDimension;
063        }
064    
065        protected void updateConfiguration() {
066            try {
067                beginCall = Integer.parseInt(textBegin.getText());
068                endCall = Integer.parseInt(textEnd.getText());
069    
070                canvas.setName("Time - Invocations", "Stack");
071                super.updateConfiguration();
072            } catch (NumberFormatException e) {
073                Scene.showErrorMessage("Begin call and end call must be an integer and smaller than "+Integer.MAX_VALUE+".");
074                configure();
075            };
076        }
077    
078        public void restoreConfiguration(SerializedVisualization config) {
079    
080            beginCall = Long.parseLong(config.BeginEvent);
081            endCall = Long.parseLong(config.EndEvent);
082            textBegin.setText(config.BeginEvent);
083            textEnd.setText(config.EndEvent);
084            super.restoreConfiguration(config);
085        }
086    
087        public SerializedVisualization getCurrentConfiguration() {
088            SerializedVisualization data = super.getCurrentConfiguration();
089    
090            data.BeginEvent = String.valueOf(beginCall);
091            data.EndEvent = String.valueOf(endCall);
092            data.xAxis = xAxis.getName();
093            data.yAxis = entityIdFilter.getName();
094            data.zAxis = filter2.getName();
095    
096            return data;
097        }
098    
099        public void preVisualize() {
100            xMax = 0;
101            event = 0;
102            stack = null;
103            image = null;
104            imageMap.clear();
105            methodStacks.clear();
106            currentThread = -1;
107            getSelection();
108            installPainter();
109            super.preVisualize();
110        }
111    
112        public void receiveElement(Element element) {
113            long methodId = entityIdFilter.getField(element);
114            long threadId = filter2.getField(element);
115            long callno = xAxis.getField(element) - 1;
116    
117            countEvents(callno);
118    
119            switchThread(threadId);
120    
121            if ((callno*2<beginCall*2) || (callno*2>endCall*2+1)) {
122                if (element.isOptional()) {// method return;
123                    if (!stack.empty()) stack.pop();
124                } else
125                    stack.push(new Long(methodId));
126                return;
127            }
128    
129            event++;
130            if (!element.isOptional()) // method enter;
131                stack.push(new Long(methodId));
132    
133            for (int j=0;j<stack.size();j++) {
134                painter.paint(image,callno-beginCall,j,((Long)stack.get(j)).intValue());
135            }
136    
137            if (element.isOptional()) {// method return;
138                if (!stack.empty()) stack.pop();
139            }
140        }
141    
142        public void visualize() {
143            if (imageMap.size() == 0 ) return;
144            while (selected==null) {
145                selected = td.showDialog();
146                if (selected != null) {
147                    image = (AutoImage)imageMap.get(new Long(selected.substring(7,selected.length())));
148                    canvas.setName("Time - "+ xAxis.getDataFilter().getName() + "(" + event/2 +" events)", "Stack");
149                    sort();
150                    selected = null;
151                    break;
152                }
153            }
154        }
155    
156        public void makeSelection() {
157            preMakeSelection();
158            if (selectionName==null) return;
159    
160            /*if (SELECT_OPTION == 0) {
161                Scene.showErrorMessage("No data is to be selected.");
162                return;
163            }*/
164    
165            if (dataSourceId != Scene.getDataSourceManager().getCurrentDataSourceId()) {
166                Scene.showErrorMessage("The active data source used currently is different from \n" +
167                                       "this visualization, please choose \"" +
168                                       Scene.getDataSourceManager().getUsedDataSourceName(dataSourceId)+"\".");
169                return;
170            }
171    
172            int x1 = canvas.getStartX();
173            int x2 = canvas.getEndX();
174            int y1 = canvas.getEndY();
175            int y2 = canvas.getStartY();
176    
177            if (!normalOrientation) {
178                int temp;
179                temp = x1;
180                x1 = y1;
181                y1 = temp;
182                temp = x2;
183                x2 = y2;
184                y2 = temp;
185            }
186    
187            if (((x1<0)&&(x2<0)) || ((x1>=timeMap.size()))&&(x2>=timeMap.size()))
188               return;
189    
190            if (x1 < 0) x1 = 0;
191    
192            if (x2 > timeMap.size())
193                x2 = (timeMap.size()-1);
194    
195    
196            long start, end;
197            if ((SELECT_OPTION & 0x000f) == 0) {
198                start = 0;
199                end = Long.MAX_VALUE;
200            } else {
201                long eventInterval[] = (long[])timeMap.get((int)(x1+beginCall));
202                start = eventInterval[1];
203                eventInterval = (long[])timeMap.get((int)(x2+beginCall));
204                end = eventInterval[1];
205            }
206    
207            if (y1 < 0) y1 = 0;
208    
209            int methodId;
210            ArrayList idList = new ArrayList();
211            for (int i = x1; i <= x2; i++) {
212                for (int j = y1; j <= y2; j++) {
213                    if (normalOrientation)
214                        methodId = (int)getEntityId(i,j);
215                    else
216                        methodId = (int)getEntityId(j,i);
217                    if ((methodId == -1)||(idList.contains(new Integer(methodId)))) continue;
218                    idList.add(new Integer(methodId));
219                }
220            }
221    
222    
223            int selection[] = null;
224    
225            if ((SELECT_OPTION & 0x00f0) == 0x0010) {
226                selection = new int[idList.size()];
227                for (int i=0; i<selection.length; i++)
228                    selection[i] = ((Integer)idList.get(i)).intValue();
229            } else {
230                selection = new int[entityIdFilter.getEntityNumber()];
231                for (int i=0; i<selection.length; i++)
232                    selection[i] = i;
233            }
234    
235            entityIdFilter.makeSelection(selectionName,subjectDefinition.getType(),selection,start,end,timeMap);
236        }
237    
238        protected String mouseMove(int x, int y) {
239            int X = canvas.getImageX(x);
240            int Y = canvas.getImageY(y);
241    
242            if ((X>=0) && (Y >= 0) && (image != null)) {
243                if (image.getSortedColor(null,null,X,Y)==null)
244                    Scene.setStatus("  ");
245                else
246                    Scene.setStatus(getEntityName(X,Y)+" "+X+":"+Y);
247            } else {
248                Scene.setStatus(" ");
249            }
250            return null;
251        }
252    
253        protected ArrayList createOptionalMenu() {
254            if (menuList.size() > 0) return null;
255    
256            menuList.clear();
257            itemChangeThread = new JMenuItem("Switch thread...");
258            itemChangeThread.setMnemonic(KeyEvent.VK_T);
259            itemChangeThread.addActionListener(new ActionListener() {
260                public void actionPerformed(ActionEvent e) {
261                    visualize();
262                }
263            });
264    
265            menuList.add(itemChangeThread);
266            return menuList;
267        }
268    
269        private String getEntityName(int x, int y) {
270            String returnVal = "";
271            int mappedId = (int)getEntityId(x,y);
272            Entity entity = entityIdFilter.getEntityFromInt(mappedId);
273    
274            if (entity != null) returnVal = entity.getName();
275            return returnVal;
276        }
277    
278        private long getEntityId(int x, int y) {
279            Color color = (Color)image.getSortedColor(null,null,x,y);
280            if ((color == null)||(painter == null)) return -1;
281            return ((RandomPainter)painter).getKeyFromColor(color);
282        }
283    
284        protected void switchThread(long threadId) {
285            if (currentThread != threadId) {
286                stack = (Stack)methodStacks.get(new Long(threadId));
287                if (stack == null) {
288                    stack = new Stack();
289                    methodStacks.put(new Long(threadId),stack);
290                }
291                super.switchThread(threadId);
292            }
293        }
294    
295        protected void installPainter() {
296            painter = new RandomPainter();
297        }
298    
299        public JCheckBox[] createSelectionOptions() {
300            if (selectionOptions!=null) return selectionOptions;
301    
302            chkSelectTimeFrame = new JCheckBox("Time Frame");
303            chkSelectTimeFrame.setMnemonic(KeyEvent.VK_T);
304            chkSelectTimeFrame.addActionListener(new ActionListener() {
305                public void actionPerformed(ActionEvent e) {
306                    boolean selected = chkSelectTimeFrame.isSelected();
307                    SELECT_OPTION = switchOption(selected, SELECT_OPTION, SELECT_TIME_FRAME);
308                }
309            });
310            chkSelectTimeFrame.setSelected(true);
311    
312            chkSelectOccurredEntities = new JCheckBox("Occurred Entities");
313            chkSelectOccurredEntities.setMnemonic(KeyEvent.VK_O);
314            chkSelectOccurredEntities.addActionListener(new ActionListener() {
315                public void actionPerformed(ActionEvent e) {
316                    boolean selected = chkSelectOccurredEntities.isSelected();
317                    SELECT_OPTION = switchOption(selected, SELECT_OPTION, SELECT_OCCURRED_ENTITIES);
318                }
319            });
320            chkSelectOccurredEntities.setSelected(true);
321    
322            selectionOptions = new JCheckBox[2];
323            selectionOptions[0] = chkSelectTimeFrame;
324            selectionOptions[1] = chkSelectOccurredEntities;
325    
326            return selectionOptions;
327        }
328    
329        protected JPanel createConfigurationPanel() {
330            JPanel returnVal = new JPanel(new GridLayout(1, 1, 5, 5));
331            JPanel panelEvent = new JPanel(new GridLayout(2,2));
332    
333            Box panelBottom = new Box(BoxLayout.Y_AXIS);
334            returnVal.add(panelBottom);
335    
336            textBegin = new JTextField(String.valueOf(beginCall));
337            textEnd = new JTextField(String.valueOf(endCall));
338            panelEvent.add(new JLabel("From Call No:"));
339            panelEvent.add(textBegin);
340    
341            toEventNo = new JLabel("To Call No:");
342            panelEvent.add(toEventNo);
343            panelEvent.add(textEnd);
344            panelBottom.add(panelEvent);
345    
346            return returnVal;
347        }
348    
349        protected void updateComboSubject() {
350            super.updateComboSubject();
351            String range = String.valueOf(Scene.getDataManager().getDataSource().getNumberOfEvents(elementDefinition[comboSubject.getSelectedIndex()].getName()));
352            toEventNo.setText("To Call No:("+range+")");
353        }
354    
355        public Object clone() {
356            StackViz o = (StackViz)super.clone();
357            o.dimension[0] = o.xAxis;
358            o.dimension[1] = o.entityIdFilter;
359            o.dimension[2] = o.filter2;
360    
361    
362            o.td = new ThreadChooser(o.imageMap,false);
363    
364            o.methodStacks = new HashMap();
365            Iterator it = methodStacks.keySet().iterator();
366            while (it.hasNext()) {
367                Object key = it.next();
368                Stack newStack = new Stack(), oldStack = (Stack)methodStacks.get(key);
369                o.methodStacks.put(key,newStack);
370                for (int i=0; i<oldStack.size(); i++)
371                    newStack.add(oldStack.get(i));
372            }
373    
374            o.menuList = new ArrayList();
375            o.createDialog();
376            return o;
377        }
378    
379    }