aboutsummaryrefslogtreecommitdiffstats
path: root/ddms
diff options
context:
space:
mode:
Diffstat (limited to 'ddms')
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatBufferChangeListener.java (renamed from ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageEventListener.java)12
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterContentProvider.java6
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterSettingsDialog.java2
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageContentProvider.java43
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageLabelProvider.java144
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageList.java53
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java606
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatReceiver.java27
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatViewerFilter.java46
9 files changed, 387 insertions, 552 deletions
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageEventListener.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatBufferChangeListener.java
index 2caf50d..1a547c7 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatMessageEventListener.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/ILogCatBufferChangeListener.java
@@ -19,11 +19,13 @@ package com.android.ddmuilib.logcat;
import java.util.List;
/**
- * Listeners interested in log cat messages should implement this interface.
+ * Listeners interested in changes in the logcat buffer should implement this interface.
*/
-public interface ILogCatMessageEventListener {
- /** Called on reception of logcat messages.
- * @param receivedMessages list of messages received
+public interface ILogCatBufferChangeListener {
+ /**
+ * Called when the logcat buffer changes.
+ * @param addedMessages list of messages that were added to the logcat buffer
+ * @param deletedMessages list of messages that were removed from the logcat buffer
*/
- void messageReceived(List<LogCatMessage> receivedMessages);
+ void bufferChanged(List<LogCatMessage> addedMessages, List<LogCatMessage> deletedMessages);
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterContentProvider.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterContentProvider.java
index 164f484..68c08d4 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterContentProvider.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterContentProvider.java
@@ -39,10 +39,6 @@ public final class LogCatFilterContentProvider implements IStructuredContentProv
*/
@Override
public Object[] getElements(Object model) {
- if (model instanceof List<?>) {
- return ((List<?>) model).toArray();
- }
- return null;
+ return ((List<?>) model).toArray();
}
-
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterSettingsDialog.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterSettingsDialog.java
index f68ee05..39b3fa9 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterSettingsDialog.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatFilterSettingsDialog.java
@@ -165,7 +165,7 @@ public final class LogCatFilterSettingsDialog extends TitleAreaDialog {
* on the dialog is valid or not. If it is not valid, the message
* field stores the reason why it isn't.
*/
- private final class DialogStatus {
+ private static final class DialogStatus {
final boolean valid;
final String message;
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageContentProvider.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageContentProvider.java
deleted file mode 100644
index bd7b520..0000000
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageContentProvider.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ddmuilib.logcat;
-
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * A JFace content provider for the LogCat log messages, used in the {@link LogCatPanel}.
- */
-public final class LogCatMessageContentProvider implements IStructuredContentProvider {
- @Override
- public void dispose() {
- }
-
- @Override
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
-
- @Override
- public Object[] getElements(Object model) {
- if (model instanceof LogCatMessageList) {
- Object[] e = ((LogCatMessageList) model).toArray();
- return e;
- }
-
- return null;
- }
-}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageLabelProvider.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageLabelProvider.java
deleted file mode 100644
index 1d83a9c..0000000
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageLabelProvider.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ddmuilib.logcat;
-
-import com.android.ddmlib.Log.LogLevel;
-
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ViewerCell;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Point;
-
-/**
- * A JFace Column label provider for the LogCat log messages. It expects elements of type
- * {@link LogCatMessage}.
- */
-public final class LogCatMessageLabelProvider extends ColumnLabelProvider {
- private static final int INDEX_LOGLEVEL = 0;
- private static final int INDEX_LOGTIME = 1;
- private static final int INDEX_PID = 2;
- private static final int INDEX_APPNAME = 3;
- private static final int INDEX_TAG = 4;
- private static final int INDEX_TEXT = 5;
-
- /* Default Colors for different log levels. */
- private static final Color INFO_MSG_COLOR = new Color(null, 0, 127, 0);
- private static final Color DEBUG_MSG_COLOR = new Color(null, 0, 0, 127);
- private static final Color ERROR_MSG_COLOR = new Color(null, 255, 0, 0);
- private static final Color WARN_MSG_COLOR = new Color(null, 255, 127, 0);
- private static final Color VERBOSE_MSG_COLOR = new Color(null, 0, 0, 0);
-
- /** Amount of pixels to shift the tooltip by. */
- private static final Point LOGCAT_TOOLTIP_SHIFT = new Point(10, 10);
-
- private Font mLogFont;
- private int mWrapWidth = 100;
-
- /**
- * Construct a column label provider for the logcat table.
- * @param font default font to use
- */
- public LogCatMessageLabelProvider(Font font) {
- mLogFont = font;
- }
-
- private String getCellText(LogCatMessage m, int columnIndex) {
- switch (columnIndex) {
- case INDEX_LOGLEVEL:
- return Character.toString(m.getLogLevel().getPriorityLetter());
- case INDEX_LOGTIME:
- return m.getTime();
- case INDEX_PID:
- return m.getPid();
- case INDEX_APPNAME:
- return m.getAppName();
- case INDEX_TAG:
- return m.getTag();
- case INDEX_TEXT:
- return m.getMessage();
- default:
- return "";
- }
- }
-
- @Override
- public void update(ViewerCell cell) {
- Object element = cell.getElement();
- if (!(element instanceof LogCatMessage)) {
- return;
- }
- LogCatMessage m = (LogCatMessage) element;
-
- String text = getCellText(m, cell.getColumnIndex());
- cell.setText(text);
- cell.setFont(mLogFont);
- cell.setForeground(getForegroundColor(m));
- }
-
- private Color getForegroundColor(LogCatMessage m) {
- LogLevel l = m.getLogLevel();
-
- if (l.equals(LogLevel.VERBOSE)) {
- return VERBOSE_MSG_COLOR;
- } else if (l.equals(LogLevel.INFO)) {
- return INFO_MSG_COLOR;
- } else if (l.equals(LogLevel.DEBUG)) {
- return DEBUG_MSG_COLOR;
- } else if (l.equals(LogLevel.ERROR)) {
- return ERROR_MSG_COLOR;
- } else if (l.equals(LogLevel.WARN)) {
- return WARN_MSG_COLOR;
- }
-
- return null;
- }
-
- public void setFont(Font preferredFont) {
- if (mLogFont != null) {
- mLogFont.dispose();
- }
-
- mLogFont = preferredFont;
- }
-
- public void setMinimumLengthForToolTips(int widthInChars) {
- mWrapWidth = widthInChars;
- }
-
- /**
- * Obtain the tool tip to show for a particular logcat message.
- * We display a tool tip only for messages longer than the width set by
- * {@link #setMinimumLengthForToolTips(int)}.
- */
- @Override
- public String getToolTipText(Object element) {
- String text = element.toString();
- if (text.length() > mWrapWidth) {
- return text;
- } else {
- return null;
- }
- }
-
- @Override
- public Point getToolTipShift(Object object) {
- // The only reason we override this method is that the default shift amounts
- // don't seem to work on OS X Lion.
- return LOGCAT_TOOLTIP_SHIFT;
- }
-}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageList.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageList.java
index 0d0e3c2..080dbc1 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageList.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatMessageList.java
@@ -16,6 +16,8 @@
package com.android.ddmuilib.logcat;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -33,7 +35,6 @@ public final class LogCatMessageList {
private int mFifoSize;
private BlockingQueue<LogCatMessage> mQ;
- private LogCatMessage[] mQArray;
/**
* Construct an empty message list.
@@ -43,7 +44,6 @@ public final class LogCatMessageList {
mFifoSize = maxMessages;
mQ = new ArrayBlockingQueue<LogCatMessage>(mFifoSize);
- mQArray = new LogCatMessage[mFifoSize];
}
/**
@@ -64,8 +64,6 @@ public final class LogCatMessageList {
mQ.offer(curMessages[i]);
}
}
-
- mQArray = new LogCatMessage[mFifoSize];
}
/**
@@ -73,17 +71,30 @@ public final class LogCatMessageList {
* message will be popped off of it.
* @param m log to be inserted
*/
- public synchronized void appendMessage(final LogCatMessage m) {
- if (mQ.remainingCapacity() == 0) {
- /* make space by removing the first entry */
- mQ.poll();
+ public synchronized void appendMessages(final List<LogCatMessage> messages) {
+ ensureSpace(messages.size());
+ for (LogCatMessage m: messages) {
+ mQ.offer(m);
}
- mQ.offer(m);
}
/**
- * Returns the number of additional elements that this queue can
- * ideally (in the absence of memory or resource constraints)
+ * Ensure that there is sufficient space for given number of messages.
+ * @return list of messages that were deleted to create additional space.
+ */
+ public synchronized List<LogCatMessage> ensureSpace(int messageCount) {
+ List<LogCatMessage> l = new ArrayList<LogCatMessage>(messageCount);
+
+ while (mQ.remainingCapacity() < messageCount) {
+ l.add(mQ.poll());
+ }
+
+ return l;
+ }
+
+ /**
+ * Returns the number of additional elements that this queue can
+ * ideally (in the absence of memory or resource constraints)
* accept without blocking.
* @return the remaining capacity
*/
@@ -91,25 +102,13 @@ public final class LogCatMessageList {
return mQ.remainingCapacity();
}
- /**
- * Clear all messages in the list.
- */
+ /** Clear all messages in the list. */
public synchronized void clear() {
mQ.clear();
}
- /**
- * Obtain all the messages currently present in the list.
- * @return array containing all the log messages
- */
- public Object[] toArray() {
- if (mQ.size() == mFifoSize) {
- /*
- * Once the queue is full, it stays full until the user explicitly clears
- * all the logs. Optimize for this case by not reallocating the array.
- */
- return mQ.toArray(mQArray);
- }
- return mQ.toArray();
+ /** Obtain a copy of the message list. */
+ public synchronized List<LogCatMessage> getAllMessages() {
+ return new ArrayList<LogCatMessage>(mQ);
}
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
index 7aa0328..45f0c69 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
@@ -30,12 +30,7 @@ import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
-import org.eclipse.jface.viewers.ColumnViewer;
-import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.ViewerCell;
-import org.eclipse.jface.window.ToolTip;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
@@ -50,6 +45,7 @@ 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.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
@@ -63,7 +59,6 @@ import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
@@ -83,7 +78,7 @@ import java.util.List;
* LogCatPanel displays a table listing the logcat messages.
*/
public final class LogCatPanel extends SelectionDependentPanel
- implements ILogCatMessageEventListener {
+ implements ILogCatBufferChangeListener {
/** Preference key to use for storing list of logcat filters. */
public static final String LOGCAT_FILTERS_LIST = "logcat.view.filters.list";
@@ -121,20 +116,20 @@ public final class LogCatPanel extends SelectionDependentPanel
private static final String IMAGE_SAVE_LOG_TO_FILE = "save.png"; //$NON-NLS-1$
private static final String IMAGE_CLEAR_LOG = "clear.png"; //$NON-NLS-1$
private static final String IMAGE_DISPLAY_FILTERS = "displayfilters.png"; //$NON-NLS-1$
- private static final String IMAGE_PAUSE_LOGCAT = "pause_logcat.png"; //$NON-NLS-1$
+ private static final String IMAGE_SCROLL_LOCK = "pause_logcat.png"; //$NON-NLS-1$
private static final int[] WEIGHTS_SHOW_FILTERS = new int[] {15, 85};
private static final int[] WEIGHTS_LOGCAT_ONLY = new int[] {0, 100};
+ /** Index of the default filter in the saved filters column. */
+ private static final int DEFAULT_FILTER_INDEX = 0;
+
private LogCatReceiver mReceiver;
private IPreferenceStore mPrefStore;
private List<LogCatFilter> mLogCatFilters;
private int mCurrentSelectedFilterIndex;
- private int mRemovedEntriesCount = 0;
- private int mPreviousRemainingCapacity = 0;
-
private ToolItem mNewFilterToolItem;
private ToolItem mDeleteFilterToolItem;
private ToolItem mEditFilterToolItem;
@@ -143,28 +138,40 @@ public final class LogCatPanel extends SelectionDependentPanel
private Combo mLiveFilterLevelCombo;
private Text mLiveFilterText;
- private TableViewer mViewer;
+ private List<LogCatFilter> mCurrentFilters = Collections.emptyList();
+
+ private Table mTable;
private boolean mShouldScrollToLatestLog = true;
- private ToolItem mPauseLogcatCheckBox;
- private boolean mLastItemPainted = false;
+ private ToolItem mScrollLockCheckBox;
private String mLogFileExportFolder;
- private LogCatMessageLabelProvider mLogCatMessageLabelProvider;
+
+ private Font mFont;
+ private int mWrapWidthInChars;
private SashForm mSash;
+ // messages added since last refresh, synchronized on mLogBuffer
+ private List<LogCatMessage> mLogBuffer;
+
+ // # of messages deleted since last refresh, synchronized on mLogBuffer
+ private int mDeletedLogCount;
+
/**
* Construct a logcat panel.
* @param prefStore preference store where UI preferences will be saved
*/
public LogCatPanel(IPreferenceStore prefStore) {
mPrefStore = prefStore;
+ mLogBuffer = new ArrayList<LogCatMessage>(LogCatMessageList.MAX_MESSAGES_DEFAULT);
initializeFilters();
setupDefaultPreferences();
initializePreferenceUpdateListeners();
+
+ mFont = getFontFromPrefStore();
}
private void initializeFilters() {
@@ -196,15 +203,24 @@ public final class LogCatPanel extends SelectionDependentPanel
@Override
public void propertyChange(PropertyChangeEvent event) {
String changedProperty = event.getProperty();
-
if (changedProperty.equals(LogCatPanel.LOGCAT_VIEW_FONT_PREFKEY)) {
- mLogCatMessageLabelProvider.setFont(getFontFromPrefStore());
- refreshLogCatTable();
- } else if (changedProperty.equals(
- LogCatMessageList.MAX_MESSAGES_PREFKEY)) {
+ if (mFont != null) {
+ mFont.dispose();
+ }
+ mFont = getFontFromPrefStore();
+ recomputeWrapWidth();
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ for (TableItem it: mTable.getItems()) {
+ it.setFont(mFont);
+ }
+ }
+ });
+ } else if (changedProperty.equals(LogCatMessageList.MAX_MESSAGES_PREFKEY)) {
mReceiver.resizeFifo(mPrefStore.getInt(
LogCatMessageList.MAX_MESSAGES_PREFKEY));
- refreshLogCatTable();
+ reloadLogBuffer();
}
}
});
@@ -246,7 +262,7 @@ public final class LogCatPanel extends SelectionDependentPanel
mReceiver = LogCatReceiverFactory.INSTANCE.newReceiver(device, mPrefStore);
mReceiver.addMessageReceivedEventListener(this);
- mViewer.setInput(mReceiver.getMessages());
+ reloadLogBuffer();
// Always scroll to last line whenever the selected device changes.
// Run this in a separate async thread to give the table some time to update after the
@@ -430,7 +446,7 @@ public final class LogCatPanel extends SelectionDependentPanel
* @param appName application name to filter by
*/
public void selectTransientAppFilter(String appName) {
- assert mViewer.getTable().getDisplay().getThread() == Thread.currentThread();
+ assert mTable.getDisplay().getThread() == Thread.currentThread();
LogCatFilter f = findTransientAppFilter(appName);
if (f == null) {
@@ -501,11 +517,7 @@ public final class LogCatPanel extends SelectionDependentPanel
createLogcatViewTable(c);
}
- /**
- * Create the search bar at the top of the logcat messages table.
- * FIXME: Currently, this feature is incomplete: The UI elements are created, but they
- * are all set to disabled state.
- */
+ /** Create the search bar at the top of the logcat messages table. */
private void createLiveFilters(Composite parent) {
Composite c = new Composite(parent, SWT.NONE);
c.setLayout(new GridLayout(3, false));
@@ -557,8 +569,6 @@ public final class LogCatPanel extends SelectionDependentPanel
mReceiver.clearMessages();
refreshLogCatTable();
- mRemovedEntriesCount = 0;
-
// the filters view is not cleared unless the filters are re-applied.
updateAppliedFilters();
}
@@ -580,17 +590,17 @@ public final class LogCatPanel extends SelectionDependentPanel
}
});
- mPauseLogcatCheckBox = new ToolItem(toolBar, SWT.CHECK);
- mPauseLogcatCheckBox.setImage(
- ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_PAUSE_LOGCAT,
+ mScrollLockCheckBox = new ToolItem(toolBar, SWT.CHECK);
+ mScrollLockCheckBox.setImage(
+ ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_SCROLL_LOCK,
toolBar.getDisplay()));
- mPauseLogcatCheckBox.setSelection(false);
- mPauseLogcatCheckBox.setToolTipText("Pause receiving new logcat messages.");
- mPauseLogcatCheckBox.addSelectionListener(new SelectionAdapter() {
+ mScrollLockCheckBox.setSelection(false);
+ mScrollLockCheckBox.setToolTipText("Scroll Lock");
+ mScrollLockCheckBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
- boolean pauseLogcat = mPauseLogcatCheckBox.getSelection();
- setScrollToLatestLog(!pauseLogcat, false);
+ boolean scrollLock = mScrollLockCheckBox.getSelection();
+ setScrollToLatestLog(!scrollLock);
}
});
}
@@ -620,13 +630,13 @@ public final class LogCatPanel extends SelectionDependentPanel
Thread t = new Thread(new Runnable() {
@Override
public void run() {
+ BufferedWriter w = null;
try {
- BufferedWriter w = new BufferedWriter(new FileWriter(fName));
+ w = new BufferedWriter(new FileWriter(fName));
for (LogCatMessage m : selectedMessages) {
w.append(m.toString());
w.newLine();
}
- w.close();
} catch (final IOException e) {
Display.getDefault().asyncExec(new Runnable() {
@Override
@@ -637,6 +647,14 @@ public final class LogCatPanel extends SelectionDependentPanel
+ e.getMessage());
}
});
+ } finally {
+ if (w != null) {
+ try {
+ w.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
}
}
});
@@ -675,44 +693,25 @@ public final class LogCatPanel extends SelectionDependentPanel
}
private List<LogCatMessage> getSelectedLogCatMessages() {
- Table table = mViewer.getTable();
- int[] indices = table.getSelectionIndices();
+ int[] indices = mTable.getSelectionIndices();
Arrays.sort(indices); /* Table.getSelectionIndices() does not specify an order */
- // Get items from the table's input as opposed to getting each table item's data.
- // Retrieving table item's data can return NULL in case of a virtual table if the item
- // has not been displayed yet.
- Object input = mViewer.getInput();
- if (!(input instanceof LogCatMessageList)) {
- return Collections.emptyList();
- }
-
- List<LogCatMessage> filteredItems = applyCurrentFilters((LogCatMessageList) input);
List<LogCatMessage> selectedMessages = new ArrayList<LogCatMessage>(indices.length);
for (int i : indices) {
- // consider removed logcat message entries
- i -= mRemovedEntriesCount;
- if (i >= 0 && i < filteredItems.size()) {
- LogCatMessage m = filteredItems.get(i);
- selectedMessages.add(m);
+ Object data = mTable.getItem(i).getData();
+ if (data instanceof LogCatMessage) {
+ selectedMessages.add((LogCatMessage) data);
}
}
return selectedMessages;
}
- private List<LogCatMessage> applyCurrentFilters(LogCatMessageList msgList) {
- Object[] items = msgList.toArray();
- List<LogCatMessage> filteredItems = new ArrayList<LogCatMessage>(items.length);
- List<LogCatViewerFilter> filters = getFiltersToApply();
-
- for (Object item : items) {
- if (!(item instanceof LogCatMessage)) {
- continue;
- }
+ private List<LogCatMessage> applyCurrentFilters(List<LogCatMessage> msgList) {
+ List<LogCatMessage> filteredItems = new ArrayList<LogCatMessage>(msgList.size());
- LogCatMessage msg = (LogCatMessage) item;
- if (!isMessageFiltered(msg, filters)) {
+ for (LogCatMessage msg: msgList) {
+ if (isMessageAccepted(msg, mCurrentFilters)) {
filteredItems.add(msg);
}
}
@@ -720,33 +719,30 @@ public final class LogCatPanel extends SelectionDependentPanel
return filteredItems;
}
- private boolean isMessageFiltered(LogCatMessage msg, List<LogCatViewerFilter> filters) {
- for (LogCatViewerFilter f : filters) {
- if (!f.select(null, null, msg)) {
- // message does not make it through this filter
- return true;
+ private boolean isMessageAccepted(LogCatMessage msg, List<LogCatFilter> filters) {
+ for (LogCatFilter f : filters) {
+ if (!f.matches(msg)) {
+ // not accepted by this filter
+ return false;
}
}
- return false;
+ // accepted by all filters
+ return true;
}
private void createLogcatViewTable(Composite parent) {
- // The SWT.VIRTUAL bit causes the table to be rendered faster. However it makes all rows
- // to be of the same height, thereby clipping any rows with multiple lines of text.
- // In such a case, users can view the full text by hovering over the item and looking at
- // the tooltip.
- final Table table = new Table(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.VIRTUAL);
- mViewer = new TableViewer(table);
+ mTable = new Table(parent, SWT.FULL_SELECTION | SWT.MULTI);
- table.setLayoutData(new GridData(GridData.FILL_BOTH));
- table.getHorizontalBar().setVisible(true);
+ mTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+ mTable.getHorizontalBar().setVisible(true);
/** Columns to show in the table. */
String[] properties = {
"Level",
"Time",
"PID",
+ "TID",
"Application",
"Tag",
"Text",
@@ -758,32 +754,31 @@ public final class LogCatPanel extends SelectionDependentPanel
" ",
" 00-00 00:00:00.0000 ",
" 0000",
+ " 0000",
" com.android.launcher",
" SampleTagText",
" Log Message field should be pretty long by default. As long as possible for correct display on Mac.",
};
- mLogCatMessageLabelProvider = new LogCatMessageLabelProvider(getFontFromPrefStore());
for (int i = 0; i < properties.length; i++) {
- TableColumn tc = TableHelper.createTableColumn(mViewer.getTable(),
+ TableHelper.createTableColumn(mTable,
properties[i], /* Column title */
SWT.LEFT, /* Column Style */
sampleText[i], /* String to compute default col width */
getColPreferenceKey(properties[i]), /* Preference Store key for this column */
mPrefStore);
- TableViewerColumn tvc = new TableViewerColumn(mViewer, tc);
- tvc.setLabelProvider(mLogCatMessageLabelProvider);
}
- mViewer.getTable().setLinesVisible(true); /* zebra stripe the table */
- mViewer.getTable().setHeaderVisible(true);
- mViewer.setContentProvider(new LogCatMessageContentProvider());
- WrappingToolTipSupport.enableFor(mViewer, ToolTip.NO_RECREATE);
+ // don't zebra stripe the table: When the buffer is full, and scroll lock is on, having
+ // zebra striping means that the background could keep changing depending on the number
+ // of new messages added to the bottom of the log.
+ mTable.setLinesVisible(false);
+ mTable.setHeaderVisible(true);
// Set the row height to be sufficient enough to display the current font.
// This is not strictly necessary, except that on WinXP, the rows showed up clipped. So
// we explicitly set it to be sure.
- mViewer.getTable().addListener(SWT.MeasureItem, new Listener() {
+ mTable.addListener(SWT.MeasureItem, new Listener() {
@Override
public void handleEvent(Event event) {
event.height = event.gc.getFontMetrics().getHeight();
@@ -791,143 +786,45 @@ public final class LogCatPanel extends SelectionDependentPanel
});
// Update the label provider whenever the text column's width changes
- TableColumn textColumn = mViewer.getTable().getColumn(properties.length - 1);
+ TableColumn textColumn = mTable.getColumn(properties.length - 1);
textColumn.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent event) {
- TableColumn tc = (TableColumn) event.getSource();
- int width = tc.getWidth();
- GC gc = new GC(tc.getParent());
- int avgCharWidth = gc.getFontMetrics().getAverageCharWidth();
- gc.dispose();
-
- if (mLogCatMessageLabelProvider != null) {
- mLogCatMessageLabelProvider.setMinimumLengthForToolTips(width/avgCharWidth);
- }
+ recomputeWrapWidth();
}
});
- setupAutoScrollLockBehavior();
initDoubleClickListener();
+ recomputeWrapWidth();
}
- /**
- * Setup to automatically enable or disable scroll lock. From a user's perspective,
- * the logcat window will: <ul>
- * <li> Automatically scroll and reveal new entries if the scrollbar is at the bottom. </li>
- * <li> Not scroll even when new messages are received if the scrollbar is not at the bottom.
- * </li>
- * </ul>
- * This requires that we are able to detect where the scrollbar is and what direction
- * it is moving. Unfortunately, that proves to be very platform dependent. Here's the behavior
- * of the scroll events on different platforms: <ul>
- * <li> On Windows, scroll bar events specify which direction the scrollbar is moving, but
- * it is not possible to determine if the scrollbar is right at the end. </li>
- * <li> On Mac/Cocoa, scroll bar events do not specify the direction of movement (it is always
- * set to SWT.DRAG), and it is not possible to identify where the scrollbar is since
- * small movements of the scrollbar are not reflected in sb.getSelection(). </li>
- * <li> On Linux/gtk, we don't get the direction, but we can accurately locate the
- * scrollbar location using getSelection(), getThumb() and getMaximum().
- * </ul>
- */
- private void setupAutoScrollLockBehavior() {
- if (DdmConstants.CURRENT_PLATFORM == DdmConstants.PLATFORM_WINDOWS) {
- // On Windows, it is not possible to detect whether the scrollbar is at the
- // bottom using the values of ScrollBar.getThumb, getSelection and getMaximum.
- // Instead we resort to the following workaround: attach to the paint listener
- // and see if the last item has been painted since the previous scroll event.
- // If the last item has been painted, then we assume that we are at the bottom.
- mViewer.getTable().addListener(SWT.PaintItem, new Listener() {
- @Override
- public void handleEvent(Event event) {
- TableItem item = (TableItem) event.item;
- TableItem[] items = mViewer.getTable().getItems();
- if (items.length > 0 && items[items.length - 1] == item) {
- mLastItemPainted = true;
- }
- }
- });
- mViewer.getTable().getVerticalBar().addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent event) {
- boolean scrollToLast;
- if (event.detail == SWT.ARROW_UP || event.detail == SWT.PAGE_UP
- || event.detail == SWT.HOME) {
- // if we know that we are moving up, then do not scroll down
- scrollToLast = false;
- } else {
- // otherwise, enable scrollToLast only if the last item was displayed
- scrollToLast = mLastItemPainted;
- }
-
- setScrollToLatestLog(scrollToLast, true);
- mLastItemPainted = false;
- }
- });
- } else if (DdmConstants.CURRENT_PLATFORM == DdmConstants.PLATFORM_LINUX) {
- // On Linux/gtk, we do not get any details regarding the scroll event (up/down/etc).
- // So we completely rely on whether the scrollbar is at the bottom or not.
- mViewer.getTable().getVerticalBar().addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent event) {
- ScrollBar sb = (ScrollBar) event.getSource();
- boolean scrollToLast = sb.getSelection() + sb.getThumb() == sb.getMaximum();
- setScrollToLatestLog(scrollToLast, true);
- }
- });
- } else {
- // On Mac, we do not get any details regarding the (trackball) scroll event,
- // nor can we rely on getSelection() changing for small movements. As a result, we
- // do not setup any auto scroll lock behavior. Mac users have to manually pause and
- // unpause if they are looking at a particular item in a high volume stream of events.
+ public void recomputeWrapWidth() {
+ if (mTable == null || mTable.isDisposed()) {
+ return;
}
- }
-
- private void setScrollToLatestLog(boolean scroll, boolean updateCheckbox) {
- mShouldScrollToLatestLog = scroll;
- if (updateCheckbox) {
- mPauseLogcatCheckBox.setSelection(!scroll);
- }
+ // get width of the last column (log message)
+ TableColumn tc = mTable.getColumn(mTable.getColumnCount() - 1);
+ int colWidth = tc.getWidth();
- if (scroll) {
- mViewer.refresh();
- scrollToLatestLog();
- }
- }
+ // get font width
+ GC gc = new GC(tc.getParent());
+ gc.setFont(mFont);
+ int avgCharWidth = gc.getFontMetrics().getAverageCharWidth();
+ gc.dispose();
- private static class WrappingToolTipSupport extends ColumnViewerToolTipSupport {
- protected WrappingToolTipSupport(ColumnViewer viewer, int style,
- boolean manualActivation) {
- super(viewer, style, manualActivation);
- }
+ int MIN_CHARS_PER_LINE = 50; // show atleast these many chars per line
+ mWrapWidthInChars = Math.max(colWidth/avgCharWidth, MIN_CHARS_PER_LINE);
- @Override
- protected Composite createViewerToolTipContentArea(Event event, ViewerCell cell,
- Composite parent) {
- Composite comp = new Composite(parent, SWT.NONE);
- GridLayout l = new GridLayout(1, false);
- l.horizontalSpacing = 0;
- l.marginWidth = 0;
- l.marginHeight = 0;
- l.verticalSpacing = 0;
- comp.setLayout(l);
-
- Text text = new Text(comp, SWT.BORDER | SWT.V_SCROLL | SWT.WRAP);
- text.setEditable(false);
- text.setText(cell.getElement().toString());
- text.setLayoutData(new GridData(500, 150));
-
- return comp;
- }
+ int OFFSET_AT_END_OF_LINE = 10; // leave some space at the end of the line
+ mWrapWidthInChars -= OFFSET_AT_END_OF_LINE;
+ }
- @Override
- public boolean isHideOnMouseDown() {
- return false;
- }
+ private void setScrollToLatestLog(boolean scroll) {
+ mShouldScrollToLatestLog = scroll;
- public static final void enableFor(ColumnViewer viewer, int style) {
- new WrappingToolTipSupport(viewer, style, false);
+ if (scroll) {
+ scrollToLatestLog();
}
}
@@ -952,7 +849,7 @@ public final class LogCatPanel extends SelectionDependentPanel
* Perform all necessary updates whenever a filter is selected (by user or programmatically).
*/
private void filterSelectionChanged() {
- int idx = getSelectedSavedFilterIndex();
+ int idx = mFiltersTableViewer.getTable().getSelectionIndex();
if (idx == -1) {
/* One of the filters should always be selected.
* On Linux, there is no way to deselect an item.
@@ -971,84 +868,80 @@ public final class LogCatPanel extends SelectionDependentPanel
}
private void resetUnreadCountForSelectedFilter() {
- int index = getSelectedSavedFilterIndex();
- mLogCatFilters.get(index).resetUnreadCount();
-
+ mLogCatFilters.get(mCurrentSelectedFilterIndex).resetUnreadCount();
refreshFiltersTable();
}
- private int getSelectedSavedFilterIndex() {
- return mFiltersTableViewer.getTable().getSelectionIndex();
- }
-
private void updateFiltersToolBar() {
/* The default filter at index 0 can neither be edited, nor removed. */
- boolean en = getSelectedSavedFilterIndex() != 0;
+ boolean en = mCurrentSelectedFilterIndex != DEFAULT_FILTER_INDEX;
mEditFilterToolItem.setEnabled(en);
mDeleteFilterToolItem.setEnabled(en);
}
private void updateAppliedFilters() {
- List<LogCatViewerFilter> filters = getFiltersToApply();
- mViewer.setFilters(filters.toArray(new LogCatViewerFilter[filters.size()]));
-
- /* whenever filters are changed, the number of displayed logs changes
- * drastically. Display the latest log in such a situation. */
- scrollToLatestLog();
+ mCurrentFilters = getFiltersToApply();
+ reloadLogBuffer();
}
- private List<LogCatViewerFilter> getFiltersToApply() {
+ private List<LogCatFilter> getFiltersToApply() {
/* list of filters to apply = saved filter + live filters */
- List<LogCatViewerFilter> filters = new ArrayList<LogCatViewerFilter>();
- filters.add(getSelectedSavedFilter());
+ List<LogCatFilter> filters = new ArrayList<LogCatFilter>();
+
+ if (mCurrentSelectedFilterIndex != DEFAULT_FILTER_INDEX) {
+ filters.add(getSelectedSavedFilter());
+ }
+
filters.addAll(getCurrentLiveFilters());
return filters;
}
- private List<LogCatViewerFilter> getCurrentLiveFilters() {
- List<LogCatViewerFilter> liveFilters = new ArrayList<LogCatViewerFilter>();
-
- List<LogCatFilter> liveFilterSettings = LogCatFilter.fromString(
+ private List<LogCatFilter> getCurrentLiveFilters() {
+ return LogCatFilter.fromString(
mLiveFilterText.getText(), /* current query */
LogLevel.getByString(mLiveFilterLevelCombo.getText())); /* current log level */
- for (LogCatFilter s : liveFilterSettings) {
- liveFilters.add(new LogCatViewerFilter(s));
- }
-
- return liveFilters;
}
- private LogCatViewerFilter getSelectedSavedFilter() {
- int index = getSelectedSavedFilterIndex();
- return new LogCatViewerFilter(mLogCatFilters.get(index));
+ private LogCatFilter getSelectedSavedFilter() {
+ return mLogCatFilters.get(mCurrentSelectedFilterIndex);
}
-
@Override
public void setFocus() {
}
- /**
- * Update view whenever a message is received.
- * @param receivedMessages list of messages from logcat
- * Implements {@link ILogCatMessageEventListener#messageReceived()}.
- */
@Override
- public void messageReceived(List<LogCatMessage> receivedMessages) {
+ public void bufferChanged(List<LogCatMessage> addedMessages,
+ List<LogCatMessage> deletedMessages) {
+
+ synchronized (mLogBuffer) {
+ addedMessages = applyCurrentFilters(addedMessages);
+ deletedMessages = applyCurrentFilters(deletedMessages);
+
+ mLogBuffer.addAll(addedMessages);
+ mDeletedLogCount += deletedMessages.size();
+ }
+
refreshLogCatTable();
+ updateUnreadCount(addedMessages);
+ refreshFiltersTable();
+ }
- if (mShouldScrollToLatestLog) {
- updateUnreadCount(receivedMessages);
- refreshFiltersTable();
- } else {
- LogCatMessageList messageList = mReceiver.getMessages();
- int remainingCapacity = messageList.remainingCapacity();
- if (remainingCapacity == 0) {
- mRemovedEntriesCount +=
- receivedMessages.size() - mPreviousRemainingCapacity;
- }
- mPreviousRemainingCapacity = remainingCapacity;
+ private void reloadLogBuffer() {
+ mTable.removeAll();
+
+ synchronized (mLogBuffer) {
+ mLogBuffer.clear();
+ mDeletedLogCount = 0;
+ }
+
+ if (mReceiver == null) {
+ return;
}
+
+ List<LogCatMessage> addedMessages = mReceiver.getMessages().getAllMessages();
+ List<LogCatMessage> deletedMessages = Collections.emptyList();
+ bufferChanged(addedMessages, deletedMessages);
}
/**
@@ -1089,34 +982,210 @@ public final class LogCatPanel extends SelectionDependentPanel
*/
private void refreshLogCatTable() {
synchronized (this) {
- if (mCurrentRefresher == null && mShouldScrollToLatestLog) {
+ if (mCurrentRefresher == null) {
mCurrentRefresher = new LogCatTableRefresherTask();
Display.getDefault().asyncExec(mCurrentRefresher);
}
}
}
+ /**
+ * The {@link LogCatTableRefresherTask} takes care of refreshing the table with the
+ * new log messages that have been received. Since the log behaves like a circular buffer,
+ * the first step is to remove items from the top of the table (if necessary). This step
+ * is complicated by the fact that a single log message may span multiple rows if the message
+ * was wrapped. Once the deleted items are removed, the new messages are added to the bottom
+ * of the table. If scroll lock is enabled, the item that was original visible is made visible
+ * again, if not, the last item is made visible.
+ */
private class LogCatTableRefresherTask implements Runnable {
@Override
public void run() {
- if (mViewer.getTable().isDisposed()) {
+ if (mTable.isDisposed()) {
return;
}
synchronized (LogCatPanel.this) {
mCurrentRefresher = null;
}
+ // Current topIndex so that it can be restored if scroll locked.
+ int topIndex = mTable.getTopIndex();
+
+ mTable.setRedraw(false);
+
+ // Obtain the list of new messages, and the number of deleted messages.
+ List<LogCatMessage> newMessages;
+ int deletedMessageCount;
+ synchronized (mLogBuffer) {
+ newMessages = new ArrayList<LogCatMessage>(mLogBuffer);
+ mLogBuffer.clear();
+
+ deletedMessageCount = mDeletedLogCount;
+ mDeletedLogCount = 0;
+ }
+
+ int originalItemCount = mTable.getItemCount();
+
+ // Remove entries from the start of the table if they were removed in the log buffer
+ // This is complicated by the fact that a single message may span multiple TableItems
+ // if it was word-wrapped.
+ deletedMessageCount -= removeFromTable(mTable, deletedMessageCount);
+
+ // Compute number of table items that were deleted from the table.
+ int deletedItemCount = originalItemCount - mTable.getItemCount();
+
+ // If there are more messages to delete (after deleting messages from the table),
+ // then delete them from the start of the newly added messages list
+ if (deletedMessageCount > 0) {
+ assert deletedMessageCount < newMessages.size();
+ for (int i = 0; i < deletedMessageCount; i++) {
+ newMessages.remove(0);
+ }
+ }
+
+ // Add the remaining messages to the table.
+ for (LogCatMessage m: newMessages) {
+ List<String> wrappedMessageList = wrapMessage(m.getMessage(), mWrapWidthInChars);
+ Color c = getForegroundColor(m);
+ for (int i = 0; i < wrappedMessageList.size(); i++) {
+ TableItem item = new TableItem(mTable, SWT.NONE);
+
+ if (i == 0) {
+ // Only set the message data in the first item. This allows code that
+ // examines the table item data (such as copy selection) to distinguish
+ // between real messages versus lines that are really just wrapped
+ // content from the previous message.
+ item.setData(m);
+
+ item.setText(new String[] {
+ Character.toString(m.getLogLevel().getPriorityLetter()),
+ m.getTime(),
+ m.getPid(),
+ m.getTid(),
+ m.getAppName(),
+ m.getTag(),
+ wrappedMessageList.get(i)
+ });
+ } else {
+ item.setText(new String[] {
+ "", "", "", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "", "", "", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ wrappedMessageList.get(i)
+ });
+ }
+ item.setForeground(c);
+ item.setFont(mFont);
+ }
+ }
+
if (mShouldScrollToLatestLog) {
- mViewer.refresh();
scrollToLatestLog();
+ } else {
+ // If scroll locked, show the same item that was original visible in the table.
+ int index = Math.max(topIndex - deletedItemCount, 0);
+ mTable.setTopIndex(index);
+ }
+
+ mTable.setRedraw(true);
+ }
+
+ /**
+ * Removes given number of messages from the table, starting at the top of the table.
+ * Note that the number of messages deleted is not equal to the number of rows
+ * deleted since a single message could span multiple rows. This method first calculates
+ * the number of rows that correspond to the number of messages to delete, and then
+ * removes all those rows.
+ * @param table table from which messages should be removed
+ * @param msgCount number of messages to be removed
+ * @return number of messages that were actually removed
+ */
+ private int removeFromTable(Table table, int msgCount) {
+ int deletedMessageCount = 0; // # of messages that have been deleted
+ int lastItemToDelete = 0; // index of the last item that should be deleted
+
+ while (deletedMessageCount < msgCount && lastItemToDelete < table.getItemCount()) {
+ // only rows that begin a message have their item data set
+ TableItem item = table.getItem(lastItemToDelete);
+ if (item.getData() != null) {
+ deletedMessageCount++;
+ }
+
+ lastItemToDelete++;
+ }
+
+ // If there are any table items left over at the end that are wrapped over from the
+ // previous message, mark them for deletion as well.
+ if (lastItemToDelete < table.getItemCount()
+ && table.getItem(lastItemToDelete).getData() == null) {
+ lastItemToDelete++;
}
+
+ table.remove(0, lastItemToDelete - 1);
+
+ return deletedMessageCount;
}
}
/** Scroll to the last line. */
private void scrollToLatestLog() {
- mRemovedEntriesCount = 0;
- mViewer.getTable().setTopIndex(mViewer.getTable().getItemCount() - 1);
+ mTable.setTopIndex(mTable.getItemCount() - 1);
+ }
+
+ /**
+ * Splits the message into multiple lines if the message length exceeds given width.
+ * If the message was split, then a wrap character \u23ce is appended to the end of all
+ * lines but the last one.
+ */
+ private List<String> wrapMessage(String msg, int wrapWidth) {
+ if (msg.length() < wrapWidth) {
+ return Collections.singletonList(msg);
+ }
+
+ List<String> wrappedMessages = new ArrayList<String>();
+
+ int offset = 0;
+ int len = msg.length();
+
+ while (len > 0) {
+ int copylen = Math.min(wrapWidth, len);
+ String s = msg.substring(offset, offset + copylen);
+
+ offset += copylen;
+ len -= copylen;
+
+ if (len > 0) { // if there are more lines following, then append a wrap marker
+ s += " \u23ce"; //$NON-NLS-1$
+ }
+
+ wrappedMessages.add(s);
+ }
+
+ return wrappedMessages;
+ }
+
+ /* Default Colors for different log levels. */
+ private static final Color INFO_MSG_COLOR = new Color(null, 0, 127, 0);
+ private static final Color DEBUG_MSG_COLOR = new Color(null, 0, 0, 127);
+ private static final Color ERROR_MSG_COLOR = new Color(null, 255, 0, 0);
+ private static final Color WARN_MSG_COLOR = new Color(null, 255, 127, 0);
+ private static final Color VERBOSE_MSG_COLOR = new Color(null, 0, 0, 0);
+
+ private static Color getForegroundColor(LogCatMessage m) {
+ LogLevel l = m.getLogLevel();
+
+ if (l.equals(LogLevel.VERBOSE)) {
+ return VERBOSE_MSG_COLOR;
+ } else if (l.equals(LogLevel.INFO)) {
+ return INFO_MSG_COLOR;
+ } else if (l.equals(LogLevel.DEBUG)) {
+ return DEBUG_MSG_COLOR;
+ } else if (l.equals(LogLevel.ERROR)) {
+ return ERROR_MSG_COLOR;
+ } else if (l.equals(LogLevel.WARN)) {
+ return WARN_MSG_COLOR;
+ }
+
+ return null;
}
private List<ILogCatMessageSelectionListener> mMessageSelectionListeners;
@@ -1124,7 +1193,7 @@ public final class LogCatPanel extends SelectionDependentPanel
private void initDoubleClickListener() {
mMessageSelectionListeners = new ArrayList<ILogCatMessageSelectionListener>(1);
- mViewer.getTable().addSelectionListener(new SelectionAdapter() {
+ mTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
List<LogCatMessage> selectedMessages = getSelectedLogCatMessages();
@@ -1153,7 +1222,6 @@ public final class LogCatPanel extends SelectionDependentPanel
public void setTableFocusListener(ITableFocusListener listener) {
mTableFocusListener = listener;
- final Table table = mViewer.getTable();
final IFocusedTableActivator activator = new IFocusedTableActivator() {
@Override
public void copy(Clipboard clipboard) {
@@ -1162,11 +1230,11 @@ public final class LogCatPanel extends SelectionDependentPanel
@Override
public void selectAll() {
- table.selectAll();
+ mTable.selectAll();
}
};
- table.addFocusListener(new FocusListener() {
+ mTable.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
mTableFocusListener.focusGained(activator);
@@ -1198,6 +1266,6 @@ public final class LogCatPanel extends SelectionDependentPanel
/** Select all items in the logcat table. */
public void selectAll() {
- mViewer.getTable().selectAll();
+ mTable.selectAll();
}
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatReceiver.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatReceiver.java
index c9606f6..8f2d52c 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatReceiver.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatReceiver.java
@@ -38,7 +38,7 @@ public final class LogCatReceiver {
private LogCatMessageList mLogMessages;
private IDevice mCurrentDevice;
private LogCatOutputReceiver mCurrentLogCatOutputReceiver;
- private Set<ILogCatMessageEventListener> mLogCatMessageListeners;
+ private Set<ILogCatBufferChangeListener> mLogCatMessageListeners;
private LogCatMessageParser mLogCatMessageParser;
private LogCatPidToNameMapper mPidToNameMapper;
private IPreferenceStore mPrefStore;
@@ -55,7 +55,7 @@ public final class LogCatReceiver {
mCurrentDevice = device;
mPrefStore = prefStore;
- mLogCatMessageListeners = new HashSet<ILogCatMessageEventListener>();
+ mLogCatMessageListeners = new HashSet<ILogCatBufferChangeListener>();
mLogCatMessageParser = new LogCatMessageParser();
mPidToNameMapper = new LogCatPidToNameMapper(mCurrentDevice);
@@ -147,14 +147,16 @@ public final class LogCatReceiver {
}
private void processLogLines(String[] lines) {
- List<LogCatMessage> messages = mLogCatMessageParser.processLogLines(lines,
+ List<LogCatMessage> newMessages = mLogCatMessageParser.processLogLines(lines,
mPidToNameMapper);
- if (messages.size() > 0) {
- for (LogCatMessage m : messages) {
- mLogMessages.appendMessage(m);
+ if (newMessages.size() > 0) {
+ List<LogCatMessage> deletedMessages;
+ synchronized (mLogMessages) {
+ deletedMessages = mLogMessages.ensureSpace(newMessages.size());
+ mLogMessages.appendMessages(newMessages);
}
- sendMessageReceivedEvent(messages);
+ sendLogChangedEvent(newMessages, deletedMessages);
}
}
@@ -177,17 +179,18 @@ public final class LogCatReceiver {
* Add to list of message event listeners.
* @param l listener to notified when messages are received from the device
*/
- public void addMessageReceivedEventListener(ILogCatMessageEventListener l) {
+ public void addMessageReceivedEventListener(ILogCatBufferChangeListener l) {
mLogCatMessageListeners.add(l);
}
- public void removeMessageReceivedEventListener(ILogCatMessageEventListener l) {
+ public void removeMessageReceivedEventListener(ILogCatBufferChangeListener l) {
mLogCatMessageListeners.remove(l);
}
- private void sendMessageReceivedEvent(List<LogCatMessage> messages) {
- for (ILogCatMessageEventListener l : mLogCatMessageListeners) {
- l.messageReceived(messages);
+ private void sendLogChangedEvent(List<LogCatMessage> addedMessages,
+ List<LogCatMessage> deletedMessages) {
+ for (ILogCatBufferChangeListener l : mLogCatMessageListeners) {
+ l.bufferChanged(addedMessages, deletedMessages);
}
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatViewerFilter.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatViewerFilter.java
deleted file mode 100644
index f7b8dce..0000000
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatViewerFilter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.ddmuilib.logcat;
-
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerFilter;
-
-/**
- * A JFace {@link ViewerFilter} for the {@link LogCatPanel} displaying logcat messages.
- * This is a simple wrapper around {@link LogCatFilter}.
- */
-public final class LogCatViewerFilter extends ViewerFilter {
- private LogCatFilter mFilter;
-
- /**
- * Construct a {@link ViewerFilter} filtering logcat messages based on
- * user provided filter settings for PID, Tag and log level.
- * @param filter filter to use
- */
- public LogCatViewerFilter(LogCatFilter filter) {
- mFilter = filter;
- }
-
- @Override
- public boolean select(Viewer viewer, Object parent, Object element) {
- if (!(element instanceof LogCatMessage)) {
- return false;
- }
-
- LogCatMessage m = (LogCatMessage) element;
- return mFilter.matches(m);
- }
-}