Bumping manifests a=b2g-bump
[gecko.git] / layout / forms / nsListControlFrame.h
blob81bc9b000e4e68e3fc2d385150241eff4c7d217d
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 #ifndef nsListControlFrame_h___
6 #define nsListControlFrame_h___
8 #ifdef DEBUG_evaughan
9 //#define DEBUG_rods
10 #endif
12 #ifdef DEBUG_rods
13 //#define DO_REFLOW_DEBUG
14 //#define DO_REFLOW_COUNTER
15 //#define DO_UNCONSTRAINED_CHECK
16 //#define DO_PIXELS
17 #endif
19 #include "mozilla/Attributes.h"
20 #include "nsGfxScrollFrame.h"
21 #include "nsIFormControlFrame.h"
22 #include "nsIListControlFrame.h"
23 #include "nsISelectControlFrame.h"
24 #include "nsAutoPtr.h"
25 #include "nsSelectsAreaFrame.h"
27 // X.h defines KeyPress
28 #ifdef KeyPress
29 #undef KeyPress
30 #endif
32 class nsIDOMHTMLSelectElement;
33 class nsIDOMHTMLOptionsCollection;
34 class nsIComboboxControlFrame;
35 class nsPresContext;
36 class nsListEventListener;
38 namespace mozilla {
39 namespace dom {
40 class HTMLOptionElement;
41 class HTMLOptionsCollection;
42 } // namespace dom
43 } // namespace mozilla
45 /**
46 * Frame-based listbox.
49 class nsListControlFrame MOZ_FINAL : public nsHTMLScrollFrame,
50 public nsIFormControlFrame,
51 public nsIListControlFrame,
52 public nsISelectControlFrame
54 public:
55 friend nsContainerFrame* NS_NewListControlFrame(nsIPresShell* aPresShell,
56 nsStyleContext* aContext);
58 NS_DECL_QUERYFRAME
59 NS_DECL_FRAMEARENA_HELPERS
61 // nsIFrame
62 virtual nsresult HandleEvent(nsPresContext* aPresContext,
63 mozilla::WidgetGUIEvent* aEvent,
64 nsEventStatus* aEventStatus) MOZ_OVERRIDE;
66 virtual void SetInitialChildList(ChildListID aListID,
67 nsFrameList& aChildList) MOZ_OVERRIDE;
69 virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
70 virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
72 virtual void Reflow(nsPresContext* aCX,
73 nsHTMLReflowMetrics& aDesiredSize,
74 const nsHTMLReflowState& aReflowState,
75 nsReflowStatus& aStatus) MOZ_OVERRIDE;
77 virtual void Init(nsIContent* aContent,
78 nsContainerFrame* aParent,
79 nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
81 virtual void DidReflow(nsPresContext* aPresContext,
82 const nsHTMLReflowState* aReflowState,
83 nsDidReflowStatus aStatus) MOZ_OVERRIDE;
84 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
86 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
87 const nsRect& aDirtyRect,
88 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
90 virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
92 /**
93 * Get the "type" of the frame
95 * @see nsGkAtoms::scrollFrame
97 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
99 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
101 return nsHTMLScrollFrame::IsFrameOfType(aFlags &
102 ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
105 #ifdef DEBUG_FRAME_DUMP
106 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
107 #endif
109 // nsIFormControlFrame
110 virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
111 virtual void SetFocus(bool aOn = true, bool aRepaint = false) MOZ_OVERRIDE;
113 virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE;
114 virtual bool ShouldPropagateComputedHeightToScrolledContent() const MOZ_OVERRIDE;
116 // for accessibility purposes
117 #ifdef ACCESSIBILITY
118 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
119 #endif
121 // nsIListControlFrame
122 virtual void SetComboboxFrame(nsIFrame* aComboboxFrame) MOZ_OVERRIDE;
123 virtual int32_t GetSelectedIndex() MOZ_OVERRIDE;
124 virtual mozilla::dom::HTMLOptionElement* GetCurrentOption() MOZ_OVERRIDE;
127 * Gets the text of the currently selected item.
128 * If the there are zero items then an empty string is returned
129 * If there is nothing selected, then the 0th item's text is returned.
131 virtual void GetOptionText(uint32_t aIndex, nsAString& aStr) MOZ_OVERRIDE;
133 virtual void CaptureMouseEvents(bool aGrabMouseEvents) MOZ_OVERRIDE;
134 virtual nscoord GetHeightOfARow() MOZ_OVERRIDE;
135 virtual uint32_t GetNumberOfOptions() MOZ_OVERRIDE;
136 virtual void AboutToDropDown() MOZ_OVERRIDE;
139 * @note This method might destroy the frame, pres shell and other objects.
141 virtual void AboutToRollup() MOZ_OVERRIDE;
144 * Dispatch a DOM onchange event synchroniously.
145 * @note This method might destroy the frame, pres shell and other objects.
147 virtual void FireOnChange() MOZ_OVERRIDE;
150 * Makes aIndex the selected option of a combobox list.
151 * @note This method might destroy the frame, pres shell and other objects.
153 virtual void ComboboxFinish(int32_t aIndex) MOZ_OVERRIDE;
154 virtual void OnContentReset() MOZ_OVERRIDE;
156 // nsISelectControlFrame
157 NS_IMETHOD AddOption(int32_t index) MOZ_OVERRIDE;
158 NS_IMETHOD RemoveOption(int32_t index) MOZ_OVERRIDE;
159 NS_IMETHOD DoneAddingChildren(bool aIsDone) MOZ_OVERRIDE;
162 * Gets the content (an option) by index and then set it as
163 * being selected or not selected.
165 NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) MOZ_OVERRIDE;
166 NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
169 * Mouse event listeners.
170 * @note These methods might destroy the frame, pres shell and other objects.
172 nsresult MouseDown(nsIDOMEvent* aMouseEvent);
173 nsresult MouseUp(nsIDOMEvent* aMouseEvent);
174 nsresult MouseMove(nsIDOMEvent* aMouseEvent);
175 nsresult DragMove(nsIDOMEvent* aMouseEvent);
176 nsresult KeyDown(nsIDOMEvent* aKeyEvent);
177 nsresult KeyPress(nsIDOMEvent* aKeyEvent);
180 * Returns the options collection for mContent, if any.
182 mozilla::dom::HTMLOptionsCollection* GetOptions() const;
184 * Returns the HTMLOptionElement for a given index in mContent's collection.
186 mozilla::dom::HTMLOptionElement* GetOption(uint32_t aIndex) const;
188 static void ComboboxFocusSet();
190 // Helper
191 bool IsFocused() { return this == mFocused; }
194 * Function to paint the focus rect when our nsSelectsAreaFrame is painting.
195 * @param aPt the offset of this frame, relative to the rendering reference
196 * frame
198 void PaintFocus(nsRenderingContext& aRC, nsPoint aPt);
200 * If this frame IsFocused(), invalidates an area that includes anything
201 * that PaintFocus will or could have painted --- basically the whole
202 * GetOptionsContainer, plus some extra stuff if there are no options. This
203 * must be called every time mEndSelectionIndex changes.
205 void InvalidateFocus();
208 * Function to calculate the height a row, for use with the "size" attribute.
209 * Can't be const because GetNumberOfOptions() isn't const.
211 nscoord CalcHeightOfARow();
214 * Function to ask whether we're currently in what might be the
215 * first pass of a two-pass reflow.
217 bool MightNeedSecondPass() const {
218 return mMightNeedSecondPass;
221 void SetSuppressScrollbarUpdate(bool aSuppress) {
222 nsHTMLScrollFrame::SetSuppressScrollbarUpdate(aSuppress);
226 * Return whether the list is in dropdown mode.
228 bool IsInDropDownMode() const;
231 * Return the number of displayed rows in the list.
233 uint32_t GetNumDisplayRows() const { return mNumDisplayRows; }
236 * Return true if the drop-down list can display more rows.
237 * (always false if not in drop-down mode)
239 bool GetDropdownCanGrow() const { return mDropdownCanGrow; }
242 * Dropdowns need views
244 virtual bool NeedsView() MOZ_OVERRIDE { return IsInDropDownMode(); }
247 * Frees statics owned by this class.
249 static void Shutdown();
251 #ifdef ACCESSIBILITY
253 * Post a custom DOM event for the change, so that accessibility can
254 * fire a native focus event for accessibility
255 * (Some 3rd party products need to track our focus)
257 void FireMenuItemActiveEvent(); // Inform assistive tech what got focused
258 #endif
260 protected:
262 * Updates the selected text in a combobox and then calls FireOnChange().
263 * @note This method might destroy the frame, pres shell and other objects.
264 * Returns false if calling it destroyed |this|.
266 bool UpdateSelection();
269 * Returns whether mContent supports multiple selection.
271 bool GetMultiple() const {
272 return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
277 * Toggles (show/hide) the combobox dropdown menu.
278 * @note This method might destroy the frame, pres shell and other objects.
280 void DropDownToggleKey(nsIDOMEvent* aKeyEvent);
282 nsresult IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
284 * @note This method might destroy the frame, pres shell and other objects.
286 void ScrollToFrame(mozilla::dom::HTMLOptionElement& aOptElement);
288 * @note This method might destroy the frame, pres shell and other objects.
290 void ScrollToIndex(int32_t anIndex);
293 * When the user clicks on the comboboxframe to show the dropdown
294 * listbox, they then have to move the mouse into the list. We don't
295 * want to process those mouse events as selection events (i.e., to
296 * scroll list items into view). So we ignore the events until
297 * the mouse moves below our border-inner-edge, when
298 * mItemSelectionStarted is set.
300 * @param aPoint relative to this frame
302 bool IgnoreMouseEventForSelection(nsIDOMEvent* aEvent);
305 * If the dropdown is showing and the mouse has moved below our
306 * border-inner-edge, then set mItemSelectionStarted.
308 void UpdateInListState(nsIDOMEvent* aEvent);
309 void AdjustIndexForDisabledOpt(int32_t aStartIndex, int32_t &anNewIndex,
310 int32_t aNumOptions, int32_t aDoAdjustInc, int32_t aDoAdjustIncNext);
313 * Resets the select back to it's original default values;
314 * those values as determined by the original HTML
316 virtual void ResetList(bool aAllowScrolling);
318 explicit nsListControlFrame(nsStyleContext* aContext);
319 virtual ~nsListControlFrame();
322 * Sets the mSelectedIndex and mOldSelectedIndex from figuring out what
323 * item was selected using content
324 * @param aPoint the event point, in listcontrolframe coordinates
325 * @return NS_OK if it successfully found the selection
327 nsresult GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, int32_t& aCurIndex);
329 bool CheckIfAllFramesHere();
330 bool IsLeftButton(nsIDOMEvent* aMouseEvent);
332 // guess at a row height based on our own style.
333 nscoord CalcFallbackRowHeight(float aFontSizeInflation);
335 // CalcIntrinsicBSize computes our intrinsic height (taking the "size"
336 // attribute into account). This should only be called in non-dropdown mode.
337 nscoord CalcIntrinsicBSize(nscoord aHeightOfARow, int32_t aNumberOfOptions);
339 // Dropped down stuff
340 void SetComboboxItem(int32_t aIndex);
343 * Method to reflow ourselves as a dropdown list. This differs from
344 * reflow as a listbox because the criteria for needing a second
345 * pass are different. This will be called from Reflow() as needed.
347 void ReflowAsDropdown(nsPresContext* aPresContext,
348 nsHTMLReflowMetrics& aDesiredSize,
349 const nsHTMLReflowState& aReflowState,
350 nsReflowStatus& aStatus);
352 // Selection
353 bool SetOptionsSelectedFromFrame(int32_t aStartIndex,
354 int32_t aEndIndex,
355 bool aValue,
356 bool aClearAll);
357 bool ToggleOptionSelectedFromFrame(int32_t aIndex);
359 * @note This method might destroy the frame, pres shell and other objects.
361 bool SingleSelection(int32_t aClickedIndex, bool aDoToggle);
362 bool ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
363 bool aClearAll);
365 * @note This method might destroy the frame, pres shell and other objects.
367 bool PerformSelection(int32_t aClickedIndex, bool aIsShift,
368 bool aIsControl);
370 * @note This method might destroy the frame, pres shell and other objects.
372 bool HandleListSelection(nsIDOMEvent * aDOMEvent, int32_t selectedIndex);
373 void InitSelectionRange(int32_t aClickedIndex);
374 void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
375 bool aIsShift, bool aIsControlOrMeta);
377 public:
378 nsSelectsAreaFrame* GetOptionsContainer() const {
379 return static_cast<nsSelectsAreaFrame*>(GetScrolledFrame());
382 protected:
383 nscoord HeightOfARow() {
384 return GetOptionsContainer()->HeightOfARow();
388 * @return how many displayable options/optgroups this frame has.
390 uint32_t GetNumberOfRows();
392 // Data Members
393 int32_t mStartSelectionIndex;
394 int32_t mEndSelectionIndex;
396 nsIComboboxControlFrame *mComboboxFrame;
397 uint32_t mNumDisplayRows;
398 bool mChangesSinceDragStart:1;
399 bool mButtonDown:1;
400 // Has the user selected a visible item since we showed the
401 // dropdown?
402 bool mItemSelectionStarted:1;
404 bool mIsAllContentHere:1;
405 bool mIsAllFramesHere:1;
406 bool mHasBeenInitialized:1;
407 bool mNeedToReset:1;
408 bool mPostChildrenLoadedReset:1;
410 //bool value for multiple discontiguous selection
411 bool mControlSelectMode:1;
413 // True if we're in the middle of a reflow and might need a second
414 // pass. This only happens for auto heights.
415 bool mMightNeedSecondPass:1;
418 * Set to aPresContext->HasPendingInterrupt() at the start of Reflow.
419 * Set to false at the end of DidReflow.
421 bool mHasPendingInterruptAtStartOfReflow:1;
423 // True if the drop-down can show more rows. Always false if this list
424 // is not in drop-down mode.
425 bool mDropdownCanGrow:1;
427 // True if the selection can be set to nothing or disabled options.
428 bool mForceSelection:1;
430 // The last computed height we reflowed at if we're a combobox dropdown.
431 // XXXbz should we be using a subclass here? Or just not worry
432 // about the extra member on listboxes?
433 nscoord mLastDropdownComputedHeight;
435 // At the time of our last dropdown, the backstop color to draw in case we
436 // are translucent.
437 nscolor mLastDropdownBackstopColor;
439 nsRefPtr<nsListEventListener> mEventListener;
441 static nsListControlFrame * mFocused;
442 static nsString * sIncrementalString;
444 #ifdef DO_REFLOW_COUNTER
445 int32_t mReflowId;
446 #endif
448 private:
449 // for incremental typing navigation
450 static nsAString& GetIncrementalString ();
451 static DOMTimeStamp gLastKeyTime;
453 class MOZ_STACK_CLASS AutoIncrementalSearchResetter
455 public:
456 AutoIncrementalSearchResetter() :
457 mCancelled(false)
460 ~AutoIncrementalSearchResetter()
462 if (!mCancelled) {
463 nsListControlFrame::GetIncrementalString().Truncate();
466 void Cancel()
468 mCancelled = true;
470 private:
471 bool mCancelled;
475 #endif /* nsListControlFrame_h___ */