mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Add drag auto-scrolling to trees. bug#28226, r=hyatt.
This commit is contained in:
parent
1372f7334a
commit
1821dfd254
@ -20,6 +20,7 @@
|
||||
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Pinkerton (pinkerton@netscape.com)
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
@ -34,12 +35,118 @@
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsTreeItemDragCapturer.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDragService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
|
||||
#define TICK_FACTOR 50
|
||||
|
||||
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
|
||||
|
||||
nsresult NS_NewAutoScrollTimer(nsXULTreeOuterGroupFrame* aTree, nsDragAutoScrollTimer **aResult) ;
|
||||
|
||||
|
||||
//
|
||||
// nsDragOverListener
|
||||
//
|
||||
// Just a little class that listens for dragOvers to trigger the auto-scrolling
|
||||
// code.
|
||||
//
|
||||
class nsDragOverListener : public nsIDOMDragListener
|
||||
{
|
||||
public:
|
||||
|
||||
nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree );
|
||||
virtual ~nsDragOverListener() { } ;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIDOMDragListener
|
||||
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
|
||||
virtual nsresult DragEnter(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragOver(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragExit(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragDrop(nsIDOMEvent* aDragEvent);
|
||||
virtual nsresult DragGesture(nsIDOMEvent* aDragEvent);
|
||||
|
||||
protected:
|
||||
|
||||
nsXULTreeOuterGroupFrame* mTree;
|
||||
|
||||
}; // nsDragEnterListener
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsDragOverListener, nsIDOMEventListener, nsIDOMDragListener)
|
||||
|
||||
nsDragOverListener :: nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree )
|
||||
: mTree ( inTree )
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DragOver
|
||||
//
|
||||
// Kick off our timer/capturing for autoscrolling, the drag has entered us. We
|
||||
// will continue capturing the mouse until the auto-scroll manager tells us to
|
||||
// stop (either the drag is over, it left the window, or someone else wants a
|
||||
// crack at auto-scrolling).
|
||||
//
|
||||
nsresult
|
||||
nsDragOverListener :: DragOver(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDragEvent) );
|
||||
if ( mouseEvent ) {
|
||||
PRInt32 x = 0, y = 0;
|
||||
mouseEvent->GetClientX ( &x );
|
||||
mouseEvent->GetClientY ( &y );
|
||||
mTree->HandleAutoScrollTracking ( nsPoint(x,y) );
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
} // DragOver
|
||||
|
||||
|
||||
//
|
||||
// The rest are stubs
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsDragOverListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
nsDragOverListener::DragEnter(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
nsDragOverListener::DragGesture(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
nsDragOverListener::DragExit(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult
|
||||
nsDragOverListener::DragDrop(nsIDOMEvent* aDragEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// NS_NewXULTreeOuterGroupFrame
|
||||
//
|
||||
@ -66,14 +173,28 @@ NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRB
|
||||
// Constructor
|
||||
nsXULTreeOuterGroupFrame::nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||
:nsXULTreeGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal),
|
||||
mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0), mTwipIndex(0),
|
||||
mTreeIsSorted(PR_FALSE)
|
||||
{}
|
||||
mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0), mTwipIndex(0), mAutoScrollTimer(nsnull),
|
||||
mTreeIsSorted(PR_FALSE), mDragOverListener(nsnull), mCurrentlyTrackingAutoScroll(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Destructor
|
||||
nsXULTreeOuterGroupFrame::~nsXULTreeOuterGroupFrame()
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
GetContent(getter_AddRefs(content));
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(content));
|
||||
|
||||
// NOTE: the last Remove will delete the drag capturer
|
||||
if ( receiver && mDragOverListener )
|
||||
receiver->RemoveEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_TRUE);
|
||||
|
||||
delete mRowGroupInfo;
|
||||
|
||||
StopAutoScrollTimer();
|
||||
NS_IF_RELEASE ( mAutoScrollTimer );
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
@ -93,8 +214,15 @@ nsXULTreeOuterGroupFrame::Release(void)
|
||||
//
|
||||
NS_INTERFACE_MAP_BEGIN(nsXULTreeOuterGroupFrame)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDragTracker)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsXULTreeGroupFrame)
|
||||
|
||||
|
||||
//
|
||||
// Init
|
||||
//
|
||||
// Setup scrolling and event listeners for drag auto-scrolling
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent,
|
||||
nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow)
|
||||
@ -124,6 +252,16 @@ nsXULTreeOuterGroupFrame::Init(nsIPresContext* aPresContext, nsIContent* aConten
|
||||
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(verticalScrollbar));
|
||||
scrollbarFrame->SetScrollbarMediator(this);
|
||||
|
||||
// Our frame's lifetime is bounded by the lifetime of the content model, so we're guaranteed
|
||||
// that the content node won't go away on us. As a result, our listener can't go away before the
|
||||
// frame is deleted. Since the content node holds owning references to our drag capturer, which
|
||||
// we tear down in the dtor, there is no need to hold an owning ref to it ourselves.
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(aContent));
|
||||
if ( receiver ) {
|
||||
mDragOverListener = new nsDragOverListener(this);
|
||||
receiver->AddEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_FALSE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
} // Init
|
||||
@ -290,8 +428,6 @@ nsXULTreeOuterGroupFrame::PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex)
|
||||
if (aOldIndex == aNewIndex)
|
||||
return NS_OK;
|
||||
|
||||
printf("Old Index: %d, New Index: %d\n", aOldIndex, aNewIndex);
|
||||
|
||||
PRInt32 oldTwipIndex, newTwipIndex;
|
||||
oldTwipIndex = (aOldIndex*mOnePixel);
|
||||
newTwipIndex = (aNewIndex*mOnePixel);
|
||||
@ -793,6 +929,9 @@ nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
void
|
||||
nsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex)
|
||||
{
|
||||
if ( aRowIndex < 0 )
|
||||
return;
|
||||
|
||||
PRInt32 newIndex = aRowIndex;
|
||||
PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex;
|
||||
PRBool up = newIndex < mCurrentIndex;
|
||||
@ -918,3 +1057,219 @@ nsXULTreeOuterGroupFrame :: AttributeChanged ( nsIPresContext* aPresContext, nsI
|
||||
} // AttributeChanged
|
||||
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//
|
||||
// StopTracking
|
||||
//
|
||||
// Stop tracking auto-scrolling
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame :: StopTracking ( )
|
||||
{
|
||||
// turn off capturing of the mouse.
|
||||
CaptureMouse ( mPresContext, PR_FALSE );
|
||||
|
||||
StopAutoScrollTimer ( );
|
||||
mCurrentlyTrackingAutoScroll = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HandleAutoScrollTracking
|
||||
//
|
||||
// Do all the setup for tracking drag auto-scrolling. This can be called repeatedly, but the
|
||||
// setup will only be done once. Handles capturing the mouse, starting a timer, and registering
|
||||
// ourselves with a manager that will let us know when we're to stop tracking.
|
||||
//
|
||||
nsresult
|
||||
nsXULTreeOuterGroupFrame :: HandleAutoScrollTracking ( const nsPoint & aPoint )
|
||||
{
|
||||
if ( !mCurrentlyTrackingAutoScroll ) {
|
||||
|
||||
CaptureMouse ( mPresContext, PR_TRUE );
|
||||
|
||||
// register with the drag auto-scroll manager so we're told when to stop
|
||||
// tracking
|
||||
nsCOMPtr<nsIDragService> dragServ ( do_GetService("component://netscape/widget/dragservice") );
|
||||
if ( dragServ ) {
|
||||
nsCOMPtr<nsIDragSession> session;
|
||||
dragServ->GetCurrentSession ( getter_AddRefs(session) );
|
||||
if ( session )
|
||||
session->StartTracking(this);
|
||||
}
|
||||
|
||||
mCurrentlyTrackingAutoScroll = PR_TRUE; // setup complete
|
||||
}
|
||||
|
||||
// kick off our timer
|
||||
StartAutoScrollTimer ( aPoint, 30 );
|
||||
|
||||
return NS_OK;
|
||||
|
||||
} // HandleAutoScrollTracking
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULTreeOuterGroupFrame::StartAutoScrollTimer(const nsPoint& aPoint, PRUint32 aDelay)
|
||||
{
|
||||
nsresult result;
|
||||
|
||||
if (!mAutoScrollTimer) {
|
||||
result = NS_NewAutoScrollTimer(this, &mAutoScrollTimer);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (!mAutoScrollTimer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result = mAutoScrollTimer->SetDelay(aDelay);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
return DoAutoScroll(aPoint);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULTreeOuterGroupFrame::StopAutoScrollTimer()
|
||||
{
|
||||
if (mAutoScrollTimer)
|
||||
return mAutoScrollTimer->Stop();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DoAutoScroll
|
||||
//
|
||||
// Given the current mouse position, checks if it is w/in the bounds of the row area
|
||||
// of the tree. If not, scroll up or down in increments of one row.
|
||||
//
|
||||
nsresult
|
||||
nsXULTreeOuterGroupFrame::DoAutoScroll ( const nsPoint& aPoint )
|
||||
{
|
||||
if ( mAutoScrollTimer )
|
||||
mAutoScrollTimer->Stop();
|
||||
|
||||
float pixelsToTwips = 0.0;
|
||||
mPresContext->GetPixelsToTwips ( &pixelsToTwips );
|
||||
nsPoint mouseInTwips ( NSToIntRound(aPoint.x * pixelsToTwips), NSToIntRound(aPoint.y * pixelsToTwips) );
|
||||
|
||||
// compute the offset to top level in twips and subtract the offset from
|
||||
// the mouse coord to put it into our coordinates.
|
||||
nscoord frameOffsetX = 0, frameOffsetY = 0;
|
||||
nsIFrame* curr = this;
|
||||
curr->GetParent(&curr);
|
||||
while ( curr ) {
|
||||
nsPoint origin;
|
||||
curr->GetOrigin(origin); // in twips
|
||||
frameOffsetX += origin.x; // build the offset incrementally
|
||||
frameOffsetY += origin.y;
|
||||
curr->GetParent(&curr); // moving up the chain
|
||||
} // until we reach the top
|
||||
mouseInTwips.MoveBy ( -frameOffsetX, -frameOffsetY );
|
||||
|
||||
const int kMarginHeight = NSToIntRound ( 12 * pixelsToTwips );
|
||||
|
||||
if ( mouseInTwips.x <= 0 || mouseInTwips.x >= mRect.width )
|
||||
UnregisterTracking();
|
||||
else {
|
||||
// scroll up or down, accordingly. if the mouse is outside of the scroll margin, stop the tracking altogether.
|
||||
PRBool continueTracking = PR_TRUE;
|
||||
if ( mouseInTwips.y < 0 ) {
|
||||
if ( mouseInTwips.y > -kMarginHeight )
|
||||
ScrollToIndex ( mCurrentIndex - 1 );
|
||||
else {
|
||||
continueTracking = PR_FALSE;
|
||||
UnregisterTracking();
|
||||
}
|
||||
}
|
||||
else if ( mouseInTwips.y > GetAvailableHeight() ) {
|
||||
if ( mouseInTwips.y < GetAvailableHeight() + kMarginHeight )
|
||||
ScrollToIndex ( mCurrentIndex + 1 );
|
||||
else {
|
||||
continueTracking = PR_FALSE;
|
||||
UnregisterTracking();
|
||||
}
|
||||
}
|
||||
|
||||
// restart the timer
|
||||
if ( mAutoScrollTimer && continueTracking )
|
||||
mAutoScrollTimer->Start(aPoint);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// UnregisterTracking
|
||||
//
|
||||
// Tell the drag session that we're done tracking the mouse
|
||||
//
|
||||
void
|
||||
nsXULTreeOuterGroupFrame :: UnregisterTracking ( )
|
||||
{
|
||||
nsCOMPtr<nsIDragService> dragService ( do_GetService("component://netscape/widget/dragservice") );
|
||||
if ( dragService ) {
|
||||
// tell anyone interested to stop tracking drags
|
||||
nsCOMPtr<nsIDragSession> session;
|
||||
dragService->GetCurrentSession ( getter_AddRefs(session) );
|
||||
if ( session )
|
||||
session->StopTracking();
|
||||
}
|
||||
|
||||
} // UnregisterTracking
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// nsDragAutoScrollTimer Impl
|
||||
//
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsDragAutoScrollTimer, nsITimerCallback)
|
||||
|
||||
|
||||
//
|
||||
// Notify
|
||||
//
|
||||
// Called when the timer fires. Tells the tree to try to scroll.
|
||||
//
|
||||
void
|
||||
nsDragAutoScrollTimer :: Notify(nsITimer *timer)
|
||||
{
|
||||
mTree->DoAutoScroll(mPoint);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
NS_NewAutoScrollTimer(nsXULTreeOuterGroupFrame* aTree, nsDragAutoScrollTimer **aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aResult = new nsDragAutoScrollTimer(aTree);
|
||||
|
||||
if (!aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Pinkerton (pinkerton@netscape.com)
|
||||
*/
|
||||
|
||||
#ifndef NSXULTREEOUTERGROUPFRAME
|
||||
@ -32,8 +33,15 @@
|
||||
#include "nsXULTreeGroupFrame.h"
|
||||
#include "nsIScrollbarMediator.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDragTracker.h"
|
||||
|
||||
|
||||
class nsCSSFrameConstructor;
|
||||
class nsDragOverListener;
|
||||
class nsDragAutoScrollTimer;
|
||||
|
||||
|
||||
#define TREE_LINE_HEIGHT 225
|
||||
|
||||
@ -61,17 +69,95 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class nsXULTreeOuterGroupFrame : public nsXULTreeGroupFrame, public nsIScrollbarMediator
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
//
|
||||
// nsDragAutoScrollTimer
|
||||
//
|
||||
// A timer class for handling auto-scrolling during drags
|
||||
//
|
||||
class nsDragAutoScrollTimer : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDragAutoScrollTimer ( nsXULTreeOuterGroupFrame* inTree )
|
||||
: mPoint(0,0), mDelay(30), mTree(inTree)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
virtual ~nsDragAutoScrollTimer()
|
||||
{
|
||||
if (mTimer)
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
nsresult Start(const nsPoint& aPoint)
|
||||
{
|
||||
mPoint = aPoint;
|
||||
|
||||
if ( !mTimer ) {
|
||||
nsresult result;
|
||||
mTimer = do_CreateInstance("component://netscape/timer", &result);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
|
||||
return mTimer->Init(this, mDelay);
|
||||
}
|
||||
|
||||
nsresult Stop()
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
mTimer = nsnull;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult SetDelay(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(void) Notify(nsITimer *timer) ;
|
||||
|
||||
private:
|
||||
nsXULTreeOuterGroupFrame *mTree;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsPoint mPoint;
|
||||
PRUint32 mDelay;
|
||||
|
||||
}; // nsDragAutoScrollTimer
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
class nsXULTreeOuterGroupFrame : public nsXULTreeGroupFrame, public nsIScrollbarMediator,
|
||||
public nsIDragTracker
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIDRAGTRACKER
|
||||
|
||||
friend class nsDragAutoScrollTimer;
|
||||
friend class nsDragOverListener;
|
||||
friend nsresult NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell,
|
||||
nsIFrame** aNewFrame,
|
||||
PRBool aIsRoot = PR_FALSE,
|
||||
nsIBoxLayout* aLayoutManager = nsnull,
|
||||
PRBool aDefaultHorizontal = PR_TRUE);
|
||||
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent,
|
||||
nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow);
|
||||
|
||||
@ -79,8 +165,6 @@ protected:
|
||||
nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||
virtual ~nsXULTreeOuterGroupFrame();
|
||||
|
||||
void ComputeTotalRowCount(PRInt32& aRowCount, nsIContent* aParent);
|
||||
|
||||
public:
|
||||
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
|
||||
{
|
||||
@ -152,15 +236,33 @@ public:
|
||||
NS_IMETHOD InternalPositionChanged(PRBool aUp, PRInt32 aDelta);
|
||||
|
||||
PRBool IsTreeSorted ( ) const { return mTreeIsSorted; }
|
||||
|
||||
|
||||
protected: // Data Members
|
||||
|
||||
void ComputeTotalRowCount(PRInt32& aRowCount, nsIContent* aParent);
|
||||
|
||||
// Drag Auto-scrolling. Call HandleAutoScrollTracking() to setup everything and
|
||||
// do the scrolling magic. It can be called multiple times, though the
|
||||
// setup will only be done once.
|
||||
nsresult HandleAutoScrollTracking ( const nsPoint & aPoint );
|
||||
nsresult StartAutoScrollTimer(const nsPoint& aPoint, PRUint32 aDelay);
|
||||
nsresult StopAutoScrollTimer();
|
||||
nsresult DoAutoScroll(const nsPoint& aPoint);
|
||||
void UnregisterTracking ( ) ;
|
||||
|
||||
nsXULTreeRowGroupInfo* mRowGroupInfo;
|
||||
PRInt32 mRowHeight;
|
||||
nscoord mOnePixel;
|
||||
PRInt32 mCurrentIndex; // Row-based
|
||||
PRInt32 mTwipIndex; // Not really accurate. Used to handle thumb dragging
|
||||
PRPackedBool mTreeIsSorted;
|
||||
PRPackedBool mCurrentlyTrackingAutoScroll; // used to track if we've done setup already
|
||||
|
||||
// our auto-scroll event listener registered with the content model. See the discussion
|
||||
// in Init() for why this is a weak ref.
|
||||
nsDragOverListener* mDragOverListener;
|
||||
nsDragAutoScrollTimer* mAutoScrollTimer; // actually a strong ref
|
||||
|
||||
}; // class nsXULTreeOuterGroupFrame
|
||||
|
||||
|
||||
|
@ -1320,7 +1320,7 @@ NS_IMETHODIMP nsViewManager2::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *a
|
||||
|
||||
//Find the view to which we're initially going to send the event
|
||||
//for hittesting.
|
||||
if (nsnull != mMouseGrabber && NS_IS_MOUSE_EVENT(aEvent)) {
|
||||
if (nsnull != mMouseGrabber && (NS_IS_MOUSE_EVENT(aEvent) || NS_IS_DRAG_EVENT(aEvent))) {
|
||||
view = mMouseGrabber;
|
||||
}
|
||||
else if (nsnull != mKeyGrabber && NS_IS_KEY_EVENT(aEvent)) {
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsISupportsArray.idl"
|
||||
#include "nsITransferable.idl"
|
||||
#include "nsIDragTracker.idl"
|
||||
|
||||
|
||||
%{ C++
|
||||
#include "nsSize.h"
|
||||
@ -72,6 +74,22 @@ interface nsIDragSession : nsISupports
|
||||
*/
|
||||
boolean isDataFlavorSupported ( in string aDataFlavor ) ;
|
||||
|
||||
/**
|
||||
* Tell the session who needs to know when the drag completes so that it can
|
||||
* stop tracking the mouse. There can be only one object tracking the drag at
|
||||
* a time.
|
||||
*
|
||||
* @param aTracker - object who needs to know when tracking
|
||||
* should cease.
|
||||
*/
|
||||
void startTracking ( in nsIDragTracker aScroller );
|
||||
|
||||
/**
|
||||
* Call to tell the object that is tracking the drag that it
|
||||
* can forget about it (mouse left the window or the drop completed).
|
||||
*/
|
||||
void stopTracking ( ) ;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -167,6 +167,12 @@ nsMacWindow :: DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr t
|
||||
|
||||
case kDragTrackingLeaveWindow:
|
||||
{
|
||||
// stop any drag tracking in this window
|
||||
nsCOMPtr<nsIDragSession> session;
|
||||
sDragService->GetCurrentSession ( getter_AddRefs(session) );
|
||||
if ( session )
|
||||
session->StopTracking();
|
||||
|
||||
// tell the drag service that we're done with it.
|
||||
if ( sDragService ) {
|
||||
sDragService->EndDragSession();
|
||||
@ -177,10 +183,9 @@ nsMacWindow :: DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr t
|
||||
// was in our window.
|
||||
nsCOMPtr<nsIDragSessionMac> macSession ( do_QueryInterface(sDragService) );
|
||||
if ( macSession )
|
||||
macSession->SetDragReference ( 0 );
|
||||
|
||||
}
|
||||
|
||||
macSession->SetDragReference ( 0 );
|
||||
}
|
||||
|
||||
// let gecko know that the mouse has left the window so it
|
||||
// can stop tracking and sending enter/exit events to frames.
|
||||
Point mouseLocGlobal;
|
||||
@ -217,7 +222,7 @@ nsMacWindow :: DragReceiveHandler (WindowPtr theWindow, void *handlerRefCon,
|
||||
|
||||
OSErr result = noErr;
|
||||
printf("DragReceiveHandler called. We got a drop!!!!, DragRef is %ld\n", theDragRef);
|
||||
|
||||
|
||||
// pass the drop event along to Gecko
|
||||
Point mouseLocGlobal;
|
||||
::GetDragMouse ( theDragRef, &mouseLocGlobal, nsnull );
|
||||
@ -227,26 +232,24 @@ nsMacWindow :: DragReceiveHandler (WindowPtr theWindow, void *handlerRefCon,
|
||||
|
||||
// once the event has gone to gecko, check the "canDrop" state in the
|
||||
// drag session to see what we should return to the OS (drag accepted or not).
|
||||
nsIDragService* dragService;
|
||||
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
|
||||
NS_GET_IID(nsIDragService),
|
||||
(nsISupports **)&dragService);
|
||||
if ( NS_SUCCEEDED(rv) && dragService ) {
|
||||
nsCOMPtr<nsIDragService> dragService ( do_GetService(kCDragServiceCID) );
|
||||
if ( dragService ) {
|
||||
nsCOMPtr<nsIDragSession> dragSession;
|
||||
dragService->GetCurrentSession ( getter_AddRefs(dragSession) );
|
||||
if ( dragSession ) {
|
||||
// stop any drag tracking in this window
|
||||
dragSession->StopTracking();
|
||||
|
||||
// fail if the target has set that it can't accept the drag
|
||||
PRBool canDrop = PR_FALSE;
|
||||
if ( NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) )
|
||||
if ( canDrop == PR_FALSE )
|
||||
result = dragNotAcceptedErr;
|
||||
}
|
||||
|
||||
|
||||
// we don't need the drag session anymore, the user has released the
|
||||
// mouse and the event has already gone to gecko.
|
||||
dragService->EndDragSession();
|
||||
|
||||
nsServiceManager::ReleaseService(kCDragServiceCID, dragService);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -178,3 +178,26 @@ NS_IMETHODIMP nsBaseDragService::EndDragSession ()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseDragService :: StartTracking ( nsIDragTracker *aScroller )
|
||||
{
|
||||
StopTracking();
|
||||
mCurrentlyTracking = aScroller;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseDragService :: StopTracking()
|
||||
{
|
||||
if ( mCurrentlyTracking ) {
|
||||
mCurrentlyTracking->StopTracking();
|
||||
mCurrentlyTracking = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
} // StopTracking
|
||||
|
||||
|
@ -53,7 +53,9 @@ protected:
|
||||
PRBool mCanDrop;
|
||||
PRBool mDoingDrag;
|
||||
nsSize mTargetSize;
|
||||
PRUint32 mDragAction;
|
||||
PRUint32 mDragAction;
|
||||
nsCOMPtr<nsIDragTracker> mCurrentlyTracking;
|
||||
|
||||
};
|
||||
|
||||
#endif // nsBaseDragService_h__
|
||||
|
Loading…
Reference in New Issue
Block a user