Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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/. */
6 //
7 // David Hyatt & Eric Vaughan
8 // Netscape Communications
9 //
10 // See documentation in associated header file
11 //
13 #include "nsProgressMeterFrame.h"
14 #include "nsCSSRendering.h"
15 #include "nsIContent.h"
16 #include "nsPresContext.h"
17 #include "nsGkAtoms.h"
18 #include "nsNameSpaceManager.h"
19 #include "nsCOMPtr.h"
20 #include "nsBoxLayoutState.h"
21 #include "nsIReflowCallback.h"
22 #include "nsContentUtils.h"
23 #include "mozilla/Attributes.h"
25 class nsReflowFrameRunnable : public nsRunnable
26 {
27 public:
28 nsReflowFrameRunnable(nsIFrame* aFrame,
29 nsIPresShell::IntrinsicDirty aIntrinsicDirty,
30 nsFrameState aBitToAdd);
32 NS_DECL_NSIRUNNABLE
34 nsWeakFrame mWeakFrame;
35 nsIPresShell::IntrinsicDirty mIntrinsicDirty;
36 nsFrameState mBitToAdd;
37 };
39 nsReflowFrameRunnable::nsReflowFrameRunnable(nsIFrame* aFrame,
40 nsIPresShell::IntrinsicDirty aIntrinsicDirty,
41 nsFrameState aBitToAdd)
42 : mWeakFrame(aFrame),
43 mIntrinsicDirty(aIntrinsicDirty),
44 mBitToAdd(aBitToAdd)
45 {
46 }
48 NS_IMETHODIMP
49 nsReflowFrameRunnable::Run()
50 {
51 if (mWeakFrame.IsAlive()) {
52 mWeakFrame->PresContext()->PresShell()->
53 FrameNeedsReflow(mWeakFrame, mIntrinsicDirty, mBitToAdd);
54 }
55 return NS_OK;
56 }
58 //
59 // NS_NewToolbarFrame
60 //
61 // Creates a new Toolbar frame and returns it
62 //
63 nsIFrame*
64 NS_NewProgressMeterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
65 {
66 return new (aPresShell) nsProgressMeterFrame(aPresShell, aContext);
67 }
69 NS_IMPL_FRAMEARENA_HELPERS(nsProgressMeterFrame)
71 //
72 // nsProgressMeterFrame dstr
73 //
74 // Cleanup, if necessary
75 //
76 nsProgressMeterFrame :: ~nsProgressMeterFrame ( )
77 {
78 }
80 class nsAsyncProgressMeterInit MOZ_FINAL : public nsIReflowCallback
81 {
82 public:
83 nsAsyncProgressMeterInit(nsIFrame* aFrame) : mWeakFrame(aFrame) {}
85 virtual bool ReflowFinished() MOZ_OVERRIDE
86 {
87 bool shouldFlush = false;
88 nsIFrame* frame = mWeakFrame.GetFrame();
89 if (frame) {
90 nsAutoScriptBlocker scriptBlocker;
91 frame->AttributeChanged(kNameSpaceID_None, nsGkAtoms::mode, 0);
92 shouldFlush = true;
93 }
94 delete this;
95 return shouldFlush;
96 }
98 virtual void ReflowCallbackCanceled() MOZ_OVERRIDE
99 {
100 delete this;
101 }
103 nsWeakFrame mWeakFrame;
104 };
106 NS_IMETHODIMP
107 nsProgressMeterFrame::DoLayout(nsBoxLayoutState& aState)
108 {
109 if (mNeedsReflowCallback) {
110 nsIReflowCallback* cb = new nsAsyncProgressMeterInit(this);
111 if (cb) {
112 PresContext()->PresShell()->PostReflowCallback(cb);
113 }
114 mNeedsReflowCallback = false;
115 }
116 return nsBoxFrame::DoLayout(aState);
117 }
119 nsresult
120 nsProgressMeterFrame::AttributeChanged(int32_t aNameSpaceID,
121 nsIAtom* aAttribute,
122 int32_t aModType)
123 {
124 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
125 "Scripts not blocked in nsProgressMeterFrame::AttributeChanged!");
126 nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
127 aModType);
128 if (NS_OK != rv) {
129 return rv;
130 }
132 // did the progress change?
133 bool undetermined = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mode,
134 nsGkAtoms::undetermined, eCaseMatters);
135 if (nsGkAtoms::mode == aAttribute ||
136 (!undetermined &&
137 (nsGkAtoms::value == aAttribute || nsGkAtoms::max == aAttribute))) {
138 nsIFrame* barChild = GetFirstPrincipalChild();
139 if (!barChild) return NS_OK;
140 nsIFrame* remainderChild = barChild->GetNextSibling();
141 if (!remainderChild) return NS_OK;
142 nsCOMPtr<nsIContent> remainderContent = remainderChild->GetContent();
143 if (!remainderContent) return NS_OK;
145 int32_t flex = 1, maxFlex = 1;
146 if (!undetermined) {
147 nsAutoString value, maxValue;
148 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
149 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxValue);
151 nsresult error;
152 flex = value.ToInteger(&error);
153 maxFlex = maxValue.ToInteger(&error);
154 if (NS_FAILED(error) || maxValue.IsEmpty()) {
155 maxFlex = 100;
156 }
157 if (maxFlex < 1) {
158 maxFlex = 1;
159 }
160 if (flex < 0) {
161 flex = 0;
162 }
163 if (flex > maxFlex) {
164 flex = maxFlex;
165 }
166 }
168 nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
169 barChild->GetContent(), nsGkAtoms::flex, flex));
170 nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
171 remainderContent, nsGkAtoms::flex, maxFlex - flex));
172 nsContentUtils::AddScriptRunner(new nsReflowFrameRunnable(
173 this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY));
174 }
175 return NS_OK;
176 }
178 #ifdef DEBUG_FRAME_DUMP
179 nsresult
180 nsProgressMeterFrame::GetFrameName(nsAString& aResult) const
181 {
182 return MakeFrameName(NS_LITERAL_STRING("ProgressMeter"), aResult);
183 }
184 #endif