Mozilla/mozilla/widget/src/mac/nsScrollbar.cpp
pierre%netscape.com 37d4d179e6 fix last part of #2336 "Miscellaneous cosmetic problems with scrollbars"
git-svn-id: svn://10.0.0.236/trunk@22709 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-03 09:05:50 +00:00

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