|
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 // Eric Vaughan |
|
8 // Netscape Communications |
|
9 // |
|
10 // See documentation in associated header file |
|
11 // |
|
12 |
|
13 #include "nsScrollbarFrame.h" |
|
14 #include "nsScrollbarButtonFrame.h" |
|
15 #include "nsGkAtoms.h" |
|
16 #include "nsIScrollableFrame.h" |
|
17 #include "nsIScrollbarMediator.h" |
|
18 #include "mozilla/LookAndFeel.h" |
|
19 #include "nsThemeConstants.h" |
|
20 #include "nsRenderingContext.h" |
|
21 #include "nsIContent.h" |
|
22 |
|
23 using namespace mozilla; |
|
24 |
|
25 // |
|
26 // NS_NewScrollbarFrame |
|
27 // |
|
28 // Creates a new scrollbar frame and returns it |
|
29 // |
|
30 nsIFrame* |
|
31 NS_NewScrollbarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext) |
|
32 { |
|
33 return new (aPresShell) nsScrollbarFrame (aPresShell, aContext); |
|
34 } |
|
35 |
|
36 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarFrame) |
|
37 |
|
38 NS_QUERYFRAME_HEAD(nsScrollbarFrame) |
|
39 NS_QUERYFRAME_ENTRY(nsScrollbarFrame) |
|
40 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame) |
|
41 |
|
42 void |
|
43 nsScrollbarFrame::Init(nsIContent* aContent, |
|
44 nsIFrame* aParent, |
|
45 nsIFrame* aPrevInFlow) |
|
46 { |
|
47 nsBoxFrame::Init(aContent, aParent, aPrevInFlow); |
|
48 |
|
49 // We want to be a reflow root since we use reflows to move the |
|
50 // slider. Any reflow inside the scrollbar frame will be a reflow to |
|
51 // move the slider and will thus not change anything outside of the |
|
52 // scrollbar or change the size of the scrollbar frame. |
|
53 mState |= NS_FRAME_REFLOW_ROOT; |
|
54 } |
|
55 |
|
56 nsresult |
|
57 nsScrollbarFrame::Reflow(nsPresContext* aPresContext, |
|
58 nsHTMLReflowMetrics& aDesiredSize, |
|
59 const nsHTMLReflowState& aReflowState, |
|
60 nsReflowStatus& aStatus) |
|
61 { |
|
62 nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); |
|
63 NS_ENSURE_SUCCESS(rv, rv); |
|
64 |
|
65 // nsGfxScrollFrame may have told us to shrink to nothing. If so, make sure our |
|
66 // desired size agrees. |
|
67 if (aReflowState.AvailableWidth() == 0) { |
|
68 aDesiredSize.Width() = 0; |
|
69 } |
|
70 if (aReflowState.AvailableHeight() == 0) { |
|
71 aDesiredSize.Height() = 0; |
|
72 } |
|
73 |
|
74 return NS_OK; |
|
75 } |
|
76 |
|
77 nsIAtom* |
|
78 nsScrollbarFrame::GetType() const |
|
79 { |
|
80 return nsGkAtoms::scrollbarFrame; |
|
81 } |
|
82 |
|
83 nsresult |
|
84 nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID, |
|
85 nsIAtom* aAttribute, |
|
86 int32_t aModType) |
|
87 { |
|
88 nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, |
|
89 aModType); |
|
90 |
|
91 // if the current position changes, notify any nsGfxScrollFrame |
|
92 // parent we may have |
|
93 if (aAttribute != nsGkAtoms::curpos) |
|
94 return rv; |
|
95 |
|
96 nsIScrollableFrame* scrollable = do_QueryFrame(GetParent()); |
|
97 if (!scrollable) |
|
98 return rv; |
|
99 |
|
100 nsCOMPtr<nsIContent> kungFuDeathGrip(mContent); |
|
101 scrollable->CurPosAttributeChanged(mContent); |
|
102 return rv; |
|
103 } |
|
104 |
|
105 NS_IMETHODIMP |
|
106 nsScrollbarFrame::HandlePress(nsPresContext* aPresContext, |
|
107 WidgetGUIEvent* aEvent, |
|
108 nsEventStatus* aEventStatus) |
|
109 { |
|
110 return NS_OK; |
|
111 } |
|
112 |
|
113 NS_IMETHODIMP |
|
114 nsScrollbarFrame::HandleMultiplePress(nsPresContext* aPresContext, |
|
115 WidgetGUIEvent* aEvent, |
|
116 nsEventStatus* aEventStatus, |
|
117 bool aControlHeld) |
|
118 { |
|
119 return NS_OK; |
|
120 } |
|
121 |
|
122 NS_IMETHODIMP |
|
123 nsScrollbarFrame::HandleDrag(nsPresContext* aPresContext, |
|
124 WidgetGUIEvent* aEvent, |
|
125 nsEventStatus* aEventStatus) |
|
126 { |
|
127 return NS_OK; |
|
128 } |
|
129 |
|
130 NS_IMETHODIMP |
|
131 nsScrollbarFrame::HandleRelease(nsPresContext* aPresContext, |
|
132 WidgetGUIEvent* aEvent, |
|
133 nsEventStatus* aEventStatus) |
|
134 { |
|
135 return NS_OK; |
|
136 } |
|
137 |
|
138 void |
|
139 nsScrollbarFrame::SetScrollbarMediatorContent(nsIContent* aMediator) |
|
140 { |
|
141 mScrollbarMediator = aMediator; |
|
142 } |
|
143 |
|
144 nsIScrollbarMediator* |
|
145 nsScrollbarFrame::GetScrollbarMediator() |
|
146 { |
|
147 if (!mScrollbarMediator) |
|
148 return nullptr; |
|
149 nsIFrame* f = mScrollbarMediator->GetPrimaryFrame(); |
|
150 |
|
151 // check if the frame is a scroll frame. If so, get the scrollable frame |
|
152 // inside it. |
|
153 nsIScrollableFrame* scrollFrame = do_QueryFrame(f); |
|
154 if (scrollFrame) { |
|
155 f = scrollFrame->GetScrolledFrame(); |
|
156 } |
|
157 |
|
158 nsIScrollbarMediator* sbm = do_QueryFrame(f); |
|
159 return sbm; |
|
160 } |
|
161 |
|
162 nsresult |
|
163 nsScrollbarFrame::GetMargin(nsMargin& aMargin) |
|
164 { |
|
165 aMargin.SizeTo(0,0,0,0); |
|
166 |
|
167 if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { |
|
168 nsPresContext* presContext = PresContext(); |
|
169 nsITheme* theme = presContext->GetTheme(); |
|
170 if (theme) { |
|
171 nsIntSize size; |
|
172 bool isOverridable; |
|
173 nsRefPtr<nsRenderingContext> rc = |
|
174 presContext->PresShell()->CreateReferenceRenderingContext(); |
|
175 theme->GetMinimumWidgetSize(rc, this, NS_THEME_SCROLLBAR, &size, |
|
176 &isOverridable); |
|
177 if (IsHorizontal()) { |
|
178 aMargin.top = -presContext->DevPixelsToAppUnits(size.height); |
|
179 } |
|
180 else { |
|
181 if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { |
|
182 aMargin.right = -presContext->DevPixelsToAppUnits(size.width); |
|
183 } |
|
184 else { |
|
185 aMargin.left = -presContext->DevPixelsToAppUnits(size.width); |
|
186 } |
|
187 } |
|
188 return NS_OK; |
|
189 } |
|
190 } |
|
191 |
|
192 return nsBox::GetMargin(aMargin); |
|
193 } |