mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 957445: Part 1 - Scrolling moved from nsScrollbarButtonFrame and nsSliderFrame into nsIScrollbarMediator, r=mats
This commit is contained in:
parent
edcad2a7e9
commit
43c4d9fdf2
@ -7,6 +7,7 @@
|
||||
#define nsIScrollbarMediator_h___
|
||||
|
||||
#include "nsQueryFrame.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
class nsScrollbarFrame;
|
||||
|
||||
@ -15,11 +16,35 @@ class nsIScrollbarMediator
|
||||
public:
|
||||
NS_DECL_QUERYFRAME_TARGET(nsIScrollbarMediator)
|
||||
|
||||
// The aScrollbar argument denotes the scrollbar that's firing the notification.
|
||||
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) = 0;
|
||||
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) = 0;
|
||||
/**
|
||||
* The aScrollbar argument denotes the scrollbar that's firing the notification.
|
||||
* aScrollbar is never null.
|
||||
* aDirection is either -1, 0, or 1.
|
||||
*/
|
||||
|
||||
NS_IMETHOD VisibilityChanged(bool aVisible) = 0;
|
||||
/**
|
||||
* One of the following three methods is called when the scrollbar's button is
|
||||
* clicked.
|
||||
* @note These methods might destroy the frame, pres shell, and other objects.
|
||||
*/
|
||||
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
|
||||
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
|
||||
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) = 0;
|
||||
/**
|
||||
* RepeatButtonScroll is called when the scrollbar's button is held down. When the
|
||||
* button is first clicked the increment is set; RepeatButtonScroll adds this
|
||||
* increment to the current position.
|
||||
* @note This method might destroy the frame, pres shell, and other objects.
|
||||
*/
|
||||
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) = 0;
|
||||
/**
|
||||
* aOldPos and aNewPos are scroll positions.
|
||||
* @note This method might destroy the frame, pres shell, and other objects.
|
||||
*/
|
||||
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
nscoord aOldPos,
|
||||
nscoord aNewPos) = 0;
|
||||
virtual void VisibilityChanged(bool aVisible) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -324,16 +324,56 @@ nsListBoxBodyFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
|
||||
|
||||
///////////// nsIScrollbarMediator ///////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex)
|
||||
void
|
||||
nsListBoxBodyFrame::ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
UpdateIndex(aDirection);
|
||||
aScrollbar->SetIncrementToPage(aDirection);
|
||||
aScrollbar->MoveToNewPosition();
|
||||
}
|
||||
|
||||
void
|
||||
nsListBoxBodyFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
UpdateIndex(aDirection);
|
||||
aScrollbar->SetIncrementToWhole(aDirection);
|
||||
aScrollbar->MoveToNewPosition();
|
||||
}
|
||||
|
||||
void
|
||||
nsListBoxBodyFrame::ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
UpdateIndex(aDirection);
|
||||
aScrollbar->SetIncrementToLine(aDirection);
|
||||
aScrollbar->MoveToNewPosition();
|
||||
}
|
||||
|
||||
void
|
||||
nsListBoxBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar)
|
||||
{
|
||||
int32_t increment = aScrollbar->GetIncrement();
|
||||
if (increment < 0) {
|
||||
UpdateIndex(-1);
|
||||
} else if (increment > 0) {
|
||||
UpdateIndex(1);
|
||||
}
|
||||
aScrollbar->MoveToNewPosition();
|
||||
}
|
||||
|
||||
void
|
||||
nsListBoxBodyFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
nscoord aOldPos,
|
||||
nscoord aNewPos)
|
||||
{
|
||||
if (mScrolling || mRowHeight == 0)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
nscoord oldTwipIndex, newTwipIndex;
|
||||
nscoord oldTwipIndex;
|
||||
oldTwipIndex = mCurrentIndex*mRowHeight;
|
||||
newTwipIndex = nsPresContext::CSSPixelsToAppUnits(aNewIndex);
|
||||
int32_t twipDelta = newTwipIndex > oldTwipIndex ? newTwipIndex - oldTwipIndex : oldTwipIndex - newTwipIndex;
|
||||
int32_t twipDelta = aNewPos > oldTwipIndex ? aNewPos - oldTwipIndex : oldTwipIndex - aNewPos;
|
||||
|
||||
int32_t rowDelta = twipDelta / mRowHeight;
|
||||
int32_t remainder = twipDelta % mRowHeight;
|
||||
@ -341,11 +381,11 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
|
||||
rowDelta++;
|
||||
|
||||
if (rowDelta == 0)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
// update the position to be row based.
|
||||
|
||||
int32_t newIndex = newTwipIndex > oldTwipIndex ? mCurrentIndex + rowDelta : mCurrentIndex - rowDelta;
|
||||
int32_t newIndex = aNewPos > oldTwipIndex ? mCurrentIndex + rowDelta : mCurrentIndex - rowDelta;
|
||||
//aNewIndex = newIndex*mRowHeight/mOnePixel;
|
||||
|
||||
nsListScrollSmoother* smoother = GetSmoother();
|
||||
@ -356,11 +396,11 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
|
||||
|
||||
smoother->Stop();
|
||||
|
||||
smoother->mDelta = newTwipIndex > oldTwipIndex ? rowDelta : -rowDelta;
|
||||
smoother->mDelta = aNewPos > oldTwipIndex ? rowDelta : -rowDelta;
|
||||
|
||||
smoother->Start();
|
||||
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
smoother->Stop();
|
||||
@ -370,17 +410,16 @@ nsListBoxBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIn
|
||||
|
||||
if (mCurrentIndex < 0) {
|
||||
mCurrentIndex = 0;
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
return InternalPositionChanged(newTwipIndex < oldTwipIndex, rowDelta);
|
||||
InternalPositionChanged(aNewPos < oldTwipIndex, rowDelta);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsListBoxBodyFrame::VisibilityChanged(bool aVisible)
|
||||
{
|
||||
if (mRowHeight == 0)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
int32_t lastPageTopRow = GetRowCount() - (GetAvailableHeight() / mRowHeight);
|
||||
if (lastPageTopRow < 0)
|
||||
@ -390,27 +429,23 @@ nsListBoxBodyFrame::VisibilityChanged(bool aVisible)
|
||||
mCurrentIndex = lastPageTopRow;
|
||||
InternalPositionChanged(true, delta);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsListBoxBodyFrame::ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex)
|
||||
void
|
||||
nsListBoxBodyFrame::UpdateIndex(int32_t aDirection)
|
||||
{
|
||||
if (aOldIndex == aNewIndex)
|
||||
return NS_OK;
|
||||
if (aNewIndex < aOldIndex)
|
||||
if (aDirection == 0)
|
||||
return;
|
||||
if (aDirection < 0)
|
||||
mCurrentIndex--;
|
||||
else mCurrentIndex++;
|
||||
if (mCurrentIndex < 0) {
|
||||
mCurrentIndex = 0;
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
InternalPositionChanged(aNewIndex < aOldIndex, 1);
|
||||
|
||||
return NS_OK;
|
||||
InternalPositionChanged(aDirection < 0, 1);
|
||||
}
|
||||
|
||||
|
||||
///////////// nsIReflowCallback ///////////////
|
||||
|
||||
bool
|
||||
|
@ -56,9 +56,15 @@ public:
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE;
|
||||
|
||||
// nsIScrollbarMediator
|
||||
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE;
|
||||
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
|
||||
NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE;
|
||||
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) MOZ_OVERRIDE;
|
||||
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
int32_t aOldPos,
|
||||
int32_t aNewPos) MOZ_OVERRIDE;
|
||||
virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE;
|
||||
|
||||
|
||||
// nsIReflowCallback
|
||||
virtual bool ReflowFinished() MOZ_OVERRIDE;
|
||||
@ -89,6 +95,7 @@ public:
|
||||
nsresult DoInternalPositionChanged(bool aUp, int32_t aDelta);
|
||||
nsListScrollSmoother* GetSmoother();
|
||||
void VerticalScroll(int32_t aDelta);
|
||||
void UpdateIndex(int32_t aDirection);
|
||||
|
||||
// frames
|
||||
nsIFrame* GetFirstFrame();
|
||||
|
@ -78,7 +78,6 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
|
||||
WidgetGUIEvent* aEvent,
|
||||
@ -109,10 +108,7 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
|
||||
|
||||
if (scrollbar == nullptr)
|
||||
return false;
|
||||
|
||||
// get the scrollbars content node
|
||||
nsIContent* content = scrollbar->GetContent();
|
||||
|
||||
|
||||
static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment,
|
||||
&nsGkAtoms::decrement,
|
||||
nullptr };
|
||||
@ -120,51 +116,65 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
|
||||
nsGkAtoms::type,
|
||||
strings, eCaseMatters);
|
||||
int32_t direction;
|
||||
if (index == 0)
|
||||
if (index == 0)
|
||||
direction = 1;
|
||||
else if (index == 1)
|
||||
direction = -1;
|
||||
else
|
||||
return false;
|
||||
|
||||
// Whether or not to repeat the click action.
|
||||
bool repeat = true;
|
||||
// Use smooth scrolling by default.
|
||||
bool smoothScroll = true;
|
||||
switch (pressedButtonAction) {
|
||||
case 0:
|
||||
mIncrement = direction * nsSliderFrame::GetIncrement(content);
|
||||
break;
|
||||
case 1:
|
||||
mIncrement = direction * nsSliderFrame::GetPageIncrement(content);
|
||||
break;
|
||||
case 2:
|
||||
if (direction == -1)
|
||||
mIncrement = -nsSliderFrame::GetCurrentPosition(content);
|
||||
else
|
||||
mIncrement = nsSliderFrame::GetMaxPosition(content) -
|
||||
nsSliderFrame::GetCurrentPosition(content);
|
||||
// Don't repeat or use smooth scrolling if scrolling to beginning or end
|
||||
// of a page.
|
||||
repeat = smoothScroll = false;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
// We were told to ignore this click, or someone assigned a non-standard
|
||||
// value to the button's action.
|
||||
return false;
|
||||
}
|
||||
bool repeat = pressedButtonAction != 2;
|
||||
// set this attribute so we can style it later
|
||||
nsWeakFrame weakFrame(this);
|
||||
mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true);
|
||||
|
||||
nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED);
|
||||
|
||||
if (weakFrame.IsAlive()) {
|
||||
DoButtonAction(smoothScroll);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return false;
|
||||
}
|
||||
if (repeat)
|
||||
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
switch (pressedButtonAction) {
|
||||
case 0:
|
||||
sb->SetIncrementToLine(direction);
|
||||
if (m) {
|
||||
m->ScrollByLine(sb, direction);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
sb->SetIncrementToPage(direction);
|
||||
if (m) {
|
||||
m->ScrollByPage(sb, direction);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
sb->SetIncrementToWhole(direction);
|
||||
if (m) {
|
||||
m->ScrollByWhole(sb, direction);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
// We were told to ignore this click, or someone assigned a non-standard
|
||||
// value to the button's action.
|
||||
return false;
|
||||
}
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return false;
|
||||
}
|
||||
if (!m) {
|
||||
sb->MoveToNewPosition();
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (repeat) {
|
||||
StartRepeat();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -182,12 +192,21 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
|
||||
void nsScrollbarButtonFrame::Notify()
|
||||
{
|
||||
// Since this is only going to get called if we're scrolling a page length
|
||||
// or a line increment, we will always use smooth scrolling.
|
||||
if (mCursorOnThis ||
|
||||
LookAndFeel::GetInt(
|
||||
LookAndFeel::eIntID_ScrollbarButtonAutoRepeatBehavior, 0)) {
|
||||
DoButtonAction(true);
|
||||
// get the scrollbar control
|
||||
nsIFrame* scrollbar;
|
||||
GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
if (m) {
|
||||
m->RepeatButtonScroll(sb);
|
||||
} else {
|
||||
sb->MoveToNewPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,56 +218,6 @@ nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext,
|
||||
//MouseClicked();
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarButtonFrame::DoButtonAction(bool aSmoothScroll)
|
||||
{
|
||||
// get the scrollbar control
|
||||
nsIFrame* scrollbar;
|
||||
GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
|
||||
|
||||
if (scrollbar == nullptr)
|
||||
return;
|
||||
|
||||
// get the scrollbars content node
|
||||
nsCOMPtr<nsIContent> content = scrollbar->GetContent();
|
||||
|
||||
// get the current pos
|
||||
int32_t curpos = nsSliderFrame::GetCurrentPosition(content);
|
||||
int32_t oldpos = curpos;
|
||||
|
||||
// get the max pos
|
||||
int32_t maxpos = nsSliderFrame::GetMaxPosition(content);
|
||||
|
||||
// increment the given amount
|
||||
if (mIncrement)
|
||||
curpos += mIncrement;
|
||||
|
||||
// make sure the current position is between the current and max positions
|
||||
if (curpos < 0)
|
||||
curpos = 0;
|
||||
else if (curpos > maxpos)
|
||||
curpos = maxpos;
|
||||
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
if (m) {
|
||||
m->ScrollbarButtonPressed(sb, oldpos, curpos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set the current position of the slider.
|
||||
nsAutoString curposStr;
|
||||
curposStr.AppendInt(curpos);
|
||||
|
||||
if (aSmoothScroll)
|
||||
content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
|
||||
content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, true);
|
||||
if (aSmoothScroll)
|
||||
content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScrollbarButtonFrame::GetChildWithTag(nsPresContext* aPresContext,
|
||||
nsIAtom* atom, nsIFrame* start,
|
||||
|
@ -67,7 +67,6 @@ public:
|
||||
protected:
|
||||
virtual void MouseClicked(nsPresContext* aPresContext,
|
||||
mozilla::WidgetGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||
void DoButtonAction(bool aSmoothScroll);
|
||||
|
||||
void StartRepeat() {
|
||||
nsRepeatService::GetInstance()->Start(Notify, this);
|
||||
@ -80,7 +79,6 @@ protected:
|
||||
static_cast<nsScrollbarButtonFrame*>(aData)->Notify();
|
||||
}
|
||||
|
||||
int32_t mIncrement;
|
||||
bool mCursorOnThis;
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
|
||||
#include "nsScrollbarFrame.h"
|
||||
#include "nsSliderFrame.h"
|
||||
#include "nsScrollbarButtonFrame.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
@ -19,6 +20,7 @@
|
||||
#include "nsThemeConstants.h"
|
||||
#include "nsRenderingContext.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -186,3 +188,103 @@ nsScrollbarFrame::GetMargin(nsMargin& aMargin)
|
||||
|
||||
return nsBox::GetMargin(aMargin);
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::SetIncrementToLine(int32_t aDirection)
|
||||
{
|
||||
// get the scrollbar's content node
|
||||
nsIContent* content = GetContent();
|
||||
mSmoothScroll = true;
|
||||
mIncrement = aDirection * nsSliderFrame::GetIncrement(content);
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::SetIncrementToPage(int32_t aDirection)
|
||||
{
|
||||
// get the scrollbar's content node
|
||||
nsIContent* content = GetContent();
|
||||
mSmoothScroll = true;
|
||||
mIncrement = aDirection * nsSliderFrame::GetPageIncrement(content);
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarFrame::SetIncrementToWhole(int32_t aDirection)
|
||||
{
|
||||
// get the scrollbar's content node
|
||||
nsIContent* content = GetContent();
|
||||
if (aDirection == -1)
|
||||
mIncrement = -nsSliderFrame::GetCurrentPosition(content);
|
||||
else
|
||||
mIncrement = nsSliderFrame::GetMaxPosition(content) -
|
||||
nsSliderFrame::GetCurrentPosition(content);
|
||||
// Don't repeat or use smooth scrolling if scrolling to beginning or end
|
||||
// of a page.
|
||||
mSmoothScroll = false;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsScrollbarFrame::MoveToNewPosition()
|
||||
{
|
||||
// get the scrollbar's content node
|
||||
nsCOMPtr<nsIContent> content = GetContent();
|
||||
|
||||
// get the current pos
|
||||
int32_t curpos = nsSliderFrame::GetCurrentPosition(content);
|
||||
|
||||
// get the max pos
|
||||
int32_t maxpos = nsSliderFrame::GetMaxPosition(content);
|
||||
|
||||
// increment the given amount
|
||||
if (mIncrement) {
|
||||
curpos += mIncrement;
|
||||
}
|
||||
|
||||
// make sure the current position is between the current and max positions
|
||||
if (curpos < 0) {
|
||||
curpos = 0;
|
||||
} else if (curpos > maxpos) {
|
||||
curpos = maxpos;
|
||||
}
|
||||
|
||||
// set the current position of the slider.
|
||||
nsAutoString curposStr;
|
||||
curposStr.AppendInt(curpos);
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
if (mSmoothScroll) {
|
||||
content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
|
||||
}
|
||||
content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, false);
|
||||
// notify the nsScrollbarFrame of the change
|
||||
AttributeChanged(kNameSpaceID_None, nsGkAtoms::curpos, nsIDOMMutationEvent::MODIFICATION);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return curpos;
|
||||
}
|
||||
// notify all nsSliderFrames of the change
|
||||
nsIFrame::ChildListIterator childLists(this);
|
||||
for (; !childLists.IsDone(); childLists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(childLists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
nsIFrame* f = childFrames.get();
|
||||
nsSliderFrame* sliderFrame = do_QueryFrame(f);
|
||||
if (sliderFrame) {
|
||||
sliderFrame->AttributeChanged(kNameSpaceID_None, nsGkAtoms::curpos, nsIDOMMutationEvent::MODIFICATION);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return curpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// See if we have appearance information for a theme.
|
||||
const nsStyleDisplay* disp = StyleDisplay();
|
||||
nsPresContext* presContext = PresContext();
|
||||
if (disp->mAppearance) {
|
||||
nsITheme *theme = presContext->GetTheme();
|
||||
if (theme && theme->ThemeSupportsWidget(presContext, this, disp->mAppearance)) {
|
||||
bool repaint;
|
||||
theme->WidgetStateChanged(this, disp->mAppearance, nsGkAtoms::curpos, &repaint);
|
||||
}
|
||||
}
|
||||
content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
|
||||
return curpos;
|
||||
}
|
||||
|
@ -83,6 +83,25 @@ public:
|
||||
|
||||
virtual nsresult GetMargin(nsMargin& aMargin) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* The following three methods set the value of mIncrement when a
|
||||
* scrollbar button is pressed.
|
||||
*/
|
||||
void SetIncrementToLine(int32_t aDirection);
|
||||
void SetIncrementToPage(int32_t aDirection);
|
||||
void SetIncrementToWhole(int32_t aDirection);
|
||||
/**
|
||||
* MoveToNewPosition() adds mIncrement to the current position and
|
||||
* updates the curpos attribute.
|
||||
* @note This method might destroy the frame, pres shell, and other objects.
|
||||
*/
|
||||
int32_t MoveToNewPosition();
|
||||
int32_t GetIncrement() { return mIncrement; }
|
||||
|
||||
protected:
|
||||
int32_t mIncrement; // Amount to scroll, in CSSPixels
|
||||
bool mSmoothScroll;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mScrollbarMediator;
|
||||
}; // class nsScrollbarFrame
|
||||
|
@ -60,6 +60,10 @@ NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsSliderFrame)
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsSliderFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsSliderFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext):
|
||||
nsBoxFrame(aPresShell, aContext),
|
||||
mCurPos(0),
|
||||
@ -245,19 +249,25 @@ nsSliderFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
|
||||
if (current < min || current > max)
|
||||
{
|
||||
if (current < min || max < min)
|
||||
current = min;
|
||||
else if (current > max)
|
||||
current = max;
|
||||
int32_t direction = 0;
|
||||
if (current < min || max < min) {
|
||||
current = min;
|
||||
direction = -1;
|
||||
} else if (current > max) {
|
||||
current = max;
|
||||
direction = 1;
|
||||
}
|
||||
|
||||
// set the new position and notify observers
|
||||
nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
|
||||
if (scrollbarFrame) {
|
||||
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
|
||||
scrollbarFrame->SetIncrementToWhole(direction);
|
||||
if (mediator) {
|
||||
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), current);
|
||||
mediator->ScrollByWhole(scrollbarFrame, direction);
|
||||
}
|
||||
}
|
||||
// 'this' might be destroyed here
|
||||
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new nsSetAttrRunnable(scrollbar, nsGkAtoms::curpos, current));
|
||||
@ -619,10 +629,6 @@ nsSliderFrame::PageUpDown(nscoord change)
|
||||
nsCOMPtr<nsIContent> scrollbar;
|
||||
scrollbar = GetContentOfBox(scrollbarBox);
|
||||
|
||||
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
|
||||
nsGkAtoms::reverse, eCaseMatters))
|
||||
change = -change;
|
||||
|
||||
nscoord pageIncrement = GetPageIncrement(scrollbar);
|
||||
int32_t curpos = GetCurrentPosition(scrollbar);
|
||||
int32_t minpos = GetMinPosition(scrollbar);
|
||||
@ -776,6 +782,7 @@ nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t aNewPo
|
||||
{
|
||||
nsCOMPtr<nsIContent> scrollbar = aScrollbar;
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
mUserChanged = true;
|
||||
|
||||
@ -784,21 +791,23 @@ nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar, int32_t aNewPo
|
||||
// See if we have a mediator.
|
||||
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
|
||||
if (mediator) {
|
||||
nsRefPtr<nsPresContext> context = PresContext();
|
||||
nsCOMPtr<nsIContent> content = GetContent();
|
||||
mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), aNewPos);
|
||||
// 'mediator' might be dangling now...
|
||||
UpdateAttribute(scrollbar, aNewPos, false, aIsSmooth);
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
if (frame && frame->GetType() == nsGkAtoms::sliderFrame) {
|
||||
static_cast<nsSliderFrame*>(frame)->CurrentPositionChanged();
|
||||
nscoord oldPos = nsPresContext::CSSPixelsToAppUnits(GetCurrentPosition(scrollbar));
|
||||
nscoord newPos = nsPresContext::CSSPixelsToAppUnits(aNewPos);
|
||||
mediator->ThumbMoved(scrollbarFrame, oldPos, newPos);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
CurrentPositionChanged();
|
||||
mUserChanged = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAttribute(scrollbar, aNewPos, true, aIsSmooth);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
mUserChanged = false;
|
||||
|
||||
#ifdef DEBUG_SLIDER
|
||||
@ -1124,7 +1133,8 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext,
|
||||
mDestinationPoint = eventPoint;
|
||||
#endif
|
||||
StartRepeat();
|
||||
PageUpDown(change);
|
||||
PageScroll(change);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1188,7 +1198,8 @@ nsSliderFrame::EnsureOrient()
|
||||
}
|
||||
|
||||
|
||||
void nsSliderFrame::Notify(void)
|
||||
void
|
||||
nsSliderFrame::Notify(void)
|
||||
{
|
||||
bool stop = false;
|
||||
|
||||
@ -1225,9 +1236,29 @@ void nsSliderFrame::Notify(void)
|
||||
if (stop) {
|
||||
StopRepeat();
|
||||
} else {
|
||||
PageUpDown(mChange);
|
||||
PageScroll(mChange);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSliderFrame::PageScroll(nscoord aChange)
|
||||
{
|
||||
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
|
||||
nsGkAtoms::reverse, eCaseMatters)) {
|
||||
aChange = -aChange;
|
||||
}
|
||||
nsIFrame* scrollbar = GetScrollbar();
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
sb->SetIncrementToPage(aChange);
|
||||
if (m) {
|
||||
m->ScrollByPage(sb, aChange);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PageUpDown(aChange);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsSliderMediator,
|
||||
nsIDOMEventListener)
|
||||
|
@ -42,6 +42,8 @@ class nsSliderFrame : public nsBoxFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsSliderFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
friend class nsSliderMediator;
|
||||
|
||||
@ -161,6 +163,7 @@ private:
|
||||
static void Notify(void* aData) {
|
||||
(static_cast<nsSliderFrame*>(aData))->Notify();
|
||||
}
|
||||
void PageScroll(nscoord aChange);
|
||||
|
||||
nsPoint mDestinationPoint;
|
||||
nsRefPtr<nsSliderMediator> mMediator;
|
||||
|
@ -4155,48 +4155,85 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, int32_t aPosition
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeBodyFrame::ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex)
|
||||
void
|
||||
nsTreeBodyFrame::ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
ScrollByPages(aDirection);
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
int32_t newIndex = aDirection < 0 ? 0 : mTopRowIndex;
|
||||
ScrollToRow(newIndex);
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection)
|
||||
{
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
ScrollByLines(aDirection);
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar)
|
||||
{
|
||||
ScrollParts parts = GetScrollParts();
|
||||
int32_t increment = aScrollbar->GetIncrement();
|
||||
int32_t direction = 0;
|
||||
if (increment < 0) {
|
||||
direction = -1;
|
||||
} else if (increment > 0) {
|
||||
direction = 1;
|
||||
}
|
||||
bool isHorizontal = aScrollbar->IsHorizontal();
|
||||
|
||||
if (aScrollbar == parts.mVScrollbar) {
|
||||
if (aNewIndex > aOldIndex)
|
||||
ScrollToRowInternal(parts, mTopRowIndex+1);
|
||||
else if (aNewIndex < aOldIndex)
|
||||
ScrollToRowInternal(parts, mTopRowIndex-1);
|
||||
nsWeakFrame weakFrame(this);
|
||||
if (isHorizontal) {
|
||||
int32_t curpos = aScrollbar->MoveToNewPosition();
|
||||
if (weakFrame.IsAlive()) {
|
||||
ScrollHorzInternal(parts, curpos);
|
||||
}
|
||||
} else {
|
||||
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
ScrollToRowInternal(parts, mTopRowIndex+direction);
|
||||
}
|
||||
|
||||
UpdateScrollbars(parts);
|
||||
|
||||
return NS_OK;
|
||||
if (weakFrame.IsAlive() && mScrollbarActivity) {
|
||||
mScrollbarActivity->ActivityOccurred();
|
||||
}
|
||||
if (weakFrame.IsAlive()) {
|
||||
UpdateScrollbars(parts);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeBodyFrame::PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex)
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
nscoord aOldPos,
|
||||
nscoord aNewPos)
|
||||
{
|
||||
ScrollParts parts = GetScrollParts();
|
||||
|
||||
if (aOldIndex == aNewIndex)
|
||||
return NS_OK;
|
||||
if (aOldPos == aNewPos)
|
||||
return;
|
||||
|
||||
nsWeakFrame weakFrame(this);
|
||||
|
||||
// Vertical Scrollbar
|
||||
if (parts.mVScrollbar == aScrollbar) {
|
||||
nscoord rh = nsPresContext::AppUnitsToIntCSSPixels(mRowHeight);
|
||||
|
||||
nscoord newrow = aNewIndex/rh;
|
||||
nscoord newIndex = nsPresContext::AppUnitsToIntCSSPixels(aNewPos);
|
||||
nscoord newrow = newIndex/rh;
|
||||
ScrollInternal(parts, newrow);
|
||||
// Horizontal Scrollbar
|
||||
} else if (parts.mHScrollbar == aScrollbar) {
|
||||
nsresult rv = ScrollHorzInternal(parts, aNewIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
int32_t newIndex = nsPresContext::AppUnitsToIntCSSPixels(aNewPos);
|
||||
ScrollHorzInternal(parts, newIndex);
|
||||
}
|
||||
if (weakFrame.IsAlive()) {
|
||||
UpdateScrollbars(parts);
|
||||
}
|
||||
|
||||
UpdateScrollbars(parts);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The style cache.
|
||||
|
@ -134,9 +134,14 @@ public:
|
||||
virtual bool PseudoMatches(nsCSSSelector* aSelector) MOZ_OVERRIDE;
|
||||
|
||||
// nsIScrollbarMediator
|
||||
NS_IMETHOD PositionChanged(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t& aNewIndex) MOZ_OVERRIDE;
|
||||
NS_IMETHOD ScrollbarButtonPressed(nsScrollbarFrame* aScrollbar, int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
|
||||
NS_IMETHOD VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); return NS_OK; }
|
||||
virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection) MOZ_OVERRIDE;
|
||||
virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) MOZ_OVERRIDE;
|
||||
virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
nscoord aOldPos,
|
||||
nscoord aNewPos) MOZ_OVERRIDE;
|
||||
virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE { Invalidate(); }
|
||||
|
||||
// nsIScrollbarOwner
|
||||
virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE {
|
||||
|
Loading…
Reference in New Issue
Block a user