home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-25 | 17.4 KB | 534 lines | [TEXT/R*ch] |
- // ===========================================================================
- // File: CMPDPanelSelectTable.cp
- // Version: 1.0 - Feb 1, 1996
- // Author: Mike Shields (mshields@inconnect.com)
- //
- // Copyright ©1996 Mike Shields. All rights reserved.
- // I hereby grant users of CMPDPanelSelectTable permission to use it (or any modified
- // version of it) in applications (or any other type of Macintosh software
- // like extensions -- freeware, shareware, commercial, or other) for free,
- // subject to the terms that:
- //
- // (1) This agreement is non-exclusive.
- //
- // (2) I, Mike Shields, retain the copyright to the original source code.
- //
- // These two items are the only required conditions for use. However, I do have
- // an additional request. Note, however, that this is only a request, and
- // that it is not a required condition for use of this code.
- //
- // (1) That I be given credit for CMPDPanelSelectTable code in the copyrights or
- // acknowledgements section of your manual or other appropriate documentation.
- //
- //
- // I would like to repeat that this last item is only a request. You are prefectly
- // free to choose not to do any or all of them.
- //
- // This source code is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- // ===========================================================================
- // CMPDPanelSelectTable.h <- double-click + Command-D to see class declaration
- //
- // Displays a scrolling list of icons and title strings. Also acts
- // like a control and broadcasts a hit message when an item changes.
-
- #include "CMPDPanelSelectTable.h"
-
- #include <LTableMonoGeometry.h>
- #include <LTableSingleSelector.h>
- #include <LTableArrayStorage.h>
-
- #include <LStream.h>
- #include <LString.h>
- #include <UTextTraits.h>
- #include <UDrawingUtils.h>
- #include <PP_Messages.h>
- #include <UKeyFilters.h>
- #include <PP_KeyCodes.h>
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
-
- #ifndef __LOWMEM__
- #include <LowMem.h>
- #endif
-
- #ifndef __ICONS__
- #include <Icons.h>
- #endif
-
- const short kMinimumRowHeight = 50;
-
- #pragma mark === Construction & Destruction ===
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::CreateFromStream
- //----------------------------------------------------------------------------------------
- // Static function registered with URegistrar to create a MPDPanelSelectTable from the data
- // in a stream
- CMPDPanelSelectTable* CMPDPanelSelectTable::CreateFromStream(LStream *inStream)
- {
- return (new CMPDPanelSelectTable(inStream));
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::CMPDPanelSelectTable
- //----------------------------------------------------------------------------------------
- // Default Contructor
- CMPDPanelSelectTable::CMPDPanelSelectTable()
- : mTextTraitsID(0)
- {
- if ( mSuperCommander != nil )
- {
- mSuperCommander->SetLatentSub(this);
- }
- mUseDragSelect = true;
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::CMPDPanelSelectTable
- //----------------------------------------------------------------------------------------
- // Construct from input parameters
- CMPDPanelSelectTable::CMPDPanelSelectTable(const SPaneInfo &inPaneInfo,
- const SViewInfo &inViewInfo,
- ResIDT inTextTraitsID)
- : LTableView(inPaneInfo, inViewInfo), mTextTraitsID(inTextTraitsID)
- {
- if ( mSuperCommander != nil )
- {
- mSuperCommander->SetLatentSub(this);
- }
-
- SetTableGeometry(new LTableMonoGeometry(this, mFrameSize.width, kMinimumRowHeight));
- SetTableSelector(new LTableSingleSelector(this));
- SetTableStorage(new LTableArrayStorage(this, sizeof(SIconTableRec)));
-
- mRows = 0;
- mCols = 1;
- mUseDragSelect = true;
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::CMPDPanelSelectTable
- //----------------------------------------------------------------------------------------
- // Construct from the data in a Stream
- CMPDPanelSelectTable::CMPDPanelSelectTable(LStream *inStream)
- : LTableView(inStream)
- {
- Int16 rowHeight;
- inStream->ReadData(&rowHeight, sizeof(Int16));
- SignalIf_(rowHeight < kMinimumRowHeight);
-
- inStream->ReadData(&mTextTraitsID, sizeof(ResIDT));
-
- if ( mSuperCommander != nil )
- {
- mSuperCommander->SetLatentSub(this);
- }
-
- SetTableGeometry(new LTableMonoGeometry(this, mFrameSize.width, rowHeight));
- SetTableSelector(new LTableSingleSelector(this));
- SetTableStorage(new LTableArrayStorage(this, sizeof(SIconTableRec)));
-
- mRows = 0;
- mCols = 1;
- mUseDragSelect = true;
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::~CMPDPanelSelectTable
- //----------------------------------------------------------------------------------------
- // Destructor
- CMPDPanelSelectTable::~CMPDPanelSelectTable()
- {
- }
-
- #pragma mark === PanelSelect Management ===
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::InsertPanelIDAt
- //----------------------------------------------------------------------------------------
- // Insert data into the MPDPanelSelectTable describing a panel identifier to be displayed
- // in the control
- void CMPDPanelSelectTable::InsertPanelIDs(MPDPtr inPanelIDData)
- {
- SIconTableRec rowData;
-
- for ( Int16 i = 0; i < inPanelIDData->numItems; i++ )
- {
- rowData.iconID = inPanelIDData->MPDList[i].iconID;
- LString::CopyPStr(inPanelIDData->MPDList[i].name, rowData.name, sizeof(rowData.name));
-
- InsertRows(1, inPanelIDData->numItems, &rowData, sizeof(SIconTableRec), false);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::SelectPanelID
- //----------------------------------------------------------------------------------------
- // Select a specific PanelID
- void CMPDPanelSelectTable::SelectPanelID(PanelIDIndexT inPanelID)
- {
- STableCell theSelection(inPanelID, 1);
-
- ScrollCellIntoFrame(theSelection);
- SelectCell(theSelection);
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::GetCurrentPanelID
- //----------------------------------------------------------------------------------------
- // Return the index of the currently selected PanelID
- PanelIDIndexT CMPDPanelSelectTable::GetCurrentPanelID(void) const
- {
- STableCell theSelection;
-
- if ( GetNextSelectedCell(theSelection) )
- return theSelection.row;
- else
- return 0;
- }
-
- #pragma mark === Clicking & Drawing ===
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::ClickSelf
- //----------------------------------------------------------------------------------------
- // Handle a mouse click within a MPDPanelSelectTable. We want to make this object the target
- // if switching the target can be allowed.
- void CMPDPanelSelectTable::ClickSelf(const SMouseDownEvent &inMouseDown)
- {
- STableCell hitCell;
- SPoint32 imagePt;
-
- LocalToImagePoint(inMouseDown.whereLocal, imagePt);
-
- if ( SwitchTarget(this) )
- if ( GetCellHitBy(imagePt, hitCell) ) // Only pass the click on up if we're clicking on a cell
- LTableView::ClickSelf(inMouseDown);
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::DrawCell
- //----------------------------------------------------------------------------------------
- // draw a specific cell.
- void CMPDPanelSelectTable::DrawCell(const STableCell &inCell,
- const Rect &inLocalRect)
- {
- DrawCellSelf(inCell, inLocalRect, CellIsSelected(inCell));
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::DrawCellSelf
- //----------------------------------------------------------------------------------------
- // draw a specific cell along with the appropriate hilighting. This is used by DrawCell,
- // HiliteCellActively, and HiliteCellInactively
- void CMPDPanelSelectTable::DrawCellSelf(const STableCell &inCell, const Rect &inLocalRect,
- Boolean inHilite)
- {
- #define kIconHeight 32
- #define kIconNameGap 2
- #define kNameHeight 12
- #define kNameWidthSlop 4
- #define kPanelIDTotalHeight (kIconHeight + kIconNameGap + kNameHeight)
-
- SIconTableRec iconAndName;
- Uint32 dataSize = sizeof(SIconTableRec);
- Rect iconRect;
- Rect textRect;
- LStr255 iconName;
-
- // get the data for the cell we're about to draw.
- GetCellData(inCell, &iconAndName, dataSize);
- iconName = iconAndName.name;
-
- // Draw the icon with the correct hilite on it.
- iconRect.left = inLocalRect.left + ((inLocalRect.right - inLocalRect.left - kIconHeight) / 2);
- iconRect.right = iconRect.left + kIconHeight;
- iconRect.top = inLocalRect.top + ((inLocalRect.bottom - inLocalRect.top - kPanelIDTotalHeight) / 4);
- iconRect.bottom = iconRect.top + kIconHeight;
- if ( inHilite )
- ::PlotIconID(&iconRect, atNone, ttSelected, iconAndName.iconID);
- else
- ::PlotIconID(&iconRect, atNone, ttNone, iconAndName.iconID);
-
- // first check to see if the string is too long. If so, change over to condensed text.
- // This might make it it.
- UTextTraits::SetPortTextTraits(mTextTraitsID);
- short textWidth = ::TextWidth((Ptr)&iconName[1], 0, iconName.Length());
- if ( textWidth > (inLocalRect.right - inLocalRect.left) )
- {
- ::TextFace(condense);
- textWidth = ::TextWidth((Ptr)&iconName[1], 0, iconName.Length());
- }
-
- // We'll call TruncString no matter what because it will truncate it if it still needs to be
- // otherwise it'll leave it alone.
- ::TruncString(inLocalRect.right - inLocalRect.left, iconName, truncMiddle);
-
- textRect.left = inLocalRect.left + ((inLocalRect.right - inLocalRect.left - (textWidth + kNameWidthSlop)) / 2);
- textRect.right = textRect.left + textWidth + kNameWidthSlop;
- textRect.top = iconRect.bottom + kIconNameGap;
- textRect.bottom = textRect.top + kNameHeight;
- UTextDrawing::DrawWithJustification((Ptr)&iconName[1], iconName.Length(),
- textRect, teCenter);
-
- if ( inHilite )
- {
- LMSetHiliteMode(LMGetHiliteMode() ^ (1 << hiliteBit));
- ::InvertRect(&textRect);
- }
- }
-
- #pragma mark === Hiliting ===
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::HiliteCellActively
- //----------------------------------------------------------------------------------------
- // Draw or undraw active hiliting for a Cell. This is the same no matter what.
- void CMPDPanelSelectTable::HiliteSelection(Boolean inActively, Boolean inHilite)
- {
- STableCell theCell;
-
- while ( GetNextSelectedCell(theCell) )
- {
- if (inActively)
- HiliteCellActively(theCell, inHilite);
- else
- HiliteCellInactively(theCell, inHilite);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::HiliteCellActively
- //----------------------------------------------------------------------------------------
- // Draw or undraw active hiliting for a Cell. This is the same no matter what.
- void CMPDPanelSelectTable::HiliteCellActively(const STableCell &inCell, Boolean inHilite)
- {
- Rect cellFrame;
- if ( GetLocalCellRect(inCell, cellFrame) && FocusExposed() )
- {
- ApplyForeAndBackColors();
- ::EraseRect(&cellFrame);
- DrawCellSelf(inCell, cellFrame, inHilite);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CMPDPanelSelectTable::HiliteCellInactively
- //----------------------------------------------------------------------------------------
- // Draw or undraw inactive hiliting for a Cell. This is the same no matter what.
- void CMPDPanelSelectTable::HiliteCellInactively(const STableCell &inCell, Boolean inHilite)
- {
- Rect cellFrame;
- if ( GetLocalCellRect(inCell, cellFrame) && FocusExposed() )
- {
- ApplyForeAndBackColors();
- ::EraseRect(&cellFrame);
- DrawCellSelf(inCell, cellFrame, inHilite);
- }
- }
-
- #pragma mark === Selection ===
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::SelectionChanged
- //---------------------------------------------------------------------------
- // Broadcast the fact that the table selection has changed
- void CMPDPanelSelectTable::SelectionChanged()
- {
- ReportPanelIDChanged();
- }
-
- #pragma mark === Command Handling ===
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::ObeyCommand
- //---------------------------------------------------------------------------
- // Handle the msg_TabSelect command to switch ourselves to be the target
- Boolean CMPDPanelSelectTable::ObeyCommand(CommandT inCommand, void* ioParam)
- {
- Boolean cmdHandled = true;
-
- switch (inCommand)
- {
- case msg_TabSelect:
- if ( !IsEnabled() )
- {
- cmdHandled = false;
- }
- break;
-
- default:
- cmdHandled = LCommander::ObeyCommand(inCommand, ioParam);
- break;
- }
-
- return cmdHandled;
- }
-
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::HandleKeyPress
- //---------------------------------------------------------------------------
- // Supports keyboard navigation
- Boolean CMPDPanelSelectTable::HandleKeyPress(const EventRecord &inKeyEvent)
- {
- Boolean keyHandled = true;
- Char16 theKey = inKeyEvent.message & charCodeMask;
-
- FocusDraw();
-
- if ( UKeyFilters::IsNavigationKey(theKey) )
- {
- DoNavigationKey(inKeyEvent);
- }
- else
- {
- keyHandled = LCommander::HandleKeyPress(inKeyEvent);
- }
-
- return keyHandled;
- }
-
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::DoNavigationKey
- //---------------------------------------------------------------------------
- // Implements keyboard navigation by supporting selection change using
- // the arrow keys, page up, page down, home, and end
- void CMPDPanelSelectTable::DoNavigationKey(const EventRecord&inKeyEvent)
- {
- char theKey = inKeyEvent.message & charCodeMask;
- Boolean cmdKeyDown = (inKeyEvent.modifiers & cmdKey) != 0;
- STableCell theSelection;
- Boolean cellIsSelected = GetNextSelectedCell(theSelection);
-
- switch ( theKey )
- {
- case char_UpArrow:
- case char_LeftArrow:
- if ( cellIsSelected )
- {
- // Select cell one above the first
- // selected cell
- if ( theSelection.row > 1 )
- {
- theSelection.row -= 1;
- SelectCell(theSelection);
- ScrollCellIntoFrame(theSelection);
- }
- }
- else
- {
- theSelection.SetCell(1, 1);
- SelectCell(theSelection);
- ScrollCellIntoFrame(theSelection);
- }
- break;
-
- case char_DownArrow:
- case char_RightArrow:
- if ( cellIsSelected )
- {
- // Select cell one after the first
- // selected cell
- if ( theSelection.row < mRows )
- {
- theSelection.row += 1;
- SelectCell(theSelection);
- ScrollCellIntoFrame(theSelection);
- }
- }
- else
- {
- theSelection.SetCell(1, 1);
- SelectCell(theSelection);
- ScrollCellIntoFrame(theSelection);
- }
- break;
-
- case char_Home:
- ScrollPinnedImageBy(0, -mImageSize.height, true);
- break;
-
- case char_End:
- ScrollPinnedImageBy(0, mImageSize.height, true);
- break;
-
- case char_PageUp:
- case char_PageDown:
- {
- Rect frame;
- Uint16 cellHeight;
- Uint32 scrollValue;
- Uint16 numOfFullVisibleCells;
-
- CalcLocalFrameRect(frame);
- cellHeight = GetRowHeight(1);
- numOfFullVisibleCells = (frame.bottom - frame.top) % cellHeight;
- scrollValue = numOfFullVisibleCells * cellHeight;
-
- ScrollPinnedImageBy(0, (theKey == char_PageUp) ? -scrollValue : scrollValue, true);
- break;
- }
- }
- }
-
- #pragma mark === Accessing Cells ===
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::ScrollCellIntoFrame
- //---------------------------------------------------------------------------
- // Scroll the TableView as little as possible to move the specified Cell
- // so that it's entirely within the Frame of the TableView
- void CMPDPanelSelectTable::ScrollCellIntoFrame(const STableCell &inCell)
- {
- SPoint32 cellTopLeft;
- SPoint32 cellBotRight;
- mTableGeometry->GetImageCellBounds(inCell, cellTopLeft.h, cellTopLeft.v,
- cellBotRight.h, cellBotRight.v);
-
- if ( ImagePointIsInFrame(cellTopLeft.h, cellTopLeft.v) &&
- ImagePointIsInFrame(cellBotRight.h, cellBotRight.v) )
- {
- return; // Cell is already within Frame
- }
-
- Rect frame;
- SPoint32 frameTopLeft;
- SPoint32 frameBotRight;
-
- CalcLocalFrameRect(frame);
-
- LocalToImagePoint(topLeft(frame), frameTopLeft);
- LocalToImagePoint(botRight(frame), frameBotRight);
-
- if ( frameBotRight.v < cellBotRight.v )
- {
- // Cell is off the bottom of the frame
- ScrollPinnedImageBy(0, -(frameBotRight.v - cellBotRight.v), true);
- }
- else if ( frameTopLeft.v > cellTopLeft.v )
- {
- // Cell is off the top of the frame
- ScrollPinnedImageBy(0, -(frameTopLeft.v - cellTopLeft.v), true);
- }
- }
-
- #pragma mark === Targeting Control ===
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::BeTarget
- //---------------------------------------------------------------------------
- // Tell our TargeterBox that we are now the target.
- void CMPDPanelSelectTable::BeTarget()
- {
- LCommander::BeTarget();
- ShowFocus();
- }
-
- //---------------------------------------------------------------------------
- // CMPDPanelSelectTable::DontBeTarget
- //---------------------------------------------------------------------------
- // Tell our TargeterBox that we are no longer the target.
- void CMPDPanelSelectTable::DontBeTarget()
- {
- LCommander::DontBeTarget();
- HideFocus();
- }
-
-