[Title] change logview to logtab style
authorhyunsik.noh <hyunsik.noh@samsung.com>
Tue, 29 Nov 2011 12:24:21 +0000 (21:24 +0900)
committerhyunsik.noh <hyunsik.noh@samsung.com>
Tue, 29 Nov 2011 12:24:21 +0000 (21:24 +0900)
[Type] Enhancement
[Module] common
[Priority] Minor

com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/log/AddViewDialog.java
com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/log/LogPanel.java
com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/log/LogTab.java [new file with mode: 0644]
com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/ui/LogView.java

index a8ce161..5d08c9f 100644 (file)
@@ -31,23 +31,55 @@ public class AddViewDialog extends Dialog {
     private static final int DLG_WIDTH = 400;
     private static final int DLG_HEIGHT = 250;
 
-    private Shell mParent;
+    private Shell parent;
 
-    private Shell mShell;
+    private Shell shell;
 
-    private boolean mOk = false;
+    private boolean bOk = false;
 
     private Boolean bMsg = false;
     private Boolean bPid = false;
     private Boolean bTag = false;
+    
+    private String tabName = null;
     private String device = null;
     private String keyword = null;
+    
+    private Text tabNameText;
     private Text searchText;                   
-    private Button mOkButton;
+    private Button okButton;
 
     public AddViewDialog(Shell parent) {
         super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
     }
+    
+    public AddViewDialog(Shell parent, String deviceName) {
+        super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
+        device = deviceName;
+    }
+    
+    public AddViewDialog(Shell parent, LogTab tab) {
+        super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
+        if( tab != null)
+        {
+        tabName = tab.getFilterName();
+        device = tab.getFilterDeviceName();
+        keyword = tab.getFilterWord();
+        int bMode = tab.getFilteringMode();
+
+        if ((bMode & LogTab.FILTER_PID) != 0) {
+               bPid = true;
+                               }
+        
+        if ((bMode & LogTab.FILTER_TAG) != 0) {
+               bTag = true;
+                               }
+
+        if ((bMode & LogTab.FILTER_MSG) != 0) {
+               bMsg = true;
+                               }
+        }
+               }        
 
     /**
      * Opens the dialog. The method will return when the user closes the dialog
@@ -58,47 +90,61 @@ public class AddViewDialog extends Dialog {
     public boolean open() {
         createUI();
 
-        if (mParent == null || mShell == null) {
+        if (parent == null || shell == null) {
             return false;
         }
 
-        mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT);
-        Rectangle r = mParent.getBounds();
+        shell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT);
+        Rectangle r = parent.getBounds();
         // get the center new top left.
         int cx = r.x + r.width/2;
         int x = cx - DLG_WIDTH / 2;
         int cy = r.y + r.height/2;
         int y = cy - DLG_HEIGHT / 2;
-        mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT);
+        shell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT);
 
-        mShell.open();
+        shell.open();
 
-        Display display = mParent.getDisplay();
-        while (!mShell.isDisposed()) {
+        Display display = parent.getDisplay();
+        while (!shell.isDisposed()) {
             if (!display.readAndDispatch())
                 display.sleep();
         }
 
-        return mOk;
+        return bOk;
     }
 
     private void createUI() {
-        mParent = getParent();
-        mShell = new Shell(mParent, getStyle());
-        mShell.setText("Add New LogView");
+        parent = getParent();
+        shell = new Shell(parent, getStyle());
+        shell.setText("Add LogTab");
 
-        mShell.setLayout(new GridLayout(1, false));
+        shell.setLayout(new GridLayout(1, false));
 
-        mShell.addListener(SWT.Close, new Listener() {
+        shell.addListener(SWT.Close, new Listener() {
             public void handleEvent(Event event) {
             }
         });
 
-        Composite top = new Composite(mShell, SWT.NONE);
+        Composite top = new Composite(shell, SWT.NONE);
         top.setLayoutData(new GridData(GridData.FILL_BOTH));
         top.setLayout(new GridLayout(2, false));
         
         Label l = new Label(top, SWT.NONE);
+        l.setText("TabName : ");
+        
+        tabNameText = new Text(top, SWT.SINGLE | SWT.BORDER);
+        if( tabName != null)
+               tabNameText.setText(tabName);
+        tabNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        tabNameText.addModifyListener(new ModifyListener() {
+                public void modifyText(ModifyEvent e) {        
+                        tabName = tabNameText.getText() ;
+                        validate();
+                        }
+                });
+        
+        l = new Label(top, SWT.NONE);
         l.setText("Device : ");
 
         final Combo dCombo = new Combo(top, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.CENTER);
@@ -106,14 +152,30 @@ public class AddViewDialog extends Dialog {
         
         dCombo.setLayoutData(gd);
         IDevice[] devices = SmartDevelopmentBridge.getBridge().getDevices();
+                               
         if( devices.length != 0 )
         {
                for( IDevice d : devices )
                {                
                 dCombo.add(d.getSerialNumber());
                }
-               dCombo.select(0);
-               device = dCombo.getItem(0);             
+               
+               if( device != null)
+                       {
+                                       for( int i = 0; i< devices.length; i++)
+                                       {
+                                               if(device.equals(devices[i].getSerialNumber()))
+                                               {
+                                                       dCombo.select(i);
+                                                       break;
+                                               }
+                                       }
+                       }
+               else
+               {
+                       dCombo.select(0);
+                       device = dCombo.getItem(0);
+               }                               
         }
         
         dCombo.addSelectionListener(new SelectionAdapter() {
@@ -127,21 +189,22 @@ public class AddViewDialog extends Dialog {
                 }
             }
         });
-        
 
         // separator
-        l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL);
+        l = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
         l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 
         // center part with the filter parameters
-        Composite mid = new Composite(mShell, SWT.NONE);
+        Composite mid = new Composite(shell, SWT.NONE);
         mid.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
         mid.setLayout(new GridLayout(3, false));
 
 
         final Button btnPid = new Button(mid, SWT.CHECK);
         btnPid.setText("Pid");
+        if( bPid )
+               btnPid.setSelection(true);
         btnPid.addSelectionListener(new SelectionListener(){
 
                        @Override
@@ -161,6 +224,8 @@ public class AddViewDialog extends Dialog {
         
         final Button btnTag = new Button(mid, SWT.CHECK);
         btnTag.setText("Tag");
+        if( bTag )
+               btnTag.setSelection(true);
         btnTag.addSelectionListener(new SelectionListener(){
 
                        @Override
@@ -179,6 +244,8 @@ public class AddViewDialog extends Dialog {
 
         final Button btnMsg = new Button(mid, SWT.CHECK);
         btnMsg.setText("Message");
+        if( bMsg )
+               btnMsg.setSelection(true);
         btnMsg.addSelectionListener(new SelectionListener(){
 
                        @Override
@@ -195,7 +262,7 @@ public class AddViewDialog extends Dialog {
                        }               
         });
         
-        Composite bottom = new Composite(mShell, SWT.NONE);
+        Composite bottom = new Composite(shell, SWT.NONE);
         bottom.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
         bottom.setLayout(new GridLayout(2, false));
 
@@ -203,8 +270,10 @@ public class AddViewDialog extends Dialog {
         l.setText("Search : ");
 
         searchText = new Text(bottom, SWT.SINGLE | SWT.BORDER);
-        searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));        
         searchText.setEnabled(false);
+        if(keyword != null)
+               searchText.setText(keyword);
         searchText.addModifyListener(new ModifyListener() {
                 public void modifyText(ModifyEvent e) {        
                         keyword = searchText.getText() ;
@@ -213,33 +282,33 @@ public class AddViewDialog extends Dialog {
                 });
 
         // separator
-        l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL);
+        l = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
         l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
         // bottom part with the ok/cancel
-        Composite bottomComp = new Composite(mShell, SWT.NONE);
+        Composite bottomComp = new Composite(shell, SWT.NONE);
         bottomComp
                 .setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
         bottomComp.setLayout(new GridLayout(2, true));
 
-        mOkButton = new Button(bottomComp, SWT.NONE);
-        mOkButton.setText("OK");
-        mOkButton.setEnabled(false);
-        mOkButton.addSelectionListener(new SelectionAdapter() {
+        okButton = new Button(bottomComp, SWT.NONE);
+        okButton.setText("OK");
+        okButton.setEnabled(false);
+        okButton.addSelectionListener(new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
-                mOk = true;
-                mShell.close();
+                bOk = true;
+                shell.close();
             }
         });
-        mShell.setDefaultButton(mOkButton);
+        shell.setDefaultButton(okButton);
 
         Button cancelButton = new Button(bottomComp, SWT.NONE);
         cancelButton.setText("Cancel");
         cancelButton.addSelectionListener(new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
-                mShell.close();
+                shell.close();
             }
         });
 
@@ -251,6 +320,11 @@ public class AddViewDialog extends Dialog {
            return keyword;
     }
     
+    public String getName()
+    {
+           return tabName;
+    }
+    
     public String getDevice()
     {
            return device;
@@ -277,10 +351,15 @@ public class AddViewDialog extends Dialog {
 //     */
     private void validate() {
 //
+           if( tabName == null || tabName.equals(""))
+           {
+                   okButton.setEnabled(false);
+                   return ;
+           }
         // then we check it only contains digits.
            if( device == null )
            {
-                   mOkButton.setEnabled(false);
+                   okButton.setEnabled(false);
                    return ;
            }
            
@@ -291,7 +370,7 @@ public class AddViewDialog extends Dialog {
                    
                    if( keyword == null || keyword.equals(""))
                            {
-                           mOkButton.setEnabled(false);
+                           okButton.setEnabled(false);
                            return ;
                            }
                                                            
@@ -300,6 +379,16 @@ public class AddViewDialog extends Dialog {
                    if( searchText.getEnabled())
                            searchText.setEnabled(false);
            }
-        mOkButton.setEnabled(true);
+        okButton.setEnabled(true);
+    }
+    
+    public void setName( String name )
+    {
+       this.tabName = name;
+    }
+    
+    public void setKeyword( String word )
+    {
+       this.keyword = word;
     }
 }
\ No newline at end of file
index 960ba82..2437442 100644 (file)
@@ -20,13 +20,9 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.eclipse.jface.action.Action;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.SWTException;
 import org.eclipse.swt.dnd.Clipboard;
 import org.eclipse.swt.dnd.TextTransfer;
 import org.eclipse.swt.dnd.Transfer;
@@ -34,1027 +30,918 @@ import org.eclipse.swt.events.ControlEvent;
 import org.eclipse.swt.events.ControlListener;
 import org.eclipse.swt.events.FocusEvent;
 import org.eclipse.swt.events.FocusListener;
-import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
+import org.eclipse.swt.widgets.Text;
 
-import com.samsung.tizen.common.connection.ConnectionPlugin;
 import com.samsung.tizen.common.connection.ddmuilib.ITableFocusListener;
 import com.samsung.tizen.common.connection.ddmuilib.ITableFocusListener.IFocusedTableActivator;
 import com.samsung.tizen.common.connection.ddmuilib.Panel;
-import com.samsung.tizen.common.connection.ui.LogView;
-import com.samsung.tizen.sdblib.FileListingService.FileEntry;
 import com.samsung.tizen.sdblib.IDevice;
-import com.samsung.tizen.sdblib.Log;
 import com.samsung.tizen.sdblib.Log.LogLevel;
-import com.samsung.tizen.sdblib.MultiLineReceiver;
 import com.samsung.tizen.sdblib.SmartDevelopmentBridge;
 
 public class LogPanel extends Panel {
 
-    private static final int STRING_BUFFER_LENGTH = 10000;
-
-    public static final int FILTER_NONE = 0x0;
-    public static final int FILTER_PID = 0x1;
-    public static final int FILTER_TAG = 0x2;
-    public static final int FILTER_MSG = 0x4;
-
-    public static final int LEVEL_NONE = 0x0;
-    public static final int LEVEL_VERBOSE = 0x1;
-    public static final int LEVEL_DEBUG = 0x2;
-    public static final int LEVEL_INFO = 0x4;
-    public static final int LEVEL_WARNING = 0x8;
-    public static final int LEVEL_ERROR = 0x16;
-    
-//    public static String PREFS_TIME;
-//    public static String PREFS_LEVEL;
-//    public static String PREFS_PID;
-//    public static String PREFS_TAG;
-//    public static String PREFS_MESSAGE;
-    public FileWriter autoFile = null;
-    private IDevice mCurrentDevice = null;
-
-    /**
-     * This pattern is meant to parse the first line of a log message with the option
-     * 'logcat -v long'. The first line represents the date, tag, severity, etc.. while the
-     * following lines are the message (can be several line).<br>
-     * This first line looks something like<br>
-     * <code>"[ 00-00 00:00:00.000 &lt;pid&gt;:0x&lt;???&gt; &lt;severity&gt;/&lt;tag&gt;]"</code>
-     * <br>
-     * Note: severity is one of V, D, I, W, or EM<br>
-     * Note: the fraction of second value can have any number of digit.
-     * Note the tag should be trim as it may have spaces at the end.
-     */
-       private static Pattern sLogPattern = Pattern.compile(
-                           "^\\[\\s(\\d\\d-\\d\\d\\s\\d\\d:\\d\\d:\\d\\d\\.\\d+)" + //$NON-NLS-1$
-                           "\\s+(\\d*):[\\s]+([0-9a-fA-F]+)\\s([VDIWE])/(.*)\\]$"); //$NON-NLS-1$
-    
-        private String mDefaultLogSave;
-
-        private Composite parent;
-        private Label label;
-    private Table table;
-
-    private LogColors mColors;
-
-    private LogCatOuputReceiver mCurrentLogger;
-
-    /**
-     * Circular buffer containing the logcat output. This is unfiltered.
-     * The valid content goes from <code>mBufferStart</code> to
-     * <code>mBufferEnd - 1</code>. Therefore its number of item is
-     * <code>mBufferEnd - mBufferStart</code>.
-     */
-    private LogMessage[] mBuffer = new LogMessage[STRING_BUFFER_LENGTH];
-    
-    private final ArrayList<LogMessage> mfMessages = new ArrayList<LogMessage>();
-    private final ArrayList<LogMessage> mNewMessages = new ArrayList<LogMessage>();
-    
-    private int mRemovedMessageCount = 0;
-
-    /** Represents the oldest message in the buffer */
-    private int mBufferStart = -1;
-
-    /**
-     * Represents the next usable item in the buffer to receive new message.
-     * This can be equal to mBufferStart, but when used mBufferStart will be
-     * incremented as well.
-     */
-    private int mBufferEnd = -1;
-
-    /** Filtering mode */
-    private int mFilterMode = FILTER_NONE;
-    private int mLevelMode = LEVEL_NONE;
-    private String filterWord = null;
-
-    /** Device currently running logcat */
-    private IDevice mCurrentLoggedDevice = null;
-
-    private Action[] mLogLevelActions;
-
-    /** message data, separated from content for multi line messages */
-    protected static class LogMessageInfo {
-        public LogLevel logLevel;
-        public int pid;
-        public String pidString;
-        public String tag;
-        public String time;
-    }
-
-    /** pointer to the latest LogMessageInfo. this is used for multi line
-     * log message, to reuse the info regarding level, pid, etc...
-     */
-    private LogMessageInfo mLastMessageInfo = null;
-
-    private boolean mPendingAsyncRefresh = false;
-
-    private ITableFocusListener mGlobalListener;
-
-    /** message data, separated from content for multi line messages */
-    protected static class LogMessage {
-        public LogMessageInfo data;
-        public String msg;
-
-        @Override
-        public String toString() {
-            return data.time + ": " //$NON-NLS-1$
-                + data.logLevel + "/" //$NON-NLS-1$
-                + data.tag + "(" //$NON-NLS-1$
-                + data.pidString + "): " //$NON-NLS-1$
-                + msg;
-        }
-    }
-
-    /**
-     * objects able to receive the output of a remote shell command,
-     * specifically a logcat command in this case
-     */
-    private final class LogCatOuputReceiver extends MultiLineReceiver {
-
-        public boolean isCancelled = false;
-
-        public LogCatOuputReceiver() {
-            super();
-
-            setTrimLine(false);
-        }
-
-        @Override
-        public void processNewLines(String[] lines) {
-            if (isCancelled == false) {
-                processLogLines(lines);
-            }
-        }
-
-        public boolean isCancelled() {
-            return isCancelled;
-        }
-    }
-
-    /**
-     * Create the log view with some default parameters
-     * @param colors The display color object
-     * @param filterStorage the storage for user defined filters.
-     * @param mode The filtering mode
-     */
-    public LogPanel(LogColors colors) {
-        mColors = colors;
-    }
-
-    public void setActions( Action[] logLevelActions ) {
-        mLogLevelActions = logLevelActions;
-    }
-
-    /**
-     * Sent when a new device is selected.
-     * @param selectedDevice the selected device.
-     */
-    public final void deviceSelected(FileEntry selectedEntry) {
-           if( selectedEntry == null)
-                   return;
-           IDevice selectedDevice = selectedEntry.getFileListingService().getDevice();
-           
-        if (selectedDevice != mCurrentDevice) {
-            mCurrentDevice = selectedDevice;
-            deviceSelected();
-        }
-    }
-    
-    /**
-     * Returns the current {@link Device}.
-     * @return the current device or null if none are selected.
-     */
-    protected final IDevice getCurrentDevice() {
-        return mCurrentDevice;
-    }
-
-    /**
-     * Sent when a new device is selected. The new device can be accessed
-     * with {@link #getCurrentDevice()}.
-     */
-    public void deviceSelected() {
-        startLogCat(getCurrentDevice());
-    }
-
-    /**
-     * Creates a control capable of displaying some information.  This is
-     * called once, when the application is initializing, from the UI thread.
-     */
-    @Override
-    protected Control createControl(Composite p) {
-           
-           parent = p;
-           
-           parent.setLayoutData(new GridData(GridData.FILL_VERTICAL));
-           parent.setLayout(new GridLayout(1, false));         
-           
-           Composite top = new Composite( parent, SWT.NONE );
-           top.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-           top.setLayout(new GridLayout(1, false));  
-           label = new Label( top, SWT.NONE);
-
-           Composite mid = new Composite( parent, SWT.NONE );
-           mid.setLayoutData(new GridData(GridData.FILL_BOTH));
-           mid.setLayout(new FillLayout());
-        
-        table = new Table( mid, SWT.MULTI | SWT.FULL_SELECTION);
-        table.setHeaderVisible( true );
-        table.setLinesVisible( true );
-        
-        ControlListener listener = null;
-            listener = new ControlListener() {
-                public void controlMoved(ControlEvent e) {
-                       }
-
-                public void controlResized(ControlEvent e) {
-                    Rectangle r = table.getClientArea();
-
-                    // get the size of all but the last column
-                    int total = table.getColumn(0).getWidth();
-                    total += table.getColumn(1).getWidth();
-                    total += table.getColumn(2).getWidth();
-                    total += table.getColumn(3).getWidth();
-
-                    if (r.width > total) {
-                     table.getColumn(4).setWidth(r.width-total);
-                       }
-                       }
-                       };
-
-            table.addControlListener(listener);
-        
-        // then its column
-        TableColumn col = createTableColumn(table, "Time", SWT.LEFT, "00-00 00:00:00.000");
-        col.addControlListener(listener);
-
-        col = createTableColumn(table, "Level", SWT.LEFT, "Verbose" );
-        col.addControlListener(listener);
-
-        col = createTableColumn(table, "Pid", SWT.LEFT, "9999999");
-        col.addControlListener(listener);
-
-        col = createTableColumn(table, "Tag", SWT.LEFT, "ABCDEFGHIJK");
-        col.addControlListener(listener);
-
-        col = createTableColumn(table, "Message", SWT.LEFT,
-                "abcdefghijklmnopqrstuvwxyz0123456789" );
-        col.setResizable(false);
-
-        return null;
-    }
-
-    @Override
-    protected void postCreation() {
-        // pass
-    }
-
-    /**
-     * Sets the focus to the proper object.
-     */
-    @Override
-    public void setFocus() {
-    }
-
-
-    /**
-     * Starts a new logcat and set mCurrentLogCat as the current receiver.
-     * @param device the device to connect logcat to.
-     */
-    public void startLogCat(final IDevice device) {
-          
-        if (device == mCurrentLoggedDevice) {
-            return;
-        }
-
-        // if we have a logcat already running
-        if (mCurrentLoggedDevice != null) {
-            stopLogCat(false);
-            mCurrentLoggedDevice = null;
-        }
-        resetUI(false);
-        
-        if (device != null) {
-                
-                try {
-                        autoFile = new FileWriter( "AUTO_LOG" );
-                        autoFile.write( "Deivce : "+device.getSerialNumber());
-                        autoFile.append('\n');
-                        autoFile.append( "Time : "+new Date().toString());
-                        autoFile.append('\n');
-                        autoFile.append('\n');
-                        } catch (IOException e) {
-                       e.printStackTrace();
+       private String mDefaultLogSave;
+
+       private Composite parent;
+       private TabFolder folders;
+
+       private LogColors colors;
+
+       /**
+        * Circular buffer containing the logcat output. This is unfiltered. The
+        * valid content goes from <code>mBufferStart</code> to
+        * <code>mBufferEnd - 1</code>. Therefore its number of item is
+        * <code>mBufferEnd - mBufferStart</code>.
+        */
+       private final ArrayList<LogTab> tabs = new ArrayList<LogTab>();
+
+       private LogTab currentTab;
+       private static int tabCnt = 0;
+
+       private Action[] mLogLevelActions;
+
+       /** message data, separated from content for multi line messages */
+       protected static class LogMessageInfo {
+               public LogLevel logLevel;
+               public int pid;
+               public String pidString;
+               public String tag;
+               public String time;
+       }
+
+       private ITableFocusListener mGlobalListener;
+
+       /** message data, separated from content for multi line messages */
+       protected static class LogMessage {
+               public LogMessageInfo data;
+               public String msg;
+
+               @Override
+               public String toString() {
+                       return data.time + ": " //$NON-NLS-1$
+                                       + data.logLevel + "/" //$NON-NLS-1$
+                                       + data.tag + "(" //$NON-NLS-1$
+                                       + data.pidString + "): " //$NON-NLS-1$
+                                       + msg;
                }
-            // create a new output receiver
-                        mCurrentLogger = new LogCatOuputReceiver();
-
-            // start the logcat in a different thread
-            new Thread(device.getSerialNumber()+" Logger")  { //$NON-NLS-1$
-                @Override
-                public void run() {
-
-                    while (device.isOnline() == false &&
-                                 mCurrentLogger != null &&
-                                 mCurrentLogger.isCancelled == false) {
-                        try {
-                            sleep(2000);
-                        } catch (InterruptedException e) {
-                            return;
-                        }
-                    }
-
-                    if (mCurrentLogger == null || mCurrentLogger.isCancelled) {
-                        // logcat was stopped/cancelled before the device became ready.
-                        return;
-                    }
-
-                    try {
-                        mCurrentLoggedDevice = device;
-                        setLabel( device.getSerialNumber());
-                       
-                        device.executeShellCommand("dlogutil -v long *:v", mCurrentLogger, 0 /*timeout*/); //$NON-NLS-1$
-                    } catch (Exception e) {
-                        Log.e("Logcat", e);
-                    } finally {
-                        // at this point the command is terminated.
-                       mCurrentLogger = null;
-                        mCurrentLoggedDevice = null;
-                    }
-                }
-            }.start();
-        }
-    }
-
-    /** Stop the current logcat */
-    public void stopLogCat(boolean inUiThread) {
-        if (mCurrentLogger != null) {
-                         mCurrentLogger.isCancelled = true;
-
-            // when the thread finishes, no one will reference that object
-            // and it'll be destroyed
-                   mCurrentLogger = null;
-
-            // reset the content buffer
-            for (int i = 0 ; i < STRING_BUFFER_LENGTH; i++) {
-                mBuffer[i] = null;
-            }
-
-            // because it's a circular buffer, it's hard to know if
-            // the array is empty with both start/end at 0 or if it's full
-            // with both start/end at 0 as well. So to mean empty, we use -1
-            mBufferStart = -1;
-            mBufferEnd = -1;
-
-//            resetFilters();
-            resetUI(inUiThread);
-        }
-    }
-
-      /**
-     * Empty the current circular buffer.
-     */
-    public void bufferClear() {
-        synchronized (mBuffer) {
-            for (int i = 0 ; i < STRING_BUFFER_LENGTH; i++) {
-                mBuffer[i] = null;
-            }
-
-            mBufferStart = -1;
-            mBufferEnd = -1;
-
-        }
-    }
-
-    /**
-     * Copies the current selection of the current filter as multiline text.
-     *
-     * @param clipboard The clipboard to place the copied content.
-     */
-    public void copy(Clipboard clipboard) {
-        // get the current table and its selection
-        copyTable(clipboard, table);
-    }
-
-    /**
-     * Selects all lines.
-     */
-    public void selectAll() {
-        table.selectAll();
-    }
-
-    /**
-     * Sets a TableFocusListener which will be notified when one of the tables
-     * gets or loses focus.
-     *
-     * @param listener
-     */
-    public void setTableFocusListener(ITableFocusListener listener) {
-        // record the global listener, to make sure table created after
-        // this call will still be setup.
-        mGlobalListener = listener;
-        
-        addTableToFocusListener(table);
-    }
-
-    /**
-     * Sets up a Table object to notify the global Table Focus listener when it
-     * gets or loses the focus.
-     *
-     * @param table the Table object.
-     */
-    private void addTableToFocusListener(final Table table) {
-        // create the activator for this table
-        final IFocusedTableActivator activator = new IFocusedTableActivator() {
-            public void copy(Clipboard clipboard) {
-                copyTable(clipboard, table);
-            }
-
-            public void selectAll() {
-                table.selectAll();
-            }
-        };
-
-        // add the focus listener on the table to notify the global listener
-        table.addFocusListener(new FocusListener() {
-            public void focusGained(FocusEvent e) {
-                mGlobalListener.focusGained(activator);
-            }
-
-            public void focusLost(FocusEvent e) {
-                mGlobalListener.focusLost(activator);
-            }
-        });
-    }
-
-    /**
-     * Copies the current selection of a Table into the provided Clipboard, as
-     * multi-line text.
-     *
-     * @param clipboard The clipboard to place the copied content.
-     * @param table The table to copy from.
-     */
-    private static void copyTable(Clipboard clipboard, Table table) {
-        int[] selection = table.getSelectionIndices();
-
-        // we need to sort the items to be sure.
-        Arrays.sort(selection);
-
-        // all lines must be concatenated.
-        StringBuilder sb = new StringBuilder();
-
-        // loop on the selection and output the file.
-        for (int i : selection) {
-            TableItem item = table.getItem(i);
-            LogMessage msg = (LogMessage)item.getData();
-            String line = msg.toString();
-            sb.append(line);
-            sb.append('\n');
-        }
-
-        // now add that to the clipboard
-        clipboard.setContents(new Object[] {
-            sb.toString()
-        }, new Transfer[] {
-            TextTransfer.getInstance()
-        });
-    }
-
-    public void resetUI(boolean inUiThread) {
-           
-            // the ui is static we just empty it.
-            if (table.isDisposed() == false) {
-                if (inUiThread) {
-                    emptyTables();
-                } else {
-                    Display d = table.getDisplay();
-
-                    // run sync as we need to update right now.
-                    d.syncExec(new Runnable() {
-                        public void run() {
-                            if (table.isDisposed() == false) {
-                                emptyTables();
-                            }
-                        }
-                    });
-                }
-            }
-    }
-
-    /**
-     * Process new Log lines coming from {@link LogCatOuputReceiver}.
-     * @param lines the new lines
-     */
-    protected void processLogLines(String[] lines) {
-        // WARNING: this will not work if the string contains more line than
-        // the buffer holds.
-
-        if (lines.length > STRING_BUFFER_LENGTH) {
-            Log.e("LogCat", "Receiving more lines than STRING_BUFFER_LENGTH");
-        }
-
-        // parse the lines and create LogMessage that are stored in a temporary list
-        final ArrayList<LogMessage> newMessages = new ArrayList<LogMessage>();
-
-        synchronized (mBuffer) {
-            for (String line : lines) {
-                // ignore empty lines.
-                if (line.length() > 0) {
-                    // check for header lines.
-                    Matcher matcher = sLogPattern.matcher(line);
-                    if (matcher.matches()) {
-                        // this is a header line, parse the header and keep it around.
-                        mLastMessageInfo = new LogMessageInfo();
-
-                        mLastMessageInfo.time = matcher.group(1);
-                        mLastMessageInfo.pidString = matcher.group(2);
-                        mLastMessageInfo.pid = Integer.valueOf(mLastMessageInfo.pidString);
-                        mLastMessageInfo.logLevel = LogLevel.getByLetterString(matcher.group(4));
-                        mLastMessageInfo.tag = matcher.group(5).trim();
-                    } else {
-                        // This is not a header line.
-                        // Create a new LogMessage and process it.
-                        LogMessage mc = new LogMessage();
-
-                        if (mLastMessageInfo == null) {
-                          return ;
-                        }
-
-                        // If someone printed a log message with
-                        // embedded '\n' characters, there will
-                        // one header line followed by multiple text lines.
-                        // Use the last header that we saw.
-                        mc.data = mLastMessageInfo;
-
-                        // tabs seem to display as only 1 tab so we replace the leading tabs
-                        // by 4 spaces.
-                        mc.msg = line.replaceAll("\t", "    "); //$NON-NLS-1$ //$NON-NLS-2$
-
-                        // process the new LogMessage.
-                        processNewMessage(mc);
-
-                        // store the new LogMessage
-                        newMessages.add(mc);
-                    }
-                }
-            }
-
-            // if we don't have a pending Runnable that will do the refresh, we ask the Display
-            // to run one in the UI thread.
-            if (mPendingAsyncRefresh == false) {
-                mPendingAsyncRefresh = true;
-
-                try {
-                    Display display = table.getDisplay();
-
-                    // run in sync because this will update the buffer start/end indices
-                    display.asyncExec(new Runnable() {
-                        public void run() {
-                            asyncRefresh();
-                        }
-                    });
-                } catch (SWTException e) {
-                    // display is disposed, we're probably quitting. Let's stop.
-                    stopLogCat(false);
-                }
-            }
-        }
-    }
-
-    /**
-     * Refreshes the UI with new messages.
-     */
-    private void asyncRefresh() {
-        if (table.isDisposed() == false) {
-            synchronized (mBuffer) {
-                try {
-//                    // the circular buffer has been updated, let have the filter flush their
-//                    // display with the new messages.
-                 flush();
-
-                } finally {
-                    // the pending refresh is done.
-                    mPendingAsyncRefresh = false;
-                }
-            }
-        } else {
-            stopLogCat(true);
-        }
-    }
-
-    /**
-     * Processes a new Message.
-     * <p/>This adds the new message to the buffer, and gives it to the existing filters.
-     * @param newMessage
-     */
-    private void processNewMessage(LogMessage newMessage) {
-//        // if we are in auto filtering mode, make sure we have
-//        // a filter for this
-
-        // compute the index where the message goes.
-        // was the buffer empty?
-        int messageIndex = -1;
-        if (mBufferStart == -1) {
-            messageIndex = mBufferStart = 0;
-            mBufferEnd = 1;
-        } else {
-            messageIndex = mBufferEnd;
-
-            // check we aren't overwriting start
-            if (mBufferEnd == mBufferStart) {
-                mBufferStart = (mBufferStart + 1) % STRING_BUFFER_LENGTH;
-            }
-
-            // increment the next usable slot index
-            mBufferEnd = (mBufferEnd + 1) % STRING_BUFFER_LENGTH;
-        }
-
-        LogMessage oldMessage = null;
-
-        // record the message that was there before
-        if (mBuffer[messageIndex] != null) {
-            oldMessage = mBuffer[messageIndex];
-        }
-
-        // then add the new one
-        mBuffer[messageIndex] = newMessage;
-        
-        synchronized (mfMessages) {
-               if (oldMessage != null) 
-               {
-                       if( mfMessages.size() > STRING_BUFFER_LENGTH)
-                   {
-                               int index = mfMessages.indexOf(oldMessage);                
-                               if (index != -1) {
-                       // TODO check that index will always be -1 or 0, as only the oldest message is ever removed.
-                                       mfMessages.remove(index);
-                                       mRemovedMessageCount++;
-                               }
-                       } 
-               }
-           }
-           
-           boolean filter = accept(newMessage);
-           if (filter) {
-               // at this point the message is accepted, we add it to the list
-                   mfMessages.add(newMessage);                         
-                   mNewMessages.add( newMessage );
-                   autosave( newMessage );
-               }                        
-
-    }
-
-    /**
-     * Refill the default filter. Not to be called directly.
-     * @see initFilter()
-     */
-    public void refill() {
-           msgClear();
-
-           synchronized( mBuffer )
-           {
-           for( LogMessage logMsg : mBuffer)
-           {
-                   if( accept (logMsg))
-                   {
-                           mNewMessages.add(logMsg);
-                           autosave( logMsg );
-                   }
-           }
-           }
-        flush();
-    }
-    
-    public void msgClear() {
-               mRemovedMessageCount = 0;
-               mNewMessages.clear();
-               mfMessages.clear();
-               table.removeAll();
-           }
-
-    private void emptyTables() {
-           table.removeAll();
-               }
-    
-    /**
-     * Takes all the accepted messages and display them.
-     * This must be called from a UI thread.
-     */
-    public void flush() {
-        // if scroll bar is at the bottom, we will scroll
-        ScrollBar bar = table.getVerticalBar();
-        boolean scroll = bar.getMaximum() == bar.getSelection() + bar.getThumb();
-        
-        // if we are not going to scroll, get the current first item being shown.
-        int topIndex = table.getTopIndex();
-
-        // disable drawing
-        table.setRedraw(false);
-        
-        int totalCount = mNewMessages.size();
-
-        try {
-            // remove the items of the old messages.
-            for (int i = 0 ; i < mRemovedMessageCount && table.getItemCount() > 0 ; i++) {
-                    table.remove(0);
-            }
-    
-            // add the new items
-            for (int i = 0  ; i < totalCount ; i++) {
-                LogMessage msg = mNewMessages.get(i);
-                addTableItem(msg);
-            }
-        } catch (SWTException e) {
-            // log the error and keep going. Content of the logcat table maybe unexpected
-            // but at least ddms won't crash.
-            Log.e("LogFilter", e);
-        }
-        
-        // redraw
-        table.setRedraw(true);
-
-        // scroll if needed, by showing the last item
-        if (scroll) {
-            totalCount = table.getItemCount();
-            if (totalCount > 0) {
-                    table.showItem(table.getItem(totalCount-1));
-            }
-        } else if (mRemovedMessageCount > 0) {
-            // we need to make sure the topIndex is still visible.
-            // Because really old items are removed from the list, this could make it disappear
-            // if we don't change the scroll value at all.
-
-            topIndex -= mRemovedMessageCount;
-            if (topIndex < 0) {
-                // looks like it disappeared. Lets just show the first item
-                    table.showItem(table.getItem(0));
-            } else {
-                    table.showItem(table.getItem(topIndex));
-            }
-        }
-        
-        mNewMessages.clear();
-        mRemovedMessageCount = 0;
-        
-        if( autoFile!=null)
-                try {
-                        autoFile.flush();
-                        } catch (IOException e) {
-                                e.printStackTrace();
-                                }
-    }
-    
-    /**
-     * Add a TableItem for the index-th item of the buffer
-     * @param filter The index of the table in which to insert the item.
-     */
-    private void addTableItem(LogMessage msg) {
-        TableItem item = new TableItem(table, SWT.NONE);
-        item.setText(0, msg.data.time);
-        item.setText(1, new String(new char[] { msg.data.logLevel.getPriorityLetter() }));
-        item.setText(2, msg.data.pidString);
-        item.setText(3, msg.data.tag);
-        item.setText(4, msg.msg);
-
-        // add the buffer index as data
-        item.setData(msg);
-
-        if (msg.data.logLevel == LogLevel.INFO) {
-            item.setForeground(mColors.infoColor);
-        } else if (msg.data.logLevel == LogLevel.DEBUG) {
-            item.setForeground(mColors.debugColor);
-        } else if (msg.data.logLevel == LogLevel.ERROR) {
-            item.setForeground(mColors.errorColor);
-        } else if (msg.data.logLevel == LogLevel.WARN) {
-            item.setForeground(mColors.warningColor);
-        } else {
-            item.setForeground(mColors.verboseColor);
-        }
-    }
-    
-    public void setLevel( int level, boolean setLevel )
-    {
-           level = (int) Math.pow(2, level);
-           if( setLevel )                  
-                   mLevelMode |= level;
-           else
-                   mLevelMode &= (~level);       
-    }
-    
-//    /**
-//     * Filters a message.
-//     * @param logMessage the Message
-//     * @return true if the message is accepted by the filter.
-//     */
-    boolean accept(LogMessage logMessage) {
-               
-           if( logMessage == null )
-                   return false;
-           
-           if( mLevelMode != LEVEL_NONE )
-           {
-                   int a = 0;
-                   a = ( mLevelMode & (0x1 << (logMessage.data.logLevel.getPriority() - 2 )));
-                           
-                   if( a == 0 )
-                           return false;
-           }
-           
-           if( mFilterMode != FILTER_NONE && filterWord != null)
-           {               
-                   if( (mFilterMode & FILTER_PID) != 0 )
-                   {
-                           if( !Integer.toString(logMessage.data.pid).contains(filterWord))
-                                   return false;                           
-                   }
-                   
-                   if( (mFilterMode & FILTER_TAG) != 0 )
-                   {
-                           if( !logMessage.data.tag.contains(filterWord))
-                                   return false;                           
-                   }               
-                   
-                   if( (mFilterMode & FILTER_MSG) != 0)
-                   {
-                           if( !logMessage.msg.toLowerCase().contains(filterWord.toLowerCase()))
-                                   return false;                           
-                   }       
-           }
-        return true;
-    }
-    
-    /**
-     * saves the current selection in a text file.
-     * @return false if the saving failed.
-     */
-    public boolean save() {
-        synchronized (mBuffer) {
-            FileDialog dlg = new FileDialog(parent.getShell(), SWT.SAVE);
-            String fileName;
-
-            dlg.setText("Save log...");
-            dlg.setFileName("log.txt");
-            String defaultPath = mDefaultLogSave;
-            if (defaultPath == null) {
-                defaultPath = System.getProperty("user.home"); //$NON-NLS-1$
-            }
-            dlg.setFilterPath(defaultPath);
-            dlg.setFilterNames(new String[] {
-                "Text Files (*.txt)"
-            });
-            dlg.setFilterExtensions(new String[] {
-                "*.txt"
-            });
-
-            fileName = dlg.open();
-            if (fileName != null) {
-                mDefaultLogSave = dlg.getFilterPath();
-
-                int[] selection = table.getSelectionIndices();
-
-                // we need to sort the items to be sure.
-                Arrays.sort(selection);
-
-                // loop on the selection and output the file.
-                try {
-                    FileWriter writer = new FileWriter(fileName);
-
-                    for (int i : selection) {
-                        TableItem item = table.getItem(i);
-                        LogMessage msg = (LogMessage)item.getData();
-                        String line = msg.toString();
-                        writer.write(line);
-                        writer.write('\n');
-                    }
-                    writer.flush();
-
-                } catch (IOException e) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-    
-    public void clear() {
-               for (int i = 0 ; i < STRING_BUFFER_LENGTH; i++) {
-                       mBuffer[i] = null;
-                   }
-
-                   mBufferStart = -1;
-                   mBufferEnd = -1;
-
-                   msgClear();
-           }
-    
-    public void addView()
-    {
-           AddViewDialog dlg = new AddViewDialog(parent.getShell());
-//         LogView view = null;
-           if(dlg.open())
-           {
-                   IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
-                   
-                   try {
-//                         view = (LogView)
-                                           page.showView(ConnectionPlugin.ID_LOGS_VIEW, "LogView"+LogView.viewCnt++, page.VIEW_ACTIVATE);
-                           } catch (PartInitException e) {
-                                   // TODO Auto-generated catch block
-                                   e.printStackTrace();
-                                   }
-           }else
-                   return ;
-                   
-                   for( IDevice device : SmartDevelopmentBridge.getBridge().getDevices())
-                   {
-                           if(device.getSerialNumber().equals( dlg.getDevice()))
-                           {
-                                           int filterMode = 0;
-                                           
-                                           if( dlg.getMsgChecked())
-                                                   filterMode |= FILTER_MSG;
-                                           if( dlg.getPidChecked())
-                                                   filterMode |= FILTER_PID;
-                                           if( dlg.getTagChecked())
-                                                   filterMode |= FILTER_TAG;
-                                           
-                                         
-                                           if( filterMode != FILTER_NONE )
-                                                   LogView.newLogView.getPanel().filterWord = dlg.getKeyword();
-                                           
-                                           LogView.newLogView.getPanel().mFilterMode = filterMode;
-
-                                           LogView.newLogView.selectionChanged(device.getFileListingService().getRoot());
-                                           break;
-                           }
-                   }
-    }
-    
-    public void setLabel(final String device)
-    {
-           Display d = label.getDisplay();
-
-           // run sync as we need to update right now.
-           d.syncExec(new Runnable() {
-                   public void run() {
-                           if (label.isDisposed() == false)                                
-                   {
-                                   label.setBounds(0, 0, 700, 40);
-                                   if( filterWord == null) {
-                                               
-                                           label.setText("Logs From " +device);
-                                   }
-                                   else
-                                           label.setText("Search result about " + "\""+ filterWord + "\"" + " from "+ device );                                                        
-                   }
-               }
-           });
-    }
-    
-    private void autosave(LogMessage msg)
-    {
-           if( autoFile!=null)
-                 try {
-                         autoFile.append(msg.toString());
-                         autoFile.append('\n');
-                         } 
-           catch (IOException e) 
-               {
-                                 e.printStackTrace();
-               }           
-    }     
-    
-       public static TableColumn createTableColumn(Table parent, String header,
-                           int style, String sample_text) {
+       }
+
+       /**
+        * Create the log panel with some default parameters
+        * 
+        * @param colors
+        *            The display color object
+        */
+       public LogPanel(LogColors colors) {
+               this.colors = colors;
+       }
+
+       /**
+        * Creates a control capable of displaying some information. This is called
+        * once, when the application is initializing, from the UI thread.
+        */
+       @Override
+       protected Control createControl(Composite p) {
+
+               parent = p;
+
+               // Composite top = new Composite(parent, SWT.NONE);
+               // top.setLayoutData(new GridData(GridData.FILL_BOTH));
+               // top.setLayout(new GridLayout(1, false));
+
+               // create the tab folder
+               folders = new TabFolder(parent, SWT.NONE);
+               folders.setLayoutData(new GridData(GridData.FILL_BOTH));
+               folders.addSelectionListener(new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               if (currentTab != null) {
+                                       currentTab.setSelectedState(false);
+                               }
+                               currentTab = getCurrentLogTab();
+                               currentTab.setSelectedState(true);
+                               // updateColumns(currentTab.getTable());
+                               currentTab.initTab();
+                               // selectionChanged(currentTab);
+                       }
+               });
+
+               createTabs();
+
+               return null;
+       }
+
+       /**
+        * 
+        * Create the LogFilters with default devicesd
+        * 
+        */
+       private void createTabs() {
+               IDevice[] devices = SmartDevelopmentBridge.getBridge().getDevices();
+               for (IDevice device : devices) {
+                       LogTab tab = new LogTab(device.getSerialNumber(), device, colors);
+                       tabs.add(tab);
+                       createTab(tab, tabCnt++, false);
+                       tab.setSupportsDelete(false);
+                       tab.setSupportsEdit(false);
+                       tab.startLogTab();
+               }
+
+       }
+
+       private TabItem createTab(final LogTab tab, int index, boolean fillTable) {
+               TabItem item = null;
+               if (index != -1) {
+                       item = new TabItem(folders, SWT.NONE, index);
+               } else {
+                       item = new TabItem(folders, SWT.NONE);
+               }
+               item.setText(tab.getFilterName());
+
+               Composite top = new Composite(folders, SWT.NONE);
+               top.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+               top.setLayout(new GridLayout(1, false));
+               item.setControl(top);
 
-                       // create the column
-                       TableColumn col = new TableColumn(parent, style);
+               // top.setLayout(new FillLayout());
 
-                       // if there is no pref store or the entry is missing, we use the sample
-                       // text and pack the column.
-                       // Otherwise we just read the width from the prefs and apply it.
-                       col.setText(sample_text);
-                       col.pack();
+               Composite mid = new Composite(top, SWT.NONE);
+               mid.setLayoutData(new GridData(GridData.FILL_BOTH));
+               mid.setLayout(new FillLayout());
 
-                      // set the header
-                       col.setText(header);
+               final Table table = new Table(mid, SWT.MULTI | SWT.FULL_SELECTION);
 
-                      return col;
-                   }
+               tab.setWidgets(item, table);
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+
+               if (mGlobalListener != null) {
+                       addTableToFocusListener(table);
+               }
+
+               ControlListener listener = null;
+               listener = new ControlListener() {
+                       public void controlMoved(ControlEvent e) {
+
+                       }
+
+                       public void controlResized(ControlEvent e) {
+                               Rectangle r = table.getClientArea();
+
+                               // get the size of all but the last column
+                               int total = table.getColumn(0).getWidth();
+                               total += table.getColumn(1).getWidth();
+                               total += table.getColumn(2).getWidth();
+                               total += table.getColumn(3).getWidth();
+
+                               if (r.width > total) {
+                                       table.getColumn(4).setWidth(r.width - total);
+                               }
+                       }
+               };
+
+               table.addControlListener(listener);
+
+               // then its column
+               TableColumn col = createTableColumn(table, "Time", SWT.LEFT,
+                               "00-00 00:00:00.000");
+               col.addControlListener(listener);
+
+               col = createTableColumn(table, "Level", SWT.LEFT, "Verbose");
+               col.addControlListener(listener);
+
+               col = createTableColumn(table, "Pid", SWT.LEFT, "9999999");
+               col.addControlListener(listener);
+
+               col = createTableColumn(table, "Tag", SWT.LEFT, "ABCDEFGHIJK");
+               col.addControlListener(listener);
+
+               col = createTableColumn(table, "Message", SWT.LEFT,
+                               "abcdefghijklmnopqrstuvwxyz0123456789");
+               col.setResizable(false);
+
+               Composite bottom = new Composite(top, SWT.NONE);
+               bottom.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               bottom.setLayout(new GridLayout(3, false));
+
+               final Combo combo = new Combo(bottom, SWT.READ_ONLY);
+               String comboItems[] = {"Pid", "Tag", "Message"};
+               combo.setItems(comboItems);
+               combo.setToolTipText("Keyword Search: Pid or Tag, Message");
+
+               final Text filterText = new Text(bottom, SWT.SINGLE | SWT.BORDER);
+               filterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               filterText.setMessage(" Input Keyword ");
+               filterText.addModifyListener(new ModifyListener() {
+
+                       @Override
+                       public void modifyText(ModifyEvent e) {
+                               int index = combo.getSelectionIndex();
+                               if (index != -1) {
+                                       tab.setFilterMode((int) Math.pow(2, index));
+                                       tab.setFilterWord(filterText.getText());
+                                       tab.refill();
+                               }
+                       }
+               });
+
+               folders.setSelection(item);
+
+               return item;
+       }
+
+       @Override
+       protected void postCreation() {
+               // pass
+       }
+
+       /**
+        * Sets the focus to the proper object.
+        */
+       @Override
+       public void setFocus() {
+       }
+
+       /**
+        * Copies the current selection of the current filter as multiline text.
+        * 
+        * @param clipboard
+        *            The clipboard to place the copied content.
+        */
+       public void copy(Clipboard clipboard) {
+               // get the current table and its selection
+               copyTable(clipboard, currentTab.getTable());
+       }
+
+       /**
+        * Selects all lines.
+        */
+       public void selectAll() {
+               currentTab.getTable().selectAll();
+       }
+
+       /**
+        * Sets a TableFocusListener which will be notified when one of the tables
+        * gets or loses focus.
+        * 
+        * @param listener
+        */
+       public void setTableFocusListener(ITableFocusListener listener) {
+               // record the global listener, to make sure table created after
+               // this call will still be setup.
+               mGlobalListener = listener;
+
+               for (LogTab tab : tabs) {
+                       addTableToFocusListener(tab.getTable());
+               }
+       }
+
+       /**
+        * Sets up a Table object to notify the global Table Focus listener when it
+        * gets or loses the focus.
+        * 
+        * @param table
+        *            the Table object.
+        */
+       private void addTableToFocusListener(final Table table) {
+               // create the activator for this table
+               final IFocusedTableActivator activator = new IFocusedTableActivator() {
+                       public void copy(Clipboard clipboard) {
+                               copyTable(clipboard, table);
+                       }
+
+                       public void selectAll() {
+                               table.selectAll();
+                       }
+               };
+
+               // add the focus listener on the table to notify the global
+               // listener
+               table.addFocusListener(new FocusListener() {
+                       public void focusGained(FocusEvent e) {
+                               mGlobalListener.focusGained(activator);
+                       }
+
+                       public void focusLost(FocusEvent e) {
+                               mGlobalListener.focusLost(activator);
+                       }
+               });
+       }
+
+       /**
+        * Copies the current selection of a Table into the provided Clipboard, as
+        * multi-line text.
+        * 
+        * @param clipboard
+        *            The clipboard to place the copied content.
+        * @param table
+        *            The table to copy from.
+        */
+       private static void copyTable(Clipboard clipboard, Table table) {
+               int[] selection = table.getSelectionIndices();
+
+               // we need to sort the items to be sure.
+               Arrays.sort(selection);
+
+               // all lines must be concatenated.
+               StringBuilder sb = new StringBuilder();
+
+               // loop on the selection and output the file.
+               for (int i : selection) {
+                       TableItem item = table.getItem(i);
+                       LogMessage msg = (LogMessage) item.getData();
+                       String line = msg.toString();
+                       sb.append(line);
+                       sb.append('\n');
+               }
+
+               // now add that to the clipboard
+               clipboard.setContents(new Object[]{sb.toString()},
+                               new Transfer[]{TextTransfer.getInstance()});
+       }
+
+       // public void resetUI(boolean inUiThread) {
+       //
+       // // the ui is static we just empty it.
+       // if (table.isDisposed() == false) {
+       // if (inUiThread) {
+       // emptyTables();
+       // } else {
+       // Display d = table.getDisplay();
+       //
+       // // run sync as we need to update right now.
+       // d.syncExec(new Runnable() {
+       // public void run() {
+       // if (table.isDisposed() == false) {
+       // emptyTables();
+       // }
+       // }
+       // });
+       // }
+       // }
+       // }
+
+       // /**
+       // * Process new Log lines coming from {@link LogCatOuputReceiver}.
+       // * @param lines the new lines
+       // */
+       // protected void processLogLines(String[] lines) {
+       // // WARNING: this will not work if the string contains more line than
+       // // the buffer holds.
+       //
+       // if (lines.length > STRING_BUFFER_LENGTH) {
+       // Log.e("LogCat", "Receiving more lines than STRING_BUFFER_LENGTH");
+       // }
+       //
+       // // parse the lines and create LogMessage that are stored in a
+       // temporary list
+       // final ArrayList<LogMessage> newMessages = new ArrayList<LogMessage>();
+       //
+       // synchronized (mBuffer) {
+       // for (String line : lines) {
+       // // ignore empty lines.
+       // if (line.length() > 0) {
+       // // check for header lines.
+       // Matcher matcher = sLogPattern.matcher(line);
+       // if (matcher.matches()) {
+       // // this is a header line, parse the header and keep it around.
+       // mLastMessageInfo = new LogMessageInfo();
+       //
+       // mLastMessageInfo.time = matcher.group(1);
+       // mLastMessageInfo.pidString = matcher.group(2);
+       // mLastMessageInfo.pid = Integer.valueOf(mLastMessageInfo.pidString);
+       // mLastMessageInfo.logLevel =
+       // LogLevel.getByLetterString(matcher.group(4));
+       // mLastMessageInfo.tag = matcher.group(5).trim();
+       // } else {
+       // // This is not a header line.
+       // // Create a new LogMessage and process it.
+       // LogMessage mc = new LogMessage();
+       //
+       // if (mLastMessageInfo == null) {
+       // return ;
+       // }
+       //
+       // // If someone printed a log message with
+       // // embedded '\n' characters, there will
+       // // one header line followed by multiple text lines.
+       // // Use the last header that we saw.
+       // mc.data = mLastMessageInfo;
+       //
+       // // tabs seem to display as only 1 tab so we replace the leading tabs
+       // // by 4 spaces.
+       //                              mc.msg = line.replaceAll("\t", "    "); //$NON-NLS-1$ //$NON-NLS-2$
+       //
+       // // process the new LogMessage.
+       // processNewMessage(mc);
+       //
+       // // store the new LogMessage
+       // newMessages.add(mc);
+       // }
+       // }
+       // }
+       //
+       // // if we don't have a pending Runnable that will do the refresh, we
+       // ask the Display
+       // // to run one in the UI thread.
+       // if (mPendingAsyncRefresh == false) {
+       // mPendingAsyncRefresh = true;
+       //
+       // try {
+       // Display display = table.getDisplay();
+       //
+       // // run in sync because this will update the buffer start/end indices
+       // display.asyncExec(new Runnable() {
+       // public void run() {
+       // asyncRefresh();
+       // }
+       // });
+       // } catch (SWTException e) {
+       // // display is disposed, we're probably quitting. Let's stop.
+       // stopLogCat(false);
+       // }
+       // }
+       // }
+       // }
+       //
+       // /**
+       // * Processes a new Message.
+       // * <p/>This adds the new message to the buffer, and gives it to the
+       // existing filters.
+       // * @param newMessage
+       // */
+       // private void processNewMessage(LogMessage newMessage) {
+       // // // if we are in auto filtering mode, make sure we have
+       // // // a filter for this
+       //
+       // // compute the index where the message goes.
+       // // was the buffer empty?
+       // int messageIndex = -1;
+       // if (mBufferStart == -1) {
+       // messageIndex = mBufferStart = 0;
+       // mBufferEnd = 1;
+       // } else {
+       // messageIndex = mBufferEnd;
+       //
+       // // check we aren't overwriting start
+       // if (mBufferEnd == mBufferStart) {
+       // mBufferStart = (mBufferStart + 1) % STRING_BUFFER_LENGTH;
+       // }
+       //
+       // // increment the next usable slot index
+       // mBufferEnd = (mBufferEnd + 1) % STRING_BUFFER_LENGTH;
+       // }
+       //
+       // LogMessage oldMessage = null;
+       //
+       // // record the message that was there before
+       // if (mBuffer[messageIndex] != null) {
+       // oldMessage = mBuffer[messageIndex];
+       // }
+       //
+       // // then add the new one
+       // mBuffer[messageIndex] = newMessage;
+       //
+       // synchronized (mfMessages) {
+       // if (oldMessage != null)
+       // {
+       // if( mfMessages.size() > STRING_BUFFER_LENGTH)
+       // {
+       // int index = mfMessages.indexOf(oldMessage);
+       // if (index != -1) {
+       // // TODO check that index will always be -1 or 0, as only the oldest
+       // message is ever removed.
+       // mfMessages.remove(index);
+       // mRemovedMessageCount++;
+       // }
+       // }
+       // }
+       // }
+       //
+       // boolean filter = accept(newMessage);
+       // if (filter) {
+       // // at this point the message is accepted, we add it to the list
+       // mfMessages.add(newMessage);
+       // mNewMessages.add( newMessage );
+       // // autosave( newMessage );
+       // }
+       //
+       // }
+       //
+       // /**
+       // * Refill the default filter. Not to be called directly.
+       // * @see initFilter()
+       // */
+       // public void refill() {
+       // msgClear();
+       //
+       // synchronized( mBuffer )
+       // {
+       // for( LogMessage logMsg : mBuffer)
+       // {
+       // if( accept (logMsg))
+       // {
+       // mNewMessages.add(logMsg);
+       // // autosave( logMsg );
+       // }
+       // }
+       // }
+       // flush();
+       // }
+       //
+       // public void msgClear() {
+       // mRemovedMessageCount = 0;
+       // mNewMessages.clear();
+       // mfMessages.clear();
+       // table.removeAll();
+       // }
+
+       // private void emptyTables() {
+       // table.removeAll();
+       // }
+       //
+       // /**
+       // * Takes all the accepted messages and display them.
+       // * This must be called from a UI thread.
+       // */
+       // public void flush() {
+       // // if scroll bar is at the bottom, we will scroll
+       // ScrollBar bar = table.getVerticalBar();
+       // boolean scroll = bar.getMaximum() == bar.getSelection() +
+       // bar.getThumb();
+       //
+       // // if we are not going to scroll, get the current first item being
+       // shown.
+       // int topIndex = table.getTopIndex();
+       //
+       // // disable drawing
+       // table.setRedraw(false);
+       //
+       // int totalCount = mNewMessages.size();
+       //
+       // try {
+       // // remove the items of the old messages.
+       // for (int i = 0 ; i < mRemovedMessageCount && table.getItemCount() > 0
+       // ; i++) {
+       // table.remove(0);
+       // }
+       //
+       // // add the new items
+       // for (int i = 0 ; i < totalCount ; i++) {
+       // LogMessage msg = mNewMessages.get(i);
+       // addTableItem(msg);
+       // }
+       // } catch (SWTException e) {
+       // // log the error and keep going. Content of the logcat table maybe
+       // unexpected
+       // // but at least ddms won't crash.
+       // Log.e("LogFilter", e);
+       // }
+       //
+       // // redraw
+       // table.setRedraw(true);
+       //
+       // // scroll if needed, by showing the last item
+       // if (scroll) {
+       // totalCount = table.getItemCount();
+       // if (totalCount > 0) {
+       // table.showItem(table.getItem(totalCount-1));
+       // }
+       // } else if (mRemovedMessageCount > 0) {
+       // // we need to make sure the topIndex is still visible.
+       // // Because really old items are removed from the list, this could make
+       // it disappear
+       // // if we don't change the scroll value at all.
+       //
+       // topIndex -= mRemovedMessageCount;
+       // if (topIndex < 0) {
+       // // looks like it disappeared. Lets just show the first item
+       // table.showItem(table.getItem(0));
+       // } else {
+       // table.showItem(table.getItem(topIndex));
+       // }
+       // }
+       //
+       // mNewMessages.clear();
+       // mRemovedMessageCount = 0;
+       //
+       // // if( autoFile!=null)
+       // // try {
+       // // autoFile.flush();
+       // // } catch (IOException e) {
+       // // e.printStackTrace();
+       // // }
+       // }
+       //
+       // /**
+       // * Add a TableItem for the index-th item of the buffer
+       // * @param filter The index of the table in which to insert the item.
+       // */
+       // private void addTableItem(LogMessage msg) {
+       // TableItem item = new TableItem(table, SWT.NONE);
+       // item.setText(0, msg.data.time);
+       // item.setText(1, new String(new char[] {
+       // msg.data.logLevel.getPriorityLetter() }));
+       // item.setText(2, msg.data.pidString);
+       // item.setText(3, msg.data.tag);
+       // item.setText(4, msg.msg);
+       //
+       // // add the buffer index as data
+       // item.setData(msg);
+       //
+       // if (msg.data.logLevel == LogLevel.INFO) {
+       // item.setForeground(mColors.infoColor);
+       // } else if (msg.data.logLevel == LogLevel.DEBUG) {
+       // item.setForeground(mColors.debugColor);
+       // } else if (msg.data.logLevel == LogLevel.ERROR) {
+       // item.setForeground(mColors.errorColor);
+       // } else if (msg.data.logLevel == LogLevel.WARN) {
+       // item.setForeground(mColors.warningColor);
+       // } else {
+       // item.setForeground(mColors.verboseColor);
+       // }
+       // }
+
+       // public void setLevel( int level, boolean setLevel )
+       // {
+       // level = (int) Math.pow(2, level);
+       // if( setLevel )
+       // mLevelMode |= level;
+       // else
+       // mLevelMode &= (~level);
+       // }
+
+       // /**
+       // * Filters a message.
+       // * @param logMessage the Message
+       // * @return true if the message is accepted by the filter.
+       // */
+       // boolean accept(LogMessage logMessage) {
+       //
+       // if( logMessage == null )
+       // return false;
+       //
+       // if( mLevelMode != LEVEL_NONE )
+       // {
+       // int a = 0;
+       // a = ( mLevelMode & (0x1 << (logMessage.data.logLevel.getPriority() - 2
+       // )));
+       //
+       // if( a == 0 )
+       // return false;
+       // }
+       //
+       // if( mFilterMode != FILTER_NONE && filterWord != null)
+       // {
+       // if( (mFilterMode & FILTER_PID) != 0 )
+       // {
+       // if( !Integer.toString(logMessage.data.pid).contains(filterWord))
+       // return false;
+       // }
+       //
+       // if( (mFilterMode & FILTER_TAG) != 0 )
+       // {
+       // if( !logMessage.data.tag.contains(filterWord))
+       // return false;
+       // }
+       //
+       // if( (mFilterMode & FILTER_MSG) != 0)
+       // {
+       // if( !logMessage.msg.toLowerCase().contains(filterWord.toLowerCase()))
+       // return false;
+       // }
+       // }
+       // return true;
+       // }
+       //
+       /**
+        * saves the current selection in a text file.
+        * 
+        * @return false if the saving failed.
+        */
+       public boolean save() {
+//             synchronized (g) {
+                       FileDialog dlg = new FileDialog(parent.getShell(), SWT.SAVE);
+                       String fileName;
+
+                       dlg.setText("Save log...");
+                       dlg.setFileName("log.txt");
+                       String defaultPath = mDefaultLogSave;
+                       if (defaultPath == null) {
+                               defaultPath = System.getProperty("user.home"); //$NON-NLS-1$
+                       }
+                       dlg.setFilterPath(defaultPath);
+                       dlg.setFilterNames(new String[]{"Text Files (*.txt)"});
+                       dlg.setFilterExtensions(new String[]{"*.txt"});
+
+                       fileName = dlg.open();
+                       if (fileName != null) {
+                               mDefaultLogSave = dlg.getFilterPath();
+
+                               // loop on the selection and output the file.
+                               try {
+                                       FileWriter writer = new FileWriter(fileName);
+
+                                       for (TableItem item : getCurrentLogTab().getTable().getItems()) {
+                                               LogMessage msg = (LogMessage) item.getData();
+                                               String line = msg.toString();
+                                               writer.write(line);
+                                               writer.write('\n');
+                                       }
+                                       writer.flush();
+
+                               } catch (IOException e) {
+                                       return false;
+                               }
+                       }
+//             }
+
+               return true;
+       }
+
+       //
+       public void clear() {
+               this.getCurrentLogTab().clear();
+       }
+
+       public void addTab() {
+
+               AddViewDialog dlg = new AddViewDialog(parent.getShell(),
+                               getCurrentLogTab().getFilterDeviceName());
+               // LogView view = null;
+               if (dlg.open()) {
+                       for (IDevice device : SmartDevelopmentBridge.getBridge()
+                                       .getDevices()) {
+                               if (device.getSerialNumber().equals(dlg.getDevice())) {
+
+                                       LogTab newTab = new LogTab(device.getSerialNumber(),
+                                                       device, colors);
+                                       newTab.setFilterName(dlg.getName());
+
+                                       int filterMode = 0;
+
+                                       if (dlg.getMsgChecked())
+                                               filterMode |= LogTab.FILTER_MSG;
+                                       if (dlg.getPidChecked())
+                                               filterMode |= LogTab.FILTER_PID;
+                                       if (dlg.getTagChecked())
+                                               filterMode |= LogTab.FILTER_TAG;
+
+                                       if (filterMode != LogTab.FILTER_NONE)
+                                               newTab.setFilterWord(dlg.getKeyword());
+
+                                       newTab.setFilterMode(filterMode);
+
+                                       tabs.add(newTab);
+                                       createTab(newTab, tabCnt++, false);
+                                       newTab.startLogTab();
+
+                                       break;
+                               }
+                       }
+               } else
+                       return;
+       }
+
+       public void removeTab() {
+
+               int index = folders.getSelectionIndex();
+
+               LogTab tab = tabs.get(index);
+               if (!tab.supportsDelete())
+                       return;
+               tab.stopLogTab(true);
+               tabs.remove(index);
+               tabCnt--;
+               tab.dispose();
+               if (!tabs.isEmpty())
+                       folders.setSelection(0);
+
+       }
+
+       public void editTab() {
+
+               LogTab oldTab = getCurrentLogTab();
+               if( !oldTab.supportsEdit())
+                       return ;
+               AddViewDialog dlg = new AddViewDialog(parent.getShell(), oldTab);
+               if (dlg.open()) {
+                       for (IDevice device : SmartDevelopmentBridge.getBridge()
+                                       .getDevices()) {
+                               if (device.getSerialNumber().equals(dlg.getDevice())) {
+                                       boolean bRestart = false;
+                                       if (!oldTab.getFilterDeviceName().equals(
+                                                       device.getSerialNumber())) {
+                                               oldTab.stopLogTab(true);
+                                               oldTab.setDevice(device);
+                                               bRestart = true;
+                                       }
+
+                                       for (TabItem item : folders.getItems()) {
+                                               if (item.getText().equals(oldTab.getFilterName())) {
+                                                       item.setText(dlg.getName());
+                                                       oldTab.setFilterName(dlg.getName());
+                                               }
+                                       }
+
+                                       int filterMode = 0;
+
+                                       if (dlg.getMsgChecked())
+                                               filterMode |= LogTab.FILTER_MSG;
+                                       if (dlg.getPidChecked())
+                                               filterMode |= LogTab.FILTER_PID;
+                                       if (dlg.getTagChecked())
+                                               filterMode |= LogTab.FILTER_TAG;
+
+                                       if (filterMode != LogTab.FILTER_NONE)
+                                               oldTab.setFilterWord(dlg.getKeyword());
+
+                                       oldTab.setFilterMode(filterMode);
+                                       if (bRestart)
+                                               oldTab.startLogTab();
+                                       else
+                                               oldTab.refill();
+                                       break;
+                               }
+                       }
+               } else
+                       return;
+       }
+
+       // private void autosave(LogMessage msg)
+       // {
+       // if( autoFile!=null)
+       // try {
+       // autoFile.append(msg.toString());
+       // autoFile.append('\n');
+       // }
+       // catch (IOException e)
+       // {
+       // e.printStackTrace();
+       // }
+       // }
+
+       public static TableColumn createTableColumn(Table parent, String header,
+                       int style, String sample_text) {
+
+               // create the column
+               TableColumn col = new TableColumn(parent, style);
+
+               // if there is no pref store or the entry is missing, we use the
+               // sample
+               // text and pack the column.
+               // Otherwise we just read the width from the prefs and apply it.
+               col.setText(sample_text);
+               col.pack();
+
+               // set the header
+               col.setText(header);
+
+               return col;
+       }
+
+       public LogTab getCurrentLogTab() {
+               if (tabs.size() != 0) {
+                       int index = folders.getSelectionIndex();
+                       return tabs.get(index);
+               } else
+                       return null;
+               //
+               // // if mFilters is null or index is invalid, we return the
+               // default
+               // // filter. It doesn't matter if that one is null as well, since
+               // we
+               // // would return null anyway.
+               // if (index == 0 || mFilters == null) {
+               // return mDefaultFilter;
+               // }
+
+       }
+
+       public void stopAll() {
+               for (LogTab tab : tabs) {
+                       tab.stopLogTab(true);
+               }
+               tabs.clear();
+               tabCnt = 0;
+       }
 
-}
+}
\ No newline at end of file
diff --git a/com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/log/LogTab.java b/com.samsung.tizen.common.connection/src/com/samsung/tizen/common/connection/log/LogTab.java
new file mode 100644 (file)
index 0000000..d59bdfc
--- /dev/null
@@ -0,0 +1,805 @@
+package com.samsung.tizen.common.connection.log;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.samsung.tizen.common.connection.log.LogPanel.LogMessage;
+import com.samsung.tizen.common.connection.log.LogPanel.LogMessageInfo;
+import com.samsung.tizen.sdblib.IDevice;
+import com.samsung.tizen.sdblib.Log;
+import com.samsung.tizen.sdblib.Log.LogLevel;
+import com.samsung.tizen.sdblib.MultiLineReceiver;
+
+public class LogTab {
+
+       private static final int STRING_BUFFER_LENGTH = 10000;
+
+       public static final int FILTER_NONE = 0x0;
+       public static final int FILTER_PID = 0x1;
+       public static final int FILTER_TAG = 0x2;
+       public static final int FILTER_MSG = 0x4;
+
+       public static final int LEVEL_NONE = 0x0;
+       public static final int LEVEL_VERBOSE = 0x1;
+       public static final int LEVEL_DEBUG = 0x2;
+       public static final int LEVEL_INFO = 0x4;
+       public static final int LEVEL_WARNING = 0x8;
+       public static final int LEVEL_ERROR = 0x16;
+
+       private int filterMode = FILTER_NONE;
+       /**
+        * Single level log level as defined in Log.mLevelChar. Only valid if mMode
+        * is MODE_LEVEL
+        */
+       private int levelMode = LEVEL_NONE;
+
+       private String filterWord = null;
+       private String filterName = null;
+       private IDevice filterDevice = null;
+       private LogTabOuputReceiver logger = null;
+       private LogColors colors;
+
+       private Table table;
+       private TabItem tabItem;
+       private boolean mIsCurrentTabItem = false;
+       private int mUnreadCount = 0;
+
+       private static Pattern logPattern = Pattern
+                       .compile("^\\[\\s(\\d\\d-\\d\\d\\s\\d\\d:\\d\\d:\\d\\d\\.\\d+)" + //$NON-NLS-1$
+                                       "\\s+(\\d*):[\\s]+([0-9a-fA-F]+)\\s([VDIWE])/(.*)\\]$"); //$NON-NLS-1$
+
+       private final ArrayList<LogMessage> tableMessages = new ArrayList<LogMessage>();
+       private final ArrayList<LogMessage> newMessages = new ArrayList<LogMessage>();
+       // private final ArrayList<LogMessage> mfMessages = new
+       // ArrayList<LogMessage>();
+       private LogMessage[] buffer = new LogMessage[STRING_BUFFER_LENGTH];
+
+       private LogMessageInfo lastMessageInfo = null;
+       private boolean mPendingAsyncRefresh = false;
+
+       private boolean supportsDelete = true;
+       private boolean supportsEdit = true;
+       private int mRemovedMessageCount = 0;
+
+       /** Represents the oldest message in the buffer */
+       private int indexStart = -1;
+
+       /**
+        * Represents the next usable item in the buffer to receive new message.
+        * This can be equal to indexStart, but when used indexStart will be
+        * incremented as well.
+        */
+       private int indexEnd = -1;
+
+       /**
+        * Creates a filter with a particular mode.
+        * 
+        * @param name
+        *            The name to be displayed in the UI
+        */
+       public LogTab(String name, IDevice device, LogColors colors) {
+               filterName = name;
+               filterDevice = device;
+               this.colors = colors;
+       }
+
+       public LogTab() {
+       }
+
+       /** Sets the name of the filter. */
+       void setFilterName(String name) {
+               filterName = name;
+       }
+
+       /**
+        * Returns the UI display name.
+        */
+       public String getFilterName() {
+               return filterName;
+       }
+       
+       public String getFilterWord()
+       {
+               return filterWord;
+       }
+       
+       public String getFilterDeviceName()
+       {
+               return filterDevice.getSerialNumber();
+       }
+
+       /**
+        * Set the Table ui widget associated with this filter.
+        * 
+        * @param tabItem
+        *            The item in the TabFolder
+        * @param table
+        *            The Table object
+        */
+       public void setWidgets(TabItem tabItem, Table table) {
+               this.table = table;
+               this.tabItem = tabItem;
+       }
+
+       /**
+        * Returns true if the filter is ready for ui.
+        */
+       public boolean uiReady() {
+               return (table != null && tabItem != null);
+       }
+
+       /**
+        * Returns the UI table object.
+        * 
+        * @return
+        */
+       public Table getTable() {
+               return table;
+       }
+
+       public void dispose() {
+               table.dispose();
+               tabItem.dispose();
+               table = null;
+               tabItem = null;
+       }
+
+       /**
+        * Returns the current filtering mode.
+        * 
+        * @return A bitmask. Possible values are MODE_PID, MODE_TAG, MODE_LEVEL
+        */
+       public int getFilteringMode() {
+               return filterMode;
+       }
+       
+       /**
+        * Starts a new LogTab and set mCurrentLogTab as the current receiver.
+        * 
+        * @param device
+        *            the device to connect LogTab to.
+        */
+       public void startLogTab() {
+
+               // if (device == filterDevice) {
+               // return;
+               // }
+
+               // if we have a LogTab already running
+               // if (filterDevice != null) {
+               // stopLogTab(false);
+               // filterDevice = null;
+               // }
+               resetUI(false);
+
+               if (filterDevice != null) {
+
+                       // create a new output receiver
+                       logger = new LogTabOuputReceiver();
+
+                       // start the LogTab in a different thread
+                       new Thread(filterDevice.getSerialNumber() + " Logger") { //$NON-NLS-1$
+                               @Override
+                               public void run() {
+
+                                       while (filterDevice.isOnline() == false && logger != null
+                                                       && logger.isCancelled == false) {
+                                               try {
+                                                       sleep(2000);
+                                               } catch (InterruptedException e) {
+                                                       Log.e("LogTab",
+                                                                       "Device is not online or logger is null/cancelled");
+                                                       return;
+                                               }
+                                       }
+
+                                       if (logger == null || logger.isCancelled) {
+                                               // LogTab was stopped/cancelled before
+                                               // the device became ready.
+                                               return;
+                                       }
+
+                                       try {
+
+                                               filterDevice.executeShellCommand(
+                                                               "dlogutil -v long *:v", logger, 0 /* timeout */); //$NON-NLS-1$
+                                       } catch (Exception e) {
+                                               Log.e("LogTab", e);
+                                       } finally {
+                                               // at this point the command is
+                                               // terminated.
+                                               logger = null;
+                                               filterDevice = null;
+                                       }
+                               }
+                       }.start();
+               }
+       }
+
+       /** Stop the current LogTab */
+       public void stopLogTab(boolean inUiThread) {
+               if (logger != null) {
+                       logger.isCancelled = true;
+
+                       // when the thread finishes, no one will reference that
+                       // object
+                       // and it'll be destroyed
+                       logger = null;
+
+//                     // reset the content buffer
+//                     for (int i = 0; i < STRING_BUFFER_LENGTH; i++) {
+//                             buffer[i] = null;
+//                     }
+//
+//                     // because it's a circular buffer, it's hard to know if
+//                     // the array is empty with both start/end at 0 or if it's
+//                     // full
+//                     // with both start/end at 0 as well. So to mean empty, we
+//                     // use -1
+//                     indexStart = -1;
+//                     indexEnd = -1;
+                       clear();
+
+                       // resetFilters();
+                       resetUI(inUiThread);
+               }
+       }
+
+       public boolean supportsDelete() {
+               return supportsDelete;
+       }
+
+       public void setSupportsDelete(boolean support) {
+               supportsDelete = support;
+       }
+
+       public boolean supportsEdit() {
+               return supportsEdit;
+       }
+
+       public void setSupportsEdit(boolean support) {
+               supportsEdit = support;
+       }
+
+       /**
+        * Sets the selected state of the filter.
+        * 
+        * @param selected
+        *            selection state.
+        */
+       public void setSelectedState(boolean selected) {
+               if (selected) {
+                       if (tabItem != null) {
+                               tabItem.setText(filterName);
+                       }
+                       mUnreadCount = 0;
+               }
+               mIsCurrentTabItem = selected;
+       }
+
+       /**
+        * Adds a new message and optionally removes an old message.
+        * <p/>
+        * The new message is filtered through {@link #accept(LogMessage)}. Calls to
+        * {@link #flush()} from a UI thread will display it (and other pending
+        * messages) to the associated {@link Table}.
+        * 
+        * @param logMessage
+        *            the MessageData object to filter
+        * @return true if the message was accepted.
+        */
+       public boolean addMessage(LogMessage newMessage, LogMessage oldMessage) {
+               synchronized (tableMessages) {
+                       if (oldMessage != null) {
+                               int index = tableMessages.indexOf(oldMessage);
+                               if (index != -1) {
+                                       // TODO check that index will always be -1 or
+                                       // 0, as only the oldest message is ever
+                                       // removed.
+                                       tableMessages.remove(index);
+                                       mRemovedMessageCount++;
+                               }
+
+                               // now we look for it in mNewMessages. This can
+                               // happen if the new message is added
+                               // and then removed because too many messages are
+                               // added between calls to #flush()
+                               index = tableMessages.indexOf(oldMessage);
+                               if (index != -1) {
+                                       // TODO check that index will always be -1 or
+                                       // 0, as only the oldest message is ever
+                                       // removed.
+                                       tableMessages.remove(index);
+                               }
+                       }
+
+                       boolean filter = accept(newMessage);
+
+                       if (filter) {
+                               // at this point the message is accepted, we add it
+                               // to the list
+                               tableMessages.add(newMessage);
+                               newMessages.add(newMessage);
+                       }
+
+                       return filter;
+               }
+       }
+
+
+       /**
+        * Filters a message.
+        * 
+        * @param logMessage
+        *            the Message
+        * @return true if the message is accepted by the filter.
+        */
+       boolean accept(LogMessage logMessage) {
+               if (logMessage == null)
+                       return false;
+
+               if (levelMode != LEVEL_NONE) {
+                       int a = 0;
+                       a = (levelMode & (0x1 << (logMessage.data.logLevel.getPriority() - 2)));
+
+                       if (a == 0)
+                               return false;
+               }
+
+               if (filterMode != FILTER_NONE && filterWord != null) {
+                       if ((filterMode & FILTER_PID) != 0) {
+                               if (!Integer.toString(logMessage.data.pid).contains(filterWord))
+                                       return false;
+                       }
+
+                       if ((filterMode & FILTER_TAG) != 0) {
+                               if (!logMessage.data.tag.contains(filterWord))
+                                       return false;
+                       }
+
+                       if ((filterMode & FILTER_MSG) != 0) {
+                               if (!logMessage.msg.toLowerCase().contains(
+                                               filterWord.toLowerCase()))
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Takes all the accepted messages and display them. This must be called
+        * from a UI thread.
+        */
+       // @UiThread
+       public void flush() {
+
+               // if scroll bar is at the bottom, we will scroll
+               ScrollBar bar = table.getVerticalBar();
+               boolean scroll = bar.getMaximum() == bar.getSelection()
+                               + bar.getThumb();
+
+               // if we are not going to scroll, get the current first item being
+               // shown.
+               int topIndex = table.getTopIndex();
+
+               // disable drawing
+               table.setRedraw(false);
+
+               int totalCount = newMessages.size();
+
+               try {
+                       // remove the items of the old messages.
+                       for (int i = 0; i < mRemovedMessageCount
+                                       && table.getItemCount() > 0; i++) {
+                               table.remove(0);
+                       }
+
+                       // add the new items
+                       for (int i = 0; i < totalCount; i++) {
+                               LogMessage msg = newMessages.get(i);
+                               addTableItem(msg);
+                       }
+               } catch (SWTException e) {
+                       // log the error and keep going. Content of the LogTab
+                       // table maybe unexpected
+                       // but at least ddms won't crash.
+                       Log.e("LogFilter", e);
+               }
+
+               // redraw
+               table.setRedraw(true);
+
+               // scroll if needed, by showing the last item
+               if (scroll) {
+                       totalCount = table.getItemCount();
+                       if (totalCount > 0) {
+                               table.showItem(table.getItem(totalCount - 1));
+                       }
+               } else if (mRemovedMessageCount > 0) {
+                       // we need to make sure the topIndex is still visible.
+                       // Because really old items are removed from the list, this
+                       // could make it disappear
+                       // if we don't change the scroll value at all.
+
+                       topIndex -= mRemovedMessageCount;
+                       if (topIndex < 0) {
+                               // looks like it disappeared. Lets just show the
+                               // first item
+                               table.showItem(table.getItem(0));
+                       } else {
+                               table.showItem(table.getItem(topIndex));
+                       }
+               }
+
+               newMessages.clear();
+               mRemovedMessageCount = 0;
+
+       }
+
+       void setColors(LogColors colors) {
+               this.colors = colors;
+       }
+
+       int getUnreadCount() {
+               return mUnreadCount;
+       }
+
+       void setUnreadCount(int unreadCount) {
+               mUnreadCount = unreadCount;
+       }
+
+       /**
+        * Add a TableItem for the index-th item of the buffer
+        * 
+        * @param filter
+        *            The index of the table in which to insert the item.
+        */
+       private void addTableItem(LogMessage msg) {
+               TableItem item = new TableItem(table, SWT.NONE);
+               item.setText(0, msg.data.time);
+               item.setText(1,
+                               new String(new char[]{msg.data.logLevel.getPriorityLetter()}));
+               item.setText(2, msg.data.pidString);
+               item.setText(3, msg.data.tag);
+               item.setText(4, msg.msg);
+
+               // add the buffer index as data
+               item.setData(msg);
+
+               if (msg.data.logLevel == LogLevel.INFO) {
+                       item.setForeground(colors.infoColor);
+               } else if (msg.data.logLevel == LogLevel.DEBUG) {
+                       item.setForeground(colors.debugColor);
+               } else if (msg.data.logLevel == LogLevel.ERROR) {
+                       item.setForeground(colors.errorColor);
+               } else if (msg.data.logLevel == LogLevel.WARN) {
+                       item.setForeground(colors.warningColor);
+               } else {
+                       item.setForeground(colors.verboseColor);
+               }
+       }
+
+       /**
+        * objects able to receive the output of a remote shell command,
+        * specifically a LogTab command in this case
+        */
+       private final class LogTabOuputReceiver extends MultiLineReceiver {
+
+               public boolean isCancelled = false;
+
+               public LogTabOuputReceiver() {
+                       super();
+
+                       setTrimLine(false);
+               }
+
+               @Override
+               public void processNewLines(String[] lines) {
+                       if (isCancelled == false) {
+                               processLogLines(lines);
+                       }
+               }
+
+               public boolean isCancelled() {
+                       return isCancelled;
+               }
+       }
+
+       /**
+        * Process new Log lines coming from {@link LogCatOuputReceiver}.
+        * 
+        * @param lines
+        *            the new lines
+        */
+       protected void processLogLines(String[] lines) {
+               // WARNING: this will not work if the string contains more line
+               // than
+               // the buffer holds.
+
+               if (lines.length > STRING_BUFFER_LENGTH) {
+                       Log.e("LogTab", "Receiving more lines than STRING_BUFFER_LENGTH");
+               }
+
+               // parse the lines and create LogMessage that are stored in a
+               // temporary list
+               final ArrayList<LogMessage> newMessages = new ArrayList<LogMessage>();
+
+               synchronized (buffer) {
+                       for (String line : lines) {
+                               // ignore empty lines.
+                               if (line.length() > 0) {
+                                       // check for header lines.
+                                       Matcher matcher = logPattern.matcher(line);
+                                       if (matcher.matches()) {
+                                               // this is a header line, parse the
+                                               // header and keep it around.
+                                               lastMessageInfo = new LogMessageInfo();
+
+                                               lastMessageInfo.time = matcher.group(1);
+                                               lastMessageInfo.pidString = matcher.group(2);
+                                               lastMessageInfo.pid = Integer
+                                                               .valueOf(lastMessageInfo.pidString);
+                                               lastMessageInfo.logLevel = LogLevel
+                                                               .getByLetterString(matcher.group(4));
+                                               lastMessageInfo.tag = matcher.group(5).trim();
+                                       } else {
+                                               // This is not a header line.
+                                               // Create a new LogMessage and process
+                                               // it.
+                                               LogMessage mc = new LogMessage();
+
+                                               if (lastMessageInfo == null) {
+                                                       return;
+                                               }
+
+                                               // If someone printed a log message
+                                               // with
+                                               // embedded '\n' characters, there
+                                               // will
+                                               // one header line followed by
+                                               // multiple text lines.
+                                               // Use the last header that we saw.
+                                               mc.data = lastMessageInfo;
+
+                                               // tabs seem to display as only 1 tab
+                                               // so we replace the leading tabs
+                                               // by 4 spaces.
+                                               mc.msg = line.replaceAll("\t", "    "); //$NON-NLS-1$ //$NON-NLS-2$
+
+                                               // process the new LogMessage.
+                                               processNewMessage(mc);
+
+                                               // store the new LogMessage
+                                               newMessages.add(mc);
+                                       }
+                               }
+                       }
+
+                       // if we don't have a pending Runnable that will do the
+                       // refresh, we
+                       // ask the Display
+                       // to run one in the UI thread.
+                       if (mPendingAsyncRefresh == false) {
+                               mPendingAsyncRefresh = true;
+
+                               try {
+                                       Display display = table.getDisplay();
+
+                                       // run in sync because this will update the
+                                       // buffer start/end indices
+                                       display.asyncExec(new Runnable() {
+                                               public void run() {
+                                                       asyncRefresh();
+                                               }
+                                       });
+                               } catch (SWTException e) {
+                                       // display is disposed, we're probably
+                                       // quitting. Let's stop.
+                                       stopLogTab(false);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Processes a new Message.
+        * <p/>
+        * This adds the new message to the buffer, and gives it to the existing
+        * filters.
+        * 
+        * @param newMessage
+        */
+       private void processNewMessage(LogMessage newMessage) {
+               // // if we are in auto filtering mode, make sure we have
+               // // a filter for this
+
+               // compute the index where the message goes.
+               // was the buffer empty?
+               int messageIndex = -1;
+               if (indexStart == -1) {
+                       messageIndex = indexStart = 0;
+                       indexEnd = 1;
+               } else {
+                       messageIndex = indexEnd;
+
+                       // check we aren't overwriting start
+                       if (indexEnd == indexStart) {
+                               indexStart = (indexStart + 1) % STRING_BUFFER_LENGTH;
+                       }
+
+                       // increment the next usable slot index
+                       indexEnd = (indexEnd + 1) % STRING_BUFFER_LENGTH;
+               }
+
+               LogMessage oldMessage = null;
+
+               // record the message that was there before
+               if (buffer[messageIndex] != null) {
+                       oldMessage = buffer[messageIndex];
+               }
+
+               // then add the new one
+               buffer[messageIndex] = newMessage;
+
+               synchronized (tableMessages) {
+                       if (oldMessage != null) {
+                               if (tableMessages.size() > STRING_BUFFER_LENGTH) {
+                                       int index = tableMessages.indexOf(oldMessage);
+                                       if (index != -1) {
+                                               // TODO check that index will always
+                                               // be -1 or 0, as only the oldest
+                                               // message is ever removed.
+                                               tableMessages.remove(index);
+                                               mRemovedMessageCount++;
+                                       }
+                               }
+                       }
+               }
+
+               boolean filter = accept(newMessage);
+               if (filter) {
+                       // at this point the message is accepted, we add it to the
+                       // list
+                       tableMessages.add(newMessage);
+                       newMessages.add(newMessage);
+                       // autosave( newMessage );
+               }
+
+       }
+
+       /**
+        * Refreshes the UI with new messages.
+        */
+       private void asyncRefresh() {
+               if (table.isDisposed() == false) {
+                       synchronized (buffer) {
+                               try {
+                                       // the circular buffer has been updated, let
+                                       // have the filter flush
+                                       // their display with the new messages.
+                                       flush();
+
+                               } finally {
+                                       // the pending refresh is done.
+                                       mPendingAsyncRefresh = false;
+                               }
+                       }
+               } else {
+                       stopLogTab(true);
+               }
+       }
+
+       public void resetUI(boolean inUiThread) {
+
+               // the ui is static we just empty it.
+               if (table.isDisposed() == false) {
+                       if (inUiThread) {
+                               table.removeAll();
+                       } else {
+                               Display d = table.getDisplay();
+
+                               // run sync as we need to update right now.
+                               d.syncExec(new Runnable() {
+                                       public void run() {
+                                               if (table.isDisposed() == false) {
+                                                       table.removeAll();
+                                               }
+                                       }
+                               });
+                       }
+               }
+       }
+
+       public void initTab() {
+
+               // is it empty
+               if (uiReady() == false) {
+                       return;
+               }
+
+               msgClear();
+
+               if (indexStart != -1) {
+                       int max = indexEnd;
+                       if (indexEnd < indexStart) {
+                               max += STRING_BUFFER_LENGTH;
+                       }
+
+                       for (int i = indexStart; i < max; i++) {
+                               int realItemIndex = i % STRING_BUFFER_LENGTH;
+
+                               addMessage(buffer[realItemIndex], null /*
+                                                                                                                * old message
+                                                                                                                */);
+                       }
+               }
+
+               flush();
+       }
+
+       public void refill() {
+               msgClear();
+
+               synchronized (buffer) {
+                       for (LogMessage logMsg : buffer) {
+                               if (accept(logMsg)) {
+                                       newMessages.add(logMsg);
+                               }
+                       }
+               }
+               flush();
+       }
+       
+       public void setLevel(int level, boolean setLevel) {
+               level = (int) Math.pow(2, level);
+               if (setLevel)
+                       levelMode |= level;
+               else
+                       levelMode &= (~level);
+       }
+
+       public void msgClear() {
+               mRemovedMessageCount = 0;
+               newMessages.clear();
+               lastMessageInfo = null;
+               tableMessages.clear();
+               if( table.isDisposed() == false )
+                       table.removeAll();
+       }
+       
+       public void clear() {
+               for (int i = 0; i < STRING_BUFFER_LENGTH; i++) {
+                       buffer[i] = null;
+               }
+
+               indexStart = -1;
+               indexEnd = -1;
+
+               msgClear();
+       }
+
+       public void setFilterWord(String word) {
+               filterWord = word;
+       }
+
+       public void setFilterMode(int mode) {
+               filterMode = mode;
+       }
+       
+       public void setDevice( IDevice device )
+       {
+               filterDevice = device;
+       }
+       
+       
+       
+}
\ No newline at end of file
index fee290a..c3fdada 100644 (file)
@@ -29,442 +29,471 @@ import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.actions.ActionFactory;
 import org.eclipse.ui.part.ViewPart;
 
-import com.samsung.tizen.common.connection.ConnectionPlugin;
-import com.samsung.tizen.common.connection.ConnectionPlugin.ISelectionListener;
 import com.samsung.tizen.common.connection.ddmuilib.ImageLoader;
 import com.samsung.tizen.common.connection.log.LogColors;
 import com.samsung.tizen.common.connection.log.LogPanel;
-import com.samsung.tizen.sdblib.FileListingService.FileEntry;
-import com.samsung.tizen.sdblib.IDevice;
 import com.samsung.tizen.sdblib.Log.LogLevel;
 
 /**
  * The log cat view displays log output from the current device selection.
- *
+ * 
  */
-public final class LogView extends ViewPart implements ISelectionListener {
-
-    public static final String ID =
-        "com.samsung.tizen.common.connection.ui.LogView"; //$NON-NLS-1$
-
-    public static final String CHOICE_METHOD_DECLARATION =
-        ID + ".logview.MethodDeclaration"; //$NON-NLS-1$
-    public static final String CHOICE_ERROR_LINE =
-        ID + ".logview.ErrorLine"; //$NON-NLS-1$
-
-    /* Default values for the switch of perspective. */
-    public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true;
-    public static final String DEFAULT_PERSPECTIVE_ID =
-        "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$
-
-    private LogPanel mLogPanel;
-
-    public static LogView newLogView;
-    private Action addAction;
-    private Action exportAction;
-    private Action clearAction;
-//    private Action mGotoMethodDeclarationAction;
-//    private Action mGotoErrorLineAction;
-
-    private Action[] mLogLevelActions;
-    private String[] mLogLevelIcons = {
-            "v.png", //$NON-NLS-1S
-            "d.png", //$NON-NLS-1S
-            "i.png", //$NON-NLS-1S
-            "e.png", //$NON-NLS-1S
-            "w.png", //$NON-NLS-1S
-    };
-
-//    private Action mClearAction;
-
-    private Clipboard mClipboard;
-    
-    public static int viewCnt = 0;
-          
-
-    /**
-     * An implementation of {@link ILogFilterStorageManager} to bridge to the eclipse preference
-     * store, and saves the log filters.
-     */
-//    private final class FilterStorage implements ILogFilterStorageManager {
-//
-//        public LogFilter[] getFilterFromStore() {
-//            String filterPrefs = DdmsPlugin.getDefault().getPreferenceStore().getString(
-//                    PREFS_FILTERS);
-//
-//            // split in a string per filter
-//            String[] filters = filterPrefs.split("\\|"); //$NON-NLS-1$
-//
-//            ArrayList<LogFilter> list =
-//                new ArrayList<LogFilter>(filters.length);
-//
-//            for (String f : filters) {
-//                if (f.length() > 0) {
-//                    LogFilter logFilter = new LogFilter();
-//                    if (logFilter.loadFromString(f)) {
-//                        list.add(logFilter);
-//                    }
-//                }
-//            }
-//
-//            return list.toArray(new LogFilter[list.size()]);
-//        }
-//
-//        public void saveFilters(LogFilter[] filters) {
-//            StringBuilder sb = new StringBuilder();
-//            for (LogFilter f : filters) {
-//                String filterString = f.toString();
-//                sb.append(filterString);
-//                sb.append('|');
-//            }
-//
-//            DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS, sb.toString());
-//        }
-//
-//        public boolean requiresDefaultFilter() {
-//            return true;
-//        }
-//    }
-
-    /**
-     * This class defines what to do with the search match returned by a double-click or by the
-     * Go to Problem action.
-     */
-//    private class LogViewSearchRequestor extends SearchRequestor {
-//
-//        private boolean mFoundFirstMatch = false;
-//        private String mChoice;
-//        private int mLineNumber;
-//
-//        public LogViewSearchRequestor(String choice, int lineNumber) {
-//            super();
-//            mChoice = choice;
-//            mLineNumber = lineNumber;
-//        }
-//
-//        IMarker createMarkerFromSearchMatch(IFile file, SearchMatch match) {
-//            IMarker marker = null;
-//            try {
-//                if (CHOICE_METHOD_DECLARATION.equals(mChoice)) {
-//                    HashMap<String, Object> map = new HashMap<String, Object>();
-//                    map.put(IMarker.CHAR_START, new Integer(match.getOffset()));
-//                    map.put(IMarker.CHAR_END, new Integer(match.getOffset()
-//                            + match.getLength()));
-//                    marker = file.createMarker(IMarker.TEXT);
-//                    marker.setAttributes(map);
-//                } else if (CHOICE_ERROR_LINE.equals(mChoice)) {
-//                    marker = file.createMarker(IMarker.TEXT);
-//                    marker.setAttribute(IMarker.LINE_NUMBER, mLineNumber);
-//                }
-//            } catch (CoreException e) {
-//                Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
-//                DdmsPlugin.getDefault().getLog().log(s);
-//            }
-//            return marker;
-//        }
-//
-//        @Override
-//        public void acceptSearchMatch(SearchMatch match) throws CoreException {
-//            if (match.getResource() instanceof IFile && !mFoundFirstMatch) {
-//                mFoundFirstMatch = true;
-//                IFile matched_file = (IFile) match.getResource();
-//                IMarker marker = createMarkerFromSearchMatch(matched_file, match);
-//                // There should only be one exact match,
-//                // so we go immediately to that one.
-//                if (marker != null) {
-//                    switchPerspective();
-//                    openFile(matched_file, marker);
-//                }
-//            }
-//        }
-//    }
-
-    public LogView() {
-               newLogView = this;
-    }
-
-    @Override
-    public void createPartControl(Composite parent) {
-        Display d = parent.getDisplay();
-        LogColors colors = new LogColors();
-
-        ImageLoader loader = ImageLoader.getDdmUiLibLoader();
-
-        colors.infoColor = new Color(d, 0, 127, 0);
-        colors.debugColor = new Color(d, 0, 0, 127);
-        colors.errorColor = new Color(d, 255, 0, 0);
-        colors.warningColor = new Color(d, 255, 127, 0);
-        colors.verboseColor = new Color(d, 0, 0, 0);
-
-        addAction = new Action("add View") {
-            @Override
-            public void run() {
-                mLogPanel.addView();
-            }
-        };
-        addAction.setToolTipText("Add View");
-        addAction.setImageDescriptor(loader.loadDescriptor("add_tab.png"));
-
-        exportAction = new Action("Export Log") {
-            @Override
-            public void run() {
-                mLogPanel.save();
-            }
-        };
-        exportAction.setToolTipText("Export Log");
-        exportAction.setImageDescriptor(loader.loadDescriptor("Export Log.gif")); //$NON-NLS-1$
-
-        clearAction = new Action("Clear Log") {
-            @Override
-            public void run() {
-                mLogPanel.clear();
-            }
-        };
-        clearAction.setToolTipText("Clear Log");
-        clearAction.setImageDescriptor(loader.loadDescriptor("Clear Log.gif")); //$NON-NLS-1$
-        
-        
-//        mGotoMethodDeclarationAction = new CommonAction("Go to Problem (method declaration)") {
-//            @Override
-//            public void run() {
-//                goToErrorLine(CHOICE_METHOD_DECLARATION);
-//            }
-//        };
-//
-//        mGotoErrorLineAction = new CommonAction("Go to Problem (error line)") {
-//            @Override
-//            public void run() {
-//                goToErrorLine(CHOICE_ERROR_LINE);
-//            }
-//        };
-
-        LogLevel[] levels = LogLevel.values();
-        mLogLevelActions = new Action[mLogLevelIcons.length];
-        for (int i = 0 ; i < mLogLevelActions.length; i++) {
-            String name = levels[i].getStringValue();
-            mLogLevelActions[i] = new Action(name, IAction.AS_CHECK_BOX) {
-                @Override
-                public void run() {
-                    // disable the other actions and record current index
-                    for (int i = 0 ; i < mLogLevelActions.length; i++) {
-                        Action a = mLogLevelActions[i];
-                        if (a == this) {
-                          if( a.isChecked())
-                                  a.setChecked( a.isChecked() );
-                                  mLogPanel.setLevel(i , a.isChecked());
-                                  mLogPanel.refill();                                     
-                                                                               }
-                                                                       }
-                }
-            };
-
-            mLogLevelActions[i].setToolTipText(name);
-            mLogLevelActions[i].setImageDescriptor(loader.loadDescriptor(mLogLevelIcons[i]));
-        }
-
-
-        // now create the log view
-        mLogPanel = new LogPanel(colors);
-        mLogPanel.setActions(mLogLevelActions);
-
-        // get the font
-//        String fontStr = DdmsPlugin.getDefault().getPreferenceStore().getString(
-//                PreferenceInitializer.ATTR_LOGCAT_FONT);
-//        if (fontStr != null) {
-//            FontData data = new FontData(fontStr);
-//
-//            if (fontStr != null) {
-//                mLogPanel.setFont(new Font(parent.getDisplay(), data));
-//            }
-//        }
-
-        mLogPanel.createPanel(parent);
-        ConnectionPlugin.getDefault().addSelectionListener(this);
-
-        // place the actions.
-        placeActions();
-
-        // setup the copy action
-        mClipboard = new Clipboard(d);
-        IActionBars actionBars = getViewSite().getActionBars();
-        actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action("Copy") {
-            @Override
-            public void run() {
-                mLogPanel.copy(mClipboard);
-            }
-        });
-
-        // setup the select all action
-        actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
-                new Action("Select All") {
-            @Override
-            public void run() {
-                mLogPanel.selectAll();
-            }
-        });
-        setActionEnabled( false );
-
-        IDevice device = ConnectionPlugin.getDefault().getCurrentDevice();
-        if( device != null )
-                selectionChanged( device.getFileListingService().getRoot() );       
-        
-    }
-
-    @Override
-    public void dispose() {
-        mLogPanel.stopLogCat(true);
-        mClipboard.dispose();
-    }
-
-    @Override
-    public void setFocus() {
-        mLogPanel.setFocus();
-    }
-
-    /**
-     * Place the actions in the ui.
-     */
-    private void placeActions() {
-        IActionBars actionBars = getViewSite().getActionBars();
-
-        // first in the menu
-        IMenuManager menuManager = actionBars.getMenuManager();
-        menuManager.add(addAction);
-        menuManager.add(new Separator());
-        menuManager.add(exportAction);
-        menuManager.add(clearAction);        
-        menuManager.add(new Separator());
-//        menuManager.add(mGotoMethodDeclarationAction);
-//        menuManager.add(mGotoErrorLineAction);
-
-        // and then in the toolbar
-        IToolBarManager toolBarManager = actionBars.getToolBarManager();
-        toolBarManager.add(new Separator());
-        for (Action a : mLogLevelActions) {
-            toolBarManager.add(a);
-        }
-        toolBarManager.add(new Separator());
-        toolBarManager.add(addAction);
-        toolBarManager.add(new Separator());
-        toolBarManager.add(exportAction);
-        toolBarManager.add(clearAction);
-        toolBarManager.add(new Separator());
-    }
-    
-    @Override
-    public void selectionChanged(FileEntry selectedEntry) {
-           mLogPanel.deviceSelected(selectedEntry);
-           if( selectedEntry != null )
-                   setActionEnabled(true);
-        
-           }
-    
-    public LogPanel getPanel()
-    {
-           return mLogPanel;
-    }
-    
-    private void setActionEnabled(boolean on)
-    {
-           exportAction.setEnabled(on);
-           clearAction.setEnabled(on);
-           for( Action a :  mLogLevelActions)
-           {
-                   a.setEnabled(on);
-           }
-           
-    }
-
-//    void openFile(IFile file, IMarker marker) {
-//        try {
-//            IWorkbenchPage page = getViewSite().getWorkbenchWindow()
-//                    .getActivePage();
-//            if (page != null) {
-//                IDE.openEditor(page, marker);
-//                marker.delete();
-//            }
-//        } catch (CoreException e) {
-//            Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
-//            DdmsPlugin.getDefault().getLog().log(s);
-//        }
-//    }
-
-//    void switchPerspective() {
-//        IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
-//        if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) {
-//            IWorkbench workbench = PlatformUI.getWorkbench();
-//            IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
-//            IPerspectiveRegistry perspectiveRegistry = workbench.getPerspectiveRegistry();
-//            String perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID);
-//            if (perspectiveId != null
-//                    && perspectiveId.length() > 0
-//                    && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) {
-//                try {
-//                    workbench.showPerspective(perspectiveId, window);
-//                } catch (WorkbenchException e) {
-//                    e.printStackTrace();
-//                }
-//            }
-//        }
-//    }
-
-//    void goToErrorLine() {
-//        IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
-//        String value = store.getString(PreferenceInitializer.ATTR_LOGCAT_GOTO_PROBLEM);
-//        goToErrorLine(value);
-//    }
-
-//    void goToErrorLine(String choice) {
-//        try {
-//            String msg = mLogPanel.getSelectedErrorLineMessage();
-//            if (msg != null) {
-//                String error_line_matcher_string = "\\s*at\\ (.*)\\((.*)\\.java\\:(\\d+)\\)";
-//                Matcher error_line_matcher = Pattern.compile(
-//                        error_line_matcher_string).matcher(msg);
-//
-//                if (error_line_matcher.find()) {
-//                    String class_name_method = error_line_matcher.group(1);
-//
-//                    // TODO: Search currently only matches the class declaration (using
-//                    // IJavaSearchConstants.DECLARATIONS). We may want to jump to the
-//                    // "reference" of the class instead (IJavaSearchConstants.REFERENCES)
-//                    // using the filename and line number to disambiguate the search results.
-//                    String class_name_line = error_line_matcher.group(2);
-//                    int line_number = Integer.parseInt(error_line_matcher.group(3));
-//
-//                    SearchEngine se = new SearchEngine();
-//                    if (CHOICE_ERROR_LINE.equals(choice)) {
-//                        se.search(SearchPattern.createPattern(class_name_line,
-//                                IJavaSearchConstants.CLASS,
-//                                IJavaSearchConstants.DECLARATIONS,
-//                                SearchPattern.R_EXACT_MATCH
-//                                | SearchPattern.R_CASE_SENSITIVE),
-//                                new SearchParticipant[] { SearchEngine
-//                            .getDefaultSearchParticipant() },
-//                            SearchEngine.createWorkspaceScope(),
-//                            new LogViewSearchRequestor(CHOICE_ERROR_LINE, line_number),
-//                            new NullProgressMonitor());
-//                    } else if (CHOICE_METHOD_DECLARATION.equals(choice)) {
-//                        se.search(SearchPattern.createPattern(class_name_method,
-//                                IJavaSearchConstants.METHOD,
-//                                IJavaSearchConstants.DECLARATIONS,
-//                                SearchPattern.R_EXACT_MATCH
-//                                | SearchPattern.R_CASE_SENSITIVE),
-//                                new SearchParticipant[] { SearchEngine
-//                            .getDefaultSearchParticipant() },
-//                            SearchEngine.createWorkspaceScope(),
-//                            new LogViewSearchRequestor(CHOICE_METHOD_DECLARATION, 0),
-//                            new NullProgressMonitor());
-//                    }
-//                }
-//            }
-//        } catch (Exception e) {
-//            Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
-//            DdmsPlugin.getDefault().getLog().log(s);
-//        }
-//    }
-
-//    public void onDoubleClick() {
-//        goToErrorLine();
-//    }
-}
+public final class LogView extends ViewPart {
+
+       public static final String ID = "com.samsung.tizen.common.connection.ui.LogView"; //$NON-NLS-1$
+
+       public static final String CHOICE_METHOD_DECLARATION = ID + ".logview.MethodDeclaration"; //$NON-NLS-1$
+       public static final String CHOICE_ERROR_LINE = ID + ".logview.ErrorLine"; //$NON-NLS-1$
+
+       /* Default values for the switch of perspective. */
+       public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true;
+       public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$
+
+       private LogPanel mLogPanel;
+
+       public static LogView newLogView;
+       private static Action addAction;
+       private static Action removeAction;
+       private static Action editAction;
+       private static Action exportAction;
+       private static Action clearAction;
+       // private Action mGotoMethodDeclarationAction;
+       // private Action mGotoErrorLineAction;
+
+       private static Action[] mLogLevelActions;
+       private String[] mLogLevelIcons = { "v.png", //$NON-NLS-1S
+                       "d.png", //$NON-NLS-1S
+                       "i.png", //$NON-NLS-1S
+                       "e.png", //$NON-NLS-1S
+                       "w.png", //$NON-NLS-1S
+       };
+
+       // private Action mClearAction;
+
+       private Clipboard mClipboard;
+
+//     public static int viewCnt = 0;
+
+       /**
+        * An implementation of {@link ILogFilterStorageManager} to bridge to the
+        * eclipse preference store, and saves the log filters.
+        */
+       // private final class FilterStorage implements ILogFilterStorageManager
+       // {
+       //
+       // public LogFilter[] getFilterFromStore() {
+       // String filterPrefs =
+       // DdmsPlugin.getDefault().getPreferenceStore().getString(
+       // PREFS_FILTERS);
+       //
+       // // split in a string per filter
+       //            String[] filters = filterPrefs.split("\\|"); //$NON-NLS-1$
+       //
+       // ArrayList<LogFilter> list =
+       // new ArrayList<LogFilter>(filters.length);
+       //
+       // for (String f : filters) {
+       // if (f.length() > 0) {
+       // LogFilter logFilter = new LogFilter();
+       // if (logFilter.loadFromString(f)) {
+       // list.add(logFilter);
+       // }
+       // }
+       // }
+       //
+       // return list.toArray(new LogFilter[list.size()]);
+       // }
+       //
+       // public void saveFilters(LogFilter[] filters) {
+       // StringBuilder sb = new StringBuilder();
+       // for (LogFilter f : filters) {
+       // String filterString = f.toString();
+       // sb.append(filterString);
+       // sb.append('|');
+       // }
+       //
+       // DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS,
+       // sb.toString());
+       // }
+       //
+       // public boolean requiresDefaultFilter() {
+       // return true;
+       // }
+       // }
+
+       /**
+        * This class defines what to do with the search match returned by a
+        * double-click or by the Go to Problem action.
+        */
+       // private class LogViewSearchRequestor extends SearchRequestor {
+       //
+       // private boolean mFoundFirstMatch = false;
+       // private String mChoice;
+       // private int mLineNumber;
+       //
+       // public LogViewSearchRequestor(String choice, int lineNumber) {
+       // super();
+       // mChoice = choice;
+       // mLineNumber = lineNumber;
+       // }
+       //
+       // IMarker createMarkerFromSearchMatch(IFile file, SearchMatch match) {
+       // IMarker marker = null;
+       // try {
+       // if (CHOICE_METHOD_DECLARATION.equals(mChoice)) {
+       // HashMap<String, Object> map = new HashMap<String, Object>();
+       // map.put(IMarker.CHAR_START, new Integer(match.getOffset()));
+       // map.put(IMarker.CHAR_END, new Integer(match.getOffset()
+       // + match.getLength()));
+       // marker = file.createMarker(IMarker.TEXT);
+       // marker.setAttributes(map);
+       // } else if (CHOICE_ERROR_LINE.equals(mChoice)) {
+       // marker = file.createMarker(IMarker.TEXT);
+       // marker.setAttribute(IMarker.LINE_NUMBER, mLineNumber);
+       // }
+       // } catch (CoreException e) {
+       // Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID,
+       // e.getMessage(), e);
+       // DdmsPlugin.getDefault().getLog().log(s);
+       // }
+       // return marker;
+       // }
+       //
+       // @Override
+       // public void acceptSearchMatch(SearchMatch match) throws CoreException
+       // {
+       // if (match.getResource() instanceof IFile && !mFoundFirstMatch) {
+       // mFoundFirstMatch = true;
+       // IFile matched_file = (IFile) match.getResource();
+       // IMarker marker = createMarkerFromSearchMatch(matched_file, match);
+       // // There should only be one exact match,
+       // // so we go immediately to that one.
+       // if (marker != null) {
+       // switchPerspective();
+       // openFile(matched_file, marker);
+       // }
+       // }
+       // }
+       // }
+
+       public LogView() {
+               newLogView = this;
+       }
+
+       @Override
+       public void createPartControl(Composite parent) {
+               Display d = parent.getDisplay();
+               LogColors colors = new LogColors();
+
+               ImageLoader loader = ImageLoader.getDdmUiLibLoader();
+
+               colors.infoColor = new Color(d, 0, 127, 0);
+               colors.debugColor = new Color(d, 0, 0, 127);
+               colors.errorColor = new Color(d, 255, 0, 0);
+               colors.warningColor = new Color(d, 255, 127, 0);
+               colors.verboseColor = new Color(d, 0, 0, 0);
+
+               addAction = new Action("add Tab") {
+                       @Override
+                       public void run() {
+                               mLogPanel.addTab();
+                       }
+               };
+               addAction.setToolTipText("Add Tab");
+               addAction.setImageDescriptor(loader.loadDescriptor("add_tab.png"));
+               
+               removeAction = new Action("Remove View") {
+                       @Override
+                       public void run() {
+                               mLogPanel.removeTab();
+                       }
+               };
+               removeAction.setToolTipText("Remove View");
+               removeAction.setImageDescriptor(loader.loadDescriptor("add_tab.png"));
+               
+               editAction = new Action("Edit Tab") {
+                       @Override
+                       public void run() {
+                               mLogPanel.editTab();
+                       }
+               };
+               editAction.setToolTipText("Edit Tab");
+               editAction.setImageDescriptor(loader.loadDescriptor("add_tab.png"));
+
+               exportAction = new Action("Export Log") {
+                       @Override
+                       public void run() {
+                               mLogPanel.save();
+                       }
+               };
+               exportAction.setToolTipText("Export Log");
+               exportAction.setImageDescriptor(loader.loadDescriptor("Export Log.gif")); //$NON-NLS-1$
+
+               clearAction = new Action("Clear Log") {
+                       @Override
+                       public void run() {
+                               mLogPanel.clear();
+                       }
+               };
+               clearAction.setToolTipText("Clear Log");
+               clearAction.setImageDescriptor(loader.loadDescriptor("Clear Log.gif")); //$NON-NLS-1$
+
+               // mGotoMethodDeclarationAction = new
+               // CommonAction("Go to Problem (method declaration)") {
+               // @Override
+               // public void run() {
+               // goToErrorLine(CHOICE_METHOD_DECLARATION);
+               // }
+               // };
+               //
+               // mGotoErrorLineAction = new
+               // CommonAction("Go to Problem (error line)") {
+               // @Override
+               // public void run() {
+               // goToErrorLine(CHOICE_ERROR_LINE);
+               // }
+               // };
+
+               LogLevel[] levels = LogLevel.values();
+               mLogLevelActions = new Action[mLogLevelIcons.length];
+               for (int i = 0; i < mLogLevelActions.length; i++) {
+                       String name = levels[i].getStringValue();
+                       mLogLevelActions[i] = new Action(name, IAction.AS_CHECK_BOX) {
+                               @Override
+                               public void run() {
+                                       // disable the other actions and record
+                                       // current index
+                                       for (int i = 0; i < mLogLevelActions.length; i++) {
+                                               Action a = mLogLevelActions[i];
+                                               if (a == this) {
+                                                       if (a.isChecked())
+                                                               a.setChecked(a.isChecked());
+                                                        mLogPanel.getCurrentLogTab().setLevel(i , a.isChecked());
+                                                        mLogPanel.getCurrentLogTab().refill();
+                                               }
+                                       }
+                               }
+                       };
+
+                       mLogLevelActions[i].setToolTipText(name);
+                       mLogLevelActions[i].setImageDescriptor(loader
+                                       .loadDescriptor(mLogLevelIcons[i]));
+               }
+
+               // now create the log view
+               mLogPanel = new LogPanel(colors);
+               // mLogPanel.setActions(mLogLevelActions);
+
+               // get the font
+               // String fontStr =
+               // DdmsPlugin.getDefault().getPreferenceStore().getString(
+               // PreferenceInitializer.ATTR_LOGCAT_FONT);
+               // if (fontStr != null) {
+               // FontData data = new FontData(fontStr);
+               //
+               // if (fontStr != null) {
+               // mLogPanel.setFont(new Font(parent.getDisplay(), data));
+               // }
+               // }
+
+               mLogPanel.createPanel(parent);
+               // ConnectionPlugin.getDefault().addSelectionListener(this);
+
+               // place the actions.
+               placeActions();
+
+               // setup the copy action
+               mClipboard = new Clipboard(d);
+               IActionBars actionBars = getViewSite().getActionBars();
+               actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action("Copy") {
+                       @Override
+                       public void run() {
+                               mLogPanel.copy(mClipboard);
+                       }
+               });
+
+               // setup the select all action
+               actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action(
+                               "Select All") {
+                       @Override
+                       public void run() {
+                               mLogPanel.selectAll();
+                       }
+               });
+               setActionEnabled(true);
+
+//             IDevice device = ConnectionPlugin.getDefault().getCurrentDevice();
+               // if( device != null )
+               // selectionChanged( device.getFileListingService().getRoot() );
+
+       }
+
+       @Override
+       public void dispose() {
+//             mClipboard.dispose();
+               mLogPanel.stopAll();
+       }
+
+       @Override
+       public void setFocus() {
+               mLogPanel.setFocus();
+       }
+
+       /**
+        * Place the actions in the ui.
+        */
+       private void placeActions() {
+               IActionBars actionBars = getViewSite().getActionBars();
+
+               // first in the menu
+               IMenuManager menuManager = actionBars.getMenuManager();
+               menuManager.add(addAction);
+               menuManager.add(removeAction);
+               menuManager.add(editAction);
+               menuManager.add(new Separator());
+               menuManager.add(exportAction);
+               menuManager.add(clearAction);
+               menuManager.add(new Separator());
+               // menuManager.add(mGotoMethodDeclarationAction);
+               // menuManager.add(mGotoErrorLineAction);
+
+               // and then in the toolbar
+               IToolBarManager toolBarManager = actionBars.getToolBarManager();
+               toolBarManager.add(new Separator());
+               for (Action a : mLogLevelActions) {
+                       toolBarManager.add(a);
+               }
+               toolBarManager.add(new Separator());
+               toolBarManager.add(addAction);
+               toolBarManager.add(removeAction);
+               toolBarManager.add(editAction);
+               toolBarManager.add(new Separator());
+               toolBarManager.add(exportAction);
+               toolBarManager.add(clearAction);
+               toolBarManager.add(new Separator());
+       }
+
+       // @Override
+       // public void selectionChanged(FileEntry selectedEntry) {
+       // mLogPanel.deviceSelected(selectedEntry);
+       // if( selectedEntry != null )
+       // setActionEnabled(true);
+       //
+       // }
+
+       public LogPanel getPanel() {
+               return mLogPanel;
+       }
+
+       public static void setActionEnabled(boolean on) {
+               addAction.setEnabled(on);
+               removeAction.setEnabled(on);
+               editAction.setEnabled(on);
+               exportAction.setEnabled(on);
+               clearAction.setEnabled(on);
+               for (Action a : mLogLevelActions) {
+                       a.setEnabled(on);
+               }
+
+       }
+
+       // void openFile(IFile file, IMarker marker) {
+       // try {
+       // IWorkbenchPage page = getViewSite().getWorkbenchWindow()
+       // .getActivePage();
+       // if (page != null) {
+       // IDE.openEditor(page, marker);
+       // marker.delete();
+       // }
+       // } catch (CoreException e) {
+       // Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID,
+       // e.getMessage(), e);
+       // DdmsPlugin.getDefault().getLog().log(s);
+       // }
+       // }
+
+       // void switchPerspective() {
+       // IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
+       // if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) {
+       // IWorkbench workbench = PlatformUI.getWorkbench();
+       // IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+       // IPerspectiveRegistry perspectiveRegistry =
+       // workbench.getPerspectiveRegistry();
+       // String perspectiveId =
+       // store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID);
+       // if (perspectiveId != null
+       // && perspectiveId.length() > 0
+       // && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) {
+       // try {
+       // workbench.showPerspective(perspectiveId, window);
+       // } catch (WorkbenchException e) {
+       // e.printStackTrace();
+       // }
+       // }
+       // }
+       // }
+
+       // void goToErrorLine() {
+       // IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
+       // String value =
+       // store.getString(PreferenceInitializer.ATTR_LOGCAT_GOTO_PROBLEM);
+       // goToErrorLine(value);
+       // }
+
+       // void goToErrorLine(String choice) {
+       // try {
+       // String msg = mLogPanel.getSelectedErrorLineMessage();
+       // if (msg != null) {
+       // String error_line_matcher_string =
+       // "\\s*at\\ (.*)\\((.*)\\.java\\:(\\d+)\\)";
+       // Matcher error_line_matcher = Pattern.compile(
+       // error_line_matcher_string).matcher(msg);
+       //
+       // if (error_line_matcher.find()) {
+       // String class_name_method = error_line_matcher.group(1);
+       //
+       // // TODO: Search currently only matches the class declaration (using
+       // // IJavaSearchConstants.DECLARATIONS). We may want to jump to the
+       // // "reference" of the class instead (IJavaSearchConstants.REFERENCES)
+       // // using the filename and line number to disambiguate the search
+       // results.
+       // String class_name_line = error_line_matcher.group(2);
+       // int line_number = Integer.parseInt(error_line_matcher.group(3));
+       //
+       // SearchEngine se = new SearchEngine();
+       // if (CHOICE_ERROR_LINE.equals(choice)) {
+       // se.search(SearchPattern.createPattern(class_name_line,
+       // IJavaSearchConstants.CLASS,
+       // IJavaSearchConstants.DECLARATIONS,
+       // SearchPattern.R_EXACT_MATCH
+       // | SearchPattern.R_CASE_SENSITIVE),
+       // new SearchParticipant[] { SearchEngine
+       // .getDefaultSearchParticipant() },
+       // SearchEngine.createWorkspaceScope(),
+       // new LogViewSearchRequestor(CHOICE_ERROR_LINE, line_number),
+       // new NullProgressMonitor());
+       // } else if (CHOICE_METHOD_DECLARATION.equals(choice)) {
+       // se.search(SearchPattern.createPattern(class_name_method,
+       // IJavaSearchConstants.METHOD,
+       // IJavaSearchConstants.DECLARATIONS,
+       // SearchPattern.R_EXACT_MATCH
+       // | SearchPattern.R_CASE_SENSITIVE),
+       // new SearchParticipant[] { SearchEngine
+       // .getDefaultSearchParticipant() },
+       // SearchEngine.createWorkspaceScope(),
+       // new LogViewSearchRequestor(CHOICE_METHOD_DECLARATION, 0),
+       // new NullProgressMonitor());
+       // }
+       // }
+       // }
+       // } catch (Exception e) {
+       // Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID,
+       // e.getMessage(), e);
+       // DdmsPlugin.getDefault().getLog().log(s);
+       // }
+       // }
+
+       // public void onDoubleClick() {
+       // goToErrorLine();
+       // }
+}
\ No newline at end of file