Package tcg.common.ui

Source Code of tcg.common.ui.TailFrame

package tcg.common.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Insets;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;

import javax.swing.border.EtchedBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;

import tcg.common.Localization;
import tcg.common.LoggerManager;

//TODO: handle closing event!

public class TailFrame extends JFrame implements Runnable, CaretListener
{
  private static final long serialVersionUID = 1L;

  JScrollPane textPaneScrollPane;
  JTextPane textPane;
  StyledDocument styledDoc;
  Style def;
  Style errorStyle;

  long counter;
  boolean edit;
  boolean pause;

  public static final Color STATUS_BAR_COLOR= new Color(0x41,0x89,0xDD);
  public static int openFrameCount = 0;
  static final int xOffset = 30, yOffset = 30;
    public static int MAX_LINES_TO_DISPLAY = 500;

  //..StatusBar
  private JPanel statusBarPanel = null;

  private JButton pauseButton = null;
  private JButton reloadButton = null;
  //private JLabel caretPosLabel = null;
  private JLabel fileSizeValue = null;
  private JLabel fileLastModifiedValue = null;
  //private JLabel linesWaitingLabel = null;
  private JTextField searchText_ = null;
 
  //private boolean stopFileDetailsThread = false;
 
  private String fileName = "";
  //private ClassLoader cl = null;

  private Properties keywords_ = new Properties();

  private String  keyword_ = "";
 
  //long initialLineNo;
  int delayPeriod;

  private Tail  tail_ = null;
  private Thread  thread_ = null;
 
  //flag to check whether we should keep the processing thread running
  private boolean keepRunning_ = false;
  private int linesShowing = 0;
 
  @SuppressWarnings("unused")
  private static Logger logger_ = LoggerManager.getLogger(TailFrame.class.getName());

  //localized string
  private String btnPause = "Pause";
  private String tipStopScroll = "Stops scrolling. Logging will continue...";
  private String btnScroll = "Scroll";
  private String tipStartScroll = "Start scrolling...";
  private String btnReload = "Reload";
  private String tipReload = "Reload the file...";
  private String lblSearch = "Search";
  private String tipSearch = "Search for a keyword";
  private String lblSize = "Size";
  private String tipSize = "Current size of the file";
  private String lblLastModified = "Last Modified";
 
  //...Constructors
  public TailFrame(String title, Logger logger)
  {
    super();
    //super(title,true,true,true,true);
    this.setTitle(title);
   
    try
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
        }
    catch (Exception e) { }

    //get the file name -> the first file appender in the logger
    FileAppender   file_appender = null;
    String      file_path = "";
    Enumeration<?>   appender_enum = logger.getAllAppenders();
    while (appender_enum.hasMoreElements())
    {
      //appender = (Appender) appender_enum.nextElement();
      try
      {
        file_appender = FileAppender.class.cast(appender_enum.nextElement());
        file_path = file_appender.getFile();
        break;
      }
      catch (Exception ex)
      {
        //ignore
      }
    }
   
    //stored the file path locally
    this.fileName = file_path;

    //..Set the intialLine to 0
    //initialLineNo = 0;

    // Get current classloader
    //cl = this.getClass().getClassLoader();
   
    //localized
    btnPause = Localization.getLocalizedString("TAIL_BTN_PAUSE", btnPause);
    tipStopScroll = Localization.getLocalizedString("TAIL_TIPS_STOPSCROLL", tipStopScroll);
    btnScroll = Localization.getLocalizedString("TAIL_BTN_SCROLL", btnScroll);
    tipStartScroll = Localization.getLocalizedString("TAIL_TIPS_STARTSCROLL", tipStartScroll);
    btnReload = Localization.getLocalizedString("TAIL_BTN_RELOAD", btnReload);
    tipReload = Localization.getLocalizedString("TAIL_TIPS_RELOAD", tipReload);
    lblSearch = Localization.getLocalizedString("TAIL_LBL_SEARCH", lblSearch);
    tipSearch = Localization.getLocalizedString("TAIL_TIPS_SEARCH", tipSearch);
    lblSize = Localization.getLocalizedString("TAIL_LBL_SIZE", lblSize);
    tipSize = Localization.getLocalizedString("TAIL_TIPS_SIZE", tipSize);
    lblLastModified = Localization.getLocalizedString("TAIL_LBL_LASTMODIFIED", lblLastModified);
   
   
    initComponents();

    //reset the text
    textPane.setText("");
    linesShowing = 0;

    //default size
    this.setSize(800, 600);

    //listener for window's event
    addWindowListener(new java.awt.event.WindowAdapter()
    {
        public void windowClosing(WindowEvent winEvt)
        {
          stop();
        }
    });
   
    //start right away
    start();
  }
 
  public TailFrame(String title, String fileName)
  {
    super();
//    super(title,true,true,true,true);
    this.setTitle(title);
   
    try
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
        }
    catch (Exception e) { }
       
    this.fileName = fileName;

    //..Set the intialLine to 0
    //initialLineNo = 0;

    // Get current classloader
    //cl = this.getClass().getClassLoader();
   
    initComponents();

    //reset the text
    textPane.setText("");
    linesShowing = 0;

    //default size
    this.setSize(800, 600);

    //listener for window's event
    addWindowListener(new java.awt.event.WindowAdapter()
    {
        public void windowClosing(WindowEvent winEvt)
        {
          stop();
        }
    });
   
    //start right away
    start();
  }

  private void initComponents()
  {
    textPane = new JTextPane();
   
    styledDoc = textPane.getStyledDocument();

    //..Regulat Text Style
    Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
    Style regular = styledDoc.addStyle("regular", def);
    StyleConstants.setForeground(regular, Color.BLACK);
    StyleConstants.setBackground(regular, Color.WHITE);
    StyleConstants.setFontFamily(regular, "Courier New");
    StyleConstants.setFontSize(regular,12);
    StyleConstants.setLineSpacing(regular, 0.25f);

    //..Keyword1 Text Style
    Style keyword1Style =  styledDoc.addStyle("keyword1Style", regular);
    StyleConstants.setForeground(keyword1Style, Color.RED);
    StyleConstants.setBackground(keyword1Style, Color.YELLOW);
    StyleConstants.setFontFamily(keyword1Style, "Courier New");
    StyleConstants.setFontSize(keyword1Style,12);
    StyleConstants.setBold(keyword1Style,false);
    StyleConstants.setLineSpacing(keyword1Style, 0.25f);

    //..Keyword2 Text Style
    Style keyword2Style =  styledDoc.addStyle("keyword2Style", regular);
    StyleConstants.setForeground(keyword2Style, Color.GREEN);
    StyleConstants.setBackground(keyword2Style, Color.YELLOW);
    StyleConstants.setFontFamily(keyword2Style, "Courier New");
    StyleConstants.setFontSize(keyword2Style,12);
    StyleConstants.setBold(keyword2Style,false);
    StyleConstants.setLineSpacing(keyword2Style, 0.25f);
   
    textPane.setMargin(new Insets(0,15,15,0));
    textPane.setBackground(Color.WHITE);
    textPane.setLogicalStyle(regular);

    //..Set the Caret Color to white
    textPane.setCaretColor(Color.BLACK);
    textPane.addCaretListener(this);

    textPaneScrollPane = new JScrollPane(textPane);

    counter=0;
    edit = false;

    //..StatusBar
    statusBarPanel = new JPanel();
    statusBarPanel.setBorder(new EtchedBorder());
    statusBarPanel.setLayout(new BorderLayout());
    //statusBarPanel.setLayout(new GridLayout(1,4));
    //statusBarPanel.setLayout(new FlowLayout());
    statusBarPanel.setBackground(STATUS_BAR_COLOR);
 
    //..Pause Button
    pause = false;
    pauseButton = new JButton(btnPause);   
    pauseButton.setToolTipText(tipStopScroll);

    pauseButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ae)
      {
        if(pause)
        {
          pause = false;
          pauseButton.setText(btnPause);
          pauseButton.setToolTipText(tipStopScroll);
          //resume the tailing
          tail_.resume();
        }
        else
        {
          pause = true;
          pauseButton.setText(btnScroll);
          pauseButton.setToolTipText(tipStartScroll);
          //pause the tailing
          tail_.pause();

        }
      }
    });

    reloadButton = new JButton(btnReload);   
    reloadButton.setToolTipText(tipReload);

    reloadButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ae)
      {
        reset();
      }
    });

    JPanel actionPanel = new JPanel();
    actionPanel.setBackground(STATUS_BAR_COLOR);
    actionPanel.setLayout(new BorderLayout());
   
    actionPanel.add(pauseButton, BorderLayout.WEST);
    actionPanel.add(reloadButton, BorderLayout.CENTER);
 
    //Search label and text field
    JLabel searchLabel = new JLabel("  " + lblSearch);
    searchLabel.setForeground(Color.white);
   
    searchText_ = new JTextField(10);
    searchText_.setForeground(Color.BLACK);
    searchText_.setToolTipText(tipSearch);
   
    searchText_.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String newKeyword = searchText_.getText().trim();
        //only process it if the new keyword is different than the old one
        if (keyword_ == null || keyword_.length() != newKeyword.length()
            || 0 == keyword_.compareToIgnoreCase(newKeyword))
        {
          //search the keyword
          clearKeywordHighlight();
          keyword_ = newKeyword;
          searchForKeywords();
        }
      }
    });

    //..FileSize Label
    fileSizeValue = new JLabel();
    fileSizeValue.setForeground(Color.white);
    fileSizeValue.setToolTipText(tipSize);
   
    JLabel fileSizeLabel = new JLabel(lblSize + ": ");
    fileSizeLabel.setForeground(Color.white);
   
    //..FileLastModifiedDate Label
    fileLastModifiedValue = new JLabel();
    fileLastModifiedValue.setForeground(Color.white);
    //stopFileDetailsThread = false;

    JLabel fileModifiedLabel = new JLabel(lblLastModified + ": ");
    fileModifiedLabel.setForeground(Color.white);
   
    //..Caret Position Label. Not meaningful in our case
    //caretPosLabel = new JLabel("");
    //caretPosLabel.setForeground(Color.white);
   
    JPanel internalPanel = new JPanel();
    internalPanel.setBackground(STATUS_BAR_COLOR);
    internalPanel.setLayout(new BorderLayout());
   
    JPanel searchContainerPanel = new JPanel();
    searchContainerPanel.setBackground(STATUS_BAR_COLOR);

    JPanel sizeContainerPanel = new JPanel();
    sizeContainerPanel.setBackground(STATUS_BAR_COLOR);
    //sizeContainerPanel.setToolTipText(tipSize);
   
    JPanel modifiedContainerPanel = new JPanel();
    modifiedContainerPanel.setBackground(STATUS_BAR_COLOR);

    //build the layout of the status panel
    searchContainerPanel.add(searchLabel);
    searchContainerPanel.add(searchText_);
   
    sizeContainerPanel.add(fileSizeLabel);
    sizeContainerPanel.add(fileSizeValue);
   
    modifiedContainerPanel.add(fileModifiedLabel);
    modifiedContainerPanel.add(fileLastModifiedValue);
    //labelContainerPanel.add(caretPosLabel);
   
    internalPanel.add(searchContainerPanel, BorderLayout.WEST);
    internalPanel.add(sizeContainerPanel, BorderLayout.CENTER);
    internalPanel.add(modifiedContainerPanel, BorderLayout.EAST);
   
    statusBarPanel.add(actionPanel, BorderLayout.WEST);
//    pauseButton.getParent().setBackground(STATUS_BAR_COLOR);
    statusBarPanel.add(internalPanel, BorderLayout.CENTER);

    this.getContentPane().setLayout(new BorderLayout());
    getContentPane().add(textPaneScrollPane,BorderLayout.CENTER);
    getContentPane().add(statusBarPanel,BorderLayout.SOUTH);
    //getContentPane().add(containerPanel, BorderLayout.SOUTH);
   
    //TODO
    //addInternalFrameListener(new InternalFrameClosingHandler());

    setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
    setSize(getContentPane().getSize());
    openFrameCount++;

    //..Add InternalFrameEventListener
    //TODO
    //addInternalFrameListener(new TailInternalFrameListener(this));
   
    //set default close operation
    this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    //TODO: introduce window handler
  }
 
  public void reset()
  {
    //reset the text
    textPane.setText("");
    linesShowing = 0;
    //stop the current tail job
    if (tail_ != null)
    {
      tail_.stop();
      tail_ = null;
    }
    //create a new tail job
    tail_ = new Tail(fileName);
    tail_.start();
  }
 
  public synchronized void start()
  {
    if (tail_ != null && !tail_.isRunning())
    {
      //zombie. reset
      tail_ = null;
    }
   
    //tailing thread
    if (tail_ == null)
    {
      tail_ = new Tail(fileName);
      tail_.start();
    }
   
    if (thread_ != null && !thread_.isAlive() && !keepRunning_)
    {
      //zombie. reset
      thread_ = null;
    }
   
    //frame update thread
    if (thread_ == null)
    {
      thread_ = new Thread(this);
      thread_.start();
    }
  }
 
  public synchronized void stop()
  {
        //stop the tailing
      if (tail_ != null)
      {
        tail_.stop();
        tail_ = null;
      }
      //stop processing thread
      if (thread_ != null)
      {
        //stop the processing loop. make sure we interrupt the sleep.
        keepRunning_ = false;
        thread_.interrupt();
        try
        {
          thread_.join(500);
        }
        catch (Exception ex)
        {
          //ignore;
          //thread_.stop();
        }
        thread_ = null;
      }   
  }
 
  public boolean isRunning()
  {
    if (tail_ != null && tail_.isRunning() && keepRunning_)
    {
      return true;
    }
    return false;
  }

  //..Get fileName
  public String getFileName()
  {
    return fileName;
  }
 
  //...appendText
  public void append(String text, int countOfLines)
  {
    // this method is called from Tail.run().
    // a sleep statement here will slow down the while loop in run hence adds delay
    try
    {
      if(delayPeriod != 0)
      {
        Thread.sleep(delayPeriod * 200);
      }
    }
    catch(Exception e)
    {
      //ignore
    }

    int docLengthBeforeInsert = textPane.getDocument().getLength();

    String docText = "";
    int searchFrom = 0;
    int removeTextLength = 0;
    int cnt = 0;
    int tempSearchFrom = 0;

    //..First of all, insert the string in regular style
    try
    {
      styledDoc.insertString(styledDoc.getLength(), text, styledDoc.getStyle("regular"));
      linesShowing += countOfLines;

            if(linesShowing > MAX_LINES_TO_DISPLAY)
      {
              //TODO: alternative solution: we can just truncate the buffer into half
             
              //remove the same amount of line from the beginning of the text
        docText = styledDoc.getText(0,styledDoc.getLength());

        //search the same number of new line if possible
        searchFrom = 0;
        for(cnt = 0; cnt < countOfLines ; cnt++)
        {
          tempSearchFrom = docText.indexOf(Tail.NEW_LINE, (searchFrom+Tail.NEW_LINE.length()));

          if(tempSearchFrom == -1)
          {
            //can not find a new line.
            break;
          }
          else
          {
            searchFrom = tempSearchFrom;
          }
        }

        if(searchFrom == -1)
        {
          removeTextLength = docLengthBeforeInsert;
        }
        else
        {
          docText = docText.substring(0,searchFrom);
          removeTextLength = docText.length();

          //..Adjust the line number for Ln and Cl display in status bar
          //initialLineNo += countOfLines;
          //caretPosLabel.setText(" Ln "+(getLineAtCaret(textPane)+initialLineNo-1)+"  Col "+getColumnAtCaret(textPane));
        }

        //remove the text
        styledDoc.remove(0,removeTextLength);
       
        linesShowing -= cnt;
        docLengthBeforeInsert = docLengthBeforeInsert - removeTextLength;
      }
    }
    catch (BadLocationException ble)
    {
      //TODO
    }
    catch(Exception e)
    {
      //TODO
    }

    //..Highlight the text if some keyword is found
    if (keyword_ != null && keyword_.length() > 0)
    {
      ArrayList<KeywordPosition> matches = getKeywordPositions(text);
 
      int arrSize = matches.size();
      if (arrSize > 0)
      {
        int keyLength = keyword_.length();
        for(int i = 0; i<arrSize; i++)
        {
          styledDoc.setCharacterAttributes( matches.get(i).begin + docLengthBeforeInsert, keyLength, 
            styledDoc.getStyle("keyword1Style"), false);
        }
 
      }
    }

    //move caret to the end
    textPane.setCaretPosition(textPane.getDocument().getLength());
  }

  //..The thread that runs and updates the file size and last modified date
  public void run()
  {
    File file = new File(fileName);
    long fileSize = 0;
    long fileLastModifiedDate = 0;

    Date date = new Date();
    String   tempString="";
    int    countOfLines = 0;
   
    keepRunning_ = true;
//    try
//    {
      do
      {
        //get file size
        fileSize = file.length();
        if(fileSize<1024)
        {
          fileSizeValue.setText( fileSize +" Bytes  ");
        }
        else if( fileSize< (1024*1024))
        {
          tempString = (fileSize/1024.0)+"";

          //..Verify for no of digits after '.'
          if(tempString.substring(tempString.indexOf(".")).length() > 3)
          {
            tempString = tempString.substring(0,tempString.indexOf(".")+3);
          }
          else
          {
            tempString = tempString.substring(0,tempString.indexOf("."));
          }

          fileSizeValue.setText( tempString +" KB  ");
        }
        else if( fileSize< (1024*1024*1024))
        {
          tempString = (fileSize/(1024.0*1024.0))+"";

          //..Verify for no of digits after '.'
          if(tempString.substring(tempString.indexOf(".")).length() > 5)
          {
            tempString = tempString.substring(0,tempString.indexOf(".")+5);
          }
          else
          {
            tempString = tempString.substring(0,tempString.indexOf("."));
          }

          fileSizeValue.setText( tempString +" MB  ");
        }
        else
        {
          tempString = (fileSize/(1024.0*1024.0*1024.0))+"";

          //..Verify for no of digits after '.'
          if(tempString.substring(tempString.indexOf(".")).length() > 7)
          {
            tempString = tempString.substring(0,tempString.indexOf(".")+7);
          }
          else
          {
            tempString = tempString.substring(0,tempString.indexOf("."));
          }
         
          fileSizeValue.setText( tempString +" GB  ");
        }

        //get file modified date
        fileLastModifiedDate = file.lastModified();
        date = new Date(fileLastModifiedDate);
        fileLastModifiedValue.setText(date.toString()+"  ");

        //get the latest string
        tempString = tail_.read();
        countOfLines = tail_.getLastCountOfLines();
        if (tempString.length() > 0)
        {
          this.append(tempString, countOfLines);
        }
       
        if (!keepRunning_)
          break;
       
        try
        {
          Thread.sleep(500);
        }
        catch (Exception ex)
        {
          //ignore
        }

      }
      while(keepRunning_);
//    }
//    catch(Exception ex)
//    {
//      logger_.warn("Exception: " + ex.getMessage());
//    }

    //reset the flag just in case
    keepRunning_ = false;
  }

//  public boolean isPaused()
//  {
//    return pause;
//  }

//  //..Return the TextPane
//  public JTextPane getTextPane()
//  {
//    return textPane;
//  }

  //..Return the Line no at caret
  public int getLineAtCaret(JTextComponent component)
  {
    int caretPosition = component.getCaretPosition();
    Element root = component.getDocument().getDefaultRootElement();
    return root.getElementIndex( caretPosition ) + 1;
  }

  //..Return the Column no at caret
  public int getColumnAtCaret(JTextComponent component)
  {
    int caretPosition = component.getCaretPosition();
    Element root = component.getDocument().getDefaultRootElement();
    int line = root.getElementIndex( caretPosition );
    int lineStart = root.getElement( line ).getStartOffset();
    return caretPosition - lineStart + 1;
  }

  //..CaretUpdate event
  public void caretUpdate(CaretEvent ce)
  {
    //no need to update the caret position. in our context this information is not meaningful
    //  even misleading!
    //caretPosLabel.setText(" Ln "+(getLineAtCaret(textPane)+initialLineNo-1)+"  Col "+getColumnAtCaret(textPane));
  }

  public void clearKeywordHighlight()
  {
    styledDoc.setCharacterAttributes( 0, textPane.getDocument().getLength()
        styledDoc.getStyle("regular"), false)
  }
 
  public void searchForKeywords()
  {   
    //TODO: Java Bug: JTextPane.getText() inserts extra new line char.
    String str = "";
    try
    {
      str = styledDoc.getText(0, styledDoc.getLength());
    }
    catch(Exception ex)
    {
      //ignore
    };
       
    ArrayList<KeywordPosition> matches = getKeywordPositions(str);

    int arrSize = matches.size();
    int keyLength = keyword_.length();
    for(int i = 0; i<arrSize; i++)
    {
      int begin = matches.get(i).begin;
      try
      {
        styledDoc.setCharacterAttributes( begin, keyLength,
                        styledDoc.getStyle("keyword1Style"), false);
      }
      catch(Exception exc)
      {
        //ignore
      }   
    }
  }

  public ArrayList<KeywordPosition> getKeywordPositions(String text)
  {
    ArrayList<KeywordPosition> matches = new ArrayList<KeywordPosition>();
       
    if (keyword_ == null || keyword_.length() == 0)
      return matches;
   
    //make uppercase for comparison
    text = text.toUpperCase();

    try
    {
      //make uppercase for comparison. not case-sensitive.
      String tempString = keyword_.toUpperCase();

      int offSet = 0;
      while(true)
      {
        //search for the keyword
        offSet = text.indexOf(tempString, offSet);
        if (offSet == -1)
        {
          //not found
          break;
        }
       
        //found one
        KeywordPosition keyPos = new KeywordPosition(offSet, offSet + tempString.length());
        matches.add(keyPos);
       
        //advance the position
        offSet += tempString.length();
      }
    }
    catch(Exception exp)
    {
      //TODO: proper logging
    }

    return matches;
  }
 
  class SearchTextListener implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      //search the keyword
      keywords_.setProperty("0", searchText_.getText());
    }
  }
}

//..Class to store beginning and ending points of keywords
class KeywordPosition
{
  public int begin;
  public int end;

  KeywordPosition(int begin, int end)
  {
    this.begin = begin;
    this.end = end;
  }
}
TOP

Related Classes of tcg.common.ui.TailFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.