aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2011-12-13 18:16:27 -0800
committerXavier Ducrohet <xav@android.com>2011-12-14 17:00:21 -0800
commitfa8fa3cb242095a83542292da9a17881b664e92a (patch)
tree4c02035ab52fbf51ad4b232c151322fa6e3acdad
parentb1aa527122bf67f0dcf68e2fb6a70873ad5f6bb4 (diff)
downloadplatform_sdk-tools_r16.tar.gz
platform_sdk-tools_r16.tar.bz2
platform_sdk-tools_r16.zip
logcat: Improve auto scroll lock behavior. do not merge.android-sdk-adt_r16.0.1tools_r16
Setting up scroll lock automatically is broken due to the highly platform dependent nature of the scroll bar events. This patch improves the current situation significantly, but may not be the last word on this subject. This patch does the following: 1. Sets up auto scroll lock on Windows and Linux. 2. Removes auto scroll locking on Mac. Users have to manually press the Pause Logcat button. 3. Renames the "Scroll to latest" button to "Pause Logcat" to more accurately reflect what is happening. (cherry picked from commit eae62907a30288c1c7b6b8ebb2c848c7394c9067) Change-Id: Ia8169a4d2a2b0c9fff0f781dd68f46f02e63f3c3
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java125
-rw-r--r--ddms/libs/ddmuilib/src/images/pause_logcat.pngbin0 -> 180 bytes
-rw-r--r--ddms/libs/ddmuilib/src/images/scroll_latest.pngbin291 -> 0 bytes
3 files changed, 79 insertions, 46 deletions
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 608086da5..f910c147e 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
@@ -66,6 +66,7 @@ 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;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
@@ -120,7 +121,7 @@ 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_SCROLL_TO_LATEST = "scroll_latest.png"; //$NON-NLS-1$
+ private static final String IMAGE_PAUSE_LOGCAT = "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};
@@ -142,7 +143,8 @@ public final class LogCatPanel extends SelectionDependentPanel
private TableViewer mViewer;
private boolean mShouldScrollToLatestLog = true;
- private ToolItem mScrollToLastCheckBox;
+ private ToolItem mPauseLogcatCheckBox;
+ private boolean mLastItemPainted = false;
private String mLogFileExportFolder;
private LogCatMessageLabelProvider mLogCatMessageLabelProvider;
@@ -570,17 +572,17 @@ public final class LogCatPanel extends SelectionDependentPanel
}
});
- mScrollToLastCheckBox = new ToolItem(toolBar, SWT.CHECK);
- mScrollToLastCheckBox.setImage(
- ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_SCROLL_TO_LATEST,
+ mPauseLogcatCheckBox = new ToolItem(toolBar, SWT.CHECK);
+ mPauseLogcatCheckBox.setImage(
+ ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_PAUSE_LOGCAT,
toolBar.getDisplay()));
- mScrollToLastCheckBox.setSelection(true);
- mScrollToLastCheckBox.setToolTipText("Scroll to display the latest logcat message.");
- mScrollToLastCheckBox.addSelectionListener(new SelectionAdapter() {
+ mPauseLogcatCheckBox.setSelection(false);
+ mPauseLogcatCheckBox.setToolTipText("Pause receiving new logcat messages.");
+ mPauseLogcatCheckBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
- boolean shouldScroll = mScrollToLastCheckBox.getSelection();
- setScrollToLatestLog(shouldScroll, false);
+ boolean pauseLogcat = mPauseLogcatCheckBox.getSelection();
+ setScrollToLatestLog(!pauseLogcat, false);
}
});
}
@@ -792,55 +794,86 @@ public final class LogCatPanel extends SelectionDependentPanel
}
});
- setupScrollBehavior();
+ setupAutoScrollLockBehavior();
initDoubleClickListener();
}
/**
- * Update setting that controls if the table should scroll to reveal the latest logcat entry.
- * Users can impact the scrolling behavior in two ways:
- * <ul>
- * <li> Using the scrollbar: If the scrollbar is moved to the bottom, then auto scroll.</li>
- * <li> Selecting an entry in the table: If the selected entry is not currently the last
- * entry in the table, then do not scroll, otherwise auto scroll.
+ * 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 setupScrollBehavior() {
- mViewer.getTable().getVerticalBar().addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent event) {
- ScrollBar sb = (ScrollBar) event.getSource();
-
- // On Mac & Linux, when the scroll bar is at the bottom,
- // sb.getSelection + sb.getThumb = sb.getMaximum
- // But on Windows 7, the scrollbar never touches the bottom, and as a result
- // sb.getSelection + sb.getThumb is slightly less than sb.getMaximum.
- // So we assume that as long as the thumb is close to the bottom, we want to scroll.
- boolean shouldScroll =
- Math.abs(sb.getSelection() + sb.getThumb() - sb.getMaximum()) < 10;
- setScrollToLatestLog(shouldScroll, true);
- }
- });
-
- mViewer.getTable().addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent event) {
- Table table = (Table) event.getSource();
- int[] indices = table.getSelectionIndices();
+ 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() {
+ 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;
+ }
- boolean shouldScroll =
- indices.length == 1 // only 1 item selected
- && indices[0] == table.getItemCount() - 1; // and it is the last entry
- setScrollToLatestLog(shouldScroll, true);
- }
- });
+ 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.
+ }
}
private void setScrollToLatestLog(boolean scroll, boolean updateCheckbox) {
mShouldScrollToLatestLog = scroll;
if (updateCheckbox) {
- mScrollToLastCheckBox.setSelection(scroll);
+ mPauseLogcatCheckBox.setSelection(!scroll);
}
if (scroll) {
diff --git a/ddms/libs/ddmuilib/src/images/pause_logcat.png b/ddms/libs/ddmuilib/src/images/pause_logcat.png
new file mode 100644
index 000000000..b5df287e1
--- /dev/null
+++ b/ddms/libs/ddmuilib/src/images/pause_logcat.png
Binary files differ
diff --git a/ddms/libs/ddmuilib/src/images/scroll_latest.png b/ddms/libs/ddmuilib/src/images/scroll_latest.png
deleted file mode 100644
index 5d26689b7..000000000
--- a/ddms/libs/ddmuilib/src/images/scroll_latest.png
+++ /dev/null
Binary files differ