more work on #73868. converting ab from tree to outliner.

NOT PART OF THE BUILD
This commit is contained in:
sspitzer%netscape.com 2001-11-13 00:16:18 +00:00
parent c29e5d6eec
commit f3b8e16d55
3 changed files with 169 additions and 41 deletions

View File

@ -40,10 +40,20 @@
interface nsIAbCard;
[scriptable, uuid(79ad5d6e-1dd2-11b2-addd-f547dab50d75)]
interface nsIAbViewListener : nsISupports
{
void onSelectionChanged();
};
[scriptable, uuid(e35c015c-1dd1-11b2-9494-f88326252aae)]
interface nsIAbView : nsISupports
{
void init(in string aURI);
void init(in string URI, in nsIAbViewListener abViewListener);
void close();
readonly attribute string URI;
nsIAbCard getCardFromRow(in long row);
void selectAll();
void deleteSelectedCards();

View File

@ -68,10 +68,23 @@ nsAbView::nsAbView()
{
NS_INIT_ISUPPORTS();
mMailListAtom = getter_AddRefs(NS_NewAtom("MailList"));
mSuppressSelectionChange = PR_FALSE;
}
nsAbView::~nsAbView()
{
if (mDirectory) {
nsresult rv = Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to close view");
}
}
NS_IMETHODIMP nsAbView::Close()
{
mURI = "";
mDirectory = nsnull;
mAbViewListener = nsnull;
nsresult rv = NS_OK;
nsCOMPtr<nsIAddrBookSession> abSession = do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
if(NS_SUCCEEDED(rv))
@ -82,6 +95,7 @@ nsAbView::~nsAbView()
{
RemoveCardAt(i);
}
return NS_OK;
}
void nsAbView::RemoveCardAt(PRInt32 row)
@ -94,11 +108,18 @@ void nsAbView::RemoveCardAt(PRInt32 row)
PR_FREEIF(abcard);
}
NS_IMETHODIMP nsAbView::Init(const char *aURI)
NS_IMETHODIMP nsAbView::GetURI(char **aURI)
{
*aURI = nsCRT::strdup(mURI.get());
return NS_OK;
}
NS_IMETHODIMP nsAbView::Init(const char *aURI, nsIAbViewListener *abViewListener)
{
nsresult rv;
mURI = aURI;
mAbViewListener = abViewListener;
/* todo:
register as a listener of "mail.addr_book.lastnamefirst"
@ -150,6 +171,9 @@ nsresult nsAbView::EnumerateCards()
nsCOMPtr <nsIAbCard> card = do_QueryInterface(item);
// malloc these from an arena
AbCard *abcard = (AbCard *) PR_Calloc(1, sizeof(struct AbCard));
if (!abcard)
return NS_ERROR_OUT_OF_MEMORY;
abcard->card = card;
NS_IF_ADDREF(abcard->card);
rv = mCards.AppendElement((void *)abcard);
@ -189,6 +213,9 @@ NS_IMETHODIMP nsAbView::GetRowProperties(PRInt32 index, nsISupportsArray *proper
NS_IMETHODIMP nsAbView::GetCellProperties(PRInt32 row, const PRUnichar *colID, nsISupportsArray *properties)
{
if (mCards.Count() <= row)
return NS_OK;
// "Di" to distinguish "DisplayName" from "Department"
if (colID[0] != 'D' || colID[1] != 'i')
return NS_OK;
@ -313,7 +340,11 @@ nsresult nsAbView::InvalidateOutliner(PRInt32 row)
NS_IMETHODIMP nsAbView::SelectionChanged()
{
return NS_OK;
if (mAbViewListener && !mSuppressSelectionChange) {
nsresult rv = mAbViewListener->OnSelectionChanged();
NS_ENSURE_SUCCESS(rv,rv);
}
return NS_OK;
}
NS_IMETHODIMP nsAbView::CycleCell(PRInt32 row, const PRUnichar *colID)
@ -348,6 +379,11 @@ NS_IMETHODIMP nsAbView::PerformActionOnCell(const PRUnichar *action, PRInt32 row
NS_IMETHODIMP nsAbView::GetCardFromRow(PRInt32 row, nsIAbCard **aCard)
{
if (mCards.Count() <= row) {
*aCard = nsnull;
return NS_OK;
}
*aCard = ((AbCard *)(mCards.ElementAt(row)))->card;
NS_IF_ADDREF(*aCard);
return NS_OK;
@ -497,29 +533,43 @@ NS_IMETHODIMP nsAbView::OnItemAdded(nsISupports *parentDir, nsISupports *item)
if (addedCard) {
// malloc these from an arena
AbCard *abcard = (AbCard *) PR_Calloc(1, sizeof(struct AbCard));
if (!abcard)
return NS_ERROR_OUT_OF_MEMORY;
abcard->card = addedCard;
NS_IF_ADDREF(abcard->card);
rv = GenerateCollationKeysForCard(mSortedColumn.get(), abcard);
NS_ENSURE_SUCCESS(rv,rv);
PRInt32 index = FindIndexForInsert(mSortedColumn.get(), abcard);
rv = mCards.InsertElementAt((void *)abcard, index);
PRInt32 index;
rv = AddCard(abcard, PR_FALSE /* select card */, &index);
NS_ENSURE_SUCCESS(rv,rv);
if (mOutliner)
rv = mOutliner->RowCountChanged(index, 1);
NS_ENSURE_SUCCESS(rv,rv);
}
else {
// if a mailing list gets created, we'll get notified
// but the item will be a nsIAbDirectory.
// ignore it, as we've already been notified from CreateMailListAndAddToDB()
}
}
return rv;
}
nsresult nsAbView::AddCard(AbCard *abcard, PRBool selectCardAfterAdding, PRInt32 *index)
{
nsresult rv = NS_OK;
NS_ENSURE_ARG_POINTER(abcard);
*index = FindIndexForInsert(mSortedColumn.get(), abcard);
rv = mCards.InsertElementAt((void *)abcard, *index);
NS_ENSURE_SUCCESS(rv,rv);
if (mOutliner)
rv = mOutliner->RowCountChanged(*index, 1);
if (selectCardAfterAdding && mOutlinerSelection) {
mOutlinerSelection->SetCurrentIndex(*index);
mOutlinerSelection->RangedSelect(*index, *index, PR_FALSE /* augment */);
}
return rv;
}
PRInt32 nsAbView::FindIndexForInsert(const PRUnichar *colID, AbCard *abcard)
{
PRInt32 count = mCards.Count();
@ -543,34 +593,47 @@ NS_IMETHODIMP nsAbView::OnItemRemoved(nsISupports *parentDir, nsISupports *item)
nsresult rv;
nsCOMPtr <nsIAbDirectory> directory = do_QueryInterface(parentDir,&rv);
NS_ENSURE_SUCCESS(rv,rv);
if (directory.get() == mDirectory.get()) {
nsCOMPtr <nsIAbCard> card = do_QueryInterface(item);
if (item) {
PRInt32 index = FindIndexForCard(mSortedColumn.get(), card);
NS_ASSERTION(index != CARD_NOT_FOUND,"card not found");
if (index != CARD_NOT_FOUND) {
RemoveCardAt(index);
if (mOutliner)
rv = mOutliner->RowCountChanged(index, -1);
NS_ENSURE_SUCCESS(rv,rv);
rv = RemoveCardAndSelectNextCard(item);
}
return rv;
}
nsresult nsAbView::RemoveCardAndSelectNextCard(nsISupports *item)
{
nsresult rv = NS_OK;
nsCOMPtr <nsIAbCard> card = do_QueryInterface(item);
if (card) {
PRInt32 index = FindIndexForCard(card);
if (index != CARD_NOT_FOUND) {
RemoveCardAt(index);
if (mOutliner)
rv = mOutliner->RowCountChanged(index, -1);
NS_ENSURE_SUCCESS(rv,rv);
PRInt32 count = mCards.Count();
if (count && mOutlinerSelection) {
// if we deleted the last card, adjust so we select the new "last" card
if (index >= (count - 1)) {
index = count -1;
}
mOutlinerSelection->SetCurrentIndex(index);
mOutlinerSelection->RangedSelect(index, index, PR_FALSE /* augment */);
}
}
else {
// if a mailing list gets delete, we'll get notified
// but the item will be a nsIAbDirectory.
// ignore it, as we've already been notified from NotifyDirectoryItemDeleted()
}
}
return rv;
}
PRInt32 nsAbView::FindIndexForCard(const PRUnichar *colID, nsIAbCard *card)
PRInt32 nsAbView::FindIndexForCard(nsIAbCard *card)
{
PRInt32 count = mCards.Count();
PRInt32 i;
// XXX todo, binary search
// you can't implement the binary search here, as all you have is the nsIAbCard
// you might be here because one of the card properties has changed, and that property
// could be the collation key.
for (i=0; i < count; i++) {
AbCard *abcard = (AbCard*) (mCards.ElementAt(i));
if (abcard->card == card) {
@ -584,15 +647,66 @@ NS_IMETHODIMP nsAbView::OnItemPropertyChanged(nsISupports *item, const char *pro
{
nsresult rv;
nsCOMPtr <nsIAbCard> card = do_QueryInterface(item,&rv);
nsCOMPtr <nsIAbCard> card = do_QueryInterface(item);
if (!card)
return NS_OK;
PRInt32 index = FindIndexForCard(card);
if (index == -1)
return NS_OK;
AbCard *oldCard = (AbCard*) (mCards.ElementAt(index));
// malloc these from an arena
AbCard *newCard = (AbCard *) PR_Calloc(1, sizeof(struct AbCard));
if (!newCard)
return NS_ERROR_OUT_OF_MEMORY;
newCard->card = card;
NS_IF_ADDREF(newCard->card);
rv = GenerateCollationKeysForCard(mSortedColumn.get(), newCard);
NS_ENSURE_SUCCESS(rv,rv);
PRInt32 index = FindIndexForCard(mSortedColumn.get(), card);
if (index != CARD_NOT_FOUND) {
if (!nsCRT::strcmp(newCard->primaryCollationKey, oldCard->primaryCollationKey) &&
!nsCRT::strcmp(newCard->secondaryCollationKey, oldCard->secondaryCollationKey)) {
// no need to remove and add, since the collation keys haven't change.
// since they haven't chagned, the card will sort to the same place.
// we just need to clean up what we allocated.
NS_IF_RELEASE(newCard->card);
PR_FREEIF(newCard->primaryCollationKey);
PR_FREEIF(newCard->secondaryCollationKey);
PR_FREEIF(newCard);
// still need to invalidate, as the other columns may have changed
rv = InvalidateOutliner(index);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
else {
PRBool cardWasSelected = PR_FALSE;
if (mOutlinerSelection) {
rv = mOutlinerSelection->IsSelected(index, &cardWasSelected);
NS_ENSURE_SUCCESS(rv,rv);
}
mSuppressSelectionChange = PR_TRUE;
// remove the old card
RemoveCardAt(index);
// add the card we created, and select it (to restore selection) if it was selected
rv = AddCard(newCard, cardWasSelected /* select card */, &index);
mSuppressSelectionChange = PR_FALSE;
NS_ENSURE_SUCCESS(rv,rv);
// ensure restored selection is visible
if (cardWasSelected) {
if (mOutliner)
mOutliner->EnsureRowIsVisible(index);
}
}
return NS_OK;
}
NS_IMETHODIMP nsAbView::SelectAll()

View File

@ -74,13 +74,16 @@ private:
nsCOMPtr<nsIOutlinerBoxObject> mOutliner;
nsCOMPtr<nsIOutlinerSelection> mOutlinerSelection;
nsresult SortBy(const PRUnichar *colID);
nsresult CreateCollationKey(const PRUnichar *source, PRUnichar **result);
nsresult CreateCollationKey(const PRUnichar *source, PRUnichar **result);
PRInt32 FindIndexForInsert(const PRUnichar *colID, AbCard *abcard);
PRInt32 FindIndexForCard(const PRUnichar *colID, nsIAbCard *card);
PRInt32 FindIndexForCard(nsIAbCard *card);
nsresult GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *abcard);
nsresult InvalidateOutliner(PRInt32 row);
void RemoveCardAt(PRInt32 row);
nsresult AddCard(AbCard *abcard, PRBool selectCardAfterAdding, PRInt32 *index);
nsresult RemoveCardAndSelectNextCard(nsISupports *item);
nsresult EnumerateCards();
PRBool mSuppressSelectionChange;
nsCString mURI;
nsCOMPtr <nsIAbDirectory> mDirectory;
@ -88,6 +91,7 @@ private:
nsCOMPtr<nsIAtom> mMailListAtom;
nsString mSortedColumn;
nsCOMPtr<nsICollation> mCollationKeyGenerator;
nsCOMPtr<nsIAbViewListener> mAbViewListener;
};
#endif /* _nsAbView_H_ */