nsProgressMeterFrame.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. //
  6. // David Hyatt & Eric Vaughan
  7. // Netscape Communications
  8. //
  9. // See documentation in associated header file
  10. //
  11. #include "nsProgressMeterFrame.h"
  12. #include "nsCSSRendering.h"
  13. #include "nsIContent.h"
  14. #include "nsPresContext.h"
  15. #include "nsGkAtoms.h"
  16. #include "nsNameSpaceManager.h"
  17. #include "nsCOMPtr.h"
  18. #include "nsBoxLayoutState.h"
  19. #include "nsIReflowCallback.h"
  20. #include "nsContentUtils.h"
  21. #include "mozilla/Attributes.h"
  22. class nsReflowFrameRunnable : public mozilla::Runnable
  23. {
  24. public:
  25. nsReflowFrameRunnable(nsIFrame* aFrame,
  26. nsIPresShell::IntrinsicDirty aIntrinsicDirty,
  27. nsFrameState aBitToAdd);
  28. NS_DECL_NSIRUNNABLE
  29. nsWeakFrame mWeakFrame;
  30. nsIPresShell::IntrinsicDirty mIntrinsicDirty;
  31. nsFrameState mBitToAdd;
  32. };
  33. nsReflowFrameRunnable::nsReflowFrameRunnable(nsIFrame* aFrame,
  34. nsIPresShell::IntrinsicDirty aIntrinsicDirty,
  35. nsFrameState aBitToAdd)
  36. : mWeakFrame(aFrame),
  37. mIntrinsicDirty(aIntrinsicDirty),
  38. mBitToAdd(aBitToAdd)
  39. {
  40. }
  41. NS_IMETHODIMP
  42. nsReflowFrameRunnable::Run()
  43. {
  44. if (mWeakFrame.IsAlive()) {
  45. mWeakFrame->PresContext()->PresShell()->
  46. FrameNeedsReflow(mWeakFrame, mIntrinsicDirty, mBitToAdd);
  47. }
  48. return NS_OK;
  49. }
  50. //
  51. // NS_NewToolbarFrame
  52. //
  53. // Creates a new Toolbar frame and returns it
  54. //
  55. nsIFrame*
  56. NS_NewProgressMeterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
  57. {
  58. return new (aPresShell) nsProgressMeterFrame(aContext);
  59. }
  60. NS_IMPL_FRAMEARENA_HELPERS(nsProgressMeterFrame)
  61. //
  62. // nsProgressMeterFrame dstr
  63. //
  64. // Cleanup, if necessary
  65. //
  66. nsProgressMeterFrame :: ~nsProgressMeterFrame ( )
  67. {
  68. }
  69. class nsAsyncProgressMeterInit final : public nsIReflowCallback
  70. {
  71. public:
  72. explicit nsAsyncProgressMeterInit(nsIFrame* aFrame) : mWeakFrame(aFrame) {}
  73. virtual bool ReflowFinished() override
  74. {
  75. bool shouldFlush = false;
  76. nsIFrame* frame = mWeakFrame.GetFrame();
  77. if (frame) {
  78. nsAutoScriptBlocker scriptBlocker;
  79. frame->AttributeChanged(kNameSpaceID_None, nsGkAtoms::mode, 0);
  80. shouldFlush = true;
  81. }
  82. delete this;
  83. return shouldFlush;
  84. }
  85. virtual void ReflowCallbackCanceled() override
  86. {
  87. delete this;
  88. }
  89. nsWeakFrame mWeakFrame;
  90. };
  91. NS_IMETHODIMP
  92. nsProgressMeterFrame::DoXULLayout(nsBoxLayoutState& aState)
  93. {
  94. if (mNeedsReflowCallback) {
  95. nsIReflowCallback* cb = new nsAsyncProgressMeterInit(this);
  96. if (cb) {
  97. PresContext()->PresShell()->PostReflowCallback(cb);
  98. }
  99. mNeedsReflowCallback = false;
  100. }
  101. return nsBoxFrame::DoXULLayout(aState);
  102. }
  103. nsresult
  104. nsProgressMeterFrame::AttributeChanged(int32_t aNameSpaceID,
  105. nsIAtom* aAttribute,
  106. int32_t aModType)
  107. {
  108. NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
  109. "Scripts not blocked in nsProgressMeterFrame::AttributeChanged!");
  110. nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
  111. aModType);
  112. if (NS_OK != rv) {
  113. return rv;
  114. }
  115. // did the progress change?
  116. bool undetermined = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mode,
  117. nsGkAtoms::undetermined, eCaseMatters);
  118. if (nsGkAtoms::mode == aAttribute ||
  119. (!undetermined &&
  120. (nsGkAtoms::value == aAttribute || nsGkAtoms::max == aAttribute))) {
  121. nsIFrame* barChild = PrincipalChildList().FirstChild();
  122. if (!barChild) return NS_OK;
  123. nsIFrame* remainderChild = barChild->GetNextSibling();
  124. if (!remainderChild) return NS_OK;
  125. nsCOMPtr<nsIContent> remainderContent = remainderChild->GetContent();
  126. if (!remainderContent) return NS_OK;
  127. int32_t flex = 1, maxFlex = 1;
  128. if (!undetermined) {
  129. nsAutoString value, maxValue;
  130. mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
  131. mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxValue);
  132. nsresult error;
  133. flex = value.ToInteger(&error);
  134. maxFlex = maxValue.ToInteger(&error);
  135. if (NS_FAILED(error) || maxValue.IsEmpty()) {
  136. maxFlex = 100;
  137. }
  138. if (maxFlex < 1) {
  139. maxFlex = 1;
  140. }
  141. if (flex < 0) {
  142. flex = 0;
  143. }
  144. if (flex > maxFlex) {
  145. flex = maxFlex;
  146. }
  147. }
  148. nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
  149. barChild->GetContent(), nsGkAtoms::flex, flex));
  150. nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
  151. remainderContent, nsGkAtoms::flex, maxFlex - flex));
  152. nsContentUtils::AddScriptRunner(new nsReflowFrameRunnable(
  153. this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY));
  154. }
  155. return NS_OK;
  156. }
  157. #ifdef DEBUG_FRAME_DUMP
  158. nsresult
  159. nsProgressMeterFrame::GetFrameName(nsAString& aResult) const
  160. {
  161. return MakeFrameName(NS_LITERAL_STRING("ProgressMeter"), aResult);
  162. }
  163. #endif