Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLTableRowElement.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 "nsIDOMHTMLTableRowElement.h"
00038 #include "nsIDOMHTMLTableElement.h"
00039 #include "nsIDOMHTMLTableSectionElem.h"
00040 #include "nsIDOMHTMLTableCellElement.h"
00041 #include "nsIDOMEventReceiver.h"
00042 #include "nsDOMError.h"
00043 #include "nsMappedAttributes.h"
00044 #include "nsGenericHTMLElement.h"
00045 #include "nsContentList.h"
00046 #include "nsHTMLAtoms.h"
00047 #include "nsStyleConsts.h"
00048 #include "nsPresContext.h"
00049 #include "nsHTMLParts.h"
00050 #include "nsRuleData.h"
00051 
00052 // temporary
00053 #include "nsIDocument.h"
00054 #include "nsIPresShell.h"
00055 #include "nsIFrame.h"
00056 
00057 class nsHTMLTableRowElement : public nsGenericHTMLElement,
00058                               public nsIDOMHTMLTableRowElement
00059 {
00060 public:
00061   nsHTMLTableRowElement(nsINodeInfo *aNodeInfo);
00062   virtual ~nsHTMLTableRowElement();
00063 
00064   // nsISupports
00065   NS_DECL_ISUPPORTS_INHERITED
00066 
00067   // nsIDOMNode
00068   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
00069 
00070   // nsIDOMElement
00071   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
00072 
00073   // nsIDOMHTMLElement
00074   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
00075 
00076   // nsIDOMHTMLTableRowElement
00077   NS_DECL_NSIDOMHTMLTABLEROWELEMENT
00078 
00079   virtual PRBool ParseAttribute(nsIAtom* aAttribute,
00080                                 const nsAString& aValue,
00081                                 nsAttrValue& aResult);
00082   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
00083   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
00084 
00085 protected:
00086   nsresult GetSection(nsIDOMHTMLTableSectionElement** aSection);
00087   nsresult GetTable(nsIDOMHTMLTableElement** aTable);
00088   nsRefPtr<nsContentList> mCells;
00089 };
00090 
00091 #ifdef XXX_debugging
00092 static
00093 void DebugList(nsIDOMHTMLTableElement* aTable) {
00094   nsCOMPtr<nsIContent> content = do_QueryInterface(aTable);
00095   if (content) {
00096     nsCOMPtr<nsIDocument> doc;
00097     result = content->GetDocument(getter_AddRefs(doc));
00098     if (doc) {
00099       nsCOMPtr<nsIContent> root;
00100       doc->GetRootContent(getter_AddRefs(root));
00101       if (root) {
00102         root->List();
00103       }
00104       nsIPresShell *shell = doc->GetShellAt(0);
00105       if (shell) {
00106         nsIFrame* rootFrame = shell->FrameManager()->GetRootFrame();
00107         if (rootFrame) {
00108           rootFrame->List(stdout, 0);
00109         }
00110       }
00111     }
00112   }
00113 }
00114 #endif 
00115 
00116 
00117 NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow)
00118 
00119 
00120 nsHTMLTableRowElement::nsHTMLTableRowElement(nsINodeInfo *aNodeInfo)
00121   : nsGenericHTMLElement(aNodeInfo)
00122 {
00123 }
00124 
00125 nsHTMLTableRowElement::~nsHTMLTableRowElement()
00126 {
00127   if (mCells) {
00128     mCells->RootDestroyed();
00129   }
00130 }
00131 
00132 
00133 NS_IMPL_ADDREF_INHERITED(nsHTMLTableRowElement, nsGenericElement) 
00134 NS_IMPL_RELEASE_INHERITED(nsHTMLTableRowElement, nsGenericElement) 
00135 
00136 
00137 // QueryInterface implementation for nsHTMLTableRowElement
00138 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLTableRowElement,
00139                                     nsGenericHTMLElement)
00140   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLTableRowElement)
00141   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLTableRowElement)
00142 NS_HTML_CONTENT_INTERFACE_MAP_END
00143 
00144 
00145 NS_IMPL_DOM_CLONENODE(nsHTMLTableRowElement)
00146 
00147 
00148 // protected method
00149 nsresult
00150 nsHTMLTableRowElement::GetSection(nsIDOMHTMLTableSectionElement** aSection)
00151 {
00152   NS_ENSURE_ARG_POINTER(aSection);
00153   *aSection = nsnull;
00154 
00155   nsCOMPtr<nsIDOMNode> sectionNode;
00156   nsresult rv = GetParentNode(getter_AddRefs(sectionNode));
00157   if (NS_SUCCEEDED(rv) && sectionNode) {
00158     rv = CallQueryInterface(sectionNode, aSection);
00159   }
00160 
00161   return rv;
00162 }
00163 
00164 // protected method
00165 nsresult
00166 nsHTMLTableRowElement::GetTable(nsIDOMHTMLTableElement** aTable)
00167 {
00168   NS_ENSURE_ARG_POINTER(aTable);
00169   *aTable = nsnull;
00170 
00171   nsCOMPtr<nsIDOMNode> sectionNode;
00172   nsresult rv = GetParentNode(getter_AddRefs(sectionNode));
00173   if (!sectionNode) {
00174     return rv;
00175   }
00176 
00177   // We may not be in a section
00178   rv = CallQueryInterface(sectionNode, aTable);
00179   if (NS_SUCCEEDED(rv)) {
00180     return rv;
00181   }
00182 
00183   nsCOMPtr<nsIDOMNode> tableNode;
00184   rv = sectionNode->GetParentNode(getter_AddRefs(tableNode));
00185   if (!tableNode) {
00186     return rv;
00187   }
00188   
00189   return CallQueryInterface(tableNode, aTable);
00190 }
00191 
00192 NS_IMETHODIMP
00193 nsHTMLTableRowElement::GetRowIndex(PRInt32* aValue)
00194 {
00195   *aValue = -1;
00196   nsCOMPtr<nsIDOMHTMLTableElement> table;
00197 
00198   nsresult result = GetTable(getter_AddRefs(table));
00199 
00200   if (NS_SUCCEEDED(result) && table) {
00201     nsCOMPtr<nsIDOMHTMLCollection> rows;
00202 
00203     table->GetRows(getter_AddRefs(rows));
00204 
00205     PRUint32 numRows;
00206     rows->GetLength(&numRows);
00207 
00208     PRBool found = PR_FALSE;
00209 
00210     for (PRUint32 i = 0; (i < numRows) && !found; i++) {
00211       nsCOMPtr<nsIDOMNode> node;
00212 
00213       rows->Item(i, getter_AddRefs(node));
00214 
00215       if (node.get() == NS_STATIC_CAST(nsIDOMNode *, this)) {
00216         *aValue = i;
00217         found = PR_TRUE;
00218       }
00219     }
00220   }
00221 
00222   return result;
00223 }
00224 
00225 NS_IMETHODIMP
00226 nsHTMLTableRowElement::GetSectionRowIndex(PRInt32* aValue)
00227 {
00228   *aValue = -1;
00229 
00230   nsCOMPtr<nsIDOMHTMLTableSectionElement> section;
00231 
00232   nsresult result = GetSection(getter_AddRefs(section));
00233 
00234   if (NS_SUCCEEDED(result) && section) {
00235     nsCOMPtr<nsIDOMHTMLCollection> rows;
00236 
00237     section->GetRows(getter_AddRefs(rows));
00238 
00239     PRBool found = PR_FALSE;
00240     PRUint32 numRows;
00241 
00242     rows->GetLength(&numRows);
00243 
00244     for (PRUint32 i = 0; (i < numRows) && !found; i++) {
00245       nsCOMPtr<nsIDOMNode> node;
00246       rows->Item(i, getter_AddRefs(node));
00247 
00248       if (node.get() == NS_STATIC_CAST(nsIDOMNode *, this)) {
00249         *aValue = i;
00250         found = PR_TRUE;
00251       }
00252     } 
00253   }
00254 
00255   return NS_OK;
00256 }
00257 
00258 PR_STATIC_CALLBACK(PRBool)
00259 IsCell(nsIContent *aContent, PRInt32 aNamespaceID,
00260        nsIAtom* aAtom, const nsAString& aData)
00261 {
00262   nsIAtom* tag = aContent->Tag();
00263 
00264   return ((tag == nsHTMLAtoms::td || tag == nsHTMLAtoms::th) &&
00265           aContent->IsContentOfType(nsIContent::eHTML));
00266 }
00267 
00268 NS_IMETHODIMP
00269 nsHTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
00270 {
00271   if (!mCells) {
00272     mCells = new nsContentList(GetDocument(),
00273                                IsCell,
00274                                EmptyString(),
00275                                this,
00276                                PR_FALSE);
00277 
00278     NS_ENSURE_TRUE(mCells, NS_ERROR_OUT_OF_MEMORY);
00279   }
00280 
00281   NS_ADDREF(*aValue = mCells);
00282   return NS_OK;
00283 }
00284 
00285 NS_IMETHODIMP
00286 nsHTMLTableRowElement::InsertCell(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
00287 {
00288   *aValue = nsnull;
00289 
00290   if (aIndex < -1) {
00291     return NS_ERROR_DOM_INDEX_SIZE_ERR;
00292   }
00293   
00294   nsCOMPtr<nsIDOMHTMLCollection> cells;
00295   GetCells(getter_AddRefs(cells));
00296 
00297   PRUint32 cellCount;
00298   cells->GetLength(&cellCount);
00299 
00300   if (aIndex > PRInt32(cellCount)) {
00301     return NS_ERROR_DOM_INDEX_SIZE_ERR;
00302   }
00303 
00304   PRBool doInsert = (aIndex < PRInt32(cellCount)) && (aIndex != -1);
00305 
00306   // create the cell
00307   nsCOMPtr<nsINodeInfo> nodeInfo;
00308   nsContentUtils::NameChanged(mNodeInfo, nsHTMLAtoms::td,
00309                               getter_AddRefs(nodeInfo));
00310 
00311   nsCOMPtr<nsIContent> cellContent = NS_NewHTMLTableCellElement(nodeInfo);
00312   if (!cellContent) {
00313     return NS_ERROR_OUT_OF_MEMORY;
00314   }
00315 
00316   nsCOMPtr<nsIDOMNode> cellNode(do_QueryInterface(cellContent));
00317   NS_ASSERTION(cellNode, "Should implement nsIDOMNode!");
00318 
00319   nsCOMPtr<nsIDOMNode> retChild;
00320 
00321   nsresult rv;
00322   if (doInsert) {
00323     nsCOMPtr<nsIDOMNode> refCell;
00324     cells->Item(aIndex, getter_AddRefs(refCell));
00325 
00326     rv = InsertBefore(cellNode, refCell, getter_AddRefs(retChild));
00327   } else {
00328     rv = AppendChild(cellNode, getter_AddRefs(retChild));
00329   }
00330 
00331   if (retChild) {
00332     CallQueryInterface(retChild, aValue);
00333   }
00334 
00335   return NS_OK;
00336 }
00337 
00338 
00339 NS_IMETHODIMP
00340 nsHTMLTableRowElement::DeleteCell(PRInt32 aValue)
00341 {
00342   if (aValue < -1) {
00343     return NS_ERROR_DOM_INDEX_SIZE_ERR;
00344   }
00345 
00346   nsCOMPtr<nsIDOMHTMLCollection> cells;
00347   GetCells(getter_AddRefs(cells));
00348 
00349   nsresult rv;
00350   PRUint32 refIndex;
00351   if (aValue == -1) {
00352     rv = cells->GetLength(&refIndex);
00353     NS_ENSURE_SUCCESS(rv, rv);
00354 
00355     if (refIndex == 0) {
00356       return NS_OK;
00357     }
00358 
00359     --refIndex;
00360   }
00361   else {
00362     refIndex = (PRUint32)aValue;
00363   }
00364 
00365   nsCOMPtr<nsIDOMNode> cell;
00366   rv = cells->Item(refIndex, getter_AddRefs(cell));
00367   NS_ENSURE_SUCCESS(rv, rv);
00368 
00369   if (!cell) {
00370     return NS_ERROR_DOM_INDEX_SIZE_ERR;
00371   }
00372 
00373   nsCOMPtr<nsIDOMNode> retChild;
00374   return RemoveChild(cell, getter_AddRefs(retChild));
00375 }
00376 
00377 NS_IMPL_STRING_ATTR_DEFAULT_VALUE(nsHTMLTableRowElement, Align, align, "left")
00378 NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, BgColor, bgcolor)
00379 NS_IMPL_STRING_ATTR_DEFAULT_VALUE(nsHTMLTableRowElement, Ch, _char, ".")
00380 NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, ChOff, charoff)
00381 NS_IMPL_STRING_ATTR_DEFAULT_VALUE(nsHTMLTableRowElement, VAlign, valign, "middle")
00382 
00383 
00384 PRBool
00385 nsHTMLTableRowElement::ParseAttribute(nsIAtom* aAttribute,
00386                                       const nsAString& aValue,
00387                                       nsAttrValue& aResult)
00388 {
00389   /*
00390    * ignore these attributes, stored simply as strings
00391    *
00392    * ch
00393    */
00394 
00395   if (aAttribute == nsHTMLAtoms::charoff) {
00396     return aResult.ParseIntWithBounds(aValue, 0);
00397   }
00398   if (aAttribute == nsHTMLAtoms::height) {
00399     return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
00400   }
00401   if (aAttribute == nsHTMLAtoms::width) {
00402     return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
00403   }
00404   if (aAttribute == nsHTMLAtoms::align) {
00405     return ParseTableCellHAlignValue(aValue, aResult);
00406   }
00407   if (aAttribute == nsHTMLAtoms::bgcolor) {
00408     return aResult.ParseColor(aValue, GetOwnerDoc());
00409   }
00410   if (aAttribute == nsHTMLAtoms::valign) {
00411     return ParseTableVAlignValue(aValue, aResult);
00412   }
00413 
00414   return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
00415 }
00416 
00417 static 
00418 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
00419 {
00420   if (aData->mSID == eStyleStruct_Position) {
00421     // height: value
00422     if (aData->mPositionData->mHeight.GetUnit() == eCSSUnit_Null) {
00423       const nsAttrValue* value = aAttributes->GetAttr(nsHTMLAtoms::height);
00424       if (value && value->Type() == nsAttrValue::eInteger)
00425         aData->mPositionData->mHeight.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
00426       else if (value && value->Type() == nsAttrValue::ePercent)
00427         aData->mPositionData->mHeight.SetPercentValue(value->GetPercentValue());
00428     }
00429   }
00430   else if (aData->mSID == eStyleStruct_Text) {
00431     if (aData->mTextData->mTextAlign.GetUnit() == eCSSUnit_Null) {
00432       // align: enum
00433       const nsAttrValue* value = aAttributes->GetAttr(nsHTMLAtoms::align);
00434       if (value && value->Type() == nsAttrValue::eEnum)
00435         aData->mTextData->mTextAlign.SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
00436     }
00437   }
00438   else if (aData->mSID == eStyleStruct_TextReset) {
00439     if (aData->mTextData->mVerticalAlign.GetUnit() == eCSSUnit_Null) {
00440       // valign: enum
00441       const nsAttrValue* value = aAttributes->GetAttr(nsHTMLAtoms::valign);
00442       if (value && value->Type() == nsAttrValue::eEnum)
00443         aData->mTextData->mVerticalAlign.SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
00444     }
00445   }
00446 
00447   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
00448   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
00449 }
00450 
00451 NS_IMETHODIMP_(PRBool)
00452 nsHTMLTableRowElement::IsAttributeMapped(const nsIAtom* aAttribute) const
00453 {
00454   static const MappedAttributeEntry attributes[] = {
00455     { &nsHTMLAtoms::align },
00456     { &nsHTMLAtoms::valign }, 
00457     { &nsHTMLAtoms::height },
00458     { nsnull }
00459   };
00460 
00461   static const MappedAttributeEntry* const map[] = {
00462     attributes,
00463     sCommonAttributeMap,
00464     sBackgroundAttributeMap,
00465   };
00466 
00467   return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
00468 }
00469 
00470 nsMapRuleToAttributesFunc
00471 nsHTMLTableRowElement::GetAttributeMappingFunction() const
00472 {
00473   return &MapAttributesIntoRule;
00474 }