Bug 665368 - Implement a native indeterminate progress bar rendering for Windows Classic. f=kliu r=jmathies
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 22 Jul 2011 12:23:46 -0700
changeset 73248 0ef7a3e8d959b877b20fea69a731965c0b3c6a50
parent 73247 32ab46a3803b20e9f6313ff24f6610a64fdaf4e5
child 73249 1ec9c2051c07effb0cb7e04dece7e56f6edf9306
push id20841
push usermak77@bonardo.net
push dateMon, 25 Jul 2011 12:14:44 +0000
treeherdermozilla-central@87645ab8ab27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies
bugs665368
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 665368 - Implement a native indeterminate progress bar rendering for Windows Classic. f=kliu r=jmathies
widget/src/windows/nsNativeThemeWin.cpp
--- a/widget/src/windows/nsNativeThemeWin.cpp
+++ b/widget/src/windows/nsNativeThemeWin.cpp
@@ -352,20 +352,24 @@ static CaptionButtonPadding buttonData[3
 // The width of the overlay used to animate the horizontal progress bar (Vista and later).
 static const PRInt32 kProgressHorizontalVistaOverlaySize = 120;
 // The width of the overlay used for the horizontal indeterminate progress bars on XP.
 static const PRInt32 kProgressHorizontalXPOverlaySize = 55;
 // The height of the overlay used to animate the vertical progress bar (Vista and later).
 static const PRInt32 kProgressVerticalOverlaySize = 45;
 // The height of the overlay used for the vertical indeterminate progress bar (Vista and later).
 static const PRInt32 kProgressVerticalIndeterminateOverlaySize = 60;
+// The width of the overlay used to animate the indeterminate progress bar (Windows Classic).
+static const PRInt32 kProgressClassicOverlaySize = 40;
 // Speed (px per ms) of the animation for determined Vista and later progress bars.
 static const double kProgressDeterminedVistaSpeed = 0.225;
 // Speed (px per ms) of the animation for indeterminate progress bars.
 static const double kProgressIndeterminateSpeed = 0.175;
+// Speed (px per ms) of the animation for indeterminate progress bars (Windows Classic).
+static const double kProgressClassicIndeterminateSpeed = 0.0875;
 // Delay (in ms) between two indeterminate progress bar cycles.
 static const PRInt32 kProgressIndeterminateDelay = 500;
 // Delay (in ms) between two determinate progress bar animation on Vista/7.
 static const PRInt32 kProgressDeterminedVistaDelay = 1000;
 
 // Adds "hot" caption button padding to minimum widget size.
 static void AddPaddingRect(nsIntSize* aSize, CaptionButton button) {
   if (!aSize)
@@ -3358,21 +3362,95 @@ RENDER_AGAIN:
         widgetRect.right -= adjustment;
       }
 
       ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
       ::FillRect(hdc, &widgetRect, (HBRUSH) GetStockObject(GRAY_BRUSH));
  
       break;
     }
-    case NS_THEME_PROGRESSBAR_CHUNK:
     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
       ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
-
       break;
+
+    case NS_THEME_PROGRESSBAR_CHUNK: {
+      nsIFrame* stateFrame = aFrame->GetParent();
+      nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
+      const bool indeterminate = IsIndeterminateProgress(stateFrame, eventStates);
+
+      if (!indeterminate) {
+        ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
+        break;
+      }
+
+      /**
+       * The indeterminate rendering is animated: the bar goes from one side to
+       * another.
+       */
+      if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
+        NS_WARNING("unable to animate progress widget!");
+      }
+
+      const bool vertical = IsVerticalProgress(stateFrame);
+      const PRInt32 overlaySize = kProgressClassicOverlaySize;
+      const double pixelsPerMillisecond = kProgressClassicIndeterminateSpeed;
+      const PRInt32 frameSize = vertical ? widgetRect.bottom - widgetRect.top
+                                         : widgetRect.right - widgetRect.left;
+      const double interval = frameSize / pixelsPerMillisecond;
+      // We have to pass a double* to modf and we can't pass NULL.
+      double tempValue;
+      double ratio = modf(PR_IntervalToMilliseconds(PR_IntervalNow())/interval,
+                          &tempValue);
+      PRInt32 dx = 0;
+
+      // If the frame direction is RTL, we want to have the animation going RTL.
+      // ratio is in [0.0; 1.0[ range, inverting it reverse the animation.
+      if (!vertical && IsFrameRTL(aFrame)) {
+        ratio = 1.0 - ratio;
+        dx -= overlaySize;
+      }
+      dx += static_cast<PRInt32>(frameSize * ratio);
+
+      RECT overlayRect = widgetRect;
+      if (vertical) {
+        overlayRect.bottom -= dx;
+        overlayRect.top = overlayRect.bottom - overlaySize;
+      } else {
+        overlayRect.left += dx;
+        overlayRect.right = overlayRect.left + overlaySize;
+      }
+
+      // Compute the leftover part.
+      RECT leftoverRect = widgetRect;
+      if (vertical) {
+        if (overlayRect.top < widgetRect.top) {
+          leftoverRect.bottom = widgetRect.bottom;
+          leftoverRect.top = leftoverRect.bottom + overlayRect.top - widgetRect.top;
+        }
+      } else if (IsFrameRTL(aFrame)) {
+        if (overlayRect.left < widgetRect.left) {
+          leftoverRect.right = widgetRect.right;
+          leftoverRect.left = leftoverRect.right + overlayRect.left - widgetRect.left;
+        }
+      } else if (overlayRect.right > widgetRect.right) {
+        leftoverRect.left = widgetRect.left;
+        leftoverRect.right = leftoverRect.left + overlayRect.right - widgetRect.right;
+      }
+
+      // Only show the leftover if the rect has been modified.
+      if (leftoverRect.top != widgetRect.top ||
+          leftoverRect.left != widgetRect.left ||
+          leftoverRect.right != widgetRect.right) {
+        ::FillRect(hdc, &leftoverRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
+      }
+
+      ::FillRect(hdc, &overlayRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
+      break;
+    }
+
     // Draw Tab
     case NS_THEME_TAB: {
       DrawTab(hdc, widgetRect,
         IsBottomTab(aFrame) ? BF_BOTTOM : BF_TOP, 
         IsSelectedTab(aFrame),
         !IsRightToSelectedTab(aFrame),
         !IsLeftToSelectedTab(aFrame));