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