nsRangeFrame.h (6586B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef nsRangeFrame_h___ 8 #define nsRangeFrame_h___ 9 10 #include "mozilla/Decimal.h" 11 #include "mozilla/EventForwards.h" 12 #include "nsCOMPtr.h" 13 #include "nsContainerFrame.h" 14 #include "nsIAnonymousContentCreator.h" 15 #include "nsTArray.h" 16 17 class nsDisplayRangeFocusRing; 18 19 namespace mozilla { 20 class ListMutationObserver; 21 class PresShell; 22 namespace dom { 23 class Event; 24 class HTMLInputElement; 25 } // namespace dom 26 } // namespace mozilla 27 28 class nsRangeFrame final : public nsContainerFrame, 29 public nsIAnonymousContentCreator { 30 friend nsIFrame* NS_NewRangeFrame(mozilla::PresShell* aPresShell, 31 ComputedStyle* aStyle); 32 33 void Init(nsIContent* aContent, nsContainerFrame* aParent, 34 nsIFrame* aPrevInFlow) override; 35 36 friend class nsDisplayRangeFocusRing; 37 38 explicit nsRangeFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); 39 virtual ~nsRangeFrame(); 40 41 using Element = mozilla::dom::Element; 42 43 public: 44 NS_DECL_QUERYFRAME 45 NS_DECL_FRAMEARENA_HELPERS(nsRangeFrame) 46 47 // nsIFrame overrides 48 void Destroy(DestroyContext&) override; 49 50 void BuildDisplayList(nsDisplayListBuilder* aBuilder, 51 const nsDisplayListSet& aLists) override; 52 53 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, 54 const ReflowInput& aReflowInput, 55 nsReflowStatus& aStatus) override; 56 57 #ifdef DEBUG_FRAME_DUMP 58 nsresult GetFrameName(nsAString& aResult) const override { 59 return MakeFrameName(u"Range"_ns, aResult); 60 } 61 #endif 62 63 #ifdef ACCESSIBILITY 64 mozilla::a11y::AccType AccessibleType() override; 65 #endif 66 67 // nsIAnonymousContentCreator 68 nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override; 69 void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, 70 uint32_t aFilter) override; 71 72 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 73 AttrModType aModType) override; 74 75 nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput, 76 mozilla::IntrinsicISizeType aType) override; 77 78 /** 79 * Returns true if the slider's thumb moves horizontally, or else false if it 80 * moves vertically. 81 */ 82 bool IsHorizontal() const; 83 84 /** 85 * Returns true if the slider is oriented along the inline axis. 86 */ 87 bool IsInlineOriented() const { 88 return IsHorizontal() != GetWritingMode().IsVertical(); 89 } 90 91 /** 92 * Returns true if the slider's thumb moves right-to-left for increasing 93 * values; only relevant when IsHorizontal() is true. 94 */ 95 bool IsRightToLeft() const { 96 MOZ_ASSERT(IsHorizontal()); 97 return GetWritingMode().IsPhysicalRTL(); 98 } 99 100 /** 101 * Returns true if the range progresses upwards (for vertical ranges in 102 * horizontal writing mode, or for bidi-RTL in vertical mode). Only 103 * relevant when IsHorizontal() is false. 104 */ 105 bool IsUpwards() const { 106 MOZ_ASSERT(!IsHorizontal()); 107 mozilla::WritingMode wm = GetWritingMode(); 108 return wm.GetBlockDir() == mozilla::WritingMode::BlockDir::TB || 109 wm.GetInlineDir() == mozilla::WritingMode::InlineDir::BTT; 110 } 111 112 double GetMin() const; 113 double GetMax() const; 114 double GetValue() const; 115 116 /** 117 * Returns the input element's value as a fraction of the difference between 118 * the input's minimum and its maximum (i.e. returns 0.0 when the value is 119 * the same as the minimum, and returns 1.0 when the value is the same as the 120 * maximum). 121 */ 122 double GetValueAsFractionOfRange(); 123 124 /** 125 * Returns the given value as a fraction of the difference between the input's 126 * minimum and its maximum (i.e. returns 0.0 when the value is the same as the 127 * input's minimum, and returns 1.0 when the value is the same as the input's 128 * maximum). 129 */ 130 double GetDoubleAsFractionOfRange(const mozilla::Decimal& value); 131 132 /** 133 * Returns whether the frame and its child should use the native style. 134 */ 135 bool ShouldUseNativeStyle() const; 136 137 mozilla::Decimal GetValueAtEventPoint(mozilla::WidgetGUIEvent* aEvent); 138 139 /** 140 * Helper that's used when the value of the range changes to reposition the 141 * thumb, resize the range-progress element, and schedule a repaint. (This 142 * does not reflow, since the position and size of the thumb and 143 * range-progress element do not affect the position or size of any other 144 * frames.) 145 */ 146 void UpdateForValueChange(); 147 148 nsTArray<mozilla::Decimal> TickMarks(); 149 150 /** 151 * Returns the given value's offset from the range's nearest list tick mark 152 * or NaN if there are no tick marks. 153 */ 154 mozilla::Decimal NearestTickMark(const mozilla::Decimal& aValue); 155 156 protected: 157 mozilla::dom::HTMLInputElement& InputElement() const; 158 159 private: 160 // Return our preferred size in the cross-axis (the axis perpendicular 161 // to the direction of movement of the thumb). 162 nscoord AutoCrossSize(); 163 164 // Helper function which reflows the anonymous div frames. 165 void ReflowAnonymousContent(nsPresContext* aPresContext, 166 ReflowOutput& aDesiredSize, 167 const mozilla::LogicalSize& aContentBoxSize, 168 const ReflowInput& aReflowInput); 169 170 void DoUpdateThumbPosition(nsIFrame* aThumbFrame, 171 const nsSize& aRangeContentBoxSize); 172 173 void DoUpdateRangeProgressFrame(nsIFrame* aProgressFrame, 174 const nsSize& aRangeContentBoxSize); 175 176 /** 177 * The div used to show the ::-moz-range-track pseudo-element. 178 * @see nsRangeFrame::CreateAnonymousContent 179 */ 180 nsCOMPtr<Element> mTrackDiv; 181 182 /** 183 * The div used to show the ::-moz-range-progress pseudo-element, which is 184 * used to (optionally) style the specific chunk of track leading up to the 185 * thumb's current position. 186 * @see nsRangeFrame::CreateAnonymousContent 187 */ 188 nsCOMPtr<Element> mProgressDiv; 189 190 /** 191 * The div used to show the ::-moz-range-thumb pseudo-element. 192 * @see nsRangeFrame::CreateAnonymousContent 193 */ 194 nsCOMPtr<Element> mThumbDiv; 195 196 /** 197 * This mutation observer is used to invalidate paint when the @list changes, 198 * when a @list exists. 199 */ 200 RefPtr<mozilla::ListMutationObserver> mListMutationObserver; 201 }; 202 203 #endif