1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Dean Tessman <dean_tessman@hotmail.com>
24 * Mats Palmgren <mats.palmgren@bredband.net>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsComboboxControlFrame_h___
41 #define nsComboboxControlFrame_h___
48 //#define DO_REFLOW_DEBUG
49 //#define DO_REFLOW_COUNTER
50 //#define DO_UNCONSTRAINED_CHECK
52 //#define DO_NEW_REFLOW
55 //Mark used to indicate when onchange has been fired for current combobox item
56 #define NS_SKIP_NOTIFY_INDEX -2
58 #include "nsBlockFrame.h"
59 #include "nsIFormControlFrame.h"
60 #include "nsIComboboxControlFrame.h"
61 #include "nsIAnonymousContentCreator.h"
62 #include "nsISelectControlFrame.h"
63 #include "nsIRollupListener.h"
64 #include "nsPresState.h"
65 #include "nsCSSFrameConstructor.h"
66 #include "nsIStatefulFrame.h"
67 #include "nsIScrollableFrame.h"
68 #include "nsIDOMMouseListener.h"
69 #include "nsThreadUtils.h"
73 class nsIListControlFrame
;
74 class nsComboboxDisplayFrame
;
77 * Child list name indices
78 * @see #GetAdditionalChildListName()
80 #define NS_COMBO_LIST_COUNT (NS_BLOCK_LIST_COUNT + 1)
82 class nsComboboxControlFrame
: public nsBlockFrame
,
83 public nsIFormControlFrame
,
84 public nsIComboboxControlFrame
,
85 public nsIAnonymousContentCreator
,
86 public nsISelectControlFrame
,
87 public nsIRollupListener
,
88 public nsIStatefulFrame
91 friend nsIFrame
* NS_NewComboboxControlFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
, PRUint32 aFlags
);
92 friend class nsComboboxDisplayFrame
;
94 nsComboboxControlFrame(nsStyleContext
* aContext
);
95 ~nsComboboxControlFrame();
98 NS_DECL_FRAMEARENA_HELPERS
100 // nsIAnonymousContentCreator
101 virtual nsresult
CreateAnonymousContent(nsTArray
<nsIContent
*>& aElements
);
102 virtual void AppendAnonymousContentTo(nsBaseContentList
& aElements
,
104 virtual nsIFrame
* CreateFrameFor(nsIContent
* aContent
);
107 virtual already_AddRefed
<nsAccessible
> CreateAccessible();
110 virtual nscoord
GetMinWidth(nsIRenderingContext
*aRenderingContext
);
112 virtual nscoord
GetPrefWidth(nsIRenderingContext
*aRenderingContext
);
114 NS_IMETHOD
Reflow(nsPresContext
* aCX
,
115 nsHTMLReflowMetrics
& aDesiredSize
,
116 const nsHTMLReflowState
& aReflowState
,
117 nsReflowStatus
& aStatus
);
119 NS_IMETHOD
HandleEvent(nsPresContext
* aPresContext
,
121 nsEventStatus
* aEventStatus
);
123 NS_IMETHOD
BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
124 const nsRect
& aDirtyRect
,
125 const nsDisplayListSet
& aLists
);
127 void PaintFocus(nsIRenderingContext
& aRenderingContext
, nsPoint aPt
);
129 // XXXbz this is only needed to prevent the quirk percent height stuff from
130 // leaking out of the combobox. We may be able to get rid of this as more
131 // things move to IsFrameOfType.
132 virtual nsIAtom
* GetType() const;
134 virtual PRBool
IsFrameOfType(PRUint32 aFlags
) const
136 return nsBlockFrame::IsFrameOfType(aFlags
&
137 ~(nsIFrame::eReplaced
| nsIFrame::eReplacedContainsBlock
));
140 virtual nsIScrollableFrame
* GetScrollTargetFrame() {
141 return do_QueryFrame(mDropdownFrame
);
145 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const;
147 virtual void DestroyFrom(nsIFrame
* aDestructRoot
);
148 virtual nsFrameList
GetChildList(nsIAtom
* aListName
) const;
149 NS_IMETHOD
SetInitialChildList(nsIAtom
* aListName
,
150 nsFrameList
& aChildList
);
151 virtual nsIAtom
* GetAdditionalChildListName(PRInt32 aIndex
) const;
153 virtual nsIFrame
* GetContentInsertionFrame();
155 // nsIFormControlFrame
156 virtual nsresult
SetFormProperty(nsIAtom
* aName
, const nsAString
& aValue
);
157 virtual nsresult
GetFormProperty(nsIAtom
* aName
, nsAString
& aValue
) const;
159 * Inform the control that it got (or lost) focus.
160 * If it lost focus, the dropdown menu will be rolled up if needed,
161 * and FireOnChange() will be called.
162 * @param aOn PR_TRUE if got focus, PR_FALSE if lost focus.
163 * @param aRepaint if PR_TRUE then force repaint (NOTE: we always force repaint currently)
164 * @note This method might destroy |this|.
166 virtual void SetFocus(PRBool aOn
, PRBool aRepaint
);
168 //nsIComboboxControlFrame
169 virtual PRBool
IsDroppedDown() { return mDroppedDown
; }
171 * @note This method might destroy |this|.
173 virtual void ShowDropDown(PRBool aDoDropDown
);
174 virtual nsIFrame
* GetDropDown();
175 virtual void SetDropDown(nsIFrame
* aDropDownFrame
);
177 * @note This method might destroy |this|.
179 virtual void RollupFromList();
180 virtual void AbsolutelyPositionDropDown();
181 virtual PRInt32
GetIndexOfDisplayArea();
183 * @note This method might destroy |this|.
185 NS_IMETHOD
RedisplaySelectedText();
186 virtual PRInt32
UpdateRecentIndex(PRInt32 aIndex
);
187 virtual void OnContentReset();
189 // nsISelectControlFrame
190 NS_IMETHOD
AddOption(PRInt32 index
);
191 NS_IMETHOD
RemoveOption(PRInt32 index
);
192 NS_IMETHOD
DoneAddingChildren(PRBool aIsDone
);
193 NS_IMETHOD
OnOptionSelected(PRInt32 aIndex
, PRBool aSelected
);
194 NS_IMETHOD
OnSetSelectedIndex(PRInt32 aOldIndex
, PRInt32 aNewIndex
);
198 * Hide the dropdown menu and stop capturing mouse events.
199 * @note This method might destroy |this|.
201 NS_IMETHOD
Rollup(PRUint32 aCount
, nsIContent
** aLastRolledUp
);
203 * A combobox should roll up if a mousewheel event happens outside of
206 NS_IMETHOD
ShouldRollupOnMouseWheelEvent(PRBool
*aShouldRollup
)
207 { *aShouldRollup
= PR_TRUE
; return NS_OK
;}
210 * A combobox should not roll up if activated by a mouse activate message
213 NS_IMETHOD
ShouldRollupOnMouseActivate(PRBool
*aShouldRollup
)
214 { *aShouldRollup
= PR_FALSE
; return NS_OK
;}
217 NS_IMETHOD
SaveState(SpecialStateID aStateID
, nsPresState
** aState
);
218 NS_IMETHOD
RestoreState(nsPresState
* aState
);
220 static PRBool
ToolkitHasNativePopup();
225 nsresult
ReflowDropdown(nsPresContext
* aPresContext
,
226 const nsHTMLReflowState
& aReflowState
);
228 // Helper for GetMinWidth/GetPrefWidth
229 nscoord
GetIntrinsicWidth(nsIRenderingContext
* aRenderingContext
,
230 nsLayoutUtils::IntrinsicWidthType aType
);
232 class RedisplayTextEvent
;
233 friend class RedisplayTextEvent
;
235 class RedisplayTextEvent
: public nsRunnable
{
238 RedisplayTextEvent(nsComboboxControlFrame
*c
) : mControlFrame(c
) {}
239 void Revoke() { mControlFrame
= nsnull
; }
241 nsComboboxControlFrame
*mControlFrame
;
245 * Show or hide the dropdown list.
246 * @note This method might destroy |this|.
248 void ShowPopup(PRBool aShowPopup
);
251 * Show or hide the dropdown list.
252 * @param aShowList PR_TRUE to show, PR_FALSE to hide the dropdown.
253 * @note This method might destroy |this|.
254 * @return PR_FALSE if this frame is destroyed, PR_TRUE if still alive.
256 PRBool
ShowList(PRBool aShowList
);
257 void CheckFireOnChange();
258 void FireValueChangeEvent();
259 nsresult
RedisplayText(PRInt32 aIndex
);
260 void HandleRedisplayTextEvent();
261 void ActuallyDisplayText(PRBool aNotify
);
263 nsFrameList mPopupFrames
; // additional named child list
264 nsCOMPtr
<nsIContent
> mDisplayContent
; // Anonymous content used to display the current selection
265 nsCOMPtr
<nsIContent
> mButtonContent
; // Anonymous content for the button
266 nsIFrame
* mDisplayFrame
; // frame to display selection
267 nsIFrame
* mButtonFrame
; // button frame
268 nsIFrame
* mDropdownFrame
; // dropdown list frame
269 nsIListControlFrame
* mListControlFrame
; // ListControl Interface for the dropdown frame
271 // The width of our display area. Used by that frame's reflow to
272 // size to the full width except the drop-marker.
273 nscoord mDisplayWidth
;
275 PRPackedBool mDroppedDown
; // Current state of the dropdown list, PR_TRUE is dropped down
276 PRPackedBool mInRedisplayText
;
278 nsRevocableEventPtr
<RedisplayTextEvent
> mRedisplayTextEvent
;
280 PRInt32 mRecentSelectedIndex
;
281 PRInt32 mDisplayedIndex
;
282 nsString mDisplayedOptionText
;
284 // make someone to listen to the button. If its programmatically pressed by someone like Accessibility
285 // then open or close the combo box.
286 nsCOMPtr
<nsIDOMMouseListener
> mButtonListener
;
288 // static class data member for Bug 32920
289 // only one control can be focused at a time
290 static nsComboboxControlFrame
* mFocused
;
292 #ifdef DO_REFLOW_COUNTER