gecko-dev/layout/xul/base/src/nsSliderFrame.cpp

1256 lines
35 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
1999-04-20 21:39:52 +00:00
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
1999-04-20 21:39:52 +00:00
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
1999-04-20 21:39:52 +00:00
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
2000-06-03 02:12:19 +00:00
*
* Contributor(s):
* Dean Tessman <dean_tessman@hotmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
1999-04-20 21:39:52 +00:00
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
1999-04-20 21:39:52 +00:00
1999-04-20 21:43:09 +00:00
#include "nsSliderFrame.h"
#include "nsStyleContext.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsUnitConversion.h"
1999-04-20 21:39:52 +00:00
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
#include "nsStyleChangeList.h"
#include "nsCSSRendering.h"
#include "nsHTMLAtoms.h"
#include "nsIDOMEventReceiver.h"
#include "nsIViewManager.h"
2001-10-07 06:32:36 +00:00
#include "nsIWidget.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDocument.h"
#include "nsScrollbarButtonFrame.h"
1999-06-23 17:00:17 +00:00
#include "nsIScrollbarListener.h"
2000-06-06 23:13:05 +00:00
#include "nsIScrollbarMediator.h"
#include "nsIScrollbarFrame.h"
#include "nsISupportsArray.h"
1999-08-19 22:16:23 +00:00
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsIScrollableView.h"
#include "nsRepeatService.h"
2000-03-31 07:02:06 +00:00
#include "nsBoxLayoutState.h"
#include "nsSprocketLayout.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsGUIEvent.h"
1999-08-19 22:16:23 +00:00
PRBool nsSliderFrame::gMiddlePref = PR_FALSE;
PRInt32 nsSliderFrame::gSnapMultiplier = 6;
// Turn this on if you want to debug slider frames.
#undef DEBUG_SLIDER
1999-10-12 00:16:06 +00:00
static already_AddRefed<nsIContent>
GetContentOfBox(nsIBox *aBox)
{
nsIFrame *frame;
aBox->GetFrame(&frame);
nsIContent* content = frame->GetContent();
NS_IF_ADDREF(content);
return content;
}
1999-04-20 21:39:52 +00:00
nsresult
NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame)
1999-04-20 21:39:52 +00:00
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
2000-03-31 07:02:06 +00:00
nsSliderFrame* it = new (aPresShell) nsSliderFrame(aPresShell);
if (nsnull == it)
1999-04-20 21:39:52 +00:00
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
1999-04-20 21:39:52 +00:00
return NS_OK;
} // NS_NewSliderFrame
1999-04-20 21:39:52 +00:00
2000-03-31 07:02:06 +00:00
nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell):nsBoxFrame(aPresShell),
mCurPos(0), mScrollbarListener(nsnull),mChange(0), mMediator(nsnull)
1999-04-20 21:39:52 +00:00
{
}
1999-04-20 21:39:52 +00:00
1999-08-19 22:16:23 +00:00
// stop timer
nsSliderFrame::~nsSliderFrame()
{
mRedrawImmediate = PR_FALSE;
1999-08-19 22:16:23 +00:00
}
NS_IMETHODIMP
nsSliderFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow)
1999-04-20 21:39:52 +00:00
{
2000-03-31 07:02:06 +00:00
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
static PRBool gotPrefs = PR_FALSE;
if (!gotPrefs) {
gotPrefs = PR_TRUE;
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefBranch) {
prefBranch->GetBoolPref("middlemouse.scrollbarPosition", &gMiddlePref);
prefBranch->GetIntPref("slider.snapMultiplier", &gSnapMultiplier);
}
}
CreateViewForFrame(aPresContext,this,aContext,PR_TRUE);
nsIView* view = GetView();
view->GetViewManager()->SetViewContentTransparency(view, PR_TRUE);
return rv;
1999-04-20 21:39:52 +00:00
}
NS_IMETHODIMP
nsSliderFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
nsresult rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
PRInt32 start = GetChildCount();
if (start == 0)
RemoveListener();
return rv;
}
NS_IMETHODIMP
nsSliderFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
PRInt32 start = GetChildCount();
nsresult rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
if (start == 0)
AddListener();
return rv;
}
NS_IMETHODIMP
nsSliderFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// if we have no children and on was added then make sure we add the
// listener
PRInt32 start = GetChildCount();
nsresult rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
if (start == 0)
AddListener();
return rv;
}
PRInt32
nsSliderFrame::GetCurrentPosition(nsIContent* content)
{
return GetIntegerAttribute(content, nsXULAtoms::curpos, 0);
}
PRInt32
nsSliderFrame::GetMaxPosition(nsIContent* content)
{
return GetIntegerAttribute(content, nsXULAtoms::maxpos, 100);
}
PRInt32
nsSliderFrame::GetIncrement(nsIContent* content)
{
return GetIntegerAttribute(content, nsXULAtoms::increment, 1);
}
PRInt32
nsSliderFrame::GetPageIncrement(nsIContent* content)
{
return GetIntegerAttribute(content, nsXULAtoms::pageincrement, 10);
}
PRInt32
nsSliderFrame::GetIntegerAttribute(nsIContent* content, nsIAtom* atom, PRInt32 defaultValue)
{
Landing changes Vidur made while the tree was closed for beta1 work, here's a list of the changes. r=me [1] Cutting down the size of content. Made nsIJSScriptObject inherit from nsIScriptObjectOwner [2] Cutting down the size of content. Made nsITextContent inherit from nsIContent. [3] Cutting down the size of content. Moved implementation of nsIDOMReceiver to nsListenerManager. This is not true aggregation since it isn't transitive, but it's OK for now. It will be necessary for nsListenerManager to have a reference to its content in the future anyway, so the transitivity could be done. dom/public/nsDOMPropEnums.h,v - bug 12559 dom/public/nsIJSScriptObject.h,v - [1] dom/public/html/MANIFEST,v - bug 12559 dom/public/html/Makefile.in,v - bug 12559 dom/public/html/makefile.win,v - bug 12559 dom/public/html/nsIDOMHTMLInputElement.h,v - bug 17544 dom/public/idl/html/HTMLAnchorElement.idl,v - bug 12559 dom/public/idl/html/HTMLAreaElement.idl,v - bug 12559 dom/public/idl/html/HTMLInputElement.idl,v - bug 17544 dom/src/base/nsGlobalWindow.cpp,v - bug 30700 dom/src/base/nsGlobalWindow.h,v - [1] dom/src/base/nsLocation.cpp,v - [1] dom/src/html/nsJSHTMLAnchorElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLAreaElement.cpp,v - bug 12559 dom/src/html/nsJSHTMLInputElement.cpp,v - bug 17544 layout/base/public/nsIDocument.h,v - bug 27953 layout/base/public/nsITextContent.h,v - [2] layout/base/src/nsCommentNode.cpp,v - [2] layout/base/src/nsDocument.cpp,v - bug 27953 layout/base/src/nsDocument.h,v - bug 27953 layout/base/src/nsDocumentViewer.cpp,v - bug 27953 layout/base/src/nsGenericDOMDataNode.cpp,v - [3] layout/base/src/nsGenericDOMDataNode.h,v - [3] layout/base/src/nsGenericElement.cpp,v - [3] layout/base/src/nsGenericElement.h,v - [3] layout/base/src/nsNameSpaceManager.cpp,v - bug 7834 layout/base/src/nsStyleContext.cpp,v - outline property shouldn't reflow layout/base/src/nsTextNode.cpp,v - [2] layout/events/src/nsEventListenerManager.cpp,v - [3] layout/events/src/nsEventListenerManager.h,v - [3] layout/html/base/src/nsGfxScrollFrame.cpp,v - nsString->nsAutoString layout/html/content/src/nsAttributeContent.cpp,v - [2] layout/html/content/src/nsHTMLAnchorElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAppletElement.cpp,v - [1][3] layout/html/content/src/nsHTMLAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBaseFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLBodyElement.cpp,v - [1][3] layout/html/content/src/nsHTMLButtonElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDirectoryElement.cpp,v - [1][3] layout/html/content/src/nsHTMLDivElement.cpp,v - [1][3] layout/html/content/src/nsHTMLEmbedElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFieldSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFontElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFormElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLFrameSetElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHRElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHeadingElement.cpp,v - [1][3] layout/html/content/src/nsHTMLHtmlElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIFrameElement.cpp,v - [1][3] layout/html/content/src/nsHTMLImageElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInputElement.cpp,v - [1][3] layout/html/content/src/nsHTMLInsElement.cpp,v - [1][3] layout/html/content/src/nsHTMLIsIndexElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLIElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLabelElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLayerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLegendElement.cpp,v - [1][3] layout/html/content/src/nsHTMLLinkElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMapElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMenuElement.cpp,v - [1][3] layout/html/content/src/nsHTMLMetaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLModElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLObjectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLOptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParagraphElement.cpp,v - [1][3] layout/html/content/src/nsHTMLParamElement.cpp,v - [1][3] layout/html/content/src/nsHTMLPreElement.cpp,v - [1][3] layout/html/content/src/nsHTMLQuoteElement.cpp,v - [1][3] layout/html/content/src/nsHTMLScriptElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSelectElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpacerElement.cpp,v - [1][3] layout/html/content/src/nsHTMLSpanElement.cpp,v - [1][3] layout/html/content/src/nsHTMLStyleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCaptionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableCellElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableColGroupElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableRowElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTableSectionElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTextAreaElement.cpp,v - [1][3] layout/html/content/src/nsHTMLTitleElement.cpp,v - [1][3] layout/html/content/src/nsHTMLUListElement.cpp,v - [1][3] layout/html/content/src/nsHTMLWBRElement.cpp,v - [1][3] layout/html/document/src/nsHTMLDocument.cpp,v - bug 27953 layout/html/document/src/nsHTMLDocument.h,v - bug 27953 layout/xml/content/src/nsXMLCDATASection.cpp,v - [1][2] layout/xml/content/src/nsXMLDocumentType.cpp,v - [1][2] layout/xml/content/src/nsXMLElement.h,v - [1][2] layout/xml/content/src/nsXMLEntity.cpp,v - [1][2] layout/xml/content/src/nsXMLNotation.cpp,v - [1][2] layout/xml/content/src/nsXMLProcessingInstruction.cpp,v - [1][2] layout/xul/base/src/nsBoxFrame.cpp,v - nsString->nsAutoString layout/xul/base/src/nsSliderFrame.cpp,v - nsString->nsAutoString netwerk/protocol/http/src/nsHTTPRequest.cpp,v - nsString->nsAutoString rdf/content/src/nsXULDocument.cpp,v - bug 27953 rdf/content/src/nsXULDocument.h,v - bug 27953 rdf/content/src/nsXULElement.h,v - [1] xpcom/base/IIDS.h,v - bug 12559
2000-03-17 13:27:00 +00:00
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, atom, value))
{
PRInt32 error;
// convert it to an integer
defaultValue = value.ToInteger(&error);
}
return defaultValue;
}
NS_IMETHODIMP
nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
2000-03-31 07:02:06 +00:00
nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute,
aModType);
// if the current position changes
if (aAttribute == nsXULAtoms::curpos) {
rv = CurrentPositionChanged(aPresContext);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to change position");
if (NS_FAILED(rv))
return rv;
1999-10-12 00:16:06 +00:00
} else if (aAttribute == nsXULAtoms::maxpos) {
// bounds check it.
2000-03-31 07:02:06 +00:00
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
PRInt32 current = GetCurrentPosition(scrollbar);
1999-10-12 00:16:06 +00:00
PRInt32 max = GetMaxPosition(scrollbar);
if (current < 0 || current > max)
{
2000-08-29 02:03:59 +00:00
if (current < 0)
current = 0;
else if (current > max)
2000-08-29 02:03:59 +00:00
current = max;
// set the new position and notify observers
2000-08-29 02:03:59 +00:00
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(scrollbarBox));
if (scrollbarFrame) {
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
if (mediator) {
mediator->PositionChanged(GetCurrentPosition(scrollbar), current);
}
}
nsAutoString currentStr;
currentStr.AppendInt(current);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, currentStr, PR_TRUE);
1999-10-12 00:16:06 +00:00
}
}
if (aAttribute == nsXULAtoms::maxpos ||
aAttribute == nsXULAtoms::pageincrement ||
aAttribute == nsXULAtoms::increment) {
2000-03-31 07:02:06 +00:00
nsBoxLayoutState state(aPresContext);
MarkDirtyChildren(state);
}
return rv;
}
NS_IMETHODIMP
nsSliderFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
1999-08-19 22:16:23 +00:00
// if we are too small to have a thumb don't paint it.
2000-03-31 07:02:06 +00:00
nsIBox* thumb;
GetChildBox(&thumb);
if (thumb) {
nsRect thumbRect;
thumb->GetBounds(thumbRect);
nsMargin m;
thumb->GetMargin(m);
thumbRect.Inflate(m);
2000-03-31 07:02:06 +00:00
nsRect crect;
GetClientRect(crect);
1999-08-19 22:16:23 +00:00
if (crect.width < thumbRect.width || crect.height < thumbRect.height)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
1999-08-19 22:16:23 +00:00
}
return NS_OK;
1999-08-19 22:16:23 +00:00
}
}
2000-03-31 07:02:06 +00:00
return nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
1999-04-20 21:39:52 +00:00
2000-03-31 07:02:06 +00:00
NS_IMETHODIMP
nsSliderFrame::DoLayout(nsBoxLayoutState& aState)
{
// get the thumb should be our only child
nsIBox* thumbBox = nsnull;
GetChildBox(&thumbBox);
if (!thumbBox) {
SyncLayout(aState);
return NS_OK;
}
2000-03-31 07:02:06 +00:00
EnsureOrient();
if (mState & NS_STATE_DEBUG_WAS_SET) {
if (mState & NS_STATE_SET_TO_DEBUG)
SetDebug(aState, PR_TRUE);
2000-03-31 07:02:06 +00:00
else
SetDebug(aState, PR_FALSE);
1999-04-20 21:39:52 +00:00
}
2000-03-31 07:02:06 +00:00
// get the content area inside our borders
nsRect clientRect(0,0,0,0);
GetClientRect(clientRect);
2000-03-31 07:02:06 +00:00
// get the scrollbar
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
2000-03-31 07:02:06 +00:00
// get the thumb's pref size
nsSize thumbSize(0,0);
thumbBox->GetPrefSize(aState, thumbSize);
2000-03-31 07:02:06 +00:00
if (isHorizontal)
thumbSize.height = clientRect.height;
else
thumbSize.width = clientRect.width;
// get our current position and max position from our content node
1999-08-19 22:16:23 +00:00
PRInt32 curpospx = GetCurrentPosition(scrollbar);
PRInt32 maxpospx = GetMaxPosition(scrollbar);
1999-08-19 22:16:23 +00:00
if (curpospx < 0)
curpospx = 0;
else if (curpospx > maxpospx)
curpospx = maxpospx;
float p2t;
aState.GetPresContext()->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
1999-08-19 22:16:23 +00:00
// get max pos in twips
nscoord maxpos = maxpospx*onePixel;
1999-08-19 22:16:23 +00:00
// get our maxpos in twips. This is the space we have left over in the scrollbar
// after the height of the thumb has been removed
2000-03-31 07:02:06 +00:00
nscoord& desiredcoord = isHorizontal ? clientRect.width : clientRect.height;
nscoord& thumbcoord = isHorizontal ? thumbSize.width : thumbSize.height;
nscoord ourmaxpos = desiredcoord;
1999-08-19 22:16:23 +00:00
mRatio = 1;
// its possible that our max position was set to 0. In that case the
// ratio should become 1 to avoid a divide by 0.
if (float(maxpos + ourmaxpos) != 0)
mRatio = float(ourmaxpos)/float(maxpos + ourmaxpos);
1999-08-19 22:16:23 +00:00
// if there is more room than the thumb need stretch the
// thumb
2000-03-31 07:02:06 +00:00
nscoord flex = 0;
thumbBox->GetFlex(aState, flex);
if (flex > 0)
{
nscoord thumbsize = NSToCoordRound(ourmaxpos * mRatio);
if (thumbsize > thumbcoord)
{
// if the thumb is flexible make the thumb bigger.
if (isHorizontal)
thumbSize.width = thumbsize;
2000-03-31 07:02:06 +00:00
else
thumbSize.height = thumbsize;
} else {
ourmaxpos -= thumbcoord;
if (float(maxpos) != 0)
mRatio = float(ourmaxpos)/float(maxpos);
}
1999-08-19 22:16:23 +00:00
} else {
ourmaxpos -= thumbcoord;
if (float(maxpos) != 0)
mRatio = float(ourmaxpos)/float(maxpos);
1999-04-20 21:39:52 +00:00
}
1999-08-19 22:16:23 +00:00
nscoord curpos = curpospx*onePixel;
// set the thumbs y coord to be the current pos * the ratio.
1999-08-19 22:16:23 +00:00
nscoord pos = nscoord(float(curpos)*mRatio);
2000-03-31 07:02:06 +00:00
nsRect thumbRect(clientRect.x, clientRect.y, thumbSize.width, thumbSize.height);
if (isHorizontal)
1999-08-19 22:16:23 +00:00
thumbRect.x += pos;
else
1999-08-19 22:16:23 +00:00
thumbRect.y += pos;
nsRect oldThumbRect;
thumbBox->GetBounds(oldThumbRect);
LayoutChildAt(aState, thumbBox, thumbRect);
SyncLayout(aState);
1999-10-12 00:16:06 +00:00
#ifdef DEBUG_SLIDER
PRInt32 c = GetCurrentPosition(scrollbar);
PRInt32 m = GetMaxPosition(scrollbar);
printf("Current=%d, max=%d\n", c, m);
#endif
// redraw only if thumb changed size.
if (oldThumbRect != thumbRect)
Redraw(aState);
return NS_OK;
}
NS_IMETHODIMP
nsSliderFrame::HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
2000-03-31 07:02:06 +00:00
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
if (isDraggingThumb())
{
// we want to draw immediately if the user doing it directly with the
// mouse that makes redrawing much faster.
mRedrawImmediate = PR_TRUE;
switch (aEvent->message) {
case NS_MOUSE_MOVE: {
// convert coord to pixels
nscoord pos = isHorizontal ? aEvent->point.x : aEvent->point.y;
// mDragStartPx is in pixels and is in our client areas coordinate system.
1999-06-28 19:57:28 +00:00
// so we need to first convert it so twips and then get it into our coordinate system.
// convert start to twips
nscoord startpx = mDragStartPx;
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord start = startpx*onePixel;
nsIFrame* thumbFrame = mFrames.FirstChild();
1999-06-28 19:57:28 +00:00
#ifdef OLD_SLIDER_FRAME_OFFSET_CALCULATION
1999-08-19 22:16:23 +00:00
1999-06-28 19:57:28 +00:00
// get it into our coordintate system by subtracting our parents offsets.
nsIFrame* parent = this;
while(parent != nsnull)
{
2001-10-07 06:32:36 +00:00
// if we hit a scrollable view make sure we take into account
// how much we are scrolled.
nsIView* view = parent->GetView();
2001-10-07 06:32:36 +00:00
if (view) {
nsIScrollableView* scrollingView;
nsresult result = CallQueryInterface(view, &scrollingView);
2001-10-07 06:32:36 +00:00
if (NS_SUCCEEDED(result)) {
nscoord xoff = 0;
nscoord yoff = 0;
scrollingView->GetScrollPosition(xoff, yoff);
isHorizontal ? start += xoff : start += yoff;
}
}
nsRect r = parent->GetRect();
1999-06-28 19:57:28 +00:00
isHorizontal ? start -= r.x : start -= r.y;
2001-10-07 06:32:36 +00:00
if (view) {
if (view->HasWidget()) {
2001-10-07 06:32:36 +00:00
nsWindowType windowType;
view->GetWidget()->GetWindowType(windowType);
2001-10-07 06:32:36 +00:00
if (windowType == eWindowType_popup)
break;
}
}
parent = parent->GetParent();
1999-06-28 19:57:28 +00:00
}
#else // Kin's new offset calculation code.
// start is relative to the upper left corner of the rootview's widget,
// unless the slider frame is in a popup, in which case it's relative
// to the upper left corner of the popup's widget. We need start to be
// in the coordinate system for the frame's contained view so that it
// matches aEvent->point's coordinate system.
nsIView *view = GetClosestView();
nsCOMPtr<nsIWidget> rootWidget;
if (view) {
nsIViewManager* vm = view->GetViewManager();
if (vm)
vm->GetWidget(getter_AddRefs(rootWidget));
}
if (view && rootWidget) {
// Now walk view's parent hierarchy, subtracting off the
// positions of each parent view, until we hit the view
// that contains the root or popup widget.
//
// When we're done, start should be in our contained
// view's coordinate system.
while (view) {
nsIWidget* widget = view->GetWidget();
if (widget) {
nsWindowType windowType;
widget->GetWindowType(windowType);
if (widget == rootWidget || windowType == eWindowType_popup)
break;
}
nsPoint p = view->GetPosition();
start -= (isHorizontal ? p.x : p.y);
view = view->GetParent();
}
}
#endif // Kin's new offset calculation code.
//printf("Translated to start=%d\n",start);
1999-06-28 19:57:28 +00:00
start -= mThumbStart;
// take our current position and substract the start location
pos -= start;
PRBool isMouseOutsideThumb = PR_FALSE;
if (gSnapMultiplier) {
nsSize thumbSize = thumbFrame->GetSize();
if (isHorizontal) {
// horizontal scrollbar - check if mouse is above or below thumb
if (aEvent->point.y < (-gSnapMultiplier * thumbSize.height) ||
aEvent->point.y > thumbSize.height + (gSnapMultiplier * thumbSize.height))
isMouseOutsideThumb = PR_TRUE;
}
else {
// vertical scrollbar - check if mouse is left or right of thumb
if (aEvent->point.x < (-gSnapMultiplier * thumbSize.width) ||
aEvent->point.x > thumbSize.width + (gSnapMultiplier * thumbSize.width))
isMouseOutsideThumb = PR_TRUE;
}
}
if (isMouseOutsideThumb)
{
// XXX see bug 81586
SetCurrentPosition(scrollbar, thumbFrame, (int) (mThumbStart / onePixel / mRatio), PR_FALSE);
return NS_OK;
}
// convert to pixels
nscoord pospx = pos/onePixel;
// convert to our internal coordinate system
pospx = nscoord(pospx/mRatio);
// set it
SetCurrentPosition(scrollbar, thumbFrame, pospx, PR_FALSE);
1999-08-19 22:16:23 +00:00
}
break;
case NS_MOUSE_MIDDLE_BUTTON_UP:
if(!gMiddlePref)
break;
case NS_MOUSE_LEFT_BUTTON_UP:
// stop capturing
//printf("stop capturing\n");
AddListener();
DragThumb(PR_FALSE);
mRedrawImmediate = PR_FALSE;//we MUST call nsFrame HandleEvent for mouse ups to maintain the selection state and capture state.
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
// we want to draw immediately if the user doing it directly with the
// mouse that makes redrawing much faster. Switch it back now.
mRedrawImmediate = PR_FALSE;
1999-08-19 22:16:23 +00:00
//return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
return NS_OK;
}
else if ((aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN && ((nsMouseEvent *)aEvent)->isShift)
|| (gMiddlePref && aEvent->message == NS_MOUSE_MIDDLE_BUTTON_DOWN)) {
// convert coord from twips to pixels
nscoord pos = isHorizontal ? aEvent->point.x : aEvent->point.y;
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord pospx = pos/onePixel;
// adjust so that the middle of the thumb is placed under the click
nsIFrame* thumbFrame = mFrames.FirstChild();
nsSize thumbSize = thumbFrame->GetSize();
nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height;
thumbLength /= onePixel;
pospx -= (thumbLength/2);
// convert to our internal coordinate system
pospx = nscoord(pospx/mRatio);
// set it
SetCurrentPosition(scrollbar, thumbFrame, pospx, PR_FALSE);
// hack to start dragging
nsIFrame* parent = this;
while(parent != nsnull)
{
// if we hit a scrollable view make sure we take into account
// how much we are scrolled.
nsIView* view = parent->GetView();
if (view) {
nsIScrollableView* scrollingView;
nsresult result = CallQueryInterface(view, &scrollingView);
if (NS_SUCCEEDED(result)) {
nscoord xoff = 0;
nscoord yoff = 0;
scrollingView->GetScrollPosition(xoff, yoff);
isHorizontal ? pos += xoff : pos += yoff;
}
}
nsPoint p = parent->GetPosition();
pos += isHorizontal ? p.x : p.y;
parent = parent->GetParent();
}
DragThumb(PR_TRUE);
if (isHorizontal)
mThumbStart = thumbFrame->GetPosition().x;
else
mThumbStart = thumbFrame->GetPosition().y;
mDragStartPx =pos/onePixel;
}
else if (mChange != 0 && aEvent->message == NS_MOUSE_MOVE) {
// We're in the process of moving the thumb to the mouse,
// but the mouse just moved. Make sure to update our
// destination point.
mDestinationPoint = aEvent->point;
}
1999-08-19 22:16:23 +00:00
// XXX hack until handle release is actually called in nsframe.
// if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
// HandleRelease(aPresContext, aEvent, aEventStatus);
if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
1999-08-19 22:16:23 +00:00
HandleRelease(aPresContext, aEvent, aEventStatus);
1999-08-19 22:16:23 +00:00
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
1999-08-19 22:16:23 +00:00
2000-03-31 07:02:06 +00:00
nsIBox*
nsSliderFrame::GetScrollbar()
{
// if we are in a scrollbar then return the scrollbar's content node
// if we are not then return ours.
nsIFrame* scrollbar;
nsScrollbarButtonFrame::GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
if (scrollbar == nsnull)
2000-03-31 07:02:06 +00:00
return this;
nsIBox* ibox = nsnull;
scrollbar->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox);
2000-03-31 07:02:06 +00:00
if (ibox == nsnull)
return this;
return ibox;
}
void
1999-08-19 22:16:23 +00:00
nsSliderFrame::PageUpDown(nsIFrame* aThumbFrame, nscoord change)
{
// on a page up or down get our page increment. We get this by getting the scrollbar we are in and
// asking it for the current position and the page increment. If we are not in a scrollbar we will
// get the values from our own node.
2000-03-31 07:02:06 +00:00
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
1999-06-23 17:00:17 +00:00
if (mScrollbarListener)
mScrollbarListener->PagedUpDown(); // Let the listener decide our increment.
nscoord pageIncrement = GetPageIncrement(scrollbar);
PRInt32 curpos = GetCurrentPosition(scrollbar);
SetCurrentPosition(scrollbar, aThumbFrame, curpos + change*pageIncrement, PR_TRUE);
}
// called when the current position changed and we need to update the thumb's location
nsresult
nsSliderFrame::CurrentPositionChanged(nsIPresContext* aPresContext)
{
2000-03-31 07:02:06 +00:00
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
// get the current position
PRInt32 curpos = GetCurrentPosition(scrollbar);
1999-10-12 00:16:06 +00:00
// do nothing if the position did not change
if (mCurPos == curpos)
return NS_OK;
1999-10-12 00:16:06 +00:00
// get our current position and max position from our content node
PRInt32 maxpos = GetMaxPosition(scrollbar);
if (curpos < 0)
curpos = 0;
else if (curpos > maxpos)
curpos = maxpos;
// convert to pixels
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord curpospx = curpos*onePixel;
// get the thumb's rect
nsIFrame* thumbFrame = mFrames.FirstChild();
if (!thumbFrame)
return NS_OK; // The thumb may stream in asynchronously via XBL.
nsRect thumbRect = thumbFrame->GetRect();
2000-08-30 21:51:02 +00:00
nsRect clientRect;
GetClientRect(clientRect);
// figure out the new rect
nsRect newThumbRect(thumbRect);
if (isHorizontal)
2000-08-30 21:51:02 +00:00
newThumbRect.x = clientRect.x + nscoord(float(curpospx)*mRatio);
else
2000-08-30 21:51:02 +00:00
newThumbRect.y = clientRect.y + nscoord(float(curpospx)*mRatio);
// set the rect
thumbFrame->SetRect(newThumbRect);
// figure out the union of the rect so we know what to redraw
nsRect changeRect;
changeRect.UnionRect(thumbRect, newThumbRect);
if (!changeRect.IsEmpty()) {
// redraw just the change
Invalidate(aPresContext, changeRect, mRedrawImmediate);
}
1999-06-23 17:00:17 +00:00
if (mScrollbarListener)
mScrollbarListener->PositionChanged(aPresContext, mCurPos, curpos);
1999-06-23 17:00:17 +00:00
mCurPos = curpos;
return NS_OK;
}
static void UpdateAttribute(nsIContent* aScrollbar, nscoord aNewPos, PRBool aNotify, PRBool aIsSmooth) {
nsAutoString str;
str.AppendInt(aNewPos);
if (aIsSmooth) {
aScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
}
aScrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, str, aNotify);
if (aIsSmooth) {
aScrollbar->UnsetAttr(kNameSpaceID_None, nsXULAtoms::smooth, PR_FALSE);
}
}
void
nsSliderFrame::SetCurrentPosition(nsIContent* scrollbar, nsIFrame* aThumbFrame, nscoord newpos, PRBool aIsSmooth)
{
// get our current position and max position from our content node
PRInt32 maxpos = GetMaxPosition(scrollbar);
// get the new position and make sure it is in bounds
if (newpos > maxpos)
newpos = maxpos;
else if (newpos < 0)
newpos = 0;
2000-06-06 23:13:05 +00:00
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(scrollbarBox));
2000-06-06 23:13:05 +00:00
if (scrollbarFrame) {
// See if we have a mediator.
nsCOMPtr<nsIScrollbarMediator> mediator;
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
if (mediator) {
mediator->PositionChanged(GetCurrentPosition(scrollbar), newpos);
UpdateAttribute(scrollbar, newpos, PR_FALSE, aIsSmooth);
CurrentPositionChanged(GetPresContext());
2000-06-06 23:13:05 +00:00
return;
}
}
UpdateAttribute(scrollbar, newpos, PR_TRUE, aIsSmooth);
#ifdef DEBUG_SLIDER
printf("Current Pos=%d\n",newpos);
#endif
}
NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
nsIFrame** aFrame)
{
// This is EVIL, we shouldn't be messing with GetFrameForPoint just to get
// thumb mouse drag events to arrive at the slider!
if (isDraggingThumb())
{
// XXX I assume it's better not to test for visibility here.
*aFrame = this;
return NS_OK;
}
2000-03-31 07:02:06 +00:00
if (NS_SUCCEEDED(nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame)))
return NS_OK;
// always return us (if visible)
if (mRect.Contains(aPoint) && GetStyleVisibility()->IsVisible()) {
*aFrame = this;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSliderFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
2000-03-31 07:02:06 +00:00
nsresult r = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList);
AddListener();
return r;
}
nsresult
nsSliderMediator::MouseDown(nsIDOMEvent* aMouseEvent)
{
// Only process the event if the thumb is not being dragged.
if (mSlider && !mSlider->isDraggingThumb())
return mSlider->MouseDown(aMouseEvent);
return NS_OK;
}
nsresult
nsSliderMediator::MouseUp(nsIDOMEvent* aMouseEvent)
{
// Only process the event if the thumb is not being dragged.
if (mSlider && !mSlider->isDraggingThumb())
return mSlider->MouseUp(aMouseEvent);
return NS_OK;
}
nsresult
nsSliderFrame::MouseDown(nsIDOMEvent* aMouseEvent)
{
//printf("Begin dragging\n");
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
PRUint16 button = 0;
PRBool scrollToClick = PR_FALSE;
mouseEvent->GetShiftKey(&scrollToClick);
mouseEvent->GetButton(&button);
if (button != 0) {
if (button != 1 || !gMiddlePref)
return NS_OK;
scrollToClick = PR_TRUE;
}
// If shift click or middle button, first
// place the middle of the slider thumb under the click
if (scrollToClick) {
nscoord pos;
nscoord pospx;
// mouseEvent has click coordinates in pixels, convert to twips first
isHorizontal ? mouseEvent->GetClientX(&pospx) : mouseEvent->GetClientY(&pospx);
float p2t;
GetPresContext()->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
pos = pospx * onePixel;
// then get it into our coordinate system by subtracting our parents offsets.
nsIFrame* parent = this;
while(parent != nsnull) {
// if we hit a scrollable view make sure we take into account
// how much we are scrolled.
// XXX hack
nsIView* view = parent->GetView();
if (view) {
nsIScrollableView* scrollingView;
nsresult result = CallQueryInterface(view, &scrollingView);
if (NS_SUCCEEDED(result)) {
nscoord xoff = 0;
nscoord yoff = 0;
scrollingView->GetScrollPosition(xoff, yoff);
isHorizontal ? pos += xoff : pos += yoff;
}
}
pos -= (isHorizontal ? parent->GetPosition().x : parent->GetPosition().y);
parent = parent->GetParent();
}
// now convert back into pixels
pospx = pos/onePixel;
// adjust so that the middle of the thumb is placed under the click
nsIFrame* thumbFrame = mFrames.FirstChild();
nsSize thumbSize = thumbFrame->GetSize();
nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height;
thumbLength /= onePixel;
pospx -= (thumbLength/2);
// finally, convert to scrollbar's internal coordinate system
pospx = nscoord(pospx/mRatio);
nsIBox* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
// set it
SetCurrentPosition(scrollbar, thumbFrame, pospx, PR_FALSE);
}
DragThumb(PR_TRUE);
PRInt32 c = 0;
if (isHorizontal)
mouseEvent->GetClientX(&c);
else
mouseEvent->GetClientY(&c);
mDragStartPx = c;
nsIFrame* thumbFrame = mFrames.FirstChild();
if (isHorizontal)
mThumbStart = thumbFrame->GetPosition().x;
else
mThumbStart = thumbFrame->GetPosition().y;
//printf("Pressed mDragStartPx=%d\n",mDragStartPx);
return NS_OK;
}
nsresult
nsSliderFrame::MouseUp(nsIDOMEvent* aMouseEvent)
{
// printf("Finish dragging\n");
1999-08-19 22:16:23 +00:00
return NS_OK;
}
void
nsSliderFrame::DragThumb(PRBool aGrabMouseEvents)
{
// get its view
nsIView* view = GetView();
if (view) {
nsIViewManager* viewMan = view->GetViewManager();
if (viewMan) {
PRBool result;
if (aGrabMouseEvents) {
viewMan->GrabMouseEvents(view,result);
} else {
viewMan->GrabMouseEvents(nsnull,result);
}
}
}
}
PRBool
nsSliderFrame::isDraggingThumb()
{
// get its view
nsIView* view = GetView();
if (view) {
nsIViewManager* viewMan = view->GetViewManager();
if (viewMan) {
nsIView* grabbingView;
viewMan->GetMouseEventGrabber(grabbingView);
if (grabbingView == view)
return PR_TRUE;
}
}
return PR_FALSE;
}
void
nsSliderFrame::AddListener()
{
if (!mMediator) {
mMediator = new nsSliderMediator(this);
NS_ADDREF(mMediator);
}
nsIFrame* thumbFrame = mFrames.FirstChild();
if (thumbFrame) {
nsCOMPtr<nsIDOMEventReceiver>
receiver(do_QueryInterface(thumbFrame->GetContent()));
receiver->AddEventListenerByIID(mMediator, NS_GET_IID(nsIDOMMouseListener));
}
}
void
nsSliderFrame::RemoveListener()
{
NS_ASSERTION(mMediator, "No listener was ever added!!");
nsIFrame* thumbFrame = mFrames.FirstChild();
if (!thumbFrame)
return;
nsCOMPtr<nsIDOMEventReceiver>
receiver(do_QueryInterface(thumbFrame->GetContent()));
receiver->RemoveEventListenerByIID(mMediator, NS_GET_IID(nsIDOMMouseListener));
}
1999-06-23 17:00:17 +00:00
1999-08-19 22:16:23 +00:00
NS_IMETHODIMP
nsSliderFrame::HandlePress(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
1999-08-19 22:16:23 +00:00
{
if (((nsMouseEvent *)aEvent)->isShift)
return NS_OK;
1999-08-19 22:16:23 +00:00
nsIFrame* thumbFrame = mFrames.FirstChild();
if (!thumbFrame) // display:none?
return NS_OK;
nsRect thumbRect = thumbFrame->GetRect();
nscoord change = 1;
if (IsHorizontal() ? aEvent->point.x < thumbRect.x
: aEvent->point.y < thumbRect.y)
change = -1;
mChange = change;
mDestinationPoint = aEvent->point;
PageUpDown(thumbFrame, change);
nsRepeatService::GetInstance()->Start(mMediator);
1999-08-19 22:16:23 +00:00
return NS_OK;
}
NS_IMETHODIMP
nsSliderFrame::HandleRelease(nsIPresContext* aPresContext,
1999-08-19 22:16:23 +00:00
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
1999-08-19 22:16:23 +00:00
{
nsRepeatService::GetInstance()->Stop();
mChange = 0;
1999-08-19 22:16:23 +00:00
return NS_OK;
}
1999-08-29 10:51:15 +00:00
NS_IMETHODIMP
nsSliderFrame::Destroy(nsIPresContext* aPresContext)
1999-08-29 10:51:15 +00:00
{
// tell our mediator if we have one we are gone.
if (mMediator) {
mMediator->SetSlider(nsnull);
NS_RELEASE(mMediator);
mMediator = nsnull;
}
// call base class Destroy()
2000-03-31 07:02:06 +00:00
return nsBoxFrame::Destroy(aPresContext);
}
NS_IMETHODIMP
nsSliderFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
{
EnsureOrient();
return nsBoxFrame::GetPrefSize(aState, aSize);
}
NS_IMETHODIMP
nsSliderFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize)
{
EnsureOrient();
// our min size is just our borders and padding
return nsBox::GetMinSize(aState, aSize);
}
NS_IMETHODIMP
nsSliderFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize)
{
EnsureOrient();
return nsBoxFrame::GetMaxSize(aState, aSize);
}
void
nsSliderFrame::EnsureOrient()
{
nsIBox* scrollbarBox = GetScrollbar();
nsIFrame* frame = nsnull;
scrollbarBox->GetFrame(&frame);
PRBool isHorizontal = frame->GetStateBits() & NS_STATE_IS_HORIZONTAL;
2000-03-31 07:02:06 +00:00
if (isHorizontal)
mState |= NS_STATE_IS_HORIZONTAL;
else
mState &= ~NS_STATE_IS_HORIZONTAL;
1999-08-29 10:51:15 +00:00
}
1999-08-19 22:16:23 +00:00
void
1999-06-23 17:00:17 +00:00
nsSliderFrame::SetScrollbarListener(nsIScrollbarListener* aListener)
{
// Don't addref/release this, since it's actually a frame.
mScrollbarListener = aListener;
}
1999-08-19 22:16:23 +00:00
NS_IMETHODIMP nsSliderMediator::Notify(nsITimer *timer)
{
if (mSlider)
mSlider->Notify(timer);
return NS_OK;
}
NS_IMETHODIMP_(void) nsSliderFrame::Notify(nsITimer *timer)
{
PRBool stop = PR_FALSE;
nsIFrame* thumbFrame = mFrames.FirstChild();
nsRect thumbRect = thumbFrame->GetRect();
2000-03-31 07:02:06 +00:00
PRBool isHorizontal = IsHorizontal();
// See if the thumb has moved past our destination point.
// if it has we want to stop.
if (isHorizontal) {
if (mChange < 0) {
if (thumbRect.x < mDestinationPoint.x)
stop = PR_TRUE;
} else {
if (thumbRect.x + thumbRect.width > mDestinationPoint.x)
stop = PR_TRUE;
}
} else {
if (mChange < 0) {
if (thumbRect.y < mDestinationPoint.y)
stop = PR_TRUE;
} else {
if (thumbRect.y + thumbRect.height > mDestinationPoint.y)
stop = PR_TRUE;
}
}
if (stop) {
nsRepeatService::GetInstance()->Stop();
} else {
PageUpDown(thumbFrame, mChange);
}
1999-08-19 22:16:23 +00:00
}
2000-03-31 07:02:06 +00:00
NS_INTERFACE_MAP_BEGIN(nsSliderMediator)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsSliderMediator)
NS_IMPL_RELEASE(nsSliderMediator)
2000-03-31 07:02:06 +00:00