From fd468cfbd4df1e4c5fd49139c3c97e645baadf57 Mon Sep 17 00:00:00 2001 From: "kmcclusk%netscape.com" Date: Fri, 28 May 1999 21:12:09 +0000 Subject: [PATCH] fix for bug #6971. Added support for clicking and dragging over items in single and multiselect listboxes. Also supports holding down the shift and ctrl keys while dragging. --- layout/forms/nsListControlFrame.cpp | 53 ++++++++++++++++++-- layout/forms/nsListControlFrame.h | 6 +++ layout/html/forms/src/nsListControlFrame.cpp | 53 ++++++++++++++++++-- layout/html/forms/src/nsListControlFrame.h | 6 +++ 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 39962232e8a..5402b62d152 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -81,6 +81,8 @@ nsListControlFrame::nsListControlFrame() mComboboxFrame = nsnull; mFormFrame = nsnull; mDisplayed = PR_FALSE; + mButtonDown = PR_FALSE; + mLastFrame = nsnull; } //---------------------------------------------------------------------- @@ -642,7 +644,7 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) { mSelectedIndex = (PRInt32)GetSelectedIndex(mHitFrame); if (kNothingSelected != mSelectedIndex) { - if (aIsShift) { + if ((aIsShift) || (mButtonDown && (!aIsControl))) { // Shift is held down SetFrameSelected(mSelectedIndex, PR_TRUE); if (mEndExtendedIndex == kNothingSelected) { @@ -694,17 +696,57 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) } +void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) +{ + if (mMultipleSelections) { + MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); + } else { + SingleSelection(); + } +} + +PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) +{ + // Quick check, if the frames are equal they must have + // the same content + if (aFrame1 == aFrame2) + return PR_TRUE; + + PRBool result = PR_FALSE; + nsIContent* content1 = nsnull; + nsIContent* content2 = nsnull; + aFrame1->GetContent(&content1); + aFrame2->GetContent(&content2); + if (aFrame1 == aFrame2) { + result = PR_TRUE; + } + + NS_IF_RELEASE(content1); + NS_IF_RELEASE(content2); + return(result); +} + + //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - if (mMultipleSelections) { - MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); - } else { - SingleSelection(); + HandleListSelection(aPresContext, aEvent, aEventStatus); + mButtonDown = PR_TRUE; + CaptureMouseEvents(PR_TRUE); + mLastFrame = mHitFrame; + } else if (aEvent->message == NS_MOUSE_MOVE) { + if ((PR_TRUE == mButtonDown) && (! HasSameContent(mLastFrame, mHitFrame))) { + HandleListSelection(aPresContext, aEvent, aEventStatus); + mLastFrame = mHitFrame; } + } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { + mButtonDown = PR_FALSE; + CaptureMouseEvents(PR_FALSE); } aEventStatus = nsEventStatus_eConsumeNoDefault; @@ -1409,6 +1451,7 @@ nsListControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) return NS_OK; } + // Create a Borderless top level widget for drop-down lists. nsresult nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* aPosition) { diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 393ae7b137b..cd5a4f297d6 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -161,6 +161,10 @@ protected: NS_IMETHOD HandleLikeDropDownListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); + PRBool HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2); + void HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus); NS_IMETHOD HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); @@ -180,6 +184,8 @@ protected: nsIFrame* mContentFrame; nsIComboboxControlFrame *mComboboxFrame; PRBool mDisplayed; + PRBool mButtonDown; + nsIFrame* mLastFrame; }; #endif /* nsListControlFrame_h___ */ diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index 39962232e8a..5402b62d152 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -81,6 +81,8 @@ nsListControlFrame::nsListControlFrame() mComboboxFrame = nsnull; mFormFrame = nsnull; mDisplayed = PR_FALSE; + mButtonDown = PR_FALSE; + mLastFrame = nsnull; } //---------------------------------------------------------------------- @@ -642,7 +644,7 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) { mSelectedIndex = (PRInt32)GetSelectedIndex(mHitFrame); if (kNothingSelected != mSelectedIndex) { - if (aIsShift) { + if ((aIsShift) || (mButtonDown && (!aIsControl))) { // Shift is held down SetFrameSelected(mSelectedIndex, PR_TRUE); if (mEndExtendedIndex == kNothingSelected) { @@ -694,17 +696,57 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) } +void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) +{ + if (mMultipleSelections) { + MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); + } else { + SingleSelection(); + } +} + +PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) +{ + // Quick check, if the frames are equal they must have + // the same content + if (aFrame1 == aFrame2) + return PR_TRUE; + + PRBool result = PR_FALSE; + nsIContent* content1 = nsnull; + nsIContent* content2 = nsnull; + aFrame1->GetContent(&content1); + aFrame2->GetContent(&content2); + if (aFrame1 == aFrame2) { + result = PR_TRUE; + } + + NS_IF_RELEASE(content1); + NS_IF_RELEASE(content2); + return(result); +} + + //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - if (mMultipleSelections) { - MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); - } else { - SingleSelection(); + HandleListSelection(aPresContext, aEvent, aEventStatus); + mButtonDown = PR_TRUE; + CaptureMouseEvents(PR_TRUE); + mLastFrame = mHitFrame; + } else if (aEvent->message == NS_MOUSE_MOVE) { + if ((PR_TRUE == mButtonDown) && (! HasSameContent(mLastFrame, mHitFrame))) { + HandleListSelection(aPresContext, aEvent, aEventStatus); + mLastFrame = mHitFrame; } + } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { + mButtonDown = PR_FALSE; + CaptureMouseEvents(PR_FALSE); } aEventStatus = nsEventStatus_eConsumeNoDefault; @@ -1409,6 +1451,7 @@ nsListControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) return NS_OK; } + // Create a Borderless top level widget for drop-down lists. nsresult nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* aPosition) { diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index 393ae7b137b..cd5a4f297d6 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -161,6 +161,10 @@ protected: NS_IMETHOD HandleLikeDropDownListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); + PRBool HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2); + void HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus); NS_IMETHOD HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); @@ -180,6 +184,8 @@ protected: nsIFrame* mContentFrame; nsIComboboxControlFrame *mComboboxFrame; PRBool mDisplayed; + PRBool mButtonDown; + nsIFrame* mLastFrame; }; #endif /* nsListControlFrame_h___ */