gecko-dev/cmd/macfe/MailNews/AddressBook/CNameCompletionPicker.cp

415 строки
13 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CNameCompletionPicker.cp
#include "abcom.H"
#ifdef MOZ_NEWADDR
#include "CNameCompletionPicker.h"
#include "UStdDialogs.h"
#include "SearchHelpers.h"
#include "LGAPushButton.h"
LEditField* CNameCompletionPicker::mLastReceivedEditField = nil;
MSG_Pane* CNameCompletionPicker::mLastReceivedPickerPane = nil;
CMailNewsContext* CNameCompletionPicker::mLastReceivedContext = nil;
int CNameCompletionPicker::mLastReceivedNumResults = 0;
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable class [static]
//----------------------------------------------------------------------------
//
CNameCompletionTable::CNameCompletionTable(LStream* inStream )
: CMailFlexTable(inStream)
{
}
CNameCompletionTable::~CNameCompletionTable()
{
SetMessagePane(NULL);
// Do it here so that our DestroyMessagePane() is called.
// If we let the inherited CMailFlexTable do it, it will call
// its own DestroyMessagePane() because ours is already destroyed
// and the PickerPane will be deleted (which is something we
// don't want because it belongs to the CMailAddressEditField).
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::DestroyMessagePane
//----------------------------------------------------------------------------
// Don't delete the MSG_PickerPane: it belongs to the CMailAddressEditField
//
void CNameCompletionTable::DestroyMessagePane(MSG_Pane* /*inPane*/)
{
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::SetColumnHeaders
//----------------------------------------------------------------------------
//
void CNameCompletionTable::SetColumnHeaders()
{
LTableViewHeader* tableHeader = GetTableHeader();
PaneIDT headerPaneID;
// Column #1 = 'Type' is the container type (Address Book / LDAP server).
// Column #2 = 'Col0' is the entry type (User / Mailing list).
// The other columns have configurable headers.
for (short col = 2; col <= tableHeader->CountColumns(); col ++)
{
headerPaneID = tableHeader->GetColumnPaneID(col);
Int32 index = headerPaneID - eTableHeaderBase;
AB_ColumnInfo *info = AB_GetColumnInfoForPane(GetMessagePane(), AB_ColumnID(index));
LCaption* headerPane = dynamic_cast<LCaption*>(GetSuperView()->FindPaneByID(headerPaneID));
if (headerPane) headerPane->SetDescriptor(CStr255(info->displayString));
AB_FreeColumnInfo(info);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::SelectionChanged
//----------------------------------------------------------------------------
//
void CNameCompletionTable::SelectionChanged()
{
Inherited::SelectionChanged();
StartBroadcasting();
// Long story: the CTableKeyAttachment from CStandardFlexTable
// calls StopBroadcasting() on keyDown and StartBroadcasting()
// on keyUp. Problem: we are in a dialog and we never get keyUp's.
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::OpenRow
//----------------------------------------------------------------------------
//
void CNameCompletionTable::OpenRow(TableIndexT inRow)
{
if (IsValidRow(inRow))
{
BroadcastMessage(msg_OK, nil);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::GetCellDisplayData
//----------------------------------------------------------------------------
// Entirely copied from CMailingListTableView
//
void CNameCompletionTable::GetCellDisplayData(const STableCell &inCell, ResIDT& ioIcon, CStr255 &ioDisplayString)
{
ioIcon = 0;
ioDisplayString = "";
// Get the attribute corresponding to the current column
LTableViewHeader* tableHeader = GetTableHeader();
PaneIDT headerPaneID = tableHeader->GetColumnPaneID(inCell.col);
Int32 index = headerPaneID - eTableHeaderBase;
AB_ColumnInfo *info = AB_GetColumnInfoForPane(GetMessagePane(), AB_ColumnID(index));
AB_AttribID attrib = info->attribID;
AB_FreeColumnInfo(info);
// Get the data
uint16 numItems = 1;
AB_AttributeValue* value;
if (AB_GetEntryAttributesForPane(GetMessagePane(), inCell.row-1, &attrib, &value, &numItems) == AB_SUCCESS)
{
if (attrib == AB_attribEntryType)
{
ioIcon = (value->u.entryType == AB_MailingList ? 15263 : 15260);
}
else
{
ioDisplayString = value->u.string ;
}
AB_FreeEntryAttributeValue(value);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::DrawCellContents
//----------------------------------------------------------------------------
// Mostly copied from CMailingListTableView
//
void CNameCompletionTable::DrawCellContents(const STableCell &inCell, const Rect &inLocalRect)
{
ResIDT iconID = 0;
PaneIDT cellType = GetCellDataType(inCell);
switch (cellType)
{
case 'Type':
AB_ContainerType container = AB_GetEntryContainerType(GetMessagePane(), inCell.row-1);
switch (container)
{
case AB_LDAPContainer: iconID = 15250; break; // remote folder
case AB_MListContainer: iconID = 15258; break; // address book
case AB_PABContainer: iconID = 15258; break; // address book
case AB_UnknownContainer: iconID = 0; break;
}
if (iconID)
DrawIconFamily(iconID, 16, 16, 0, inLocalRect);
break;
// case 'Col0':
// ...
// case 'Col6':
default:
CStr255 displayString;
GetCellDisplayData(inCell, iconID, displayString);
if (iconID)
DrawIconFamily(iconID, 16, 16, kTransformNone, inLocalRect);
else
DrawTextString(displayString, &mTextFontInfo, 0, inLocalRect);
break;
}
}
#pragma mark -
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::DisplayDialog [static]
//----------------------------------------------------------------------------
// Show the name completion dialog
//
int CNameCompletionPicker::DisplayDialog(LEditField* inEditField, MSG_Pane* inPane, CMailNewsContext* inContext, int inNumResults)
{
// put up dialog
mLastReceivedEditField = inEditField;
mLastReceivedPickerPane = inPane;
mLastReceivedContext = inContext;
mLastReceivedNumResults = inNumResults;
RegisterClass_(CNameCompletionPicker);
RegisterClass_(CNameCompletionTable);
StStdDialogHandler handler(CNameCompletionPicker::res_ID, NULL);
CNameCompletionPicker* dlog = (CNameCompletionPicker*)handler.GetDialog();
// run the dialog
MessageT message;
do
{
message = handler.DoDialog();
} while (message != msg_OK && message != msg_Cancel);
// return the result
STableCell aCell(0,0);
if (message == msg_OK)
aCell = dlog->GetActiveTable()->GetFirstSelectedCell();
// explicitly close the dialog to save its status
dlog->DoClose();
return (aCell.row);
}
#pragma mark -
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker class
//----------------------------------------------------------------------------
//
CNameCompletionPicker::CNameCompletionPicker(LStream *inStream)
: CMailNewsWindow(inStream, WindowType_NameCompletion)
{
}
CNameCompletionPicker::~CNameCompletionPicker()
{
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::FinishCreateSelf
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::FinishCreateSelf()
{
// transmit parameters from the Compose window to the list
ReceiveComposeWindowParameters();
mNameCompletionTable = dynamic_cast<CNameCompletionTable *>(USearchHelper::FindViewSubview(this, paneID_NameCompletionTable));
FailNILRes_(mNameCompletionTable);
mNameCompletionTable->ReceiveMessagePane(mPickerPane);
// finish create stuff
Inherited::FinishCreateSelf();
CSaveWindowStatus::FinishCreateWindow();
// prepare list
mNameCompletionTable->SetColumnHeaders();
mNameCompletionTable->SetRowCount();
STableCell cellToSelect(2, 1);
mNameCompletionTable->SelectCell(cellToSelect);
// default button
LGAPushButton * defaultBtn = dynamic_cast<LGAPushButton*>(FindPaneByID(paneID_OkButton));
if (defaultBtn) defaultBtn->SetDefaultButton(true, true);
mNameCompletionTable->AddListener(this);
// show window
this->Show();
this->Select();
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::DoClose
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::DoClose()
{
// Save table data and window position
SaveStatusInfo();
// Close window
Inherited::DoClose();
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::CalcStandardBoundsForScreen
//----------------------------------------------------------------------------
// Zoom in the vertical direction only.
//
void CNameCompletionPicker::CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const
{
LWindow::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
Rect contRect = UWindows::GetWindowContentRect(mMacWindowP);
outStdBounds.left = contRect.left;
outStdBounds.right = contRect.right;
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::ListenToMessage
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::ListenToMessage(MessageT inMessage, void */*ioParam*/)
{
if (inMessage == msg_OK)
{
LControl* keyButton = (LControl*)FindPaneByID(paneID_OkButton);
keyButton->SimulateHotSpotClick(kControlButtonPart);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::HandleKeyPress
//----------------------------------------------------------------------------
// Handle Escape and Cmd-Period (copied from LDialogBox)
//
Boolean CNameCompletionPicker::HandleKeyPress(const EventRecord &inKeyEvent)
{
Boolean keyHandled = false;
PaneIDT keyButtonID = 0;
switch (inKeyEvent.message & charCodeMask)
{
case char_Enter:
case char_Return:
keyButtonID = paneID_OkButton;
break;
case char_Escape:
if ((inKeyEvent.message & keyCodeMask) == vkey_Escape)
keyButtonID = paneID_CancelButton;
break;
default:
if (UKeyFilters::IsCmdPeriod(inKeyEvent))
keyButtonID = paneID_CancelButton;
else
keyHandled = LWindow::HandleKeyPress(inKeyEvent);
break;
}
if (keyButtonID != 0)
{
LControl* keyButton = (LControl*)FindPaneByID(keyButtonID);
keyButton->SimulateHotSpotClick(kControlButtonPart);
keyHandled = true;
}
return keyHandled;
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::ReadWindowStatus
//----------------------------------------------------------------------------
// Put the window next to the edit field and try to restore its last size.
//
void CNameCompletionPicker::ReadWindowStatus(LStream *inStatusData)
{
// get last window size
Rect savedBounds;
if (inStatusData != nil)
*inStatusData >> savedBounds;
else
{
GetPaneGlobalBounds(this, &savedBounds);
savedBounds.right = savedBounds.left + 320; //¥ TODO: remove these hard-coded values
}
// put the window at the right of the caret position in the edit field
TEHandle teH = mEditField->GetMacTEH();
short caretPos = (*teH)->selStart;
Rect actualBounds;
mEditField->CalcPortFrameRect(actualBounds);
mEditField->PortToGlobalPoint(topLeft(actualBounds));
actualBounds.top -= 44; //¥ TODO: remove these hard-coded values
actualBounds.left += (caretPos + 3) * 7; //¥ TODO:
actualBounds.bottom = actualBounds.top + (savedBounds.bottom - savedBounds.top);
actualBounds.right = actualBounds.left + (savedBounds.right - savedBounds.left);
VerifyWindowBounds(this, &actualBounds);
DoSetBounds(actualBounds);
// restore table data
if (inStatusData != nil)
mNameCompletionTable->ReadSavedTableStatus(inStatusData);
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::WriteWindowStatus
//----------------------------------------------------------------------------
// Save window size and table data.
//
void CNameCompletionPicker::WriteWindowStatus(LStream *outStatusData)
{
CSaveWindowStatus::WriteWindowStatus(outStatusData);
mNameCompletionTable->WriteSavedTableStatus(outStatusData);
}
#endif //MOZ_NEWADDR