/*
 * BottomScrollPanel.java
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.core.client.widget;

import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;

import org.rstudio.core.client.Debug;
import org.rstudio.core.client.dom.DomUtils;

/**
 * An implementation of ScrollPanel that defaults its scroll position to the
 * bottom. If resized while the scroll position is at the bottom, the scroll
 * position will stay at the bottom (even if the panel is shrinking in size).
 */
public class BottomScrollPanel extends ScrollPanel
{
   public BottomScrollPanel()
   {
      scrolling_ = false;
      addScrollHandler(new ScrollHandler()
      {
         public void onScroll(ScrollEvent event)
         {
            // short circuit if we initiated this scroll
            if (scrolling_)
               return;
            
            scrolledToBottom_ = 
             
             (getVerticalScrollPosition() == 
              getMaximumVerticalScrollPosition() || 
              
             ((getVerticalScrollPosition() + getOffsetHeight()) ==
              getElement().getScrollHeight()));
         }
      });
   }

   public BottomScrollPanel(Widget widget)
   {
      this();
      setWidget(widget);
   }

   public boolean isScrolledToBottom()
   {
      return scrolledToBottom_;
   }

   @Override
   protected void onLoad()
   {
      super.onLoad();
      scrollToBottom();
   }

   @Override
   public void onResize()
   {
      if (scrolledToBottom_)
         scrollToBottom();
      super.onResize();
   }

   @Override
   public void scrollToBottom()
   {
      scrolling_ = true;
      try
      {
         DomUtils.scrollToBottom(getElement());
      }
      catch(Exception e)
      {
         Debug.logException(e);
      }
      scrolling_ = false;
      scrolledToBottom_ = true;
   }

   public void onContentSizeChanged()
   {
      if (scrolledToBottom_)
         scrollToBottom();
   }

   public void saveScrollPosition()
   {
      vScroll_ = scrolledToBottom_ ? null : getVerticalScrollPosition();
      hScroll_ = getHorizontalScrollPosition();
   }

   public void restoreScrollPosition()
   {
      if (vScroll_ == null)
         scrollToBottom();
      else
         setVerticalScrollPosition(vScroll_);

      setHorizontalScrollPosition(hScroll_);
   }
   
   public boolean hasSavedScrollPosition()
   {
      return vScroll_ != null;
   }

   private boolean scrolledToBottom_;
   private boolean scrolling_;
   private Integer vScroll_;
   private int hScroll_;
}

@@ -48,17 +48,17 @@
 ) 2009-1
-2
+7
  by RStu
@@ -820,24 +820,66 @@
 ui.Widget;%0A%0A
+import org.rstudio.core.client.BrowseCap;%0A
 import org.r
@@ -1300,24 +1300,280 @@
 g_ = false;%0A
+      %0A      // on high-dpi Windows, with a zoom factor, there%0A      // was a frequent off-by-one (internal rounding error?)%0A      // causing failure to set scrolledToBottom_%0A      vDelta_ = 0;%0A      if (BrowseCap.isWindowsDesktop())%0A         vDelta_ = 1;%0A
       addScr
@@ -1852,16 +1852,25 @@
         
+(Math.abs
 (getVert
@@ -1894,12 +1894,16 @@
 n() 
-== %0A
+- %0A     
     
@@ -1912,16 +1912,20 @@
         
+    
 getMaxim
@@ -1950,16 +1950,29 @@
 sition()
+) %3C= vDelta_)
  %7C%7C %0A   
@@ -1996,16 +1996,25 @@
         
+(Math.abs
 ((getVer
@@ -2060,11 +2060,15 @@
 ()) 
-==%0A
+- %0A    
     
@@ -2077,16 +2077,22 @@
         
+      
 getEleme
@@ -2114,16 +2114,27 @@
 eight())
+ %3C= vDelta_
 );%0A     
@@ -3535,10 +3535,34 @@
 croll_;%0A
+   private int vDelta_;%0A
 %7D%0A

Fix stuck console scrolling on high-dpi Windows