| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.java.stackanalyzer; |
| |
| import java.awt.Cursor; |
| import java.awt.Rectangle; |
| import java.awt.Toolkit; |
| import java.awt.datatransfer.Clipboard; |
| import java.awt.datatransfer.DataFlavor; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.KeyAdapter; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.MouseAdapter; |
| import java.awt.event.MouseEvent; |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.Serializable; |
| import java.util.logging.Logger; |
| import javax.swing.AbstractAction; |
| import javax.swing.DefaultListModel; |
| import javax.swing.text.DefaultEditorKit; |
| |
| import org.netbeans.modules.java.stackanalyzer.StackLineAnalyser.Link; |
| import org.openide.util.Exceptions; |
| import org.openide.util.HelpCtx; |
| import org.openide.util.NbBundle; |
| import org.openide.windows.TopComponent; |
| import org.openide.windows.WindowManager; |
| |
| |
| /** |
| * Analyser Stack Window implementation. |
| * |
| * @author Jan Becicka |
| */ |
| final class AnalyzeStackTopComponent extends TopComponent { |
| |
| private static AnalyzeStackTopComponent instance; |
| private static final String PREFERRED_ID = "AnalyzeStackTopComponent"; |
| |
| |
| private AnalyzeStackTopComponent () { |
| initComponents (); |
| setName (NbBundle.getMessage (AnalyzeStackTopComponent.class, "CTL_AnalyzeStackTopComponent")); |
| setToolTipText (NbBundle.getMessage (AnalyzeStackTopComponent.class, "HINT_AnalyzeStackTopComponent")); |
| getActionMap ().put (DefaultEditorKit.pasteAction, new PasteAction ()); |
| insertButton.getActionMap ().put (DefaultEditorKit.pasteAction, new PasteAction ()); |
| scrollPane.getActionMap ().put (DefaultEditorKit.pasteAction, new PasteAction ()); |
| list.getActionMap ().put (DefaultEditorKit.pasteAction, new PasteAction ()); |
| list.setCellRenderer (new AnalyserCellRenderer ()); |
| list.addKeyListener (new KeyAdapter () { |
| |
| @Override |
| public void keyTyped (KeyEvent e) { |
| if (e.getKeyChar () == KeyEvent.VK_ENTER) { |
| String currentLine = (String) list.getSelectedValue (); |
| open (currentLine); |
| } |
| } |
| }); |
| list.addMouseListener (new MouseAdapter () { |
| |
| @Override |
| public void mouseClicked (MouseEvent e) { |
| if (e.getClickCount () != 1) { |
| return; |
| } |
| int i = list.locationToIndex (e.getPoint ()); |
| if (i < 0) { |
| return; |
| } |
| String currentLine = (String) list.getModel ().getElementAt (i); |
| open (currentLine); |
| } |
| }); |
| list.addMouseMotionListener (new MouseAdapter () { |
| |
| @Override |
| public void mouseMoved (MouseEvent e) { |
| int i = list.locationToIndex (e.getPoint ()); |
| if (i >= 0) { |
| Rectangle r = list.getCellBounds (i, i); |
| if (r.contains (e.getPoint ())) { |
| String line = (String) list.getModel ().getElementAt (i); |
| Link link = StackLineAnalyser.analyse (line); |
| if (link != null) { |
| list.setCursor (Cursor.getPredefinedCursor (Cursor.HAND_CURSOR)); |
| return; |
| } |
| } |
| } |
| list.setCursor (Cursor.getDefaultCursor ()); |
| } |
| |
| @Override |
| public void mouseExited (MouseEvent e) { |
| list.setCursor (Cursor.getDefaultCursor ()); |
| } |
| }); |
| } |
| |
| public void fill(BufferedReader r) { |
| DefaultListModel model = new DefaultListModel (); |
| fillListModel(r, model); |
| if (!model.isEmpty()) { |
| list.setModel (model); |
| } |
| } |
| |
| /** |
| * Reads the lines from the supplied reader and fills the supplied |
| * model with the lines. |
| * @param r |
| * @param model |
| */ |
| static void fillListModel(BufferedReader r, DefaultListModel model) { |
| String currentLine; |
| String lastLine = null; |
| try { |
| while ((currentLine = r.readLine()) != null) { |
| currentLine = currentLine.trim(); |
| if (StackLineAnalyser.matches(currentLine)) { |
| if (lastLine != null) { |
| model.addElement(lastLine); |
| } |
| model.addElement(currentLine); |
| lastLine = null; |
| } else { |
| if (lastLine == null) { |
| lastLine = currentLine; |
| } else { |
| if (lastLine.endsWith("at")) { // NOI18N |
| lastLine += " "; // NOI18N |
| } |
| String together = lastLine + currentLine; |
| if (StackLineAnalyser.matches(together)) { |
| model.addElement(together); |
| lastLine = null; |
| } else { |
| model.addElement(lastLine); |
| lastLine = currentLine; |
| } |
| } |
| } |
| } |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| |
| /** This method is called from within the constructor to |
| * initialize the form. |
| * WARNING: Do NOT modify this code. The content of this method is |
| * always regenerated by the Form Editor. |
| */ |
| // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents |
| private void initComponents() { |
| |
| insertButton = new javax.swing.JButton(); |
| scrollPane = new javax.swing.JScrollPane(); |
| list = new javax.swing.JList(); |
| |
| setName("Form"); // NOI18N |
| |
| org.openide.awt.Mnemonics.setLocalizedText(insertButton, org.openide.util.NbBundle.getBundle(AnalyzeStackTopComponent.class).getString("AnalyzeStackTopComponent.insertButton.text")); // NOI18N |
| insertButton.setName("insertButton"); // NOI18N |
| insertButton.addActionListener(new java.awt.event.ActionListener() { |
| public void actionPerformed(java.awt.event.ActionEvent evt) { |
| insertButtonActionPerformed(evt); |
| } |
| }); |
| |
| scrollPane.setName("scrollPane"); // NOI18N |
| |
| list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); |
| list.setName("list"); // NOI18N |
| scrollPane.setViewportView(list); |
| |
| javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); |
| this.setLayout(layout); |
| layout.setHorizontalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) |
| .addComponent(insertButton)) |
| .addContainerGap()) |
| ); |
| layout.setVerticalGroup( |
| layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addComponent(insertButton) |
| .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 367, Short.MAX_VALUE) |
| .addContainerGap()) |
| ); |
| |
| insertButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AnalyzeStackTopComponent.class, "AnalyzeStackTopComponent.insertButton.AccessibleContext.accessibleDescription")); // NOI18N |
| |
| getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(AnalyzeStackTopComponent.class, "AnalyzeStackTopComponent.AccessibleContext.accessibleName")); // NOI18N |
| getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AnalyzeStackTopComponent.class, "AnalyzeStackTopComponent.AccessibleContext.accessibleDescription")); // NOI18N |
| }// </editor-fold>//GEN-END:initComponents |
| |
| private void insertButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_insertButtonActionPerformed |
| try { |
| Clipboard clipBoard = Toolkit.getDefaultToolkit ().getSystemClipboard (); |
| Transferable transferable = clipBoard.getContents (this); |
| if (!transferable.isDataFlavorSupported (DataFlavor.stringFlavor)) { |
| return; |
| } |
| Reader reader = DataFlavor.stringFlavor.getReaderForText (transferable); |
| BufferedReader r = new BufferedReader (reader); |
| fill(r); |
| } catch (UnsupportedFlavorException ex) { |
| Exceptions.printStackTrace (ex); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace (ex); |
| } |
| }//GEN-LAST:event_insertButtonActionPerformed |
| |
| // Variables declaration - do not modify//GEN-BEGIN:variables |
| private javax.swing.JButton insertButton; |
| private javax.swing.JList list; |
| private javax.swing.JScrollPane scrollPane; |
| // End of variables declaration//GEN-END:variables |
| |
| /** |
| * Gets default instance. Do not use directly: reserved for *.settings files only, |
| * i.e. deserialization routines; otherwise you could get a non-deserialized instance. |
| * To obtain the singleton instance, use {@link findInstance}. |
| */ |
| public static synchronized AnalyzeStackTopComponent getDefault () { |
| if (instance == null) { |
| instance = new AnalyzeStackTopComponent (); |
| } |
| return instance; |
| } |
| |
| /** |
| * Obtain the AnalyzeStackTopComponent instance. Never call {@link #getDefault} directly! |
| */ |
| public static synchronized AnalyzeStackTopComponent findInstance () { |
| TopComponent win = WindowManager.getDefault ().findTopComponent (PREFERRED_ID); |
| if (win == null) { |
| Logger.getLogger (AnalyzeStackTopComponent.class.getName ()).warning ( |
| "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); |
| AnalyzeStackTopComponent analyzeStackTopComponent = getDefault(); |
| analyzeStackTopComponent.insertButtonActionPerformed(null); |
| return analyzeStackTopComponent; |
| } |
| if (win instanceof AnalyzeStackTopComponent) { |
| AnalyzeStackTopComponent analyzeStackTopComponent = (AnalyzeStackTopComponent) win; |
| analyzeStackTopComponent.insertButtonActionPerformed(null); |
| return analyzeStackTopComponent; |
| } |
| Logger.getLogger (AnalyzeStackTopComponent.class.getName ()).warning ( |
| "There seem to be multiple components with the '" + PREFERRED_ID + |
| "' ID. That is a potential source of errors and unexpected behavior."); |
| return getDefault (); |
| } |
| |
| @Override |
| public int getPersistenceType () { |
| return TopComponent.PERSISTENCE_ALWAYS; |
| } |
| |
| @Override |
| public void componentOpened () { |
| // TODO add custom code on component opening |
| } |
| |
| @Override |
| public void componentClosed () { |
| // TODO add custom code on component closing |
| } |
| |
| /** replaces this in object stream */ |
| @Override |
| public Object writeReplace () { |
| return new ResolvableHelper (); |
| } |
| |
| @Override |
| protected String preferredID () { |
| return PREFERRED_ID; |
| } |
| |
| @Override |
| public HelpCtx getHelpCtx() { |
| return new HelpCtx("org.netbeans.modules.java.stackanalyzer.AnalyzeStackTopComponent"); //NOI18N |
| } |
| |
| |
| final static class ResolvableHelper implements Serializable { |
| |
| private static final long serialVersionUID = 1L; |
| |
| public Object readResolve () { |
| return AnalyzeStackTopComponent.getDefault (); |
| } |
| } |
| |
| private void open (String line) { |
| Link link = StackLineAnalyser.analyse (line); |
| if (link != null) { |
| link.show (); |
| } |
| } |
| |
| private class PasteAction extends AbstractAction { |
| |
| public PasteAction () { |
| } |
| |
| @Override |
| public void actionPerformed (ActionEvent e) { |
| insertButtonActionPerformed (null); |
| } |
| } |
| } |