More table editing work (bug 20973) and Page Properies dialog work (bug 14344). Added missing 'tbody' to nsIAtoms list. r=mjudge

This commit is contained in:
cmanske%netscape.com 2000-02-03 02:06:10 +00:00
Родитель c464f6f9f3
Коммит 894a83b297
24 изменённых файлов: 1258 добавлений и 472 удалений

Просмотреть файл

@ -75,10 +75,14 @@ class nsSetCaretAfterTableEdit
void CancelSetCaret() {mEd = nsnull; mTable = nsnull;}
};
// Table Editing helper utilities (not exposed in IDL)
NS_IMETHODIMP
nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan, PRBool aAfter)
nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan,
PRBool aAfter, nsIDOMElement **aNewCell)
{
if (!aCell) return NS_ERROR_NULL_POINTER;
if (aNewCell) *aNewCell = nsnull;
// And the parent and offsets needed to do an insert
nsCOMPtr<nsIDOMNode> cellParent;
@ -91,29 +95,68 @@ nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpa
{
nsCOMPtr<nsIDOMElement> newCell;
res = CreateElementWithDefaults("td", getter_AddRefs(newCell));
if (NS_SUCCEEDED(res) && newCell)
if(NS_FAILED(res)) return res;
if(!newCell) return NS_ERROR_FAILURE;
//Optional: return new cell created
if (aNewCell)
{
if( aRowSpan > 1)
{
nsAutoString newRowSpan(aRowSpan);
//newRowSpan.Append(aRowSpan, 10);
// Note: Do NOT use editor txt for this
newCell->SetAttribute("rowspan", newRowSpan);
}
if( aColSpan > 1)
{
nsAutoString newColSpan(aColSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute("colspan", newColSpan);
}
if(aAfter) cellOffset++;
res = InsertNode(newCell, cellParent, cellOffset);
*aNewCell = newCell.get();
NS_ADDREF(*aNewCell);
}
if( aRowSpan > 1)
{
nsAutoString newRowSpan(aRowSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute("rowspan", newRowSpan);
}
if( aColSpan > 1)
{
nsAutoString newColSpan(aColSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute("colspan", newColSpan);
}
if(aAfter) cellOffset++;
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
res = nsEditor::InsertNode(newCell, cellParent, cellOffset);
}
}
return res;
}
PRBool IsRowNode(nsCOMPtr<nsIDOMNode> &aNode)
{
nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
if (content)
{
content->GetTag(*getter_AddRefs(atom));
if (atom && atom.get() == nsIEditProperty::tr)
return PR_TRUE;
}
return PR_FALSE;
}
NS_IMETHODIMP nsHTMLEditor::SetColSpan(nsIDOMElement *aCell, PRInt32 aColSpan)
{
if (!aCell) return NS_ERROR_NULL_POINTER;
nsAutoString newSpan;
newSpan.Append(aColSpan, 10);
nsAutoString colSpan("colspan");
return SetAttribute(aCell, colSpan, newSpan);
}
NS_IMETHODIMP nsHTMLEditor::SetRowSpan(nsIDOMElement *aCell, PRInt32 aRowSpan)
{
if (!aCell) return NS_ERROR_NULL_POINTER;
nsAutoString newSpan;
newSpan.Append(aRowSpan, 10);
nsAutoString rowSpan("rowspan");
return SetAttribute(aCell, rowSpan, newSpan);
}
/****************************************************************/
// Table Editing interface methods
@ -138,7 +181,10 @@ nsHTMLEditor::InsertTableCell(PRInt32 aNumber, PRBool aAfter)
if (NS_FAILED(res)) return res;
if (!curCell) return NS_ERROR_FAILURE;
PRInt32 newCellIndex = aAfter ? (startColIndex+colSpan) : startColIndex;
//We control selection resetting after the insert...
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, newCellIndex, ePreviousColumn);
//...so suppress Rules System selection munging
nsAutoTxnsConserveSelection dontChangeSelection(this);
PRInt32 i;
for (i = 0; i < aNumber; i++)
@ -148,32 +194,136 @@ nsHTMLEditor::InsertTableCell(PRInt32 aNumber, PRBool aAfter)
if (NS_SUCCEEDED(res) && newCell)
{
if (aAfter) cellOffset++;
res = InsertNode(newCell, cellParent, cellOffset);
res = nsEditor::InsertNode(newCell, cellParent, cellOffset);
if(NS_FAILED(res)) break;
}
}
return res;
}
nsresult nsHTMLEditor::GetRowAt(nsCOMPtr<nsIDOMElement> &aTable, PRInt32 rowIndex, nsCOMPtr<nsIDOMElement> &aRow)
NS_IMETHODIMP
nsHTMLEditor::GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
{
aRow = nsnull;
nsCOMPtr<nsIDOMElement> tableElement;
nsresult res = GetElementOrParentByTagName("table", aTableElement, getter_AddRefs(tableElement));
if (NS_FAILED(res)) return res;
if (!tableElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode>tableNode = do_QueryInterface(tableElement);
if (!tableNode) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> tableChild;
res = tableNode->GetFirstChild(getter_AddRefs(tableChild));
if (NS_FAILED(res)) return res;
while (tableChild)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(tableChild);
if (content)
{
nsCOMPtr<nsIDOMElement> element;
nsCOMPtr<nsIAtom> atom;
content->GetTag(*getter_AddRefs(atom));
if (atom.get() == nsIEditProperty::tr)
{
// Found a row directly under <table>
element = do_QueryInterface(tableChild);
if(element)
{
aRow = element.get();
NS_ADDREF(aRow);
}
return NS_OK;
}
// Look for row in one of the row container elements
if (atom.get() == nsIEditProperty::tbody ||
atom.get() == nsIEditProperty::thead ||
atom.get() == nsIEditProperty::tfoot )
{
nsCOMPtr<nsIDOMNode> rowNode;
// All children should be rows
res = tableChild->GetFirstChild(getter_AddRefs(rowNode));
if (NS_FAILED(res)) return res;
if (rowNode && IsRowNode(rowNode))
{
element = do_QueryInterface(rowNode);
if(element)
{
aRow = element.get();
NS_ADDREF(aRow);
}
return NS_OK;
}
}
}
// Here if table child was a CAPTION or COLGROUP
// or child of a row-conainer wasn't a row (bad HTML)
// Look in next table child
res = tableChild->GetNextSibling(getter_AddRefs(tableChild));
};
return res;
}
NS_IMETHODIMP
nsHTMLEditor::GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
{
aRow = nsnull;
nsCOMPtr<nsIDOMElement> nextRow;
PRInt32 index = 0;
nsAutoString tagName("tr");
nsresult res = GetNextElementByTagName(aTable, &tagName, getter_AddRefs(nextRow));
nsCOMPtr<nsIDOMElement> rowElement;
nsresult res = GetElementOrParentByTagName("tr", aTableElement, getter_AddRefs(rowElement));
if (NS_FAILED(res)) return res;
if (!nextRow) return NS_OK;
if (!rowElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> parentTable;
res = GetElementOrParentByTagName("table", nextRow, getter_AddRefs(parentTable));
if (NS_FAILED(res)) return res;
if (!parentTable) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> rowNode = do_QueryInterface(rowElement);
if (!rowNode) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> nextRow;
nsCOMPtr<nsIDOMNode> rowParent;
nsCOMPtr<nsIDOMNode> parentSibling;
nsCOMPtr<nsIDOMElement> element;
if (parentTable == aTable)
aRow = nextRow;
rowNode->GetNextSibling(getter_AddRefs(nextRow));
if(nextRow)
{
element = do_QueryInterface(nextRow);
if(element)
{
aRow = element.get();
NS_ADDREF(aRow);
}
return NS_OK;
}
// No row found, search for rows in other table sections
res = rowNode->GetParentNode(getter_AddRefs(rowParent));
if(NS_FAILED(res)) return res;
if (!rowParent) return NS_ERROR_NULL_POINTER;
res = rowParent->GetNextSibling(getter_AddRefs(parentSibling));
if(NS_FAILED(res)) return res;
while (parentSibling)
{
res = parentSibling->GetFirstChild(getter_AddRefs(nextRow));
if(NS_FAILED(res)) return res;
if (nextRow && IsRowNode(nextRow))
{
element = do_QueryInterface(nextRow);
if(element)
{
aRow = element.get();
NS_ADDREF(aRow);
}
return NS_OK;
}
#ifdef DEBUG
printf("GetNextRow: firstChild of row's parent's sibling is not a TR!\n");
#endif
// We arrive here only if a table section has no children
// or first child of section is not a row (bad HTML!)
res = parentSibling->GetNextSibling(getter_AddRefs(parentSibling));
}
return res;
}
@ -197,25 +347,38 @@ nsHTMLEditor::InsertTableColumn(PRInt32 aNumber, PRBool aAfter)
if (NS_FAILED(res)) return res;
if (!curCell) return NS_ERROR_FAILURE;
nsAutoEditBatch beginBatching(this);
// Use column after current cell if requested
if (aAfter)
{
startColIndex += colSpan;
//Detect when user is adding after a COLSPAN=0 case
// Assume they want to stop the "0" behavior and
// really add a new column. Thus we set the
// colspan to its true value
if (colSpan == 0)
SetColSpan(curCell, actualColSpan);
}
PRInt32 rowCount, colCount, row;
PRInt32 rowCount, colCount, rowIndex;
res = GetTableSize(table, rowCount, colCount);
if (NS_FAILED(res)) return res;
PRInt32 lastColumn = colCount - 1;
nsAutoEditBatch beginBatching(this);
//We reset caret in destructor...
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, startColIndex, ePreviousRow);
//.. so suppress Rules System selection munging
nsAutoTxnsConserveSelection dontChangeSelection(this);
for ( row = 0; row < rowCount; row++)
nsCOMPtr<nsIDOMElement> rowElement;
for ( rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
if (startColIndex < colCount)
{
// We are inserting before an existing column
res = GetCellDataAt(table, row, startColIndex, *getter_AddRefs(curCell),
res = GetCellDataAt(table, rowIndex, startColIndex, *getter_AddRefs(curCell),
curStartRowIndex, curStartColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
if (NS_FAILED(res)) return res;
@ -226,16 +389,12 @@ nsHTMLEditor::InsertTableColumn(PRInt32 aNumber, PRBool aAfter)
{
if (curStartColIndex < startColIndex)
{
if (colSpan > 0)
{
// We have a cell spanning this location
// Simply increase its colspan to keep table rectangular
nsAutoString newColSpan;
newColSpan.Append(colSpan+aNumber, 10);
SetAttribute(curCell, "colspan", newColSpan);
}
// We have a cell spanning this location
// Simply increase its colspan to keep table rectangular
// Note: we do nothing if colsSpan=0,
// since it should automatically span the new column
if (colSpan > 0)
SetColSpan(curCell, colSpan+aNumber);
} else {
// Simply set selection to the current cell
// so we can let InsertTableCell() do the work
@ -246,18 +405,31 @@ nsHTMLEditor::InsertTableColumn(PRInt32 aNumber, PRBool aAfter)
}
} else {
// We are inserting after all existing columns
//TODO: A better strategy is to get the row at index "row"
// and append a cell to the end of it.
// Need to write "GetRowAt()" to do this
// Get last cell in row and insert new cell after it
res = GetCellDataAt(table, row, lastColumn, *getter_AddRefs(curCell),
curStartRowIndex, curStartColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
//TODO: Make sure table is "well formed" (call NormalizeTable)
// before appending new column
// Get current row and append new cells after last cell in row
if(rowIndex == 0)
res = GetFirstRow(table.get(), *getter_AddRefs(rowElement));
else
res = GetNextRow(rowElement.get(), *getter_AddRefs(rowElement));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> lastCell;
nsCOMPtr<nsIDOMNode> rowNode = do_QueryInterface(rowElement);
if (!rowElement) return NS_ERROR_FAILURE;
res = rowElement->GetLastChild(getter_AddRefs(lastCell));
if (NS_FAILED(res)) return res;
if (!lastCell) return NS_ERROR_FAILURE;
curCell = do_QueryInterface(lastCell);
if (curCell)
{
// Simply add same number of cells to each row
// Although tempted to check cell indexes for curCell,
// the effects of COLSPAN>1 in some cells makes this futile!
// We must use NormalizeTable first to assure proper
// that there are cells in each cellmap location
selection->Collapse(curCell, 0);
res = InsertTableCell(aNumber, PR_TRUE);
}
@ -287,7 +459,8 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
if (!curCell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> parentRow;
GetElementOrParentByTagName("tr", curCell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName("tr", curCell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
PRInt32 rowCount, colCount;
@ -303,16 +476,27 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
if (NS_FAILED(res)) return res;
if (!parentOfRow) return NS_ERROR_NULL_POINTER;
nsAutoEditBatch beginBatching(this);
if (aAfter)
{
// Use row after current cell
startRowIndex += actualRowSpan;
// offset to use for new row insert
newRowOffset += actualRowSpan;
//Detect when user is adding after a ROWSPAN=0 case
// Assume they want to stop the "0" behavior and
// really add a new row. Thus we set the
// rowspan to its true value
if (rowSpan == 0)
SetRowSpan(curCell, actualRowSpan);
}
nsAutoEditBatch beginBatching(this);
//We control selection resetting after the insert...
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, startColIndex, ePreviousColumn);
//...so suppress Rules System selection munging
nsAutoTxnsConserveSelection dontChangeSelection(this);
PRInt32 cellsInRow = 0;
if (startRowIndex < rowCount)
@ -331,16 +515,12 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
{
if (curStartRowIndex < startRowIndex)
{
if (rowSpan > 0)
{
// We have a cell spanning this location
// Simply increase its rowspan
nsAutoString newRowSpan;
newRowSpan.Append(rowSpan+aNumber, 10);
SetAttribute(curCell, "rowspan", newRowSpan);
}
// We have a cell spanning this location
// Simply increase its rowspan
//Note that if rowSpan == 0, we do nothing,
// since that cell should automatically extend into the new row
if (rowSpan > 0)
SetRowSpan(curCell, rowSpan+aNumber);
} else {
// Count the number of cells we need to add to the new row
cellsInRow += actualColSpan;
@ -366,8 +546,9 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
{
if (rowSpan == 0)
cellsInRow -= actualColSpan;
tempColIndex += actualColSpan;
}
tempColIndex += actualColSpan;
}
if (cellsInRow > 0)
@ -403,7 +584,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
return res;
}
// This is an internal helper (not exposed in IDL)
// Editor helper only
NS_IMETHODIMP
nsHTMLEditor::DeleteTable(nsCOMPtr<nsIDOMElement> &aTable, nsCOMPtr<nsIDOMSelection> &aSelection)
{
@ -467,12 +648,9 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
{
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName("tr", cell, getter_AddRefs(parentRow));
if (!parentRow)
{
res = NS_ERROR_NULL_POINTER;
break;
}
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
// We should delete the row instead,
// but first check if its the only row left
// so we can delete the entire table
@ -483,9 +661,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
if (rowCount == 1)
return DeleteTable(table, selection);
// Delete the row by placing caret in cell we were to delete
// We need to call DeleteTableRow to handle cells with rowspan
selection->Collapse(cell,0);
res = DeleteTableRow(1);
if (NS_FAILED(res)) return res;
}
@ -497,6 +673,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
// The setCaret object will call SetCaretAfterTableEdit in it's destructor
selection->ClearSelection();
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, startColIndex, ePreviousColumn);
nsAutoTxnsConserveSelection dontChangeSelection(this);
res = DeleteNode(cell);
// If we fail, don't try to delete any more cells???
@ -524,6 +701,8 @@ nsHTMLEditor::DeleteTableCellContents()
// We clear the selection to avoid problems when nodes in the selection are deleted,
selection->ClearSelection();
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, startColIndex, ePreviousColumn);
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
nsAutoEditBatch beginBatching(this);
@ -575,9 +754,6 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
// Check for counts too high
aNumber = PR_MIN(aNumber,(colCount-startColIndex));
selection->ClearSelection();
nsSetCaretAfterTableEdit setCaret(this, table, startRowIndex, startColIndex, ePreviousColumn);
// Scan through cells in row to do rowspan adjustments
nsCOMPtr<nsIDOMElement> curCell;
PRInt32 curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
@ -593,11 +769,11 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
if (NS_FAILED(res)) return res;
NS_ASSERTION((actualColSpan > 0),"Effective COLSPAN = 0 in DeleteTableColumn");
NS_ASSERTION((actualRowSpan > 0),"Effective ROWSPAN = 0 in DeleteTableColumn");
if (curCell)
{
// This must always be >= 1
NS_ASSERTION((actualRowSpan > 0),"Effective ROWSPAN = 0 in DeleteTableColumn");
// Find cells that don't start in column we are deleting
if (curStartColIndex < startColIndex || colSpan > 1 || colSpan == 0)
{
@ -607,15 +783,7 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
if (colSpan > 0)
{
NS_ASSERTION((colSpan > 1),"Bad COLSPAN in DeleteTableColumn");
nsAutoString newColSpan;
//This calculates final span for all columns deleted,
// but we are iterating aNumber times through here so
// just decrement current value by 1
//PRInt32 minSpan = startColIndex - curStartColIndex;
//PRInt32 newSpan = PR_MAX(minSpan, colSpan - aNumber);
//newColSpan.Append(newSpan, 10);
newColSpan.Append(colSpan-1, 10);
SetAttribute(curCell, "colspan", newColSpan);
SetColSpan(curCell,colSpan-1);
}
if (curStartColIndex == startColIndex)
{
@ -630,13 +798,13 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
// Delete the cell
if (1 == GetNumberOfCellsInRow(table, rowIndex))
{
// Only 1 cell in row - delete the row
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName("tr", cell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if(!parentRow) return NS_ERROR_NULL_POINTER;
// We should delete the row instead,
// but first check if its the only row left
// But first check if its the only row left
// so we can delete the entire table
// (This should never happen but it's the safe thing to do)
PRInt32 rowCount, colCount;
@ -656,6 +824,12 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
// since a row was deleted and "next"
// row now has current rowIndex
} else {
selection->ClearSelection();
nsSetCaretAfterTableEdit setCaret(this, table, curStartRowIndex, curStartColIndex, ePreviousColumn);
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
res = DeleteNode(curCell);
if (NS_FAILED(res)) return res;
@ -663,11 +837,7 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
rowIndex += actualRowSpan;
}
}
} else {
// No curCell, we've reached end of row
rowIndex++;
}
} while (curCell);
}
return res;
@ -713,13 +883,15 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber)
res = GetCellDataAt(table, startRowIndex, colIndex, *getter_AddRefs(curCell),
curStartRowIndex, curStartColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
NS_ASSERTION((actualColSpan > 0),"Effective COLSPAN = 0 in DeleteTableRow");
NS_ASSERTION((actualRowSpan > 0),"Effective ROWSPAN = 0 in DeleteTableRow");
// We don't fail if we don't find a cell, so this must be real bad
if(NS_FAILED(res)) return res;
// Find cells that don't start in row we are deleting
if (NS_SUCCEEDED(res) && curCell)
if (curCell)
{
//Real colspan must always be >= 1
NS_ASSERTION((actualColSpan > 0),"Effective COLSPAN = 0 in DeleteTableRow");
if (curStartRowIndex < startRowIndex)
{
// We have a cell spanning this location
@ -727,20 +899,12 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber)
// but we don't need to do this if rowspan=0,
// since it will automatically adjust
if (rowSpan > 0)
{
nsAutoString newRowSpan;
PRInt32 newSpan = PR_MAX((startRowIndex - curStartRowIndex), actualRowSpan - aNumber);
newRowSpan.Append(newSpan, 10);
SetAttribute(curCell, "rowspan", newRowSpan);
}
SetRowSpan(curCell, PR_MAX((startRowIndex - curStartRowIndex), actualRowSpan - aNumber));
}
// Skip over locations spanned by this cell
colIndex += actualColSpan;
}
else
colIndex++;
} while (curCell);
} while (curCell);
for (PRInt32 i = 0; i < aNumber; i++)
{
@ -767,13 +931,201 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber)
NS_IMETHODIMP
nsHTMLEditor::JoinTableCells()
{
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsIDOMSelection> selection;
nsCOMPtr<nsIDOMElement> table;
nsCOMPtr<nsIDOMElement> cell;
nsCOMPtr<nsIDOMNode> cellParent;
PRInt32 cellOffset, startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
PRBool isSelected;
PRInt32 rowCount, colCount;
nsresult res = GetTableSize(table, rowCount, colCount);
if (NS_FAILED(res)) return res;
res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRowIndex, startColIndex);
if (NS_FAILED(res)) return res;
if(!cell) return NS_ERROR_NULL_POINTER;
res = GetCellDataAt(table, startRowIndex, startColIndex, *getter_AddRefs(cell),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
if (NS_FAILED(res)) return res;
if(!cell) return NS_ERROR_NULL_POINTER;
//*** Initial test: just merge with cell to the right
nsCOMPtr<nsIDOMElement> cell2;
PRInt32 startRowIndex2, startColIndex2, rowSpan2, colSpan2, actualRowSpan2, actualColSpan2;
PRBool isSelected2;
res = GetCellDataAt(table, startRowIndex, startColIndex+actualColSpan, *getter_AddRefs(cell2),
startRowIndex2, startColIndex2, rowSpan2, colSpan2,
actualRowSpan2, actualColSpan2, isSelected2);
if (NS_FAILED(res)) return res;
nsAutoEditBatch beginBatching(this);
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(cellParent);
nsCOMPtr<nsIDOMNode> cellNode = do_QueryInterface(cell);
nsCOMPtr<nsIDOMNode> cellNode2 = do_QueryInterface(cell2);
if(cellNode && cellNode2 && parentNode)
{
PRInt32 insertIndex = 0;
// Get index of last child in target cell
nsCOMPtr<nsIDOMNodeList> childNodes;
res = cellNode->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(res)) && (childNodes))
{
// Start inserting just after last child
PRUint32 len;
res = childNodes->GetLength(&len);
if (NS_FAILED(res)) return res;
insertIndex = (PRInt32)len;
}
// Move content from cell2 to cell
nsCOMPtr<nsIDOMNode> cellChild;
res = cell2->GetFirstChild(getter_AddRefs(cellChild));
if (NS_FAILED(res)) return res;
while (cellChild)
{
nsCOMPtr<nsIDOMNode> nextChild;
res = cellChild->GetNextSibling(getter_AddRefs(nextChild));
if (NS_FAILED(res)) return res;
res = DeleteNode(cellChild);
if (NS_FAILED(res)) return res;
res = nsEditor::InsertNode(cellChild, cellNode, insertIndex);
if (NS_FAILED(res)) return res;
cellChild = nextChild;
insertIndex++;
}
// Reset target cell's spans
res = SetColSpan(cell, actualColSpan+actualColSpan2);
if (NS_FAILED(res)) return res;
// Delete cells whose contents were moved
res = DeleteNode(cell2);
if (NS_FAILED(res)) return res;
}
return res;
}
NS_IMETHODIMP
nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
{
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsIDOMElement> table;
nsresult res = NS_ERROR_FAILURE;
res = GetElementOrParentByTagName("table", aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!table) return NS_OK;
PRInt32 rowCount, colCount, rowIndex, colIndex;
res = GetTableSize(table, rowCount, colCount);
if (NS_FAILED(res)) return res;
nsAutoEditBatch beginBatching(this);
nsCOMPtr<nsIDOMElement> cell;
PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
PRBool isSelected;
#if 0
// This isn't working yet -- layout errors contribute!
// First scan all cells in row to detect bad rowspan values
for(rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
PRInt32 minRowSpan = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32
for(colIndex = 0; colIndex < colCount; colIndex++)
{
res = GetCellDataAt(aTable, rowIndex, colIndex, *getter_AddRefs(cell),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
// NOTE: This is a *real* failure.
// GetCellDataAt passes if cell is missing from cellmap
if(NS_FAILED(res)) return res;
if(cell && rowSpan > 0 && rowSpan < minRowSpan)
minRowSpan = rowSpan;
}
if(minRowSpan > 1)
{
PRInt32 spanDiff = minRowSpan - 1;
for(colIndex = 0; colIndex < colCount; colIndex++)
{
res = GetCellDataAt(aTable, rowIndex, colIndex, *getter_AddRefs(cell),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
// NOTE: This is a *real* failure.
// GetCellDataAt passes if cell is missing from cellmap
if(NS_FAILED(res)) return res;
// Fixup rowspans for cells starting in current row
if(cell && rowSpan > 0 &&
startRowIndex == rowIndex &&
startColIndex == colIndex )
{
// Set rowspan so there's at least one cell with ROWSPAN=1
SetRowSpan(cell, rowSpan-spanDiff);
}
}
}
}
// Get Table size again in case above changed anything
res = GetTableSize(table, rowCount, colCount);
if (NS_FAILED(res)) return res;
#endif
// Fill in missing cellmap locations with empty cells
for(rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
nsCOMPtr<nsIDOMElement> previousCellInRow;
for(colIndex = 0; colIndex < colCount; colIndex++)
{
res = GetCellDataAt(aTable, rowIndex, colIndex, *getter_AddRefs(cell),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
// NOTE: This is a *real* failure.
// GetCellDataAt passes if cell is missing from cellmap
if(NS_FAILED(res)) return res;
if (!cell)
{
//We are missing a cell at a cellmap location
#ifdef DEBUG
printf("NormalizeTable found missing cell at row=%d, col=%d\n", rowIndex, colIndex);
#endif
// Add a cell after the previous Cell in the current row
if(previousCellInRow)
{
// Insert a new cell after (PR_TRUE), and return the new cell to us
res = InsertCell(previousCellInRow, 1, 1, PR_TRUE, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Set this so we use returned new "cell" to set previousCellInRow below
if(cell)
startRowIndex = rowIndex;
} else {
// We don't have any cells in this row -- We are really messed up!
#ifdef DEBUG
printf("NormalizeTable found no cells in row=%d, col=%d\n", rowIndex, colIndex);
#endif
return NS_ERROR_FAILURE;
}
}
// Save the last cell found in the same row we are scanning
if(startRowIndex == rowIndex)
{
previousCellInRow = cell;
}
}
}
return res;
}
NS_IMETHODIMP
@ -861,28 +1213,24 @@ PRBool nsHTMLEditor::GetNumberOfCellsInRow(nsIDOMElement* aTable, PRInt32 rowInd
return cellCount;
}
/* Not scriptable: For convenience in C++ */
/* Not scriptable: For convenience in C++
Use GetTableRowCount and GetTableColumnCount from JavaScript
*/
NS_IMETHODIMP
nsHTMLEditor::GetTableSize(nsIDOMElement *aTable, PRInt32& aRowCount, PRInt32& aColCount)
{
nsresult res=NS_ERROR_FAILURE;
nsresult res = NS_ERROR_FAILURE;
aRowCount = 0;
aColCount = 0;
if (!aTable)
{
// Get the selected talbe or the table enclosing the selection anchor
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName("table", nsnull, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (table)
aTable = table;
else
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMElement> table;
// Get the selected talbe or the table enclosing the selection anchor
res = GetElementOrParentByTagName("table", aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (!table) return NS_ERROR_FAILURE;
// frames are not ref counted, so don't use an nsCOMPtr
nsITableLayout *tableLayoutObject;
res = GetTableLayoutObject(aTable, &tableLayoutObject);
res = GetTableLayoutObject(table.get(), &tableLayoutObject);
if (NS_FAILED(res)) return res;
if (!tableLayoutObject)
return NS_ERROR_FAILURE;
@ -1134,7 +1482,7 @@ nsHTMLEditor::SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt3
}
NS_IMETHODIMP
nsHTMLEditor::GetSelectedOrParentTableElement(nsCOMPtr<nsIDOMElement> &aTableElement, nsString& aTagName, PRBool &aIsSelected)
nsHTMLEditor::GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsString& aTagName, PRBool &aIsSelected)
{
aTableElement = nsnull;
aTagName = "";
@ -1145,50 +1493,57 @@ nsHTMLEditor::GetSelectedOrParentTableElement(nsCOMPtr<nsIDOMElement> &aTableEle
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
nsAutoString table("table");
nsAutoString tr("tr");
nsAutoString td("td");
nsAutoString tableName("table");
nsAutoString trName("tr");
nsAutoString tdName("td");
nsCOMPtr<nsIDOMNode> anchorNode;
// Find the first selected cell
// TODO: Handle multiple cells selected!
nsCOMPtr<nsIDOMElement> firstCell;
res = GetFirstSelectedCell(aTableElement);
nsCOMPtr<nsIDOMElement> tableElement;
res = GetFirstSelectedCell(tableElement);
if(NS_FAILED(res)) return res;
if (aTableElement)
if (tableElement)
{
aTagName = td;
aTagName = tdName;
aIsSelected = PR_TRUE;
return NS_OK;
goto SET_RETURN_ELEMENT;
}
// See if table or row is selected
res = GetSelectedElement(table, getter_AddRefs(aTableElement));
res = GetSelectedElement(tableName, getter_AddRefs(tableElement));
if(NS_FAILED(res)) return res;
if (aTableElement)
if (tableElement)
{
aTagName = table;
aTagName = tableName;
aIsSelected = PR_TRUE;
return NS_OK;
goto SET_RETURN_ELEMENT;
}
res = GetSelectedElement(tr, getter_AddRefs(aTableElement));
res = GetSelectedElement(trName, getter_AddRefs(tableElement));
if(NS_FAILED(res)) return res;
if (aTableElement)
if (tableElement)
{
aTagName = tr;
aTagName = trName;
aIsSelected = PR_TRUE;
return NS_OK;
goto SET_RETURN_ELEMENT;
}
// Look for a table cell parent
nsCOMPtr<nsIDOMNode> anchorNode;
res = selection->GetAnchorNode(getter_AddRefs(anchorNode));
if (NS_FAILED(res)) return res;
if (!anchorNode) return NS_ERROR_FAILURE;
res = GetElementOrParentByTagName(td, anchorNode, getter_AddRefs(aTableElement));
res = GetElementOrParentByTagName(tdName, anchorNode, getter_AddRefs(tableElement));
if(NS_FAILED(res)) return res;
if (aTableElement)
aTagName = td;
if (tableElement)
{
aTagName = tdName;
SET_RETURN_ELEMENT:
aTableElement = tableElement.get();
NS_ADDREF(aTableElement);
}
return res;
}

Просмотреть файл

@ -94,8 +94,9 @@ nsIAtom * nsIEditProperty::th;
nsIAtom * nsIEditProperty::caption;
nsIAtom * nsIEditProperty::col;
nsIAtom * nsIEditProperty::colgroup;
nsIAtom * nsIEditProperty::thead;
nsIAtom * nsIEditProperty::tfoot;
nsIAtom * nsIEditProperty::tbody;
nsIAtom * nsIEditProperty::thead;
nsIAtom * nsIEditProperty::tfoot;
nsIAtom * nsIEditProperty::li;
nsIAtom * nsIEditProperty::dt;
nsIAtom * nsIEditProperty::dd;
@ -195,6 +196,7 @@ nsEditProperty::nsEditProperty()
nsIEditProperty::caption = NS_NewAtom("caption");
nsIEditProperty::col = NS_NewAtom("col");
nsIEditProperty::colgroup = NS_NewAtom("colgroup");
nsIEditProperty::tbody = NS_NewAtom("tbody");
nsIEditProperty::thead = NS_NewAtom("thead");
nsIEditProperty::tfoot = NS_NewAtom("tfoot");
nsIEditProperty::li = NS_NewAtom("li");
@ -274,6 +276,7 @@ nsEditProperty::~nsEditProperty()
NS_IF_RELEASE(nsIEditProperty::caption);
NS_IF_RELEASE(nsIEditProperty::col);
NS_IF_RELEASE(nsIEditProperty::colgroup);
NS_IF_RELEASE(nsIEditProperty::tbody);
NS_IF_RELEASE(nsIEditProperty::thead);
NS_IF_RELEASE(nsIEditProperty::tfoot);
NS_IF_RELEASE(nsIEditProperty::li);

Просмотреть файл

@ -2758,6 +2758,7 @@ nsEditor::IsNodeBlock(nsIDOMNode *aNode, PRBool &aIsBlock)
tagAtom==nsIEditProperty::caption ||
tagAtom==nsIEditProperty::col ||
tagAtom==nsIEditProperty::colgroup ||
tagAtom==nsIEditProperty::tbody ||
tagAtom==nsIEditProperty::thead ||
tagAtom==nsIEditProperty::tfoot ||
tagAtom==nsIEditProperty::li ||

Просмотреть файл

@ -3291,6 +3291,76 @@ nsEditorShell::GetCellDataAt(nsIDOMElement *tableElement, PRInt32 rowIndex, PRIn
return result;
}
NS_IMETHODIMP
nsEditorShell::GetFirstRow(nsIDOMElement *aTableElement, nsIDOMElement **_retval)
{
if (!_retval || !aTableElement)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
if (tableEditor)
result = tableEditor->GetFirstRow(aTableElement, *_retval);
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
NS_IMETHODIMP
nsEditorShell::GetNextRow(nsIDOMElement *aCurrentRow, nsIDOMElement **_retval)
{
if (!_retval || !*_retval || !aCurrentRow)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
if (tableEditor)
result = tableEditor->GetNextRow(aCurrentRow, *_retval);
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
NS_IMETHODIMP
nsEditorShell::GetSelectedOrParentTableElement(PRUnichar **aTagName, PRBool *aIsSelected, nsIDOMElement **_retval)
{
if (!_retval || !aTagName || !aIsSelected)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
nsAutoString TagName(*aTagName);
if (tableEditor)
result = tableEditor->GetSelectedOrParentTableElement(*_retval, TagName, *aIsSelected);
// Need an ugly cast to get around "const" return value
*aTagName = (PRUnichar*)TagName.GetUnicode();
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
/* end of table editing */
NS_IMETHODIMP

Просмотреть файл

@ -2990,7 +2990,7 @@ NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
nsCOMPtr<nsIDOMElement> element;
PRBool isSelected;
nsAutoString tagName;
nsresult res = GetSelectedOrParentTableElement(element, tagName, isSelected);
nsresult res = GetSelectedOrParentTableElement(*getter_AddRefs(element), tagName, isSelected);
if (NS_FAILED(res)) return res;
if (!element)
{
@ -5570,66 +5570,71 @@ nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement)
if (aElement && IsElementInBody(aElement))
{
nsresult res = NS_OK;
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
if (tagName == "table" || tagName == "tr" ||
tagName == "td" || tagName == "th" ||
tagName == "thead" || tagName == "tfoot" ||
tagName == "tbody" || tagName == "caption")
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content)
{
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
nsCOMPtr<nsIDOMNode> parent;
// This MUST succeed if IsElementInBody was TRUE
node->GetParentNode(getter_AddRefs(parent));
nsCOMPtr<nsIDOMNode>firstChild;
// Find deepest child
PRBool hasChild;
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
nsCOMPtr<nsIAtom> atom;
content->GetTag(*getter_AddRefs(atom));
if (atom.get() == nsIEditProperty::table ||
atom.get() == nsIEditProperty::tbody ||
atom.get() == nsIEditProperty::thead ||
atom.get() == nsIEditProperty::tfoot ||
atom.get() == nsIEditProperty::caption ||
atom.get() == nsIEditProperty::tr ||
atom.get() == nsIEditProperty::td )
{
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
nsCOMPtr<nsIDOMNode> parent;
// This MUST succeed if IsElementInBody was TRUE
node->GetParentNode(getter_AddRefs(parent));
nsCOMPtr<nsIDOMNode>firstChild;
// Find deepest child
PRBool hasChild;
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
{
parent = node;
node = firstChild;
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
{
parent = node;
node = firstChild;
}
}
}
# if 0
// I've ifdef'd this out because it isn't finished and I'm not sure what the intent is.
PRInt32 offset = 0;
nsCOMPtr<nsIDOMNode>lastChild;
res = parent->GetLastChild(getter_AddRefs(lastChild));
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
{
if (node == lastChild)
PRInt32 offset = 0;
nsCOMPtr<nsIDOMNode>lastChild;
res = parent->GetLastChild(getter_AddRefs(lastChild));
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
{
// Check if node is text and has more than just a &nbsp
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
nsAutoString text;
PRUnichar nbspStr[2] = {nbsp, 0};
if (textNode && textNode->GetData(text))
if (node == lastChild)
{
// Set selection relative to the text node
parent = node;
PRInt32 len = text.Length();
if (len > 1 || text != nbspStr)
// Check if node is text and has more than just a &nbsp
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
nsAutoString text;
PRUnichar nbspStr[2] = {nbsp, 0};
if (textNode && textNode->GetData(text))
{
offset = len;
// Set selection relative to the text node
parent = node;
PRInt32 len = text.Length();
if (len > 1 || text != nbspStr)
{
offset = len;
}
}
} else {
// We have > 1 node, so set to end of content
}
} else {
// We have > 1 node, so set to end of content
}
}
#endif
// Set selection at beginning of deepest node
// Should we set
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(res) && selection && firstChild)
{
res = selection->Collapse(firstChild, 0);
if (NS_SUCCEEDED(res))
caretIsSet = PR_TRUE;
// Set selection at beginning of deepest node
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(res) && selection && firstChild)
{
res = selection->Collapse(firstChild, 0);
if (NS_SUCCEEDED(res))
caretIsSet = PR_TRUE;
}
}
}
}

Просмотреть файл

@ -190,8 +190,10 @@ public:
PRInt32& aRowSpan, PRInt32& aColSpan,
PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
PRBool& aIsSelected);
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow);
NS_IMETHOD GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow);
NS_IMETHOD SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt32 aCol, PRInt32 aDirection);
NS_IMETHOD GetSelectedOrParentTableElement(nsCOMPtr<nsIDOMElement> &aTableElement, nsString& aTagName, PRBool &aIsSelected);
NS_IMETHOD GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsString& aTagName, PRBool &aIsSelected);
// Selection and navigation
@ -321,14 +323,20 @@ protected:
// Table utilities
NS_IMETHOD InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan, PRBool aAfter);
// Insert a new cell after or before supplied aCell.
// Optional: If aNewCell supplied, returns the newly-created cell (addref'd, of course)
// This doesn't change or use the current selection
NS_IMETHOD InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan,
PRBool aAfter, nsIDOMElement **aNewCell);
NS_IMETHOD DeleteTable(nsCOMPtr<nsIDOMElement> &aTable, nsCOMPtr<nsIDOMSelection> &aSelection);
NS_IMETHOD SetColSpan(nsIDOMElement *aCell, PRInt32 aColSpan);
NS_IMETHOD SetRowSpan(nsIDOMElement *aCell, PRInt32 aRowSpan);
// Helper used to get nsITableLayout interface for methods implemented in nsTableFrame
NS_IMETHOD GetTableLayoutObject(nsIDOMElement* aTable, nsITableLayout **tableLayoutObject);
// Needed to do appropriate deleting when last cell or row is about to be deleted
// This doesn't count cells that don't start in the given row (are spanning from row above)
PRInt32 GetNumberOfCellsInRow(nsIDOMElement* aTable, PRInt32 rowIndex);
nsresult GetRowAt(nsCOMPtr<nsIDOMElement> &aTable, PRInt32 rowIndex, nsCOMPtr<nsIDOMElement> &aRow);
// Most insert methods need to get the same basic context data
NS_IMETHOD GetCellContext(nsCOMPtr<nsIDOMSelection> &aSelection,

Просмотреть файл

@ -109,6 +109,7 @@ public:
static nsIAtom *caption;
static nsIAtom *col;
static nsIAtom *colgroup;
static nsIAtom *tbody;
static nsIAtom *thead;
static nsIAtom *tfoot;
static nsIAtom *li;

Просмотреть файл

@ -3291,6 +3291,76 @@ nsEditorShell::GetCellDataAt(nsIDOMElement *tableElement, PRInt32 rowIndex, PRIn
return result;
}
NS_IMETHODIMP
nsEditorShell::GetFirstRow(nsIDOMElement *aTableElement, nsIDOMElement **_retval)
{
if (!_retval || !aTableElement)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
if (tableEditor)
result = tableEditor->GetFirstRow(aTableElement, *_retval);
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
NS_IMETHODIMP
nsEditorShell::GetNextRow(nsIDOMElement *aCurrentRow, nsIDOMElement **_retval)
{
if (!_retval || !*_retval || !aCurrentRow)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
if (tableEditor)
result = tableEditor->GetNextRow(aCurrentRow, *_retval);
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
NS_IMETHODIMP
nsEditorShell::GetSelectedOrParentTableElement(PRUnichar **aTagName, PRBool *aIsSelected, nsIDOMElement **_retval)
{
if (!_retval || !aTagName || !aIsSelected)
return NS_ERROR_NULL_POINTER;
nsresult result = NS_NOINTERFACE;
switch (mEditorType)
{
case eHTMLTextEditorType:
{
nsCOMPtr<nsITableEditor> tableEditor = do_QueryInterface(mEditor);
nsAutoString TagName(*aTagName);
if (tableEditor)
result = tableEditor->GetSelectedOrParentTableElement(*_retval, TagName, *aIsSelected);
// Need an ugly cast to get around "const" return value
*aTagName = (PRUnichar*)TagName.GetUnicode();
}
break;
default:
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}
/* end of table editing */
NS_IMETHODIMP

Просмотреть файл

@ -337,6 +337,30 @@ interface nsIEditorShell : nsISupports
out PRInt32 actualRowSpan, out PRInt32 actualColSpan,
out boolean isSelected);
/* Get the first row element in a table
tableElement may be a table or any child element a table
*/
nsIDOMElement GetFirstRow(in nsIDOMElement tableElement);
/* Get the next row element in a table after currentRow
* currentRow may be a row or any child element of a row
*/
nsIDOMElement GetNextRow(in nsIDOMElement currentRow);
/** Examine the current selection and find
* a selected TABLE, TD or TH, or TR element.
* or return the parent TD or TH if selection anchor is inside a table cell
* Returns null if no table element is found.
*
* Returns:
* The table element (table, row, or cell) found
* tagName The tagname of returned element
* Note that "td" will be returned if name is actually "th"
* isSelected Tells if element returned is a selected element
* (false if element is a parent cell of selection)
*/
nsIDOMElement GetSelectedOrParentTableElement(out wstring tagName, out boolean isSelected);
/**** end of table editing *****/
/* Get list of embedded objects, e.g. for mail compose */

Просмотреть файл

@ -2758,6 +2758,7 @@ nsEditor::IsNodeBlock(nsIDOMNode *aNode, PRBool &aIsBlock)
tagAtom==nsIEditProperty::caption ||
tagAtom==nsIEditProperty::col ||
tagAtom==nsIEditProperty::colgroup ||
tagAtom==nsIEditProperty::tbody ||
tagAtom==nsIEditProperty::thead ||
tagAtom==nsIEditProperty::tfoot ||
tagAtom==nsIEditProperty::li ||

Просмотреть файл

@ -109,6 +109,7 @@ public:
static nsIAtom *caption;
static nsIAtom *col;
static nsIAtom *colgroup;
static nsIAtom *tbody;
static nsIAtom *thead;
static nsIAtom *tfoot;
static nsIAtom *li;

Просмотреть файл

@ -94,8 +94,9 @@ nsIAtom * nsIEditProperty::th;
nsIAtom * nsIEditProperty::caption;
nsIAtom * nsIEditProperty::col;
nsIAtom * nsIEditProperty::colgroup;
nsIAtom * nsIEditProperty::thead;
nsIAtom * nsIEditProperty::tfoot;
nsIAtom * nsIEditProperty::tbody;
nsIAtom * nsIEditProperty::thead;
nsIAtom * nsIEditProperty::tfoot;
nsIAtom * nsIEditProperty::li;
nsIAtom * nsIEditProperty::dt;
nsIAtom * nsIEditProperty::dd;
@ -195,6 +196,7 @@ nsEditProperty::nsEditProperty()
nsIEditProperty::caption = NS_NewAtom("caption");
nsIEditProperty::col = NS_NewAtom("col");
nsIEditProperty::colgroup = NS_NewAtom("colgroup");
nsIEditProperty::tbody = NS_NewAtom("tbody");
nsIEditProperty::thead = NS_NewAtom("thead");
nsIEditProperty::tfoot = NS_NewAtom("tfoot");
nsIEditProperty::li = NS_NewAtom("li");
@ -274,6 +276,7 @@ nsEditProperty::~nsEditProperty()
NS_IF_RELEASE(nsIEditProperty::caption);
NS_IF_RELEASE(nsIEditProperty::col);
NS_IF_RELEASE(nsIEditProperty::colgroup);
NS_IF_RELEASE(nsIEditProperty::tbody);
NS_IF_RELEASE(nsIEditProperty::thead);
NS_IF_RELEASE(nsIEditProperty::tfoot);
NS_IF_RELEASE(nsIEditProperty::li);

Просмотреть файл

@ -2990,7 +2990,7 @@ NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
nsCOMPtr<nsIDOMElement> element;
PRBool isSelected;
nsAutoString tagName;
nsresult res = GetSelectedOrParentTableElement(element, tagName, isSelected);
nsresult res = GetSelectedOrParentTableElement(*getter_AddRefs(element), tagName, isSelected);
if (NS_FAILED(res)) return res;
if (!element)
{
@ -5570,66 +5570,71 @@ nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement)
if (aElement && IsElementInBody(aElement))
{
nsresult res = NS_OK;
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
if (tagName == "table" || tagName == "tr" ||
tagName == "td" || tagName == "th" ||
tagName == "thead" || tagName == "tfoot" ||
tagName == "tbody" || tagName == "caption")
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content)
{
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
nsCOMPtr<nsIDOMNode> parent;
// This MUST succeed if IsElementInBody was TRUE
node->GetParentNode(getter_AddRefs(parent));
nsCOMPtr<nsIDOMNode>firstChild;
// Find deepest child
PRBool hasChild;
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
nsCOMPtr<nsIAtom> atom;
content->GetTag(*getter_AddRefs(atom));
if (atom.get() == nsIEditProperty::table ||
atom.get() == nsIEditProperty::tbody ||
atom.get() == nsIEditProperty::thead ||
atom.get() == nsIEditProperty::tfoot ||
atom.get() == nsIEditProperty::caption ||
atom.get() == nsIEditProperty::tr ||
atom.get() == nsIEditProperty::td )
{
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
nsCOMPtr<nsIDOMNode> parent;
// This MUST succeed if IsElementInBody was TRUE
node->GetParentNode(getter_AddRefs(parent));
nsCOMPtr<nsIDOMNode>firstChild;
// Find deepest child
PRBool hasChild;
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
{
parent = node;
node = firstChild;
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
{
parent = node;
node = firstChild;
}
}
}
# if 0
// I've ifdef'd this out because it isn't finished and I'm not sure what the intent is.
PRInt32 offset = 0;
nsCOMPtr<nsIDOMNode>lastChild;
res = parent->GetLastChild(getter_AddRefs(lastChild));
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
{
if (node == lastChild)
PRInt32 offset = 0;
nsCOMPtr<nsIDOMNode>lastChild;
res = parent->GetLastChild(getter_AddRefs(lastChild));
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
{
// Check if node is text and has more than just a &nbsp
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
nsAutoString text;
PRUnichar nbspStr[2] = {nbsp, 0};
if (textNode && textNode->GetData(text))
if (node == lastChild)
{
// Set selection relative to the text node
parent = node;
PRInt32 len = text.Length();
if (len > 1 || text != nbspStr)
// Check if node is text and has more than just a &nbsp
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
nsAutoString text;
PRUnichar nbspStr[2] = {nbsp, 0};
if (textNode && textNode->GetData(text))
{
offset = len;
// Set selection relative to the text node
parent = node;
PRInt32 len = text.Length();
if (len > 1 || text != nbspStr)
{
offset = len;
}
}
} else {
// We have > 1 node, so set to end of content
}
} else {
// We have > 1 node, so set to end of content
}
}
#endif
// Set selection at beginning of deepest node
// Should we set
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(res) && selection && firstChild)
{
res = selection->Collapse(firstChild, 0);
if (NS_SUCCEEDED(res))
caretIsSet = PR_TRUE;
// Set selection at beginning of deepest node
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(res) && selection && firstChild)
{
res = selection->Collapse(firstChild, 0);
if (NS_SUCCEEDED(res))
caretIsSet = PR_TRUE;
}
}
}
}

Просмотреть файл

@ -190,8 +190,10 @@ public:
PRInt32& aRowSpan, PRInt32& aColSpan,
PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
PRBool& aIsSelected);
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow);
NS_IMETHOD GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow);
NS_IMETHOD SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt32 aCol, PRInt32 aDirection);
NS_IMETHOD GetSelectedOrParentTableElement(nsCOMPtr<nsIDOMElement> &aTableElement, nsString& aTagName, PRBool &aIsSelected);
NS_IMETHOD GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsString& aTagName, PRBool &aIsSelected);
// Selection and navigation
@ -321,14 +323,20 @@ protected:
// Table utilities
NS_IMETHOD InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan, PRBool aAfter);
// Insert a new cell after or before supplied aCell.
// Optional: If aNewCell supplied, returns the newly-created cell (addref'd, of course)
// This doesn't change or use the current selection
NS_IMETHOD InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpan,
PRBool aAfter, nsIDOMElement **aNewCell);
NS_IMETHOD DeleteTable(nsCOMPtr<nsIDOMElement> &aTable, nsCOMPtr<nsIDOMSelection> &aSelection);
NS_IMETHOD SetColSpan(nsIDOMElement *aCell, PRInt32 aColSpan);
NS_IMETHOD SetRowSpan(nsIDOMElement *aCell, PRInt32 aRowSpan);
// Helper used to get nsITableLayout interface for methods implemented in nsTableFrame
NS_IMETHOD GetTableLayoutObject(nsIDOMElement* aTable, nsITableLayout **tableLayoutObject);
// Needed to do appropriate deleting when last cell or row is about to be deleted
// This doesn't count cells that don't start in the given row (are spanning from row above)
PRInt32 GetNumberOfCellsInRow(nsIDOMElement* aTable, PRInt32 rowIndex);
nsresult GetRowAt(nsCOMPtr<nsIDOMElement> &aTable, PRInt32 rowIndex, nsCOMPtr<nsIDOMElement> &aRow);
// Most insert methods need to get the same basic context data
NS_IMETHOD GetCellContext(nsCOMPtr<nsIDOMSelection> &aSelection,

Просмотреть файл

@ -93,6 +93,9 @@ public:
* a collection of cells that extend past the
* previous size of the table
* If aTable is null, it uses table enclosing the selection anchor
* This doesn't doesn't change the selection,
* thus it can be used to fixup all tables
* in a page independant of the selection
*/
NS_IMETHOD NormalizeTable(nsIDOMElement *aTable)=0;
@ -156,7 +159,28 @@ public:
PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
PRBool& aIsSelected)=0;
/** Get the first row element in a table
*
* @param aTableElement Any TABLE or child-of-table element in the document
* @param aRowIndex The 0-based index of the row
*
* Returns:
* @param aRow The row at the requested index
* Returns null if there are no rows in table
*/
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)=0;
/** Get the next row element starting the search from aTableElement
*
* @param aTableElement Any TR or child-of-TR element in the document
*
* Returns:
* @param aRow The row to start search from
* and the row returned from the search
* Returns null if there isn't another row
*/
NS_IMETHOD GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)=0;
/** Preferred direction to search for neighboring cell
* when trying to locate a cell to place caret in after
* a table editing action.
@ -196,7 +220,7 @@ public:
* @param aIsSelected Tells if element returned is a selected element
* (false if element is a parent cell of selection)
*/
NS_IMETHOD GetSelectedOrParentTableElement(nsCOMPtr<nsIDOMElement> &aTableElement, nsString& aTagName, PRBool &aIsSelected)=0;
NS_IMETHOD GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsString& aTagName, PRBool &aIsSelected)=0;
};

Просмотреть файл

@ -420,7 +420,15 @@ function EditorShowClipboard()
function EditorViewSource()
{
window.openDialog( "chrome://editor/content/viewsource.xul", "_blank", "all,dialog=no", window.content.location );
// *** THIS IS NOT CORRECT - It simply loads the content from original URL,
// which will now show current editor document changes.
// Use a browser window to view source
window.openDialog( "chrome://navigator/content/",
"_blank",
"chrome,menubar,status,dialog=no,resizable",
window.content.location,
"view-source" );
}
@ -629,6 +637,20 @@ function EditorSelectBackColor(ColorPickerID, ColorWellID)
EditorSetBackgroundColor(color);
}
function EditorRemoveTextColor(ColorWellID)
{
//TODO: Set colorwell to browser's default color
editorShell.SetTextProperty("font", "color", "");
contentWindow.focus();
}
function EditorRemoveBackColor(ColorWellID)
{
//TODO: Set colorwell to browser's default color
editorShell.SetBackgroundColor("");
contentWindow.focus();
}
function EditorSetFontColor(color)
{
editorShell.SetTextProperty("font", "color", color);
@ -731,7 +753,7 @@ function EditorListProperties()
function EditorPageProperties(startTab)
{
window.openDialog("chrome://editor/content/EdPageProps.xul","_blank", "chrome,close,titlebar,modal", startTab);
window.openDialog("chrome://editor/content/EdPageProps.xul","_blank", "chrome,close,titlebar,modal", "", startTab);
contentWindow.focus();
}
@ -869,112 +891,6 @@ function EditorIndent(indent)
contentWindow.focus();
}
// Call this with insertAllowed = true to allow inserting if not in existing table,
// else use false to do nothing if not in a table
function EditorInsertOrEditTable(insertAllowed)
{
var table = editorShell.GetElementOrParentByTagName("table", null);
if (table) {
// Edit properties of existing table
dump("Existing table found ... Editing its properties\n");
window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "");
contentWindow.focus();
} else if(insertAllowed) {
EditorInsertTable();
}
}
function EditorSelectTable()
{
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorSelectTableRow()
{
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorSelectTableColumn()
{
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorSelectTableCell()
{
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorInsertTable()
{
// Insert a new table
window.openDialog("chrome://editor/content/EdInsertTable.xul", "_blank", "chrome,close,titlebar,modal", "");
contentWindow.focus();
}
function EditorInsertTableCell(after)
{
editorShell.InsertTableCell(1,after);
contentWindow.focus();
}
function EditorInsertTableRow(below)
{
editorShell.InsertTableRow(1,below);
contentWindow.focus();
}
function EditorInsertTableColumn(after)
{
editorShell.InsertTableColumn(1,after);
contentWindow.focus();
}
function JoinTableCells()
{
editorShell.JoinTableCells();
contentWindow.focus();
}
function EditorDeleteTable()
{
editorShell.DeleteTable();
contentWindow.focus();
}
function EditorDeleteTableRow()
{
// TODO: Get the number of rows to delete from the selection
editorShell.DeleteTableRow(1);
contentWindow.focus();
}
function EditorDeleteTableColumn()
{
// TODO: Get the number of cols to delete from the selection
editorShell.DeleteTableColumn(1);
contentWindow.focus();
}
function EditorDeleteTableCell()
{
// TODO: Get the number of cells to delete from the selection
editorShell.DeleteTableCell(1);
contentWindow.focus();
}
function EditorDeleteTableCellContents()
{
// TODO: Get the number of cells to delete from the selection
editorShell.DeleteTableCellContents();
contentWindow.focus();
}
function EditorMakeOrChangeList(listType)
{
// check the observer node,
@ -1382,3 +1298,179 @@ function getColorAndSetColorWell(ColorPickerID, ColorWellID)
return color;
}
// Call this with insertAllowed = true to allow inserting if not in existing table,
// else use false to do nothing if not in a table
function EditorInsertOrEditTable(insertAllowed)
{
var table = editorShell.GetElementOrParentByTagName("table", null);
if (table) {
// Edit properties of existing table
dump("Existing table found ... Editing its properties\n");
window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "");
contentWindow.focus();
} else if(insertAllowed) {
EditorInsertTable();
}
}
function GetChildOffset(parent,child)
{
if (!parent || !child)
return null;
var nodeList = parent.childNodes;
var i;
if (nodeList)
{
for ( i = 0; i<nodeList.length; i++)
{
if (nodeList.item(i) == child)
return i;
}
}
return null;
}
function AppendNodeToSelection(selection, node)
{
if (selection && node)
{
var parent = node.parentNode;
var offset = GetChildOffset(parent,node);
if (offset)
{
var range = editorShell.editorDocument.createRange();
if (range)
{
range.setStart(parent,offset);
range.setEnd(parent,offset+1);
selection.addRange(range);
}
}
}
}
function EditorSelectTableCell()
{
var selection = editorShell.editorSelection;
if (selection)
{
var cellNode = editorShell.GetElementOrParentByTagName("td",selection.anchorNode);
if (cellNode)
{
selection.clearSelection();
AppendNodeToSelection(selection, cellNode);
}
}
contentWindow.focus();
}
function EditorSelectTable()
{
var selection = editorShell.editorSelection;
if (selection)
{
var tableNode = editorShell.GetElementOrParentByTagName("table",selection.anchorNode);
if (tableNode)
{
selection.clearSelection();
AppendNodeToSelection(selection, tableNode);
}
}
contentWindow.focus();
}
function EditorSelectTableRow()
{
var tagNameObj = new Object();
var isSelectedObj = new Object();
var tagName;
var isSelected;
var tableElement = editorShell.GetSelectedOrParentTableElement(tagNameObj,isSelectedObj);
tagName = tagNameObj.value;
isSelected = isSelectedObj.value;
dump("Table element="+tableElement+" Tagname="+tagName+" IsSelected="+isSelected+"\n");
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorSelectTableColumn()
{
//TODO: FINISH THIS!
contentWindow.focus();
}
function EditorInsertTable()
{
// Insert a new table
window.openDialog("chrome://editor/content/EdInsertTable.xul", "_blank", "chrome,close,titlebar,modal", "");
contentWindow.focus();
}
function EditorInsertTableCell(after)
{
editorShell.InsertTableCell(1,after);
contentWindow.focus();
}
function EditorInsertTableRow(below)
{
editorShell.InsertTableRow(1,below);
contentWindow.focus();
}
function EditorInsertTableColumn(after)
{
editorShell.InsertTableColumn(1,after);
contentWindow.focus();
}
function EditorNormalizeTable()
{
editorShell.NormalizeTable(null);
contentWindow.focus();
}
function EditorJoinTableCells()
{
editorShell.JoinTableCells();
contentWindow.focus();
}
function EditorDeleteTable()
{
editorShell.DeleteTable();
contentWindow.focus();
}
function EditorDeleteTableRow()
{
// TODO: Get the number of rows to delete from the selection
editorShell.DeleteTableRow(1);
contentWindow.focus();
}
function EditorDeleteTableColumn()
{
// TODO: Get the number of cols to delete from the selection
editorShell.DeleteTableColumn(1);
contentWindow.focus();
}
function EditorDeleteTableCell()
{
// TODO: Get the number of cells to delete from the selection
editorShell.DeleteTableCell(1);
contentWindow.focus();
}
function EditorDeleteTableCellContents()
{
// TODO: Get the number of cells to delete from the selection
editorShell.DeleteTableCellContents();
contentWindow.focus();
}

Просмотреть файл

@ -81,8 +81,8 @@
<menupopup id="menu_View_Popup">
<menu id="viewToolbar"/>
<!-- menuseparator /> Put this back when it works.
<menuitem id="viewSourceMenuitem"/ -->
<menuseparator/>
<menuitem id="viewSourceMenuitem"/>
<menuseparator />
<menu id="charsetMenu"/>
<menu id="charsetMenu1"/>

Просмотреть файл

@ -486,8 +486,6 @@
accesskey="&formatstylesheetmenu.accesskey;"
position="13">
<menupopup>
<menuitem value="&stylesheetEditorOneCmd.label;" accesskey="&sseditor1.accesskey;" oncommand="EditorApplyStyleSheet('chrome://editor/content/EditorStyles1.css')"/>
<menuseparator />
<menuitem value="&stylesheetOldstyleCmd.label;" accesskey="&ssoldstyle.accesskey;" oncommand="EditorApplyStyleSheet('http://www.w3.org/StyleSheets/Core/Oldstyle')"/>
<menuitem value="&stylesheetModernistCmd.label;" accesskey="&ssmodernist.accesskey;" oncommand="EditorApplyStyleSheet('http://www.w3.org/StyleSheets/Core/Modernist')"/>
<menuitem value="&stylesheetMidnightCmd.label;" accesskey="&ssmidnight.accesskey;" oncommand="EditorApplyStyleSheet('http://www.w3.org/StyleSheets/Core/Midnight')"/>
@ -527,14 +525,14 @@
position="19"/>
<menuitem id="colorsAndBackground" value="&colorsAndBackground.label;"
accesskey="&colorsandbackground.accesskey;"
oncommand="EditorPageProperties('1')"
oncommand="EditorPageProperties('ColorTab')"
position="20"/>
<!-- Merge page property items here -->
</menupopup>
<menuitem id="pageProperties" value="&pageProperties.label;"
accesskey="&pageproperties.accesskey;"
oncommand="EditorPageProperties('0')"/>
oncommand="EditorPageProperties('GeneralTab')"/>
<menu id="tableMenu" value="&tableMenu.label;" accesskey="&tablemenu.accesskey;">
<menupopup>
@ -570,6 +568,7 @@
</menupopup>
</menu>
<menuseparator />
<menuitem id="tableFixupMenuitem" value="&tableFixup.label;" accesskey="&tablefixup.accesskey;" oncommand="EditorNormalizeTable()"/>
<menuitem id="tableJoinCellsMenuitem" value="&tableJoinCells.label;" accesskey="&tablejoin.accesskey;" oncommand="EditorJoinTableCells()"/>
<menuitem id="tablePropertiesMenuitem" value="&properties.label;" accesskey="&properties.accesskey;" oncommand="EditorInsertOrEditTable(false)"/>
</menupopup>
@ -579,6 +578,7 @@
<html:div id="TextColorCaption" class="color-caption" align="center">&textColorCaption.label;</html:div>
<!-- TODO: Add "Last color picked" button and text -->
<colorpicker id="TextColorPicker" palettename="standard" onclick="EditorSelectTextColor('TextColorPicker','TextColorPopupButton'); parentNode.closePopup();"/>
<titledbutton class="push" value="&formatToolbar.colorPicker.default.label;" onclick="EditorRemoveTextColor('TextColorPopupButton'); parentNode.closePopup();"/>
</popup>
<popup id="BackColorPopup" popupanchor="bottomleft">
@ -586,6 +586,7 @@
<!-- TODO: Add "Last color picked" button and text -->
<html:div id="BackColorCaption" class="color-caption" align="center">Background Color</html:div>
<colorpicker id="BackColorPicker" palettename="standard" onclick="EditorSelectBackColor('BackColorPicker','BackColorPopupButton'); parentNode.closePopup();"/>
<titledbutton class="push" value="&formatToolbar.colorPicker.default.label;" onclick="EditorRemoveBackColor('BackColorPopupButton'); parentNode.closePopup();"/>
</popup>
<menupopup id="AlignmentPopup">

Просмотреть файл

@ -30,7 +30,6 @@ install::
$(MAKE_INSTALL) EditorCommandsDebug.js $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorInitPage.html $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorInitPagePlain.html $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorStyles1.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorContent.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorOverride.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) sidebar-editor.rdf $(DIST)\bin\chrome\editor\content\default
@ -53,7 +52,6 @@ clobber::
rm -f $(DIST)\bin\chrome\editor\content\default\EditorCommandsDebug.js
rm -f $(DIST)\bin\chrome\editor\content\default\EditorInitPage.html
rm -f $(DIST)\bin\chrome\editor\content\default\EditorInitPagePlain.html
rm -f $(DIST)\bin\chrome\editor\content\default\EditorStyles1.css
rm -f $(DIST)\bin\chrome\editor\content\default\EditorContent.css
rm -f $(DIST)\bin\chrome\editor\content\default\EditorOverride.css
rm -f $(DIST)\bin\chrome\editor\content\default\sidebar-editor.rdf

Просмотреть файл

@ -101,7 +101,7 @@
<!ENTITY showFormattingToolbarCmd.label ".Show Format Toolbar">
<!ENTITY showTaskbarCmd.label "Show Taskbar">
<!ENTITY showTaskbarCmd.accesskey "t">
<!ENTITY viewPageSource.label "View Page Source">
<!ENTITY viewPageSource.label "Page Source">
<!ENTITY viewpagesource.accesskey "s">
@ -374,8 +374,6 @@
<!-- Style Sheet submenu -->
<!ENTITY stylesheetMenu.label "Apply Style Sheet">
<!ENTITY formatstylesheetmenu.accesskey "e">
<!ENTITY stylesheetEditorOneCmd.label "Editor Styles 1">
<!ENTITY sseditor1.accesskey "1">
<!ENTITY stylesheetOldstyleCmd.label "Oldstyle">
<!ENTITY ssoldstyle.accesskey "o">
<!ENTITY stylesheetModernistCmd.label "Modernist">
@ -445,7 +443,9 @@
<!ENTITY tableDeleteMenu.label "Delete">
<!ENTITY tabledeletemenu.accesskey "d">
<!ENTITY tableJoinCells.label ".Join Cells">
<!ENTITY tableFixup.label "Fixup table layout">
<!ENTITY tablefixup.accesskey "f">
<!ENTITY tableJoinCells.label "Join Cells">
<!ENTITY tablejoin.accesskey "j">
<!-- These may be shared in other menus -->
<!ENTITY properties.label "Properties...">
@ -505,6 +505,7 @@
<!ENTITY formatToolbar.boldChar "B">
<!ENTITY formatToolbar.italicChar "I">
<!ENTITY formatToolbar.underlineChar "U">
<!ENTITY formatToolbar.colorPicker.default.label "Don't Specify Color">
<!ENTITY tempNotification.label "[status message]">
<!ENTITY tempDoneLoading.label "[Document loading message]">

Просмотреть файл

@ -20,11 +20,10 @@
* Contributor(s):
*/
var textColor;
var linkColor;
var followedLinkColor;
var activeLinkColor;
var backgroundColor;
var tabPanel;
var currentTab;
var colorPage;
var colorIndex = 0;
//Cancel() is in EdDialogCommon.js
// dialog initialization code
@ -33,10 +32,54 @@ function Startup()
if (!InitEditorShell())
return;
colorPage = new Object;
if (!colorPage)
{
dump("Failed to create colorPage object!!!\n");
window.close();
}
colorPage.ColorPreview = document.getElementById("ColorPreview");
colorPage.NormalText = document.getElementById("NormalText");
colorPage.LinkText = document.getElementById("LinkText");
colorPage.ActiveLinkText = document.getElementById("ActiveLinkText");
colorPage.FollowedLinkText = document.getElementById("FollowedLinkText");
// colorPage. = documentgetElementById("");
tabPanel = document.getElementById("tabPanel");
// Set the starting Tab:
var tabName = window.arguments[1];
currentTab = document.getElementById(tabName);
if (!currentTab)
currentTab = document.getElementById("GeneralTab");
if (!tabPanel || !currentTab)
{
dump("Not all dialog controls were found!!!\n");
window.close;
}
// Trigger setting of style for the selected tab widget
currentTab.setAttribute("selected", "true");
// Activate the corresponding panel
var index = 0;
switch(tabName)
{
case "ColorTab":
index = 1;
break;
case "MetaTab":
index = 2;
break;
}
tabPanel.setAttribute("index",index);
doSetOKCancel(onOK, null);
initDialog();
InitDialog();
//.focus();
}
@ -44,29 +87,47 @@ function InitDialog()
{
}
function getColor(ColorPickerID, ColorWellID)
function GetColor(ColorPickerID, ColorWellID)
{
var color = getColorAndSetColorWell(ColorPickerID, ColorWellID);
dump("GetColor, color="+color+"\n");
if (!color)
{
// No color was clicked on,
// so user clicked on "Don't Specify Color" button
color = "inherit";
dump("Don't specify color\n");
}
var colorString = "color:"+color;
switch( ColorPickerID )
{
case "textCP":
textColor = color;
colorPage.textColor = color;
colorPage.NormalText.setAttribute("style",colorString);
break;
case "linkCP":
linkColor = color;
colorPage.linkColor = color;
colorPage.LinkText.setAttribute("style",colorString);
break;
case "followedCP":
followedLinkColor = color;
colorPage.followedLinkColor = color;
colorPage.FollowedLinkText.setAttribute("style",colorString);
break;
case "activeCP":
activeLinkColor = color;
colorPage.activeLinkColor = color;
colorPage.ActiveLinkText.setAttribute("style",colorString);
break;
case "backgroundCP":
backgroundColor = color;
colorPage.backgroundColor = color;
colorPage.ColorPreview.setAttribute("bgcolor",color);
break;
}
}
function RemoveColor(ColorWellID)
{
}
function onOK()
{

Просмотреть файл

@ -45,14 +45,14 @@
<keyset id="keyset"/>
<tabcontrol align="vertical">
<tabbox align="horizontal" flex="100%">
<tab>&generalTab.label;</tab>
<tab>&backgroundTab.label;</tab>
<tab>&metaTagsTab.label;</tab>
<tab id="GeneralTab">&generalTab.label;</tab>
<tab id="ColorTab">&backgroundTab.label;</tab>
<tab id="MetaTab">&metaTagsTab.label;</tab>
</tabbox>
<tabpanel flex="100%">
<!-- general tab -->
<box align="vertical">
<tabpanel id="tabPanel" flex="100%">
<!-- ***** general tab ***** -->
<box id="panel1" align="vertical">
<html:table>
<html:tr>
<html:td>
@ -97,85 +97,127 @@
</html:table>
</box>
<!-- colors/background tab -->
<box align="vertical">
<!-- **** colors/background tab **** -->
<box id="panel2" align="vertical">
<html:fieldset><html:legend class = "dialog" align = "left">&pageColors.label;</html:legend>
<html:input type="radio" name="ColorMode" id="DefaultColorsRadio"/>
<html:label for="DefaultColorsRadio">&defaultColorsRadio.label;</html:label>
<html:br/>
<html:input type="radio" name="ColorMode" id="CustomColorsRadio"/>
<html:label for="CustomColorsRadio">&customColorsRadio.label;</html:label>
<html:br/>
<html:div>
<html:label for="ColorScheme">&colorScheme.label;</html:label>
<!-- TODO: COLOR SCHEME SELECT LIST -->
</html:div>
<html:br/>
<box align="horizontal" flex="100%">
<box align="vertical" flex="100%">
<html:div class="middle-align">
<titledbutton class="color-well" id="textCW" popup="textPopup"/>
<titledbutton value="&normalText.label;" class="push dialog popup" align="right" popup="textPopup"/>
</html:div>
<html:div class="middle-align">
<titledbutton class="color-well" id="linkCW" popup="linkPopup"/>
<titledbutton value="&linkText.label;" class="push dialog popup" align="right" popup="linkPopup"/>
</html:div>
<html:div class="middle-align">
<titledbutton class="color-well" id="activeCW" popup="activePopup"/>
<titledbutton value="&activeLinkText.label;" class="push dialog popup" align="right" popup="activePopup"/>
</html:div>
<html:div class="middle-align">
<titledbutton class="color-well" id="followedCW" popup="followedPopup"/>
<titledbutton value="&followedLinkText.label;" class="push dialog popup" align="right" popup="followedPopup"/>
</html:div>
<html:div class="middle-align">
<titledbutton class="color-well" id="backgroundCW" popup="backgroundPopup"/>
<titledbutton value="&background.label;" class="push dialog popup" align="right" popup="backgroundPopup"/>
</html:div>
<html:input type="radio" name="ColorMode" id="DefaultColorsRadio"/>
<html:label for="DefaultColorsRadio">&defaultColorsRadio.label;</html:label>
<html:br/>
<html:input type="radio" name="ColorMode" id="CustomColorsRadio"/>
<html:label for="CustomColorsRadio">&customColorsRadio.label;</html:label>
<html:br/>
<html:div>
<spring class="bigspacer"/>
<box flex="1">
<html:label> &colorScheme.label;
<html:select id="ColorScheme" size="1" style="min-width: 10em">
<html:option> Black on White </html:option>
<html:option> Blue on White </html:option>
<html:option> White on Black </html:option>
</html:select>
</html:label>
</box>
<!-- TODO: COLOR SCHEME SELECT LIST -->
</html:div>
<spring class="bigspacer"/>
<box align="horizontal">
<spring class="bigspacer"/>
<box align="vertical" flex="100%">
<box>
<html:label class="margin-both"> &normalText.label; </html:label>
<spring flex="100%"/>
<menu class="colorpicker">
<html:div id="textCW" class="color-well"/>
<titledbutton class="popup" align="right" flex="100%" onclick="GetColor('textCP','textCW');"/>
<menupopup id="normalMenuPopup">
<colorpicker id="textCP" palettename="standard" onclick="GetColor('textCP','textCW');"/>
<titledbutton class="push" value="&colorPicker.default.label;" onclick="GetColor('textCP','textCW');"/>
</menupopup>
</menu>
</box>
<spring class="spacer"/>
<box>
<html:label class="margin-both"> &linkText.label; </html:label>
<spring flex="100%"/>
<menu class="colorpicker">
<html:div id="linkCW" class="color-well"/>
<titledbutton class="popup" align="right" flex="100%"/>
<menupopup>
<colorpicker id="linkCP" palettename="standard" onclick="GetColor('linkCP','linkCW');"/>
<titledbutton class="push" value="&colorPicker.default.label;" onclick="RemoveColor('linkCW');"/>
</menupopup>
</menu>
</box>
<spring class="spacer"/>
<box>
<html:label class="margin-both"> &activeLinkText.label; </html:label>
<spring flex="100%"/>
<menu class="colorpicker">
<html:div id="activeCW" class="color-well"/>
<titledbutton class="popup" align="right" flex="100%"/>
<menupopup>
<colorpicker id="activeCP" palettename="standard" onclick="GetColor('activeCP','activeCW');"/>
<titledbutton class="push" value="&colorPicker.default.label;" onclick="RemoveColor('activeCW');"/>
</menupopup>
</menu>
</box>
<spring class="spacer"/>
<box>
<html:label class="margin-both"> &followedLinkText.label; </html:label>
<spring flex="100%"/>
<menu class="colorpicker">
<html:div id="followedCW" class="color-well"/>
<titledbutton class="popup" align="right" flex="100%"/>
<menupopup>
<colorpicker id="followedCP" palettename="standard" onclick="GetColor('followedCP','followedCW');"/>
<titledbutton class="push" value="&colorPicker.default.label;" onclick="RemoveColor('followedCW');"/>
</menupopup>
</menu>
</box>
<spring class="spacer"/>
<box>
<html:label class="margin-both"> &background.label; </html:label>
<spring flex="100%"/>
<menu class="colorpicker">
<html:div id="backgroundCW" class="color-well"/>
<titledbutton class="popup" align="right" flex="100%"/>
<menupopup>
<colorpicker id="backgroundCP" palettename="standard" onclick="GetColor('backgroundCP','backgroundCW');"/>
<titledbutton class="push" value="&colorPicker.default.label;" onclick="RemoveColor('backgroundCW');"/>
</menupopup>
</menu>
</box>
<!-- SAMPLE WINDOW -->
<div id="TextSampleWindow"/>
</box>
<spring class="bigspacer"/>
<box align="vertical" flex="100%" id="ColorPreview">
<!-- basestyle="min-height:50px; width: 100%; border: 1px inset #CCCCCC; padding: 5px; " style="min-height:50px; width: 100%; border: 1px inset #CCCCCC; padding: 5px; "-->
<html:div id="NormalText">&normalText.label;</html:div>
<spring class="spacer"/>
<html:div id="LinkText">&linkText.label;</html:div>
<spring class="spacer"/>
<html:div id="ActiveLinkText">&activeLinkText.label;</html:div>
<spring class="spacer"/>
<html:div id="FollowedLinkText">&followedLinkText.label;</html:div>
</box>
</box>
</html:fieldset>
<box align="horizontal">
<html:input type="checkbox" id="BackgroundImageCheckbox"/>
<html:label for="BackgroundImageCheckbox">
&backgroundImage.label;
</html:label>
<html:label for="BackgroundImageCheckbox"> &backgroundImage.label; </html:label>
</box>
<box align="horizontal">
<html:input type="text" id="BackgroundImageInput" size="10"/>
<html:input type="text" class="SizeToParent" id="BackgroundImageInput" size="20"/>
<spring class="spacer"/>
<!-- from EdDialogOverlay.xul -->
<titledbutton id="ChooseFile"/>
</box>
</box> <!-- end of colors tab -->
<!-- meta tags tab -->
<box align="vertical">
<!-- **** meta tags tab **** -->
<box id="panel3" align="vertical">
</box>
</tabpanel>
</tabcontrol>
<html:div class="separator" align="horizontal"/>
<box id="okCancelButtons"/>
<popupset>
<popup id="textPopup">
<colorpicker id="textCP" palettename="standard" onclick="getColor('textCP', 'textCW'); parentNode.closePopup();"/>
</popup>
<popup id="linkPopup">
<colorpicker id="linkCP" palettename="standard" onclick="getColor('linkCP', 'linkCW'); parentNode.closePopup();"/>
</popup>
<popup id="activePopup">
<colorpicker id="activeCP" palettename="standard" onclick="getColor('activeCP', 'activeCW'); parentNode.closePopup();"/>
</popup>
<popup id="followedPopup">
<colorpicker id="followedCP" palettename="standard" onclick="getColor('followedCP', 'followedCW'); parentNode.closePopup();"/>
</popup>
<popup id="backgroundPopup">
<colorpicker id="backgroundCP" palettename="standard" onclick="getColor('backgroundCP', 'backgroundCW'); parentNode.closePopup();"/>
</popup>
</popupset>
</window>

Просмотреть файл

@ -32,11 +32,12 @@
<!ENTITY descriptionInput.label "Description">
<!ENTITY pageColors.label "Page Colors">
<!ENTITY defaultColorsRadio.label "Don't specify colors">
<!ENTITY customColorsRadio.label "Use custom colors">
<!ENTITY colorScheme.label "Color Schemes">
<!ENTITY normalText.label "Normal text">
<!ENTITY linkText.label "Link text">
<!ENTITY activeLinkText.label "Active link text">
<!ENTITY followedLinkText.label "Followed link text">
<!ENTITY background.label "Background">
<!ENTITY backgroundImage.label "Background Image">
<!ENTITY customColorsRadio.label "Use custom colors:">
<!ENTITY colorScheme.label "Color Schemes:">
<!ENTITY normalText.label "Normal text:">
<!ENTITY linkText.label "Link text:">
<!ENTITY activeLinkText.label "Active link text:">
<!ENTITY followedLinkText.label "Followed link text:">
<!ENTITY background.label "Background:">
<!ENTITY backgroundImage.label "Background Image:">
<!ENTITY colorPicker.default.label "Don't Specify Color">

Просмотреть файл

@ -55,25 +55,31 @@ div#message {
margin-left: 10px;
}
div.color-well {
width:30px;
border: 1px inset white;
/* Background color is set at runtime */
background-color:white;
}
div#TextSampleWindow {
border: 1px inset white;
width: 100px;
height: 100px;
background-color:white;
}
div.middle-align {
vertical-align: middle;
}
label.margin-both {
margin-left: 10px;
margin-right: 5px;
}
div.color-well {
width:20px;
border: 1px inset #CCCCCC;
/* Background color is set at runtime */
background-color: red;
}
/* XUL ELEMENTS */
box#ColorPreview {
border: 1px inset #CCCCCC;
padding: 5px;
width: 100%;
min-height: 50px;
height: 100px;
background-color: white;
}
/* values = margin, padding. Padding doesn't work yet */
@ -116,6 +122,11 @@ titledbutton#MisspelledWord {
font-weight: bold;
}
/* need rule for outset shape */
menu.colorpicker {
border: 1px outset #CCCCCC;
}
titledbutton.color-well {
list-style-image:url("chrome://editor/skin/images/color.gif");
border: 1px solid #CCCCCC;