001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Jan 15, 2003
005     * Time: 1:10:46 PM
006     */
007    
008    package EVolve.util.sourcebrowser;
009    
010    import java.awt.Component;
011    import java.awt.Rectangle;
012    import java.awt.event.ActionEvent;
013    import java.awt.event.ActionListener;
014    import java.awt.event.KeyEvent;
015    import java.awt.event.MouseAdapter;
016    import java.awt.event.MouseEvent;
017    import java.io.IOException;
018    import java.io.RandomAccessFile;
019    import java.util.ArrayList;
020    
021    import javax.swing.JDesktopPane;
022    import javax.swing.JInternalFrame;
023    import javax.swing.JMenuItem;
024    import javax.swing.JOptionPane;
025    import javax.swing.JPopupMenu;
026    import javax.swing.JScrollPane;
027    import javax.swing.JTextArea;
028    import javax.swing.event.InternalFrameAdapter;
029    import javax.swing.event.InternalFrameEvent;
030    
031    import EVolve.Scene;
032    
033    public class SourceBrowser implements Cloneable{
034        private JInternalFrame window;
035        private JDesktopPane desktop;
036        private String target;
037        private ArrayList textBuffer;
038        private int line_no = 0;
039        private int caretPosition = 0;
040        private JPopupMenu popup;
041        private JMenuItem itemFind, itemFindNext, itemFindPrevious;
042        private JTextArea textArea;
043        private String loadedFilename;
044    
045        public SourceBrowser() {
046            window = null;
047            desktop = Scene.getUIManager().getDesktop();
048            textBuffer = new ArrayList();
049            popup = new JPopupMenu();
050            loadedFilename = null;
051    
052            itemFind = new JMenuItem("Find...");
053            itemFind.setMnemonic(KeyEvent.VK_F);
054            itemFind.addActionListener(new ActionListener() {
055                public void actionPerformed(ActionEvent e) {
056                    target = (String)JOptionPane.showInputDialog(Scene.getFrame(), "Input string to be find:", "Find...", JOptionPane.QUESTION_MESSAGE, null, null, target);
057                    caretPosition = 0;
058                    find(target, 0, textBuffer.size(),false);
059                }
060            });
061            popup.add(itemFind);
062    
063            itemFindNext = new JMenuItem("Find Next");
064            itemFindNext.setMnemonic(KeyEvent.VK_N);
065            itemFindNext.addActionListener(new ActionListener() {
066                public void actionPerformed(ActionEvent e) {
067                    findNext(target);
068                }
069            });
070            popup.add(itemFindNext);
071    
072            itemFindPrevious = new JMenuItem("Find Previous");
073            itemFindPrevious.setMnemonic(KeyEvent.VK_P);
074            itemFindPrevious.addActionListener(new ActionListener() {
075                public void actionPerformed(ActionEvent e) {
076                    findPrevious(target);
077                }
078            });
079            popup.add(itemFindPrevious);
080        }
081    
082        public void showSourceFile(String entityName) {
083            if (entityName == null) return;
084    
085            String className = extractClassName(entityName);
086            String fileName = ClassExplorer.v().getSourceFileFromClass(className);
087    
088            if (fileName == null) {
089                return;
090            }
091    
092            if (window == null) {
093                window = new JInternalFrame(entityName,true, true, true, true);
094                window.addInternalFrameListener(new InternalFrameAdapter() {
095                    public void internalFrameClosing(InternalFrameEvent e) {
096                        window = null;
097                    }
098                });
099                window.setClosable(true);
100                window.setBounds(desktop.getSize().width - 600, 0, 600, 300);
101                window.setResizable(true);
102                desktop.add(window);
103                textArea = new JTextArea();
104            }
105            window.moveToFront();
106            window.setVisible(true);
107            if (fileName.equals(loadedFilename)) {
108                int position = find(target,0,textBuffer.size(),true);
109                textArea.setCaretPosition(position);
110            } else {
111                window.getContentPane().removeAll();
112                window.getContentPane().add(loadSourceFile(fileName));
113            }
114            window.setTitle(entityName);
115        }
116    
117        private JScrollPane loadSourceFile(String fileName) {
118            textArea = new JTextArea();
119            line_no = 0;
120    
121            try {
122                RandomAccessFile file = new RandomAccessFile(fileName,"r");
123                textBuffer.clear();
124    
125                String line = file.readLine();
126                while (line!=null) {
127                    textBuffer.add(line + "\n");
128                    textArea.append(line + "\n");
129                    line = file.readLine();
130                }
131                caretPosition  = 0;
132                int position = find(target,0,textBuffer.size(),true);
133                if (position!=-1) textArea.setCaretPosition(position);
134                addPopupTrigger(textArea);
135            } catch (IOException e) {
136                Scene.showErrorMessage("Error occurred when accessing source file:\n" +
137                                       "\""+fileName+"\".");
138            }
139    
140    
141            return new JScrollPane(textArea);
142        }
143    
144        private String extractClassName(String entityName) {
145            int index = entityName.lastIndexOf('(');
146            target = "";
147    
148            if (index == -1) {
149                /* no '(' found, this is not a method/location entity */
150                return entityName;
151            }
152            String className = entityName.substring(0,index);
153            index = className.lastIndexOf('.');
154    
155            if (index != -1) {
156                className = entityName.substring(0,index);
157                target = entityName.substring(index+1,entityName.indexOf('('));
158            }
159    
160            return className;
161        }
162    
163        private boolean isEntity(String line) {
164            if ((line!=null)&&(line.indexOf('(')!=-1))
165                //&&
166                //((line.indexOf("public") != -1) ||
167                //(line.indexOf("private") != -1) ||
168                //(line.indexOf("protected") != -1))) {
169            {
170                return true;
171            }
172    
173            return false;
174        }
175    
176        private int find(String target, int start_line_no, int end_line_no, boolean target_is_entity) {
177            String line;
178            boolean found = false;
179    
180            for (int i=start_line_no; i<end_line_no; i++) {
181                line = (String)textBuffer.get(i);
182                if ((line.indexOf(target) != -1) && ((!target_is_entity) || isEntity(line))) {
183                    found = true;
184                    line_no = i;
185                    textArea.setCaretPosition(caretPosition);
186                    break;
187                }
188                caretPosition += line.length();
189            }
190    
191            if (!found) {
192                Scene.showErrorMessage("String \""+target+"\" is not found.");
193            }
194    
195            return found ? caretPosition : -1;
196        }
197    
198        private int findNext(String target) {
199            caretPosition = 0;
200    
201            for (int i=0; i<=line_no; i++) {
202                caretPosition += ((String)textBuffer.get(i)).length();
203            }
204    
205            return find(target, line_no+1, textBuffer.size(), false);
206        }
207    
208        private int findPrevious(String target) {
209            String line;
210            boolean found = false;
211    
212            caretPosition = 0;
213    
214            for (int i=0; i<line_no-1; i++) {
215                caretPosition += ((String)textBuffer.get(i)).length();
216            }
217    
218            for (int i=line_no - 1; i>=0; i--) {
219                line = (String)textBuffer.get(i);
220                if (line.indexOf(target) != -1) {
221                    found = true;
222                    textArea.setCaretPosition(caretPosition);
223                    line_no = i;
224                    break;
225                }
226                caretPosition -= line.length();
227            }
228    
229            if (!found) {
230                Scene.showErrorMessage("String \""+target+"\" is not found.");
231            }
232    
233            return found ? caretPosition : -1;
234        }
235    
236        protected void addPopupTrigger(Component component) {
237            component.addMouseListener(new MouseAdapter() {
238                public void mouseReleased(MouseEvent e) {
239                    if (e.isPopupTrigger()) {
240                        showPopup(e);
241                    }
242                }
243    
244                public void mousePressed(MouseEvent e) {
245                    if (e.isPopupTrigger()) {
246                        showPopup(e);
247                    }
248                }
249            });
250        }
251    
252        private void showPopup(MouseEvent e) {
253            int mouseX = e.getX();
254            int mouseY = e.getY();
255            Rectangle rect = e.getComponent().getBounds();
256            Rectangle rect2 = popup.getBounds();
257            int posX= mouseX, posY = mouseY;
258            if (mouseY+rect2.height > rect.height)
259                posY = posY - rect2.height;
260            if (mouseX+rect2.width>rect.width)
261                posX = posX - rect2.width;
262                popup.show(e.getComponent(), posX, posY);
263        }
264    
265        public Object clone() {
266            SourceBrowser o = null;
267            try {
268                o = (SourceBrowser)super.clone();
269            } catch (CloneNotSupportedException e) {
270                e.printStackTrace();
271                return null;
272            }
273            o.target = target;
274            o.textBuffer = (ArrayList)textBuffer.clone();
275            o.loadedFilename = loadedFilename;
276            return o;
277        }
278    }