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
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);
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() {
}
}
});
-
// 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
final Button btnTag = new Button(mid, SWT.CHECK);
btnTag.setText("Tag");
+ if( bTag )
+ btnTag.setSelection(true);
btnTag.addSelectionListener(new SelectionListener(){
@Override
final Button btnMsg = new Button(mid, SWT.CHECK);
btnMsg.setText("Message");
+ if( bMsg )
+ btnMsg.setSelection(true);
btnMsg.addSelectionListener(new SelectionListener(){
@Override
}
});
- 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));
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() ;
});
// 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();
}
});
return keyword;
}
+ public String getName()
+ {
+ return tabName;
+ }
+
public String getDevice()
{
return device;
// */
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 ;
}
if( keyword == null || keyword.equals(""))
{
- mOkButton.setEnabled(false);
+ okButton.setEnabled(false);
return ;
}
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
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;
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 <pid>:0x<???> <severity>/<tag>]"</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
--- /dev/null
+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
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