gecko-dev/cmd/macfe/gui/CPersonalToolbarTable.cp

898 lines
25 KiB
C++
Raw Blame History

/* -*- 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.
*/
//
// Implementation of the table that is the main component of the personal toolbar.
//
#include <vector.h>
#include <algorithm>
#include "CPersonalToolbarTable.h"
#include "CPersonalToolbarManager.h"
#include "uapp.h"
#include "LTableMultiGeometry.h"
#include "CURLDragHelper.h"
#include "macutil.h"
#include "CIconTextDragTask.h"
#include "resgui.h"
#include "URDFUtilities.h"
#include "miconutils.h"
#include "UMemoryMgr.h"
static const RGBColor blue = { 0, 0, 0xFFFF };
static const RGBColor black = { 0, 0, 0 };
static const RGBColor bgColor = { 0xDDDD, 0xDDDD, 0xDDDD };
DragSendDataUPP CPersonalToolbarTable::sSendDataUPP;
CPersonalToolbarTable :: CPersonalToolbarTable ( LStream* inStream )
: LSmallIconTable(inStream), LDragAndDrop ( GetMacPort(), this ),
mDropCol(LArray::index_Bad), mHiliteCol(LArray::index_Bad), mDropOn(false)
{
// LSmallIconTable wants to use a LTableSingleGeometry, but since we want the toolbar
// to have variable column widths, replace it with a multiGeometry implementation
if ( mTableGeometry ) {
delete mTableGeometry;
mTableGeometry = new LTableMultiGeometry ( this, mFrameSize.width, 20 );
}
} // constructor
CPersonalToolbarTable :: ~CPersonalToolbarTable ( )
{
CFrontApp::GetPersonalToolbarManager()->RemoveListener(this);
//<2F><> dispose drag routine descriptor
} // destructor
//
// FinishCreateSelf
//
void
CPersonalToolbarTable :: FinishCreateSelf ( )
{
InsertRows ( 1, 1, NULL, 0, false );
CFrontApp::GetPersonalToolbarManager()->RegisterNewToolbar(this);
if ( !sSendDataUPP) {
sSendDataUPP = NewDragSendDataProc(LDropArea::HandleDragSendData);
ThrowIfNil_(sSendDataUPP);
}
} // FinishCreateSelf
//
// FillInToolbar
//
// Add rows to the table based on the bookmark information in the manager object. This will try to give each
// column as much space as possible on the fly. Don't make any assumptions about the incoming
// text mode...be paranoid!
//
void
CPersonalToolbarTable :: FillInToolbar ( )
{
const Uint32 kPadRight = 15;
const Uint32 kBMIconWidth = 28;
const Uint32 kButtonCount = CFrontApp::GetPersonalToolbarManager()->GetButtons().GetCount();
const Uint32 kMaxLength = CFrontApp::GetPersonalToolbarManager()->GetMaxToolbarButtonChars();
const Uint32 kMinLength = CFrontApp::GetPersonalToolbarManager()->GetMinToolbarButtonChars();
StTextState saved;
UTextTraits::SetPortTextTraits(kTextTraitsID);
//
// create an array that holds the # of characters currently in each column. Initialize this with
// the min column size (specified in prefs), or less if the title has less chars.
//
Uint16* widthArray = new Uint16[kButtonCount];
Uint16 totalWidth = 0;
CUserButtonInfo* curr;
Uint32 widthArrayIter = 0;
LArrayIterator it ( CFrontApp::GetPersonalToolbarManager()->GetButtons() );
while ( it.Next(&curr) ) {
Uint16 numChars = min ( kMinLength, curr->GetName().length() );
widthArray[widthArrayIter] = numChars;
totalWidth += ::TextWidth(curr->GetName().c_str(), 0, numChars) + kBMIconWidth; // extend the total...
widthArrayIter++;
} // initialize each item
InsertCols ( kButtonCount, 0, NULL, 0, false );
// compute how much room we have left to divvy out after divvying out the minimum above. Leave
// a few pixels on the right empty...
int16 emptySpace = (mFrameSize.width - kPadRight) - totalWidth;
//
// divvy out space to each column, one character at a time to each column
//
while ( emptySpace > 0 ) {
bool updated = false;
Uint32 i = 0;
LArrayIterator it2 ( CFrontApp::GetPersonalToolbarManager()->GetButtons() );
while ( it2.Next(&curr) ) {
if ( emptySpace && widthArray[i] < curr->GetName().length() && widthArray[i] < kMaxLength ) {
// subtract off the single character we're adding to the column
char addedChar = curr->GetName()[widthArray[i]];
emptySpace -= ::TextWidth(&addedChar, 0, 1);
widthArray[i]++;
updated = true; // we found something to add, allow us to continue
}
i++;
} // for each column
// prevent infinite looping if no column can be expanded and we still have extra room remaining
if ( !updated )
break;
} // while space remains to divvy out
//
// assign the widths to the columns and set the data in the columns.
//
STableCell where (1, 1);
widthArrayIter = 0;
LArrayIterator it3 ( CFrontApp::GetPersonalToolbarManager()->GetButtons() );
while ( it3.Next(&curr) ) {
string bmText = curr->GetName();
Uint32 textLength = bmText.length();
//
// fill in the cell with the name of the bookmark and set the column width to
// the width of the string. If the name is longer than the max, chop it.
//
SIconTableRec data;
Uint16 dispLength = widthArray[widthArrayIter];
::BlockMove ( bmText.c_str(), &data.name[1], dispLength + 1 );
data.name[0] = dispLength <= kMaxLength ? dispLength : kMaxLength;
data.iconID = curr->IsFolder() ? kFOLDER_ICON : kBOOKMARK_ICON;
SetCellData ( where, &data, sizeof(SIconTableRec) );
Uint32 pixelWidth = ::TextWidth(bmText.c_str(), 0, dispLength)+ kBMIconWidth;
mTableGeometry->SetColWidth ( pixelWidth, where.col, where.col );
widthArrayIter++;
where.col++; // next column, please....
} // for each bookmark in the folder
Refresh();
delete[] widthArray;
} // FillInToolbar
//
// MouseLeave
//
// Called when the mouse leaves the personal toolbar. Redraw the previous selection to get rid
// of the blue text color.
//
void
CPersonalToolbarTable :: MouseLeave ( )
{
STableCell refresh(1, mHiliteCol);
mHiliteCol = LArray::index_Bad;
StClipRgnState savedClip;
FocusDraw();
RedrawCellWithTextClipping ( refresh );
} // MouseLeave
//
// MouseWithin
//
// Called while the mouse moves w/in the personal toolbar. Find which cell the mouse is
// currently over and remember it. If we've moved to a different cell, make sure to
// refresh the old one so it is drawn normally.
//
void
CPersonalToolbarTable :: MouseWithin ( Point inPortPt, const EventRecord& )
{
// get the previous selection
STableCell old(1, mHiliteCol);
SPoint32 imagePt;
PortToLocalPoint(inPortPt);
LocalToImagePoint(inPortPt, imagePt);
STableCell hitCell;
if ( GetCellHitBy(imagePt, hitCell) )
if ( old != hitCell ) {
StClipRgnState savedClip;
mHiliteCol = hitCell.col;
FocusDraw();
if ( old.col )
RedrawCellWithTextClipping(old);
if ( hitCell.col )
RedrawCellWithTextClipping(hitCell);
ExecuteAttachments(msg_HideTooltip, this); // hide tooltip
}
} // MouseWithin
//
// Click
//
// Allow drags to occur when another window is in front of us.
//
void
CPersonalToolbarTable :: Click ( SMouseDownEvent& inMouseDown )
{
PortToLocalPoint(inMouseDown.whereLocal);
UpdateClickCount(inMouseDown);
if (ExecuteAttachments(msg_Click, &inMouseDown))
{
ClickSelf(inMouseDown);
}
}
#if 0
//
// Click
//
// Overridden to handle clase of drag and drop when communicator is in the background. Code
// copied from CWPro1 CD sample code (CDragAndDropTable.cp).
//
// FOR SOME REASON, THIS DOESN'T WORK....DUNNO WHY...
void
CPersonalToolbarTable :: Click ( SMouseDownEvent& inMouseDown )
{
if ( inMouseDown.delaySelect && DragAndDropIsPresent() ) {
// In order to support dragging from an inactive window,
// we must explicitly test for delaySelect and the
// presence of Drag and Drop.
// Convert to a local point.
PortToLocalPoint( inMouseDown.whereLocal );
// Execute click attachments.
if ( ExecuteAttachments( msg_Click, &inMouseDown ) ) {
// Handle the actual click event.
ClickSelf( inMouseDown );
}
} else {
// Call inherited for default behavior.
LTableView::Click( inMouseDown );
}
} // Click
#endif
//
// ClickSelect
//
// Override to always say that we can be selected, because there is no concept of selection
// in this toolbar.
Boolean
CPersonalToolbarTable :: ClickSelect( const STableCell &/*inCell*/, const SMouseDownEvent &/*inMouseDown*/)
{
return true;
}
//
// ClickCell
//
// Override the default behavior of selecting a cell to open the url associated with the bookmark
// there.
//
void
CPersonalToolbarTable :: ClickCell(const STableCell &inCell, const SMouseDownEvent &inMouseDown)
{
if ( ::WaitMouseMoved(inMouseDown.macEvent.where) ) {
if (LDropArea::DragAndDropIsPresent()) {
mDraggedCell = inCell; // save which cell is being dragged for later
// create the drag task
Rect bounds;
GetLocalCellRect ( inCell, bounds );
CUserButtonInfo* data = GetButtonInfo ( inCell.col );
string finalCaption = CURLDragHelper::MakeIconTextValid ( data->GetName().c_str() );
HT_Resource node = HT_GetNthItem(CFrontApp::GetPersonalToolbarManager()->GetHTView(),
URDFUtilities::PPRowToHTRow(inCell.col));
CIconTextSuite suite ( this, bounds, kBOOKMARK_ICON, finalCaption, node );
CIconTextDragTask theTask(inMouseDown.macEvent, &suite, bounds);
// setup our special data transfer proc called upon drag completion
OSErr theErr = ::SetDragSendProc ( theTask.GetDragReference(), sSendDataUPP, (LDropArea*) this );
ThrowIfOSErr_(theErr);
theTask.DoDrag();
// remove the url if it went into the trash
if ( theTask.DropLocationIsFinderTrash() )
CFrontApp::GetPersonalToolbarManager()->RemoveButton ( inCell.col );
} // if d&d allowed
} // if drag
else {
CUserButtonInfo* data = GetButtonInfo ( inCell.col );
// code for context menu here, if appropriate....
if ( data->IsFolder() ) {
SysBeep(1);
}
else {
CUserButtonInfo* clicked = GetButtonInfo ( inCell.col );
CFrontApp::DoGetURL( clicked->GetURL().c_str());
}
} // else just a click
} // ClickCell
//
// RedrawCellWithHilite
//
// A helpful utility routine that wraps DrawCell() with calls to setup the drawing params
// appropriately. When redrawing a cell during a drag and drop, call this routine instead
// of calling DrawCell directly.
//
void
CPersonalToolbarTable :: RedrawCellWithHilite ( const STableCell inCell, bool inHiliteOn )
{
Rect localCellRect;
GetLocalCellRect ( inCell, localCellRect );
// since mDropOn is used as the flag in DrawCell() for whether or not we want to
// draw the hiliting on the cell, save its value and set it to what was passed in
// before calling DrawCell().
StValueChanger<Boolean> oldHilite(mDropOn, inHiliteOn); //<2F><><EFBFBD> won't link with bool type =(
// if the hiliting is being turned off, erase the cell so it draws normally again
if ( !inHiliteOn ) {
StColorState saved;
::RGBBackColor(&bgColor);
::EraseRect(&mTextHiliteRect); // we can be sure this has been previously computed
}
DrawCell ( inCell, localCellRect );
} // RedrawCellWithHilite
//
// DrawCell
//
// Override to draw differently when this is the selected cell. Otherwise, pass it back
// to the inherited routine to draw normally.
//
void
CPersonalToolbarTable :: DrawCell ( const STableCell &inCell, const Rect &inLocalRect )
{
StTextState savedText;
StColorPenState savedColor;
::RGBForeColor(&black);
SIconTableRec iconAndName;
Uint32 dataSize = sizeof(SIconTableRec);
GetCellData(inCell, &iconAndName, dataSize);
Rect iconRect;
iconRect.left = inLocalRect.left + 3;
iconRect.right = iconRect.left + 16;
iconRect.bottom = inLocalRect.bottom - 2;
iconRect.top = iconRect.bottom - 16;
IconTransformType transform = kTransformNone;
if ( mDropOn ) // handle drop on folder
transform = kTransformSelected;
::PlotIconID(&iconRect, atNone, transform, iconAndName.iconID);
UTextTraits::SetPortTextTraits(kTextTraitsID);
if ( mDropOn ) { // handle drop on folder
mTextHiliteRect = ComputeTextRect ( iconAndName, inLocalRect );
StColorState savedColorForTextDrawing;
::RGBBackColor(&black);
::EraseRect(&mTextHiliteRect);
::TextMode(srcXor);
}
else if ( mHiliteCol == inCell.col ) {
TextFace(underline);
RGBForeColor( &blue );
}
::MoveTo(inLocalRect.left + 22, inLocalRect.bottom - 4);
::DrawString(iconAndName.name);
} // DrawCell
//
// ListenToMessage
//
// Handle broadcasts from the manager object, such as the personal toolbar folder being
// changed or bookmarks being added/deleted/moved.
//
void
CPersonalToolbarTable :: ListenToMessage ( MessageT inMessage, void* /*ioPtr*/ )
{
switch ( inMessage ) {
case CPersonalToolbarManager::k_PTToolbarChanged:
if ( mCols )
RemoveCols ( mCols, 1, false ); // out with the old...
FillInToolbar();
break;
} // case of which message
} // ListenToMessage
//
// DoDragSendData
//
// When the drag started, the ClickCell() routine cached which cell was the start of the drag in
// |mDraggedCell|. Extract the URL and Title from this cell and pass it along to the helper
// routine from CURLDragHelper
//
void
CPersonalToolbarTable :: DoDragSendData( FlavorType inFlavor, ItemReference inItemRef,
DragReference inDragRef)
{
CUserButtonInfo* dragged = GetButtonInfo ( mDraggedCell.col );
CURLDragHelper::DoDragSendData ( dragged->GetURL().c_str(),
const_cast<char*>(dragged->GetName().c_str()),
inFlavor, inItemRef, inDragRef );
} // DoDragSendData
//
// HiliteDropArea
//
// Show that this toolbar is a drop site for urls
//
void
CPersonalToolbarTable :: HiliteDropArea ( DragReference inDragRef )
{
Rect frame;
CalcLocalFrameRect ( frame );
// show the drag hilite in drop area
RgnHandle rgn = ::NewRgn();
ThrowIfNil_(rgn);
::RectRgn ( rgn, &frame );
::ShowDragHilite ( inDragRef, rgn, true );
::DisposeRgn ( rgn );
} // HiliteDropArea
//
// InsideDropArea
//
// Called repeatedly while mouse is inside this during a drag. For each column, the cell
// can be divided into several sections.
//
void
CPersonalToolbarTable :: InsideDropArea ( DragReference inDragRef )
{
FocusDraw();
Point mouseLoc;
SPoint32 imagePt;
::GetDragMouse(inDragRef, &mouseLoc, NULL);
::GlobalToLocal(&mouseLoc);
LocalToImagePoint(mouseLoc, imagePt);
Rect localRect;
TableIndexT colMouseIsOver = mTableGeometry->GetColHitBy(imagePt);
GetLocalCellRect ( STableCell(1, colMouseIsOver), localRect );
TableIndexT newDropCol;
bool newDropOn = false;
CUserButtonInfo* info = GetButtonInfo(colMouseIsOver);
if ( info ) {
if ( info->IsFolder() ) {
Rect leftSide, rightSide;
ComputeFolderDropAreas ( localRect, leftSide, rightSide );
if ( ::PtInRect(mouseLoc, &leftSide) )
newDropCol = colMouseIsOver; // before this cell
else if ( ::PtInRect(mouseLoc, &rightSide) )
newDropCol = colMouseIsOver + 1; // after this cell
else {
newDropCol = colMouseIsOver;
newDropOn = true; // hilite folder, don't draw line
}
}
else {
// draw line between rows
Rect leftSide, rightSide;
ComputeItemDropAreas ( localRect, leftSide, rightSide );
if ( ::PtInRect(mouseLoc, &leftSide) )
newDropCol = colMouseIsOver; // before this cell
else
newDropCol = colMouseIsOver + 1; // after this cell
}
} // if drag over existing column
else {
// else drag over empty part of toolbar
newDropCol = mCols + 1;
}
// if something has changed, redraw as necessary
if ( newDropCol != mDropCol || newDropOn != mDropOn ) {
// unhilight old one (if necessary)
if ( mDropOn )
RedrawCellWithHilite( STableCell(1, mDropCol), false );
else
if ( mDropCol > 0 )
DrawDividingLine ( mDropCol );
mDropCol = newDropCol;
mDropOn = newDropOn;
// hilight new one
if ( mDropOn )
RedrawCellWithHilite ( STableCell(1, mDropCol), true );
else
DrawDividingLine ( newDropCol );
} // if mouse moved to another drop location
} // InsideDropArea
//
// LeaveDropArea
//
// Clean up the drop feedback stuff when the mouse leaves the area
//
void
CPersonalToolbarTable :: LeaveDropArea( DragReference inDragRef )
{
FocusDraw();
// if we were hiliting a folder, redraw it without the hiliting. If we were drawing a
// line, undraw it.
if ( mDropOn )
RedrawCellWithHilite ( STableCell(1,mDropCol), false );
else
DrawDividingLine( mDropCol );
mDropCol = LArray::index_Bad;
mDropOn = false;
// Call inherited.
LDragAndDrop::LeaveDropArea( inDragRef );
}
//
// ComputeItemDropAreas
//
// When a drag goes over a cell that contains a single node, divide the node in half. The left
// side will represent dropping before the node, the right side after.
//
void
CPersonalToolbarTable :: ComputeItemDropAreas ( const Rect & inLocalCellRect, Rect & oLeftSide,
Rect & oRightSide )
{
oRightSide = oLeftSide = inLocalCellRect;
uint16 midPt = (oLeftSide.right - oLeftSide.left) / 2;
oLeftSide.right = oLeftSide.left + midPt;
oRightSide.left = oLeftSide.left + midPt + 1;
} // ComputeItemDropAreas
//
// ComputeFolderDropAreas
//
// When a drag goes over a cell that contains a folder, divide the cell area into 3 parts. The middle
// area, which corresponds to a drop on the folder takes up the majority of the cell space with the
// left and right areas (corresponding to drop before and drop after, respectively) taking up the rest
// at the ends.
//
void
CPersonalToolbarTable :: ComputeFolderDropAreas ( const Rect & inLocalCellRect, Rect & oLeftSide,
Rect & oRightSide )
{
// make sure the left/right area widths aren't too big for the cell
Uint16 endAreaWidth = 20;
if ( inLocalCellRect.right - inLocalCellRect.left < 50 )
endAreaWidth = 5;
oRightSide = oLeftSide = inLocalCellRect;
oLeftSide.right = oLeftSide.left + endAreaWidth;
oRightSide.left = oRightSide.right - endAreaWidth;
} // ComputeFolderDropAreas
//
// DrawDividingLine
//
// Draws a vertical black line before the given column in the toolbar (or undraws if one
// is already there). If the column given is after the right edge of the last column, it
// draws after the last column (as the user expects).
//
void
CPersonalToolbarTable :: DrawDividingLine( TableIndexT inCol )
{
Uint32 numItems = CFrontApp::GetPersonalToolbarManager()->GetButtons().GetCount();
if ( !numItems ) // don't draw anything if toolbar empty
return;
// Setup the target cell.
STableCell theCell;
theCell.row = 1;
theCell.col = inCol;
// find the boundary of the cell we're supposed to be drawing the line before. If
// the incoming column is at the end (greater than the # of buttons) then hack up
// a boundary rect to draw after the last column.
Rect cellBounds;
if ( inCol > numItems ) {
// get the boundary of the last column
theCell.col = numItems;
GetLocalCellRect ( theCell, cellBounds );
// make the left edge of our fake column the right edge of the last column
cellBounds.left = cellBounds.right;
}
else
GetLocalCellRect ( theCell, cellBounds );
// Focus the pane and get the table and cell frames.
Rect theFrame;
if ( FocusDraw() && CalcLocalFrameRect( theFrame ) ) {
// Save the draw state and clip the list view rect.
StColorPenState theDrawState;
StClipRgnState theClipState( theFrame );
// Setup the color and pen state then draw the line
::ForeColor( blackColor );
::PenMode( patXor );
::PenSize( 2, 2 );
::MoveTo( cellBounds.left, cellBounds.top );
::LineTo( cellBounds.left, cellBounds.bottom );
}
} // DrawDividingLine
//
// FindBestFlavor
//
// Scan through the list of acceptable flavors and find the best one that is contained
// in the given drag item. Returns true if it found one in the list and false if the
// drag item doesn't contain any of the desired flavors.
//
bool
CPersonalToolbarTable :: FindBestFlavor ( DragReference inDragRef, ItemReference inItemRef,
FlavorType & oFlavor )
{
static FlavorType flavors[] = { emHTNodeDrag, emBookmarkDrag, NULL }; // must end in NULL
oFlavor = '****';
short i = 0;
for ( FlavorType curr = flavors[0]; flavors[i]; i++, curr = flavors[i] ) {
FlavorFlags theFlags;
if ( ::GetFlavorFlags(inDragRef, inItemRef, curr, &theFlags) == noErr ) {
oFlavor = curr;
return true;
}
} // for each flavor in list
return false;
} // FindBestFlavor
//
// ItemIsAcceptable
//
// If FindBestFlavor() finds an acceptable flavor, then this item can be accepted. If not, it
// can't. We don't really care at this point what that flavor is.
//
Boolean
CPersonalToolbarTable :: ItemIsAcceptable ( DragReference inDragRef, ItemReference inItemRef )
{
FlavorType ignored;
return FindBestFlavor ( inDragRef, inItemRef, ignored );
} // ItemIsAcceptable
//
// ReceiveDragItem
//
// Called for each item dropped on the table. Create a new bookmark in the PT folder for
// each item
//
void
CPersonalToolbarTable :: ReceiveDragItem ( DragReference inDragRef, DragAttributes /*inDragAttrs*/,
ItemReference inItemRef, Rect & /*inItemBounds*/ )
{
FlavorType flavorToUse;
FindBestFlavor ( inDragRef, inItemRef, flavorToUse ); // ok to ignore return result
// Get the data.
Size theDataSize;
ThrowIfOSErr_( ::GetFlavorDataSize(inDragRef, inItemRef, flavorToUse, &theDataSize) );
switch ( flavorToUse ) {
case emHTNodeDrag:
HT_Resource node;
ThrowIfOSErr_( ::GetFlavorData( inDragRef, inItemRef, flavorToUse, &node, &theDataSize, 0 ) );
if ( mDropOn ) {
SysBeep(1); //<2F><><EFBFBD> implement
}
else
CFrontApp::GetPersonalToolbarManager()->AddButton ( node, mDropCol );
break;
case emBookmarkDrag:
vector<char> urlAndTitle ( theDataSize + 1 );
ThrowIfOSErr_( ::GetFlavorData( inDragRef, inItemRef, flavorToUse, urlAndTitle.begin(), &theDataSize, 0 ) );
urlAndTitle[theDataSize] = NULL;
char* title = find(urlAndTitle.begin(), urlAndTitle.end(), '\r');
if ( title != urlAndTitle.end() ) {
title[0] = NULL;
title++;
char* url = urlAndTitle.begin();
if ( mDropOn ) {
SysBeep(1); //<2F><><EFBFBD> implement
}
else
CFrontApp::GetPersonalToolbarManager()->AddButton ( url, title, mDropCol );
}
break;
} // case of which flavor
} // ReceiveDragItem
//
// GetButtonInfo
//
// fetch cell data given a column #.
//
CUserButtonInfo*
CPersonalToolbarTable :: GetButtonInfo ( Uint32 inColumn )
{
CUserButtonInfo* temp = nil;
CFrontApp::GetPersonalToolbarManager()->GetButtons().FetchItemAt (inColumn, &temp );
return temp;
} // GetButtonInfo
void
CPersonalToolbarTable :: FindTooltipForMouseLocation ( const EventRecord& inMacEvent,
StringPtr outTip )
{
Point temp = inMacEvent.where;
SPoint32 where;
GlobalToPortPoint(temp);
PortToLocalPoint(temp);
LocalToImagePoint(temp, where);
STableCell hitCell;
if ( GetCellHitBy(where, hitCell) && hitCell.col <= mCols ) {
CUserButtonInfo* bkmk = GetButtonInfo(hitCell.col);
outTip[0] = bkmk->GetName().length();
strcpy ( (char*) &outTip[1], bkmk->GetName().c_str() );
}
else
::GetIndString ( outTip, 10506, 12); // supply a helpful message...
} // FindTooltipForMouseLocation
void
CPersonalToolbarTable :: ResizeFrameBy ( Int16 inWidth, Int16 inHeight, Boolean inRefresh )
{
LSmallIconTable::ResizeFrameBy(inWidth, inHeight, inRefresh);
ListenToMessage ( CPersonalToolbarManager::k_PTToolbarChanged, nil );
} // ResizeFrameTo
//
// ComputeTextRect
//
// Compute the area of the text rectangle so we can clip to it on redraw
//
Rect
CPersonalToolbarTable :: ComputeTextRect ( const SIconTableRec & inText, const Rect & inLocalRect )
{
Rect textRect;
uint16 width = ::TextWidth(inText.name, 1, *inText.name);
textRect.left = inLocalRect.left + 20;
textRect.right = textRect.left + width + 2;
textRect.bottom = inLocalRect.bottom - 1;
textRect.top = inLocalRect.top + 1;
return textRect;
} // ComputeTextRect
//
// RedrawCellWithTextClipping
//
// A pretty way to redraw the cell because it won't flash. This sets the clip region to the
// text that needs to be redrawn so it looks fast to the user.
//
// NOTE: This blows away the current clip region so if you care, you must restore it afterwards. I
// don't do it here because you may want to make a couple of these calls in a row and restoring the
// clip rect in between would be a waste. It also blows away the background color.
//
void
CPersonalToolbarTable :: RedrawCellWithTextClipping ( const STableCell & inCell )
{
StTextState savedText;
SIconTableRec iconAndName;
Rect localRect;
UTextTraits::SetPortTextTraits(kTextTraitsID);
Uint32 dataSize = sizeof(SIconTableRec);
GetCellData(inCell, &iconAndName, dataSize);
GetLocalCellRect ( inCell, localRect );
Rect textRect = ComputeTextRect(iconAndName,localRect);
::ClipRect(&textRect);
::RGBBackColor(&bgColor);
::EraseRect(&textRect);
DrawCell(inCell, localRect);
} // RedrawCellWithTextClipping