Backout a74bd5095902, Bug 959405 - Please update the Buri Moz-central, 1.3, 1.2 with...
[gecko.git] / layout / forms / nsListControlFrame.h
blob8dc8cab598ab4a702e2514bd94110e07f00b78aa
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 : public nsHTMLScrollFrame,
50 public nsIFormControlFrame,
51 public nsIListControlFrame,
52 public nsISelectControlFrame
54 public:
55 friend nsIFrame* NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
57 NS_DECL_QUERYFRAME
58 NS_DECL_FRAMEARENA_HELPERS
60 // nsIFrame
61 NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
62 mozilla::WidgetGUIEvent* aEvent,
63 nsEventStatus* aEventStatus) MOZ_OVERRIDE;
65 NS_IMETHOD SetInitialChildList(ChildListID aListID,
66 nsFrameList& aChildList) MOZ_OVERRIDE;
68 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
69 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
71 NS_IMETHOD Reflow(nsPresContext* aCX,
72 nsHTMLReflowMetrics& aDesiredSize,
73 const nsHTMLReflowState& aReflowState,
74 nsReflowStatus& aStatus) MOZ_OVERRIDE;
76 virtual void Init(nsIContent* aContent,
77 nsIFrame* aParent,
78 nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
80 NS_IMETHOD DidReflow(nsPresContext* aPresContext,
81 const nsHTMLReflowState* aReflowState,
82 nsDidReflowStatus aStatus) MOZ_OVERRIDE;
83 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
85 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
86 const nsRect& aDirtyRect,
87 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
89 virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
91 /**
92 * Get the "type" of the frame
94 * @see nsGkAtoms::scrollFrame
96 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
98 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
100 return nsHTMLScrollFrame::IsFrameOfType(aFlags &
101 ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
104 #ifdef DEBUG_FRAME_DUMP
105 NS_IMETHOD GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
106 #endif
108 // nsIFormControlFrame
109 virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
110 virtual void SetFocus(bool aOn = true, bool aRepaint = false) MOZ_OVERRIDE;
112 virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE;
113 virtual bool ShouldPropagateComputedHeightToScrolledContent() const MOZ_OVERRIDE;
115 // for accessibility purposes
116 #ifdef ACCESSIBILITY
117 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
118 #endif
120 // nsIListControlFrame
121 virtual void SetComboboxFrame(nsIFrame* aComboboxFrame) MOZ_OVERRIDE;
122 virtual int32_t GetSelectedIndex() MOZ_OVERRIDE;
123 virtual mozilla::dom::HTMLOptionElement* GetCurrentOption() MOZ_OVERRIDE;
126 * Gets the text of the currently selected item.
127 * If the there are zero items then an empty string is returned
128 * If there is nothing selected, then the 0th item's text is returned.
130 virtual void GetOptionText(uint32_t aIndex, nsAString& aStr) MOZ_OVERRIDE;
132 virtual void CaptureMouseEvents(bool aGrabMouseEvents) MOZ_OVERRIDE;
133 virtual nscoord GetHeightOfARow() MOZ_OVERRIDE;
134 virtual uint32_t GetNumberOfOptions() MOZ_OVERRIDE;
135 virtual void AboutToDropDown() MOZ_OVERRIDE;
138 * @note This method might destroy the frame, pres shell and other objects.
140 virtual void AboutToRollup() MOZ_OVERRIDE;
143 * Dispatch a DOM onchange event synchroniously.
144 * @note This method might destroy the frame, pres shell and other objects.
146 virtual void FireOnChange() MOZ_OVERRIDE;
149 * Makes aIndex the selected option of a combobox list.
150 * @note This method might destroy the frame, pres shell and other objects.
152 virtual void ComboboxFinish(int32_t aIndex) MOZ_OVERRIDE;
153 virtual void OnContentReset() MOZ_OVERRIDE;
155 // nsISelectControlFrame
156 NS_IMETHOD AddOption(int32_t index) MOZ_OVERRIDE;
157 NS_IMETHOD RemoveOption(int32_t index) MOZ_OVERRIDE;
158 NS_IMETHOD DoneAddingChildren(bool aIsDone) MOZ_OVERRIDE;
161 * Gets the content (an option) by index and then set it as
162 * being selected or not selected.
164 NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) MOZ_OVERRIDE;
165 NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
168 * Mouse event listeners.
169 * @note These methods might destroy the frame, pres shell and other objects.
171 nsresult MouseDown(nsIDOMEvent* aMouseEvent);
172 nsresult MouseUp(nsIDOMEvent* aMouseEvent);
173 nsresult MouseMove(nsIDOMEvent* aMouseEvent);
174 nsresult DragMove(nsIDOMEvent* aMouseEvent);
175 nsresult KeyDown(nsIDOMEvent* aKeyEvent);
176 nsresult KeyPress(nsIDOMEvent* aKeyEvent);
179 * Returns the options collection for mContent, if any.
181 mozilla::dom::HTMLOptionsCollection* GetOptions() const;
183 * Returns the HTMLOptionElement for a given index in mContent's collection.
185 mozilla::dom::HTMLOptionElement* GetOption(uint32_t aIndex) const;
187 static void ComboboxFocusSet();
189 // Helper
190 bool IsFocused() { return this == mFocused; }
193 * Function to paint the focus rect when our nsSelectsAreaFrame is painting.
194 * @param aPt the offset of this frame, relative to the rendering reference
195 * frame
197 void PaintFocus(nsRenderingContext& aRC, nsPoint aPt);
199 * If this frame IsFocused(), invalidates an area that includes anything
200 * that PaintFocus will or could have painted --- basically the whole
201 * GetOptionsContainer, plus some extra stuff if there are no options. This
202 * must be called every time mEndSelectionIndex changes.
204 void InvalidateFocus();
207 * Function to calculate the height a row, for use with the "size" attribute.
208 * Can't be const because GetNumberOfOptions() isn't const.
210 nscoord CalcHeightOfARow();
213 * Function to ask whether we're currently in what might be the
214 * first pass of a two-pass reflow.
216 bool MightNeedSecondPass() const {
217 return mMightNeedSecondPass;
220 void SetSuppressScrollbarUpdate(bool aSuppress) {
221 nsHTMLScrollFrame::SetSuppressScrollbarUpdate(aSuppress);
225 * Return whether the list is in dropdown mode.
227 bool IsInDropDownMode() const;
230 * Return the number of displayed rows in the list.
232 uint32_t GetNumDisplayRows() const { return mNumDisplayRows; }
235 * Return true if the drop-down list can display more rows.
236 * (always false if not in drop-down mode)
238 bool GetDropdownCanGrow() const { return mDropdownCanGrow; }
241 * Dropdowns need views
243 virtual bool NeedsView() MOZ_OVERRIDE { return IsInDropDownMode(); }
246 * Frees statics owned by this class.
248 static void Shutdown();
250 #ifdef ACCESSIBILITY
252 * Post a custom DOM event for the change, so that accessibility can
253 * fire a native focus event for accessibility
254 * (Some 3rd party products need to track our focus)
256 void FireMenuItemActiveEvent(); // Inform assistive tech what got focused
257 #endif
259 protected:
261 * Updates the selected text in a combobox and then calls FireOnChange().
262 * @note This method might destroy the frame, pres shell and other objects.
263 * Returns false if calling it destroyed |this|.
265 bool UpdateSelection();
268 * Returns whether mContent supports multiple selection.
270 bool GetMultiple() const {
271 return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
276 * Toggles (show/hide) the combobox dropdown menu.
277 * @note This method might destroy the frame, pres shell and other objects.
279 void DropDownToggleKey(nsIDOMEvent* aKeyEvent);
281 nsresult IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
283 * @note This method might destroy the frame, pres shell and other objects.
285 void ScrollToFrame(mozilla::dom::HTMLOptionElement& aOptElement);
287 * @note This method might destroy the frame, pres shell and other objects.
289 void ScrollToIndex(int32_t anIndex);
292 * When the user clicks on the comboboxframe to show the dropdown
293 * listbox, they then have to move the mouse into the list. We don't
294 * want to process those mouse events as selection events (i.e., to
295 * scroll list items into view). So we ignore the events until
296 * the mouse moves below our border-inner-edge, when
297 * mItemSelectionStarted is set.
299 * @param aPoint relative to this frame
301 bool IgnoreMouseEventForSelection(nsIDOMEvent* aEvent);
304 * If the dropdown is showing and the mouse has moved below our
305 * border-inner-edge, then set mItemSelectionStarted.
307 void UpdateInListState(nsIDOMEvent* aEvent);
308 void AdjustIndexForDisabledOpt(int32_t aStartIndex, int32_t &anNewIndex,
309 int32_t aNumOptions, int32_t aDoAdjustInc, int32_t aDoAdjustIncNext);
312 * Resets the select back to it's original default values;
313 * those values as determined by the original HTML
315 virtual void ResetList(bool aAllowScrolling);
317 nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument, nsStyleContext* aContext);
318 virtual ~nsListControlFrame();
321 * Sets the mSelectedIndex and mOldSelectedIndex from figuring out what
322 * item was selected using content
323 * @param aPoint the event point, in listcontrolframe coordinates
324 * @return NS_OK if it successfully found the selection
326 nsresult GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, int32_t& aCurIndex);
328 bool CheckIfAllFramesHere();
329 bool IsLeftButton(nsIDOMEvent* aMouseEvent);
331 // guess at a row height based on our own style.
332 nscoord CalcFallbackRowHeight(float aFontSizeInflation);
334 // CalcIntrinsicHeight computes our intrinsic height (taking the "size"
335 // attribute into account). This should only be called in non-dropdown mode.
336 nscoord CalcIntrinsicHeight(nscoord aHeightOfARow, int32_t aNumberOfOptions);
338 // Dropped down stuff
339 void SetComboboxItem(int32_t aIndex);
342 * Method to reflow ourselves as a dropdown list. This differs from
343 * reflow as a listbox because the criteria for needing a second
344 * pass are different. This will be called from Reflow() as needed.
346 nsresult ReflowAsDropdown(nsPresContext* aPresContext,
347 nsHTMLReflowMetrics& aDesiredSize,
348 const nsHTMLReflowState& aReflowState,
349 nsReflowStatus& aStatus);
351 // Selection
352 bool SetOptionsSelectedFromFrame(int32_t aStartIndex,
353 int32_t aEndIndex,
354 bool aValue,
355 bool aClearAll);
356 bool ToggleOptionSelectedFromFrame(int32_t aIndex);
358 * @note This method might destroy the frame, pres shell and other objects.
360 bool SingleSelection(int32_t aClickedIndex, bool aDoToggle);
361 bool ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
362 bool aClearAll);
364 * @note This method might destroy the frame, pres shell and other objects.
366 bool PerformSelection(int32_t aClickedIndex, bool aIsShift,
367 bool aIsControl);
369 * @note This method might destroy the frame, pres shell and other objects.
371 bool HandleListSelection(nsIDOMEvent * aDOMEvent, int32_t selectedIndex);
372 void InitSelectionRange(int32_t aClickedIndex);
373 void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
374 bool aIsShift, bool aIsControlOrMeta);
376 public:
377 nsSelectsAreaFrame* GetOptionsContainer() const {
378 return static_cast<nsSelectsAreaFrame*>(GetScrolledFrame());
381 protected:
382 nscoord HeightOfARow() {
383 return GetOptionsContainer()->HeightOfARow();
387 * @return how many displayable options/optgroups this frame has.
389 uint32_t GetNumberOfRows();
391 // Data Members
392 int32_t mStartSelectionIndex;
393 int32_t mEndSelectionIndex;
395 nsIComboboxControlFrame *mComboboxFrame;
396 uint32_t mNumDisplayRows;
397 bool mChangesSinceDragStart:1;
398 bool mButtonDown:1;
399 // Has the user selected a visible item since we showed the
400 // dropdown?
401 bool mItemSelectionStarted:1;
403 bool mIsAllContentHere:1;
404 bool mIsAllFramesHere:1;
405 bool mHasBeenInitialized:1;
406 bool mNeedToReset:1;
407 bool mPostChildrenLoadedReset:1;
409 //bool value for multiple discontiguous selection
410 bool mControlSelectMode:1;
412 // True if we're in the middle of a reflow and might need a second
413 // pass. This only happens for auto heights.
414 bool mMightNeedSecondPass:1;
417 * Set to aPresContext->HasPendingInterrupt() at the start of Reflow.
418 * Set to false at the end of DidReflow.
420 bool mHasPendingInterruptAtStartOfReflow:1;
422 // True if the drop-down can show more rows. Always false if this list
423 // is not in drop-down mode.
424 bool mDropdownCanGrow:1;
426 // The last computed height we reflowed at if we're a combobox dropdown.
427 // XXXbz should we be using a subclass here? Or just not worry
428 // about the extra member on listboxes?
429 nscoord mLastDropdownComputedHeight;
431 // At the time of our last dropdown, the backstop color to draw in case we
432 // are translucent.
433 nscolor mLastDropdownBackstopColor;
435 nsRefPtr<nsListEventListener> mEventListener;
437 static nsListControlFrame * mFocused;
438 static nsString * sIncrementalString;
440 #ifdef DO_REFLOW_COUNTER
441 int32_t mReflowId;
442 #endif
444 private:
445 // for incremental typing navigation
446 static nsAString& GetIncrementalString ();
447 static DOMTimeStamp gLastKeyTime;
450 #endif /* nsListControlFrame_h___ */