443 lines
12 KiB
C++
443 lines
12 KiB
C++
/* -*- 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
|
|
*
|
|
* 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/
|
|
*
|
|
* 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.
|
|
*
|
|
* The Original Code is mozilla.org 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.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* 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 ***** */
|
|
|
|
#include "nsScrollbar.h"
|
|
#include "nsIDeviceContext.h"
|
|
#if TARGET_CARBON || (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
|
|
#include <ControlDefinitions.h>
|
|
#endif
|
|
|
|
#include "nsWatchTask.h"
|
|
|
|
|
|
//
|
|
// StControlActionProcOwner
|
|
//
|
|
// A class that wraps a control action proc so that it is disposed of
|
|
// correctly when the shared library shuts down
|
|
//
|
|
class StControlActionProcOwner {
|
|
public:
|
|
|
|
StControlActionProcOwner ( )
|
|
{
|
|
sControlActionProc = NewControlActionUPP(nsScrollbar::ScrollActionProc);
|
|
NS_ASSERTION(sControlActionProc, "Couldn't create live scrolling action proc");
|
|
}
|
|
~StControlActionProcOwner ( )
|
|
{
|
|
if ( sControlActionProc )
|
|
DisposeControlActionUPP(sControlActionProc);
|
|
}
|
|
|
|
ControlActionUPP ActionProc() { return sControlActionProc; }
|
|
|
|
private:
|
|
ControlActionUPP sControlActionProc;
|
|
};
|
|
|
|
|
|
static ControlActionUPP ScrollbarActionProc();
|
|
|
|
static ControlActionUPP ScrollbarActionProc()
|
|
{
|
|
static StControlActionProcOwner sActionProcOwner;
|
|
return sActionProcOwner.ActionProc();
|
|
}
|
|
|
|
|
|
NS_IMPL_ADDREF(nsScrollbar);
|
|
NS_IMPL_RELEASE(nsScrollbar);
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsScrollbar)
|
|
NS_INTERFACE_MAP_ENTRY(nsIScrollbar)
|
|
NS_INTERFACE_MAP_END_INHERITING(nsWindow)
|
|
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* nsScrollbar Constructor
|
|
* @update dc 10/31/98
|
|
* @param aIsVertical -- Tells if the scrollbar had a vertical or horizontal orientation
|
|
*/
|
|
nsScrollbar::nsScrollbar()
|
|
: nsMacControl()
|
|
, mLineIncrement(0)
|
|
, mFullImageSize(0)
|
|
, mVisibleImageSize(0)
|
|
, mMouseDownInScroll(PR_FALSE)
|
|
, mClickedPartCode(0)
|
|
{
|
|
WIDGET_SET_CLASSNAME("nsScrollbar");
|
|
SetControlType(kControlScrollBarLiveProc);
|
|
}
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* Destuctor for the nsScrollbar
|
|
* @update dc 10/31/98
|
|
*/
|
|
nsScrollbar::~nsScrollbar()
|
|
{
|
|
}
|
|
|
|
|
|
/**-------------------------------------------------------------------------------
|
|
* 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
|
|
*/
|
|
pascal 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
|
|
Invalidate(PR_FALSE);
|
|
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).
|
|
nsWatchTask::GetTask().Suspend();
|
|
::TrackControl(mControl, thePoint, ScrollbarActionProc());
|
|
nsWatchTask::GetTask().Resume();
|
|
::HiliteControl(mControl, 0);
|
|
// 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;
|
|
}
|
|
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;
|
|
|
|
PRInt32 oldValue = mValue;
|
|
mValue = ((PRInt32)aPos) > aMax ? aMax : ((int)aPos);
|
|
|
|
// redraw the scrollbar. should update be done now, or later?
|
|
if (mValue != oldValue)
|
|
{
|
|
Invalidate(PR_FALSE);
|
|
Update();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|