MessagesTable.java :  » IDE » tIDE » tide » editor » linemessages » Java Open Source

Java Open Source » IDE » tIDE 
tIDE » tide » editor » linemessages » MessagesTable.java
package tide.editor.linemessages;

import javax.swing.text.TabSet;
import snow.utils.gui.Icons;
import snow.utils.gui.GUIUtils;
import javax.swing.text.TabStop;
import snow.utils.gui.CloseControlPanel;
import snow.texteditor.SimpleDocument;
import snow.utils.DateUtils;
import snow.sortabletable.*;
import javax.swing.table.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.event.*;
import tide.compiler.CompilerOutputPanel;
import tide.sources.FileItem;
import tide.editor.MainEditorFrame;


/** Displays all the messages. (singleton added in the output tabs)
*  TODO: store column sizes
*/
public final class MessagesTable extends JPanel
{
   final private List<LineMessage> messages = new ArrayList<LineMessage>();
   final private static String[] COLUMN_NAMES = {"line", "message", "priority", "tool", "cat", "age", "relevance"};
   final private static int[] COLUMN_PREFERED_SIZES = {20, 40, 2, 4, 5, 4, 4};
   final private MessagesTableModel messagesTableModel;
   final private SortableTableModel sortableTableModel;
   final JTable table;
   final JSplitPane splitPane;
   final CompilerOutputPanel tracePanel = new CompilerOutputPanel();
   final private MultiSearchPanel asp;

   private static MessagesTable instance;

   public static synchronized MessagesTable getInstance()
   {
      if(instance == null) { instance = new MessagesTable(); }
      return instance;
   }

   private MessagesTable()
   {
      super(new BorderLayout(0,0));
      setBorder(null);

      messagesTableModel = new MessagesTableModel();
      sortableTableModel = new SortableTableModel(messagesTableModel);
      table = new JTable(sortableTableModel);
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      sortableTableModel.installGUI(table);

      JScrollPane sp = new JScrollPane(table);
      sp.setBorder(null);
      sp.getViewport().setBorder(null);

      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, sp, tracePanel);
      splitPane.setOneTouchExpandable(true);
      EventQueue.invokeLater(new Runnable() { public void run() {
         splitPane.setDividerLocation(230);   //.2 does NOT work. (maybe must wait until shown...)
      }});

      add(splitPane, BorderLayout.CENTER);
      splitPane.setBorder(null);

      asp = new MultiSearchPanel("Filter: ", null, sortableTableModel);
      JPanel northPan = new JPanel();
      northPan.setLayout(new BoxLayout(northPan, BoxLayout.X_AXIS));
      northPan.add(GUIUtils.wrapLeft(asp,0));

      add(northPan, BorderLayout.NORTH);

      northPan.add(Box.createHorizontalStrut(10));
      northPan.add(GUIUtils.createHelpLabel("Hint: use CTRL+up/down/1/9 to navigate messages."));
      northPan.add(Box.createHorizontalStrut(10));
      final JButton opts = new JButton("Options");
      northPan.add(opts);
      opts.setMargin(new Insets(0,2,0,2));

      opts.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
          JPopupMenu popup = new JPopupMenu();

          JMenuItem st =new JMenuItem("View statistics", Icons.sharedStat);
          popup.add(st);
          st.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
            showStats(false);
          } });

          JMenuItem st2 =new JMenuItem("View statistics of relevant messages", Icons.sharedStat);
          popup.add(st2);
          st2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
            showStats(true);
          } });

          JMenuItem cd =new JMenuItem("View defined categories");
          popup.addSeparator();
          popup.add(cd);
          cd.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
            CategoriesTable.showTable(MainEditorFrame.instance);
          } });

          JMenuItem cat =new JMenuItem("Remove messages defined as irrelevant", Icons.sharedCross);
          popup.addSeparator();
          popup.add(cat);
          cat.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
             LineMessagesManager.getInstance().removeIrrelevantMessages();
             refresh();
          } });

          popup.show(opts, 0, opts.getHeight());
      } });

      // show the message
      table.getSelectionModel().addListSelectionListener(
        new ListSelectionListener()
        {
           public void valueChanged(ListSelectionEvent lse)
           {
              if(lse.getValueIsAdjusting()) return;

              int posView = table.getSelectedRow() ;
              if(posView==-1)
              {
                 tracePanel.doc.setText("no selection");
                 return;
              }

              int posModel = sortableTableModel.getIndexInUnsortedFromTablePos(posView);
              if(posModel!=-1)
              {
                 LineMessage lm = messages.get(posModel);
                 tracePanel.doc.setText(lm.getMessageForOutputPanel());
              }
           }
        });

      table.addMouseListener(new MouseAdapter()
      {
        @Override public void mousePressed(MouseEvent me)
        {
           if(me.getClickCount()==2)
           {
              //select the line on double click
              int pos = sortableTableModel.getIndexInUnsortedFromTablePos( table.getSelectedRow() );
              if(pos<0) return;
              final LineMessage lm = messagesTableModel.getMessageAt(pos);
              jumpToSourceForMessage(lm);
              return;
           }

           if(me.isPopupTrigger())
           {
             showTablePopup(me);
             return;
           }
        }

        @Override public void mouseReleased(MouseEvent me)
        {
           if(me.isPopupTrigger())
           {
             showTablePopup(me);
             return;
           }
        }
      });
   }

   /** Also called from editorpanel.
   */
   public void jumpToSourceForMessage(LineMessage lm)
   {
      FileItem fi = MainEditorFrame.instance.getFileItem(lm.getSourceJavaName(), null);
      MainEditorFrame.instance.setSourceOrItemToEditOrView(fi, true);

      int line = lm.getLine();
      if(line<1) line=1;  // enforce showing
      MainEditorFrame.instance.editorPanel.selectLinePart(line-1, lm.getColumn());
   }

  private void showTablePopup(MouseEvent me)
  {
     JPopupMenu popup = new JPopupMenu();
/*
     if(table.getSelectedRowCount()==1)
     {
       int pos = sortableTableModel.getIndexInUnsortedFromTablePos( table.getSelectedRow() );
       if(pos<0) return;
       final LineMessage lm = messagesTableModel.getMessageAt(pos);
     }*/

     if(table.getSelectedRowCount()<table.getRowCount() && table.getRowCount()>1)
     {
       JMenuItem sal =new JMenuItem("select all "+table.getRowCount()+" messages");
       popup.add(sal);
       sal.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
         table.selectAll();
       } });
     }

     if(table.getSelectedRowCount()>0)
     {
       final List<LineMessage> sel = new ArrayList<LineMessage>();
       for(int r: table.getSelectedRows())
       {
          int pos = sortableTableModel.getIndexInUnsortedFromTablePos( r );
          sel.add(messagesTableModel.getMessageAt(pos));
       }
       JMenuItem remove =new JMenuItem("remove "+sel.size()+" messages", Icons.sharedCross);
       popup.addSeparator();
       popup.add(remove);
       remove.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
          messagesTableModel.remove(sel);
          if(sel.size()>0)
          {
             refresh();
          }
       } });

       popup.addSeparator();

       JMenuItem defR =new JMenuItem("Define categories as relevant");
       popup.add(defR);
       defR.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
           for(LineMessage lm : sel)
           {
              LineMessagesManager.getInstance().getRelevantCategories().add(lm.getCategory());
           }
           messagesTableModel.update();
       } });

       JMenuItem defIR =new JMenuItem("Define categories as irrelevant");
       popup.add(defIR);
       defIR.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
           for(LineMessage lm : sel)
           {
              LineMessagesManager.getInstance().getIrrelevantCategories().add(lm.getCategory());
           }
           messagesTableModel.update();
       } });

       popup.addSeparator();

       JMenuItem defS =new JMenuItem("Remove relevance definition", Icons.sharedCross);
       popup.add(defS);
       defS.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
           for(LineMessage lm : sel)
           {
              LineMessagesManager.getInstance().getIrrelevantCategories().remove(lm.getCategory());
              LineMessagesManager.getInstance().getRelevantCategories().remove(lm.getCategory());
           }
           messagesTableModel.update();
       } });

     }


     popup.show(table, me.getX(), me.getY());
  }

  // called in the EDT !
  public void selectMessage(LineMessage lm)
  {
     int pos = messages.indexOf(lm);
     if(pos==-1) return;
     int tp = sortableTableModel.getIndexInFoundFromBasicIndex(pos);
     if(tp>=0)
     {
        table.getSelectionModel().setSelectionInterval(tp,tp);
        table.scrollRectToVisible( table.getCellRect(tp,0,true) );
     }
  }

   /** Must be called in the EDT !
   *  directly calls the linepanel to refresh.
   *  called from LineMessManager
   *
   * 1) reread all messages from manager
   * 2) update the count
   * 3) call the linepanel view refresh
   */
   public void refresh()
   {
      this.messagesTableModel.refresh();
      MainEditorFrame.instance.outputPanels.setMessagesCount(messages.size());
      MainEditorFrame.instance.editorPanel.getLinePanel().refreshMessages();
   }

   public void setFilter(String filter)
   {
      asp.setQueries(Query.simpleSearchQuery(filter));
   }

   public void requestFocusForSearch()
   {
      asp.getFirstTextField().requestFocus();
   }

   //@net.jcip.annotations.ThreadSafe
   public void setShowLatest()
   {
      EventQueue.invokeLater(new Runnable() { public void run() {
        sortableTableModel.setSortedColumnAndOrder(5, false);
        sortableTableModel.sort(5, false);
      }});
   }

   private void showStats(boolean relevantOnly)
   {
      JDialog d = new JDialog(MainEditorFrame.instance, "Messages statistics", false);
      SimpleDocument doc =new SimpleDocument();
      JTextPane tp = new JTextPane(doc);
      tp.setEditable(false);
      d.add(new JScrollPane(tp), BorderLayout.CENTER);

      CloseControlPanel ccpd = new CloseControlPanel(d, false, true, "Close");
      d.add(ccpd, BorderLayout.SOUTH);
      //d.pack();
      d.setSize(720, 600);
      d.setLocationRelativeTo(MainEditorFrame.instance);
      d.setVisible(true);

      // fill the stats

      doc.appendLine(""+messages.size()+" messages");
      //NO influence here ! doc.setTabsForDoc(20, 10); // todo: tabright for numbers TabStop.

      // m(tool, m(cat, count))

      Map<String, HashMap<String, Integer>> categoriesCount = new HashMap<String, HashMap<String, Integer>>();
      int relm = 0;
      for(LineMessage mi : messages)
      {
         String ci = mi.getCategory();
         String ti = mi.getMessageOriginator();


         if(LineMessagesManager.getInstance().getRelevantCategories().contains(ci))
         {
            relm++;
         }
         else if(relevantOnly)
         {
           continue;
         }

         if(!categoriesCount.containsKey(ti))
         {
            categoriesCount.put(ti, new HashMap<String, Integer>());
         }
         Map<String, Integer> catmap = categoriesCount.get(ti);
         if(!catmap.containsKey(ci))
         {
            catmap.put(ci,1);
         }
         else
         {
            catmap.put(ci,1 + catmap.get(ci));
         }

      }

      doc.appendLine(""+relm+" relevant messages");

      TreeSet<String> toolNames = new TreeSet<String>( categoriesCount.keySet() );
      for(String ti : toolNames)
      {
         Map<String, Integer> catmap = categoriesCount.get(ti);
         int tot = 0;
         for(int ni : catmap.values())
         {
            tot+=ni;
         }
         doc.appendLine("\n"+ti+": "+tot+" message"+(tot==1?"":"s"));

         TreeSet<String> catNames = new TreeSet<String>(catmap.keySet());
         for(String ci : catNames)
         {
            int ni = catmap.get(ci);
            doc.append("\t"+ni+" \t"+ci); //+" message"+(ni==1?"":"s"));

            if(LineMessagesManager.getInstance().getRelevantCategories().contains(ci))
            {
               doc.appendError(" [Relevant]");
            }
            else if(LineMessagesManager.getInstance().getIrrelevantCategories().contains(ci))
            {
               doc.append(" [Irrelevant]");
            }
            /*else
            {
            }*/

            doc.append("\r\n");
         }
      }

      TabStop[] tabs = new TabStop[2];
      tabs[0] = new TabStop(60f, TabStop.ALIGN_RIGHT, TabStop.LEAD_NONE );
      tabs[1] = new TabStop(75f, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE );
      TabSet tabSet = new TabSet(tabs);
      doc.setTabsForDoc(tabSet);

      tp.setCaretPosition(0);
   }

   class MessagesTableModel extends FineGrainTableModel
   {
     /*public MessagesTableModel()
     {
        //no: refresh();
     }*/

     public void refresh()
     {
        synchronized(LineMessagesManager.getInstance())
        {
          messages.clear();
          for(String jn : LineMessagesManager.getInstance().messagesForFile.keySet())
          {
             messages.addAll( LineMessagesManager.getInstance().messagesForFile.get(jn) );
          }
        }
        update();
     }

     public int getRowCount()    { return messages.size(); }
     public int getColumnCount() { return COLUMN_NAMES.length; }

     public LineMessage getMessageAt(int row)
     {
        return messages.get(row);
     }

     public void remove(List<LineMessage> mess)
     {
        fireTableModelWillChange();

        for(LineMessage lm: mess)
        {
          LineMessagesManager.getInstance().remove(lm);
        }
        messages.removeAll(mess);

        fireTableDataChanged();
        fireTableModelHasChanged();
     }

     public Object getValueAt(int row, int col)
     {
        if(row<0) return "bad row:"+row;
        if(row>=messages.size()) return "bad row:"+row;

        LineMessage pi = messages.get(row);

        if(col==0) return pi.getSourceLineForTableColumn();
        if(col==1) return pi.getMessageForTableColumn();
        if(col==2) return pi.getPriority();
        if(col==3) return pi.getMessageOriginator();
        if(col==4) return pi.getCategory();
        if(col==5) return DateUtils.formatTimeDifference(System.currentTimeMillis()-pi.created);
        if(col==6)
        {
           if(LineMessagesManager.getInstance().getRelevantCategories().contains(pi.getCategory())) return "Relevant";
           if(LineMessagesManager.getInstance().getIrrelevantCategories().contains(pi.getCategory())) return "Irrelevant";
           return "?";
        }


        return "?";
     }

     public void update()
     {
        fireTableDataChanged();
        fireTableModelHasChanged();
     }


     @Override
     public String getColumnName(int column)
     {
       if(column>=0 && column<COLUMN_NAMES.length) return COLUMN_NAMES[column];
       return "??";
     }


     @Override
     public int getPreferredColumnWidth(int column)
     {
       if(column>=0 && column<COLUMN_PREFERED_SIZES.length) return COLUMN_PREFERED_SIZES[column];
       return -1;
     }

     @Override
     public int compareForColumnSort(int pos1, int pos2, int col)
     {
        synchronized(LineMessagesManager.getInstance())  // [Oct2007]: missin was causing NPEs
        {
          if(pos1>=messages.size() || pos2>=messages.size()) return 0; // NEEDED, maybe caused by a bad sync problem

          if(col==0)
          {

            LineMessage m1 = messages.get(pos1);
            LineMessage m2 = messages.get(pos2);
            int comp = m1.getSourceJavaName().compareTo(m2.getSourceJavaName());
            if(comp!=0) return comp;
            return super.compareDoubles(m1.getLine(), m2.getLine());
          }
          else if(col==5)
          {
             LineMessage m1 = messages.get(pos1);
             LineMessage m2 = messages.get(pos2);
             if(m1==null || m2==null) return 0;  // [Oct2007]

             return Long.valueOf(m1.created).compareTo(m2.created);
          }
          else
          {
             return super.compareForColumnSort(pos1,pos2,col);
          }
        }
     }

   }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.