Files
Mozilla/mozilla/widget/src/mac/nsScrollbar.cpp
pinkerton%netscape.com 8b7dab39b0 updates and cleanup to match other native scrollbar class. r=sdagley/sr=beard/a=valeski. bug# 121440
git-svn-id: svn://10.0.0.236/trunk@117805 18797224-902f-48f8-a5cc-f745e15eee43
2002-03-31 18:34:07 +00:00

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);
}
}