438 lines
13 KiB
C++
438 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "nsScrollbar.h"
|
|
#include "nsIDeviceContext.h"
|
|
|
|
NS_IMPL_ADDREF(nsScrollbar);
|
|
NS_IMPL_RELEASE(nsScrollbar);
|
|
|
|
ControlActionUPP nsScrollbar::sControlActionProc = nsnull;
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* nsScrollbar Constructor
|
|
* @update dc 10/31/98
|
|
* @param aIsVertical -- Tells if the scrollbar had a vertical or horizontal orientation
|
|
*/
|
|
nsScrollbar::nsScrollbar(PRBool /*aIsVertical*/)
|
|
: nsMacControl()
|
|
, nsIScrollbar()
|
|
, mLineIncrement(0)
|
|
, mFullImageSize(0)
|
|
, mVisibleImageSize(0)
|
|
, mMouseDownInScroll(PR_FALSE)
|
|
, mClickedPartCode(0)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
strcpy(gInstanceClassName, "nsScrollbar");
|
|
SetControlType(kControlScrollBarLiveProc);
|
|
if (!sControlActionProc)
|
|
sControlActionProc = NewControlActionProc(nsScrollbar::ScrollActionProc);
|
|
// Unfortunately, not disposed when the app quits, but that's still a non-issue.
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* The create method for a scrollbar, using a nsIWidget as the parent
|
|
* @update dc 08/31/98
|
|
* @param aParent -- the widget which will be this widgets parent in the tree
|
|
* @param aRect -- The bounds in parental coordinates of this widget
|
|
* @param aHandleEventFunction -- Procedures to be executed for this widget
|
|
* @param aContext -- device context to be used by this widget
|
|
* @param aAppShell --
|
|
* @param aToolkit -- toolkit to be used by this widget
|
|
* @param aInitData -- Initialization data used by frames
|
|
* @return -- NS_OK if everything was created correctly
|
|
*/
|
|
NS_IMETHODIMP nsScrollbar::Create(nsIWidget *aParent,
|
|
const nsRect &aRect,
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
nsIDeviceContext *aContext,
|
|
nsIAppShell *aAppShell,
|
|
nsIToolkit *aToolkit,
|
|
nsWidgetInitData *aInitData)
|
|
{
|
|
Inherited::Create(aParent, aRect, aHandleEventFunction,
|
|
aContext, aAppShell, aToolkit, aInitData);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Destuctor for the nsScrollbar
|
|
* @update dc 10/31/98
|
|
*/
|
|
nsScrollbar::~nsScrollbar()
|
|
{
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Implement the standard QueryInterface for NS_IWIDGET_IID and NS_ISUPPORTS_IID
|
|
* @update dc 08/31/98
|
|
* @param aIID The name of the class implementing the method
|
|
* @param _classiiddef The name of the #define symbol that defines the IID
|
|
* for the class (e.g. NS_ISUPPORTS_IID)
|
|
*/
|
|
nsresult nsScrollbar::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
{
|
|
if (nsnull == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
static NS_DEFINE_IID(kIScrollbarIID, NS_ISCROLLBAR_IID);
|
|
if (aIID.Equals(kIScrollbarIID)) {
|
|
*aInstancePtr = (void*) ((nsIScrollbar*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
|
|
return nsWindow::QueryInterface(aIID,aInstancePtr);
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* ScrollActionProc Callback for TrackControl
|
|
* @update jrm 99/01/11
|
|
* @param ctrl - The Control being tracked
|
|
* @param part - Part of the control (arrow, thumb, gutter) being hit
|
|
*/
|
|
void nsScrollbar::ScrollActionProc(ControlHandle ctrl, ControlPartCode part)
|
|
{
|
|
nsScrollbar* me = (nsScrollbar*)(::GetControlReference(ctrl));
|
|
NS_ASSERTION(nsnull != me, "NULL nsScrollbar");
|
|
if (nsnull != me)
|
|
me->DoScrollAction(part);
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* ScrollActionProc Callback for TrackControl
|
|
* @update jrm 99/01/11
|
|
* @param part - Part of the control (arrow, thumb, gutter) being hit
|
|
*/
|
|
void nsScrollbar::DoScrollAction(ControlPartCode part)
|
|
{
|
|
PRUint32 pos;
|
|
PRUint32 incr;
|
|
PRUint32 visibleImageSize;
|
|
PRInt32 scrollBarMessage = 0;
|
|
GetPosition(pos);
|
|
GetLineIncrement(incr);
|
|
GetThumbSize(visibleImageSize);
|
|
switch(part)
|
|
{
|
|
case kControlUpButtonPart:
|
|
{
|
|
scrollBarMessage = NS_SCROLLBAR_LINE_PREV;
|
|
SetPosition(pos - incr);
|
|
break;
|
|
}
|
|
case kControlDownButtonPart:
|
|
scrollBarMessage = NS_SCROLLBAR_LINE_NEXT;
|
|
SetPosition(pos + incr);
|
|
break;
|
|
case kControlPageUpPart:
|
|
scrollBarMessage = NS_SCROLLBAR_PAGE_PREV;
|
|
SetPosition(pos - visibleImageSize);
|
|
break;
|
|
case kControlPageDownPart:
|
|
scrollBarMessage = NS_SCROLLBAR_PAGE_NEXT;
|
|
SetPosition(pos + visibleImageSize);
|
|
break;
|
|
case kControlIndicatorPart:
|
|
scrollBarMessage = NS_SCROLLBAR_POS;
|
|
SetPosition(::GetControl32BitValue(GetControl()));
|
|
break;
|
|
}
|
|
EndDraw();
|
|
|
|
// send event to scroll the parent
|
|
nsScrollbarEvent scrollBarEvent;
|
|
scrollBarEvent.eventStructType = NS_GUI_EVENT;
|
|
scrollBarEvent.widget = this;
|
|
scrollBarEvent.message = scrollBarMessage;
|
|
GetPosition(pos);
|
|
scrollBarEvent.position = pos;
|
|
Inherited::DispatchWindowEvent(scrollBarEvent);
|
|
|
|
// update the area of the parent uncovered by the scrolling
|
|
nsIWidget* parent = GetParent();
|
|
parent->Update();
|
|
NS_RELEASE(parent);
|
|
|
|
// update this scrollbar
|
|
this-Invalidate(PR_FALSE);
|
|
this->Update();
|
|
|
|
StartDraw();
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* DispatchMouseEvent handle an event for this scrollbar
|
|
* @update dc 08/31/98
|
|
* @Param aEvent -- The mouse event to respond to for this button
|
|
* @return -- True if the event was handled, PR_FALSE if we did not handle it.
|
|
*/
|
|
PRBool nsScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent)
|
|
{
|
|
PRBool eatEvent = PR_FALSE;
|
|
switch (aEvent.message)
|
|
{
|
|
case NS_MOUSE_LEFT_DOUBLECLICK:
|
|
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
|
NS_ASSERTION(this != 0, "NULL nsScrollbar2");
|
|
::SetControlReference(mControl, (UInt32) this);
|
|
StartDraw();
|
|
{
|
|
Point thePoint;
|
|
thePoint.h = aEvent.point.x;
|
|
thePoint.v = aEvent.point.y;
|
|
mClickedPartCode = ::TestControl(mControl, thePoint);
|
|
if (mClickedPartCode > 0)
|
|
::HiliteControl(mControl, mClickedPartCode);
|
|
|
|
switch (mClickedPartCode)
|
|
{
|
|
case kControlUpButtonPart:
|
|
case kControlDownButtonPart:
|
|
case kControlPageUpPart:
|
|
case kControlPageDownPart:
|
|
case kControlIndicatorPart:
|
|
// We are assuming Appearance 1.1 or later, so we
|
|
// have the "live scroll" variant of the scrollbar,
|
|
// which lets you pass the action proc to TrackControl
|
|
// for the thumb (this was illegal in previous
|
|
// versions of the defproc).
|
|
::TrackControl(mControl, thePoint, sControlActionProc);
|
|
// We don't dispatch the mouseDown event because mouseUp is eaten
|
|
// by TrackControl anyway and the only messages the app really
|
|
// cares about are the NS_SCROLLBAR_xxx messages.
|
|
eatEvent = PR_TRUE;
|
|
break;
|
|
#if 0
|
|
case kControlIndicatorPart:
|
|
// This is what you have to do for appearance 1.0 or
|
|
// no appearance.
|
|
::TrackControl(mControl, thePoint, nsnull);
|
|
mValue = ::GetControl32BitValue(mControl);
|
|
EndDraw();
|
|
nsScrollbarEvent scrollBarEvent;
|
|
scrollBarEvent.eventStructType = NS_GUI_EVENT;
|
|
scrollBarEvent.widget = this;
|
|
scrollBarEvent.message = NS_SCROLLBAR_POS;
|
|
scrollBarEvent.position = mValue;
|
|
DispatchWindowEvent(scrollBarEvent);
|
|
nsIWidget* parent = GetParent();
|
|
parent->Update();
|
|
NS_RELEASE(parent);
|
|
StartDraw();
|
|
break;
|
|
#endif
|
|
}
|
|
SetPosition(mValue);
|
|
}
|
|
EndDraw();
|
|
break;
|
|
|
|
|
|
case NS_MOUSE_LEFT_BUTTON_UP:
|
|
mClickedPartCode = 0;
|
|
break;
|
|
|
|
case NS_MOUSE_EXIT:
|
|
if (mWidgetArmed)
|
|
{
|
|
StartDraw();
|
|
::HiliteControl(mControl, 0);
|
|
EndDraw();
|
|
}
|
|
break;
|
|
|
|
case NS_MOUSE_ENTER:
|
|
if (mWidgetArmed)
|
|
{
|
|
StartDraw();
|
|
::HiliteControl(mControl, mClickedPartCode);
|
|
EndDraw();
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (eatEvent)
|
|
return PR_TRUE;
|
|
return (Inherited::DispatchMouseEvent(aEvent));
|
|
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* set the maximum range of a scroll bar
|
|
* @update dc 09/16/98
|
|
* @param aMaxRange -- the maximum to set this to
|
|
* @return -- If a good size was returned
|
|
*/
|
|
NS_METHOD nsScrollbar::SetMaxRange(PRUint32 aEndRange) // really means set full image size.
|
|
{
|
|
mFullImageSize = ((int)aEndRange) > 0 ? aEndRange : 10;
|
|
if (mControl)
|
|
{
|
|
StartDraw();
|
|
::SetControl32BitMaximum(
|
|
mControl,
|
|
mFullImageSize > mVisibleImageSize ? mFullImageSize - mVisibleImageSize : 0);
|
|
EndDraw();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* get the maximum range of a scroll bar
|
|
* @update dc 09/16/98
|
|
* @param aMaxRange -- The current maximum this slider can be
|
|
* @return -- If a good size was returned
|
|
*/
|
|
NS_METHOD nsScrollbar::GetMaxRange(PRUint32& aMaxRange) // really means get full image size
|
|
{
|
|
aMaxRange = mFullImageSize;
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Set the current position of the slider
|
|
* @update dc 09/16/98
|
|
* @param aMaxRange -- The current value to set the slider position to.
|
|
* @return -- NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::SetPosition(PRUint32 aPos)
|
|
{
|
|
if ((PRInt32)aPos < 0)
|
|
aPos = 0;
|
|
PRUint32 aMax = mFullImageSize - mVisibleImageSize;
|
|
mValue = ((PRInt32)aPos) > aMax ? aMax : ((int)aPos);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Get the current position of the slider
|
|
* @update dc 09/16/98
|
|
* @param aMaxRange -- The current slider position.
|
|
* @return -- NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::GetPosition(PRUint32& aPos)
|
|
{
|
|
aPos = mValue;
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Set the height of a vertical, or width of a horizontal scroll bar thumb control
|
|
* @update dc 09/16/98
|
|
* @param aSize -- the size to set the thumb control to
|
|
* @return -- NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::SetThumbSize(PRUint32 aSize)
|
|
{
|
|
mVisibleImageSize = ((int)aSize) > 0 ? aSize : 1;
|
|
|
|
if (mVisibleImageSize > mFullImageSize)
|
|
mVisibleImageSize = mFullImageSize;
|
|
if (mControl)
|
|
{
|
|
StartDraw();
|
|
SetControlViewSize(mControl, mVisibleImageSize);
|
|
EndDraw();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* get the height of a vertical, or width of a horizontal scroll bar thumb control
|
|
* @update dc 09/16/98
|
|
* @param aSize -- the size to set the thumb control to
|
|
* @return -- NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::GetThumbSize(PRUint32& aSize)
|
|
{
|
|
aSize = mVisibleImageSize;
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Set the increment of the scroll bar
|
|
* @update dc 09/16/98
|
|
* @param aLineIncrement -- the control increment
|
|
* @return -- NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::SetLineIncrement(PRUint32 aLineIncrement)
|
|
{
|
|
mLineIncrement = (((int)aLineIncrement) > 0 ? aLineIncrement : 1);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Get the increment of the scroll bar
|
|
* @update dc 09/16/98
|
|
* @param aLineIncrement -- the control increment
|
|
* @return NS_OK if the position is valid
|
|
*/
|
|
NS_METHOD nsScrollbar::GetLineIncrement(PRUint32& aLineIncrement)
|
|
{
|
|
aLineIncrement = mLineIncrement;
|
|
return NS_OK;
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* See documentation in nsScrollbar.h
|
|
* @update dc 012/10/98
|
|
*/
|
|
NS_METHOD nsScrollbar::SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
|
|
PRUint32 aPosition, PRUint32 aLineIncrement)
|
|
{
|
|
SetLineIncrement(aLineIncrement);
|
|
SetPosition(aPosition);
|
|
mVisibleImageSize = aThumbSize; // needed by SetMaxRange
|
|
SetMaxRange(aMaxRange);
|
|
SetThumbSize(aThumbSize); // Needs to know the maximum value when calling Mac toolbox.
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Get the rect which the Mac control uses. This may be different for
|
|
// different controls, so this method allows overriding
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsScrollbar::GetRectForMacControl(nsRect &outRect)
|
|
{
|
|
outRect = mBounds;
|
|
outRect.x = outRect.y = 0;
|
|
|
|
if (mBounds.height > mBounds.width)
|
|
{
|
|
// vertical scroll bar
|
|
outRect.Inflate(0, 1);
|
|
}
|
|
else
|
|
{
|
|
// horizontal scroll bar
|
|
outRect.Inflate(1, 0);
|
|
}
|
|
}
|
|
|