Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLOptGroupElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsIDOMHTMLOptGroupElement.h"
00038 #include "nsIDOMEventReceiver.h"
00039 #include "nsGenericHTMLElement.h"
00040 #include "nsHTMLAtoms.h"
00041 #include "nsStyleConsts.h"
00042 #include "nsPresContext.h"
00043 #include "nsIFrame.h"
00044 #include "nsIFormControlFrame.h"
00045 #include "nsIEventStateManager.h"
00046 #include "nsIDocument.h"
00047 
00048 #include "nsISelectElement.h"
00049 #include "nsIDOMHTMLSelectElement.h"
00050 
00051 
00055 class nsHTMLOptGroupElement : public nsGenericHTMLElement,
00056                               public nsIDOMHTMLOptGroupElement
00057 {
00058 public:
00059   nsHTMLOptGroupElement(nsINodeInfo *aNodeInfo);
00060   virtual ~nsHTMLOptGroupElement();
00061 
00062   // nsISupports
00063   NS_DECL_ISUPPORTS_INHERITED
00064 
00065   // nsIDOMNode
00066   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
00067 
00068   // nsIDOMElement
00069   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
00070 
00071   // nsIDOMHTMLElement
00072   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
00073 
00074   // nsIDOMHTMLOptGroupElement
00075   NS_DECL_NSIDOMHTMLOPTGROUPELEMENT
00076 
00077   // nsIContent
00078   virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00079                                  PRBool aNotify);
00080   virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
00081   virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
00082 
00083   virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
00084                                   nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
00085                                   PRUint32 aFlags,
00086                                   nsEventStatus* aEventStatus);
00087   virtual PRInt32 IntrinsicState() const;
00088 
00089   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00090                    const nsAString& aValue, PRBool aNotify)
00091   {
00092     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
00093   }
00094   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00095                            nsIAtom* aPrefix, const nsAString& aValue,
00096                            PRBool aNotify)
00097   {
00098     nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
00099                                                 aValue, aNotify);
00100 
00101     AfterSetAttr(aNameSpaceID, aName, &aValue, aNotify);
00102     return rv;
00103   }
00104 
00105   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
00106                              PRBool aNotify)
00107   {
00108     nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
00109                                                   aNotify);
00110 
00111     AfterSetAttr(aNameSpaceID, aAttribute, nsnull, aNotify);
00112     return rv;
00113   }
00114 
00115 protected:
00116 
00121   void GetSelect(nsISelectElement **aSelectElement);
00122 
00126   void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00127                     const nsAString* aValue, PRBool aNotify);
00128 };
00129 
00130 
00131 NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup)
00132 
00133 
00134 nsHTMLOptGroupElement::nsHTMLOptGroupElement(nsINodeInfo *aNodeInfo)
00135   : nsGenericHTMLElement(aNodeInfo)
00136 {
00137 }
00138 
00139 nsHTMLOptGroupElement::~nsHTMLOptGroupElement()
00140 {
00141 }
00142 
00143 
00144 NS_IMPL_ADDREF_INHERITED(nsHTMLOptGroupElement, nsGenericElement)
00145 NS_IMPL_RELEASE_INHERITED(nsHTMLOptGroupElement, nsGenericElement)
00146 
00147 
00148 // QueryInterface implementation for nsHTMLOptGroupElement
00149 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLOptGroupElement,
00150                                     nsGenericHTMLElement)
00151   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLOptGroupElement)
00152   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLOptGroupElement)
00153 NS_HTML_CONTENT_INTERFACE_MAP_END
00154 
00155 
00156 NS_IMPL_DOM_CLONENODE(nsHTMLOptGroupElement)
00157 
00158 
00159 NS_IMPL_BOOL_ATTR(nsHTMLOptGroupElement, Disabled, disabled)
00160 NS_IMPL_STRING_ATTR(nsHTMLOptGroupElement, Label, label)
00161 
00162 
00163 nsresult
00164 nsHTMLOptGroupElement::HandleDOMEvent(nsPresContext* aPresContext,
00165                                       nsEvent* aEvent,
00166                                       nsIDOMEvent** aDOMEvent,
00167                                       PRUint32 aFlags,
00168                                       nsEventStatus* aEventStatus)
00169 {
00170   // Do not process any DOM events if the element is disabled
00171   PRBool disabled;
00172   nsresult rv = GetDisabled(&disabled);
00173   if (NS_FAILED(rv) || disabled) {
00174     return rv;
00175   }
00176 
00177   nsIFrame* frame = GetPrimaryFrame(PR_FALSE);
00178   if (frame) {
00179     const nsStyleUserInterface* uiStyle = frame->GetStyleUserInterface();
00180     if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
00181         uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
00182       return NS_OK;
00183     }
00184   }
00185 
00186   return nsGenericHTMLElement::HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
00187                                               aFlags, aEventStatus);
00188 }
00189 
00190 PRInt32
00191 nsHTMLOptGroupElement::IntrinsicState() const
00192 {
00193   PRInt32 state = nsGenericHTMLElement::IntrinsicState();
00194 
00195   PRBool disabled;
00196   GetBoolAttr(nsHTMLAtoms::disabled, &disabled);
00197   if (disabled) {
00198     state |= NS_EVENT_STATE_DISABLED;
00199     state &= ~NS_EVENT_STATE_ENABLED;
00200   } else {
00201     state &= ~NS_EVENT_STATE_DISABLED;
00202     state |= NS_EVENT_STATE_ENABLED;
00203   }
00204 
00205   return state;
00206 }
00207 
00208 void
00209 nsHTMLOptGroupElement::GetSelect(nsISelectElement **aSelectElement)
00210 {
00211   *aSelectElement = nsnull;
00212   for (nsIContent* parent = GetParent(); parent; parent = parent->GetParent()) {
00213     CallQueryInterface(parent, aSelectElement);
00214     if (*aSelectElement) {
00215       break;
00216     }
00217   }
00218 }
00219 
00220 void
00221 nsHTMLOptGroupElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00222                                     const nsAString* aValue, PRBool aNotify)
00223 {
00224   if (aNotify && aNameSpaceID == kNameSpaceID_None &&
00225       aName == nsHTMLAtoms::disabled) {
00226     nsIDocument* document = GetCurrentDoc();
00227     if (document) {
00228       mozAutoDocUpdate(document, UPDATE_CONTENT_STATE, PR_TRUE);
00229       document->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_DISABLED |
00230                                      NS_EVENT_STATE_ENABLED);
00231     }
00232   }
00233 }
00234 
00235 // nsIContent
00236 nsresult
00237 nsHTMLOptGroupElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
00238 {
00239   // Since we're appending, the relevant option index to add after is found
00240   // *after* this optgroup.
00241   nsCOMPtr<nsISelectElement> sel;
00242   GetSelect(getter_AddRefs(sel));
00243   if (sel) {
00244     sel->WillAddOptions(aKid, this, GetChildCount());
00245   }
00246 
00247   // Actually perform the append
00248   return nsGenericHTMLElement::AppendChildTo(aKid, aNotify);
00249 }
00250 
00251 nsresult
00252 nsHTMLOptGroupElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00253                                      PRBool aNotify)
00254 {
00255   nsCOMPtr<nsISelectElement> sel;
00256   GetSelect(getter_AddRefs(sel));
00257   if (sel) {
00258     sel->WillAddOptions(aKid, this, aIndex);
00259   }
00260 
00261   return nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
00262 }
00263 
00264 nsresult
00265 nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
00266 {
00267   nsCOMPtr<nsISelectElement> sel;
00268   GetSelect(getter_AddRefs(sel));
00269   if (sel) {
00270     sel->WillRemoveOptions(this, aIndex);
00271   }
00272 
00273   return nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
00274 }