/* -*- 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. */ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CDragBarContainer.cp // // // NOTE: It is assumed that the first level sub views of this container are // either CDragBar's or the CDragBarDockControl. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ #include "CDragBar.h" #include "CDragBarContainer.h" #include "CDragBarDockControl.h" #include "CDragBarDragTask.h" #include "UGraphicGizmos.h" #include #include #include #include // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CDragBarContainer::CDragBarContainer(LStream* inStream) : CBrokeredView(inStream), LDropArea(GetMacPort()), mBars(sizeof(CDragBar*)) { *inStream >> mBarListResID; mDock = NULL; SetRefreshAllWhenResized(false); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CDragBarContainer::~CDragBarContainer() { } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::FinishCreateSelf(void) { CBrokeredView::FinishCreateSelf(); // We need to get the dock first so that when we initialize the initial // state of the bars we have somewhere to put them. mDock = dynamic_cast(FindPaneByID(CDragBarDockControl::class_ID)); Assert_(mDock != NULL); mDock->AddListener(this); StResource theIDList('RidL', mBarListResID); { StHandleLocker theLock(theIDList); LDataStream theBarStream(*theIDList.mResourceH, ::GetHandleSize(theIDList)); Int16 theItemCount; theBarStream >> theItemCount; for (Int16 i = 0; i < theItemCount; i++) { PaneIDT thePaneID; theBarStream >> thePaneID; CDragBar* theBar = dynamic_cast(FindPaneByID(thePaneID)); Assert_(theBar != NULL); if (theBar->IsDocked()) mDock->AddBarToDock(theBar); mBars.InsertItemsAt(1, LArray::index_Last, &theBar); theBar->AddListener(this); } } AdjustContainer(); AdjustDock(); // Because new toolbar drag bars could adjust their frames // at FinishCreateSelf time, call RepositionBars RepositionBars(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::ListenToMessage( MessageT inMessage, void* ioParam) { if (inMessage == msg_DragBarCollapse) { CDragBar* theBar = (CDragBar*)ioParam; NoteCollapseBar(theBar); } else if (inMessage == msg_DragBarExpand) { CDragBar* theBar = (CDragBar*)ioParam; NoteExpandBar(theBar); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::SavePlace(LStream *outPlace) { *outPlace << mBars.GetCount(); CDragBar* theBar; LArrayIterator theIter(mBars, LArrayIterator::from_Start); while (theIter.Next(&theBar)) { *outPlace << theBar->GetPaneID(); *outPlace << theBar->IsDocked(); *outPlace << theBar->IsAvailable(); } mDock->SavePlace(outPlace); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::RestorePlace(LStream *inPlace) { Int32 theBarCount; *inPlace >> theBarCount; for (Int32 theIndex = LArray::index_First; theIndex <= theBarCount; theIndex++) { PaneIDT thePaneID; *inPlace >> thePaneID; Boolean bIsDocked; *inPlace >> bIsDocked; Boolean bIsAvailable; *inPlace >> bIsAvailable; CDragBar* theBar = dynamic_cast(FindPaneByID(thePaneID)); Assert_(theBar != NULL); // First we want to place the bar in the same position in the // bar array as it was before. We can tell that by its position // from when it was saved out. ArrayIndexT theBarIndex = mBars.FetchIndexOf(&theBar); Assert_(theBarIndex != LArray::index_Bad); mBars.MoveItem(theBarIndex, theIndex); // Now we need to sync the state of the bar properly. if (bIsDocked && !theBar->IsDocked()) mDock->AddBarToDock(theBar); if (bIsAvailable) theBar->Show(); else theBar->Hide(); theBar->SetAvailable(bIsAvailable); } mDock->RestorePlace(inPlace); RepositionBars(); AdjustContainer(); AdjustDock(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Hides the drag bar from the container AND dock without changing the docking // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::HideBar(CDragBar* inBar, Boolean inRefresh) { // hide drag bar if (inBar->IsAvailable()) { if (!inBar->IsDocked()) inBar->Hide(); // hide if undocked mDock->HideBar(inBar); inBar->SetAvailable(false); RepositionBars(); AdjustContainer(); AdjustDock(); if (inRefresh) Refresh(); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Show the drag bar without changing the docking // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::ShowBar(CDragBar* inBar, Boolean inRefresh) { if (!inBar->IsAvailable()) { if (!inBar->IsDocked()) inBar->Show(); // show if undocked mDock->ShowBar(inBar); inBar->SetAvailable(true); RepositionBars(); AdjustContainer(); AdjustDock(); if (inRefresh) Refresh(); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::NoteCollapseBar(CDragBar* inBar) { FocusDraw(); // 3/6/97 pkc // When inBar is NULL, we just want to adjust things, but we // don't need to add a bar to the dock if (inBar) mDock->AddBarToDock(inBar); RepositionBars(); AdjustContainer(); AdjustDock(); Refresh(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::NoteExpandBar(CDragBar* inBar) { FocusDraw(); mDock->RemoveBarFromDock(inBar); AdjustDock(); // show or hide as appropriate RepositionBars(); AdjustContainer(); Refresh(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::RepositionBars(void) { Rect theContainerFrame; CalcLocalFrameRect(theContainerFrame); Int32 theHeight = theContainerFrame.top; CDragBar* theBar; LArrayIterator theIter(mBars, LArrayIterator::from_Start); while (theIter.Next(&theBar)) { if (theBar->IsDocked()) // Docked bars are ignored continue; if (!theBar->IsAvailable()) // Unavailable (hidden from container and dock) continue; SDimension16 theBarSize; theBar->GetFrameSize(theBarSize); theBar->PlaceInSuperFrameAt(theContainerFrame.left, theHeight, false); theHeight += theBarSize.height; } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::SwapBars( CDragBar* inSourceBar, CDragBar* inDestBar, Boolean inRefresh) { if (inSourceBar == inDestBar) return; // Get the indeces and swap the bars in the array ArrayIndexT theSourceIndex = mBars.FetchIndexOf(&inSourceBar); Assert_(theSourceIndex != LArray::index_Bad); ArrayIndexT theDestIndex = mBars.FetchIndexOf(&inDestBar); Assert_(theDestIndex != LArray::index_Bad); mBars.SwapItems(theSourceIndex, theDestIndex); // align the indeces so we can loop up from one to another. if (theSourceIndex > theDestIndex) { ArrayIndexT theTemp = theSourceIndex; theSourceIndex = theDestIndex; theDestIndex = theTemp; } // Now we need to invalidate all of the bars between, and including, // the source and destination. FocusDraw(); while (theSourceIndex <= theDestIndex) { CDragBar* theBar = NULL; mBars.FetchItemAt(theSourceIndex, &theBar); Assert_(theBar != NULL); Rect thePortFrame; theBar->CalcPortFrameRect(thePortFrame); theBar->InvalPortRect(&thePortFrame); theSourceIndex++; } if (inRefresh) { RepositionBars(); UpdatePort(); // expensive call!!! use sparingly } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::AdjustContainer(void) { // First get our frame size, we need the width. SDimension16 theNewSize; GetFrameSize(theNewSize); // The height is the sum of the non-docked bars // If all bars are docked, the size is the height of the dock theNewSize.height = 0; CDragBar* theBar; LArrayIterator theIter(mBars, LArrayIterator::from_Start); while (theIter.Next(&theBar)) { if (theBar->IsDocked()) // Docked bars are ignored. continue; if (!theBar->IsAvailable()) // Unavailable (hidden from container and dock) continue; SDimension16 theBarSize; theBar->GetFrameSize(theBarSize); theNewSize.height += theBarSize.height; } SDimension16 theDockSize; mDock->GetFrameSize(theDockSize); if (mDock->HasDockedBars()) theNewSize.height += theDockSize.height; ResizeFrameTo(theNewSize.width, theNewSize.height, true); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CDragBarContainer::AdjustDock(void) { if (mDock->HasDockedBars()) mDock->Show(); else mDock->Hide(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- DROP AREA BEHAVIOUR --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ PointInDropArea // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Return whether a Point, in Global coords, is inside a DropArea Boolean CDragBarContainer::PointInDropArea( Point inPoint) { GlobalToPortPoint(inPoint); return IsHitBy(inPoint.h, inPoint.v); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CDragBarContainer::ItemIsAcceptable( DragReference inDragRef, ItemReference inItemRef) { Boolean bIsAcceptable = false; FlavorFlags theFlags; OSErr theErr = ::GetFlavorFlags(inDragRef, inItemRef, Flavor_DragBar, &theFlags); if (theErr == noErr) { DragAttributes theAttributes; theErr = ::GetDragAttributes(inDragRef, &theAttributes); if (theErr == noErr) bIsAcceptable = (theAttributes & kDragInsideSenderWindow) != 0; } return bIsAcceptable; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ EnterDropArea // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // A Drag is entering a DropArea. This call will be followed by a // corresponding LeaveDropArea call (when the Drag moves out of the // DropArea or after the Drag is received by this DropArea). // // If the DropArea can accept the Drag and the Drag is coming from outside // the DropArea, hilite the DropArea void CDragBarContainer::EnterDropArea( DragReference /* inDragRef */, Boolean /* inDragHasLeftSender */) { // NULL IMPLEMENTATION // No hiliting necessary. } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ LeaveDropArea // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // A Drag is leaving a DropArea. This call will have been preceded by // a corresponding EnterDropArea call. // // Remove hiliting of the DropArea if necessary void CDragBarContainer::LeaveDropArea( DragReference /* inDragRef */) { // No hiliting necessary. mCanAcceptCurrentDrag = false; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ InsideDropArea // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Track a Drag while it is inside a DropArea. This function is called // repeatedly while an acceptable Drag is inside a DropArea. // // This more difficult than it needs to be, because PowerPlant does not pass the refCon // through to this routine. If it did, I could easily get at the tracking bar. // Instead I need to go through the drag item reference number to get the // task, and then get the tracking bar. void CDragBarContainer::InsideDropArea(DragReference inDragRef) { FocusDraw(); Point theMouse, thePinnedMouse; OSErr theErr = ::GetDragMouse(inDragRef, &theMouse, &thePinnedMouse); if (theErr != noErr) { return; } GlobalToPortPoint(theMouse); LPane* thePane = FindShallowSubPaneContaining(theMouse.h, theMouse.v); // We have the special knowledge that the top level sub panes // can only be other drag bars, or the dock. CDragBar* theBar = dynamic_cast(thePane); if (theBar != NULL) { CDragBarDragTask* theTask = NULL; theErr = ::GetDragItemReferenceNumber(inDragRef, 1, (ItemReference*)(&theTask)); if (theErr != noErr) { return; } // See if we're over a bar, and it's not the one we're dragging CDragBar* theTrackingBar = theTask->GetTrackingBar(); if (theBar != theTrackingBar) { ArrayIndexT theBarPosition; theBarPosition = mBars.FetchIndexOf(&theBar); ArrayIndexT theTrackPosition; theTrackPosition = mBars.FetchIndexOf(&theTrackingBar); // OK, we have the indeces which correspond to the bars' top to // bottom ordering on the screen. To prevent violent swapping of the bars, // we only want to swap if the point has passed through the mid horizontal // point of the bar in the direction leading away from the current tracking // bar. Rect theBarPortFrame; theBar->CalcPortFrameRect(theBarPortFrame); Int16 theMidLine = theBarPortFrame.top + (RectHeight(theBarPortFrame) / 2); Boolean bShouldSwap; if ((theBarPosition < theTrackPosition) && (theMouse.v <= theMidLine)) bShouldSwap = true; else if ((theBarPosition > theTrackPosition) && (theMouse.v >= theMidLine)) bShouldSwap = true; else bShouldSwap = false; if (bShouldSwap) SwapBars(theTrackingBar, theBar, true); } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ ReceiveDragItem // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Process an Item which has been dragged into a DropArea // // This function gets called once for each Item contained in a completed // Drag. The Item will have returned true from ItemIsAcceptable(). // // The DropArea is focused upon entry and inItemBounds is specified // in the local coordinates of the DropArea. void CDragBarContainer::ReceiveDragItem( DragReference /* inDragRef */, DragAttributes /* inDragAttrs */, ItemReference /* inItemRef */, Rect& /* inItemBounds */) // In Local coordinates { }