423 lines
12 KiB
C++
423 lines
12 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.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 Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "nsScrollBar.h"
|
|
#include "nsGfxCIID.h"
|
|
|
|
#include "xlibrgb.h"
|
|
|
|
NS_IMPL_ADDREF(nsScrollbar)
|
|
NS_IMPL_RELEASE(nsScrollbar)
|
|
|
|
PRLogModuleInfo *XlibScrollbarLM = PR_NewLogModule("XlibScrollbar");
|
|
|
|
nsScrollbar::nsScrollbar(PRBool aIsVertical) : nsWidget(), nsIScrollbar()
|
|
{
|
|
NS_INIT_REFCNT();
|
|
mMaxRange = 0;
|
|
mPosition = 0;
|
|
mThumbSize = 0;
|
|
mLineIncrement = 1;
|
|
mIsVertical = aIsVertical;
|
|
mBackground = NS_RGB(100,100,100);
|
|
mBackgroundPixel = xlib_rgb_xpixel_from_rgb(mBackground);
|
|
mBorderPixel = xlib_rgb_xpixel_from_rgb(mBackground);
|
|
mBar = 0;
|
|
mBarBounds.x = mBarBounds.y = mBarBounds.width = mBarBounds.height = 0;
|
|
};
|
|
|
|
nsScrollbar::~nsScrollbar()
|
|
{
|
|
if (mBar) {
|
|
XDestroyWindow(mDisplay, mBar);
|
|
DeleteWindowCallback(mBar);
|
|
}
|
|
}
|
|
|
|
nsresult nsScrollbar::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
{
|
|
nsresult result = nsWidget::QueryInterface(aIID, aInstancePtr);
|
|
|
|
static NS_DEFINE_IID(kInsScrollbarIID, NS_ISCROLLBAR_IID);
|
|
if (result == NS_NOINTERFACE && aIID.Equals(kInsScrollbarIID)) {
|
|
*aInstancePtr = (void*) ((nsIScrollbar*)this);
|
|
NS_ADDREF_THIS();
|
|
result = NS_OK;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::SetMaxRange(PRUint32 aEndRange)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetMaxRange()\n"));
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Max Range set to %d\n", aEndRange));
|
|
mMaxRange = aEndRange;
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
PRUint32 nsScrollbar::GetMaxRange(PRUint32& aRange)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::GetMaxRange()\n"));
|
|
aRange = mMaxRange;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::SetPosition(PRUint32 aPos)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetPosition()\n"));
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Scroll to %d\n", aPos));
|
|
mPosition = aPos;
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
PRUint32 nsScrollbar::GetPosition(PRUint32& aPosition)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::GetPosition()\n"));
|
|
aPosition = mPosition;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::SetThumbSize(PRUint32 aSize)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetThumbSize()\n"));
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Thumb size set to %d\n", aSize));
|
|
|
|
mThumbSize = aSize;
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::GetThumbSize(PRUint32& aSize)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::GetThumbSize()\n"));
|
|
|
|
aSize = mThumbSize;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::SetLineIncrement(PRUint32 aSize)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetLineIncrement()\n"));
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Set Line Increment to %d\n", aSize));
|
|
|
|
mLineIncrement = aSize;
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::GetLineIncrement(PRUint32& aSize)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::GetLineIncrement()\n"));
|
|
|
|
aSize = mLineIncrement;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_METHOD nsScrollbar::SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
|
|
PRUint32 aPosition, PRUint32 aLineIncrement)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetParameters()\n"));
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("MaxRange = %d ThumbSize = %d aPosition = %d LineIncrement = %d\n",
|
|
aMaxRange, aThumbSize, aPosition, aLineIncrement));
|
|
|
|
SetMaxRange(aMaxRange);
|
|
SetThumbSize(aThumbSize);
|
|
SetPosition(aPosition);
|
|
SetLineIncrement(aLineIncrement);
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool nsScrollbar::OnScroll(PRUint32 scrollCode, int cPos)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::OnScroll\n"));
|
|
|
|
PRBool result = PR_FALSE;
|
|
switch (scrollCode) {
|
|
case NS_SCROLLBAR_PAGE_NEXT:
|
|
result = NextPage();
|
|
break;
|
|
case NS_SCROLLBAR_PAGE_PREV:
|
|
result = PrevPage();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PRBool nsScrollbar::OnResize(nsSizeEvent &event)
|
|
{
|
|
PRBool result;
|
|
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::OnResize\n"));
|
|
|
|
nsWidget::OnResize(event);
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
result = PR_FALSE;
|
|
return result;
|
|
}
|
|
|
|
PRBool nsScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent)
|
|
{
|
|
PRBool result;
|
|
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::DispatchMouseEvent\n"));
|
|
|
|
// check to see if this was on the main window.
|
|
switch (aEvent.message) {
|
|
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
|
if (mIsVertical == PR_TRUE) {
|
|
if (aEvent.point.y < mBarBounds.y) {
|
|
OnScroll(NS_SCROLLBAR_PAGE_PREV, 0);
|
|
}
|
|
else if (aEvent.point.y > mBarBounds.height) {
|
|
OnScroll(NS_SCROLLBAR_PAGE_NEXT, 0);
|
|
}
|
|
}
|
|
else {
|
|
if (aEvent.point.x < mBarBounds.x) {
|
|
OnScroll(NS_SCROLLBAR_PAGE_PREV, 0);
|
|
}
|
|
else if (aEvent.point.x > mBarBounds.width) {
|
|
OnScroll(NS_SCROLLBAR_PAGE_NEXT, 0);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
result = PR_FALSE;
|
|
return result;
|
|
}
|
|
|
|
|
|
void nsScrollbar::CreateNative(Window aParent, nsRect aRect)
|
|
{
|
|
XSetWindowAttributes attr;
|
|
unsigned long attr_mask;
|
|
|
|
// on a window resize, we don't want to window contents to
|
|
// be discarded...
|
|
attr.bit_gravity = SouthEastGravity;
|
|
// make sure that we listen for events
|
|
attr.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask;
|
|
// set the default background color and border to that awful gray
|
|
attr.background_pixel = mBackgroundPixel;
|
|
attr.border_pixel = mBorderPixel;
|
|
// set the colormap
|
|
attr.colormap = xlib_rgb_get_cmap();
|
|
// here's what's in the struct
|
|
attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel;
|
|
// check to see if there was actually a colormap.
|
|
if (attr.colormap)
|
|
attr_mask |= CWColormap;
|
|
|
|
CreateNativeWindow(aParent, mBounds, attr, attr_mask);
|
|
CreateGC();
|
|
// set up the scrolling bar.
|
|
attr.event_mask = Button1MotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask;
|
|
attr.background_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(192,192,192));
|
|
attr.border_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(100,100,100));
|
|
// set up the size
|
|
CalcBarBounds();
|
|
mBar = XCreateWindow(mDisplay,
|
|
mBaseWindow,
|
|
mBarBounds.x, mBarBounds.y,
|
|
mBarBounds.width, mBarBounds.height,
|
|
2, // border width
|
|
mDepth,
|
|
InputOutput,
|
|
mVisual,
|
|
attr_mask,
|
|
&attr);
|
|
AddWindowCallback(mBar, this);
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::CreateNative created window 0x%lx with bar 0x%lx\n",
|
|
mBaseWindow, mBar));
|
|
}
|
|
|
|
NS_IMETHODIMP nsScrollbar::Show(PRBool bState)
|
|
{
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::Show(): %s\n",
|
|
(bState == PR_TRUE) ? "true" : "false"));
|
|
nsWidget::Show(bState);
|
|
if (bState) {
|
|
if (mBar) {
|
|
XMapWindow(mDisplay, mBar);
|
|
}
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsScrollbar::Resize(PRInt32 aWidth,
|
|
PRInt32 aHeight,
|
|
PRBool aRepaint)
|
|
{
|
|
nsWidget::Resize(aWidth, aHeight, aRepaint);
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsScrollbar::Resize(PRInt32 aX,
|
|
PRInt32 aY,
|
|
PRInt32 aWidth,
|
|
PRInt32 aHeight,
|
|
PRBool aRepaint)
|
|
{
|
|
nsWidget::Resize(aX, aY, aWidth, aHeight, aRepaint);
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsScrollbar::NextPage(void)
|
|
{
|
|
PRUint32 max;
|
|
nsresult result = PR_FALSE;
|
|
|
|
// change it locally.
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::NextPage(): maxrange is %d thumb is %d position is %d\n", mMaxRange, mThumbSize, mPosition));
|
|
max = mMaxRange - mThumbSize;
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::NextPage(): max is %d\n", max));
|
|
mPosition += mThumbSize;
|
|
if (mPosition > max)
|
|
mPosition = max;
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::NextPage(): new position is %d\n", mPosition));
|
|
|
|
// send the event
|
|
if (mEventCallback) {
|
|
nsScrollbarEvent sevent;
|
|
sevent.message = NS_SCROLLBAR_POS;
|
|
sevent.widget = (nsWidget *)this;
|
|
sevent.eventStructType = NS_SCROLLBAR_EVENT;
|
|
sevent.position = (mPosition);
|
|
sevent.point.x = 0;
|
|
sevent.point.y = 0;
|
|
// send the event
|
|
result = ConvertStatus((*mEventCallback) (&sevent));
|
|
// the gtk code indicates that the callback can
|
|
// modify the position. how odd.
|
|
mPosition = sevent.position;
|
|
}
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return result;
|
|
}
|
|
|
|
nsresult nsScrollbar::PrevPage(void)
|
|
{
|
|
nsresult result = PR_FALSE;
|
|
// check to make sure we don't go backwards
|
|
if (mThumbSize > mPosition) {
|
|
mPosition = 0;
|
|
}
|
|
else {
|
|
mPosition -= mThumbSize;
|
|
}
|
|
|
|
// send the event
|
|
if (mEventCallback) {
|
|
nsScrollbarEvent sevent;
|
|
sevent.message = NS_SCROLLBAR_POS;
|
|
sevent.widget = (nsWidget *)this;
|
|
sevent.eventStructType = NS_SCROLLBAR_EVENT;
|
|
sevent.position = (mPosition);
|
|
// send the event
|
|
result = ConvertStatus((*mEventCallback) (&sevent));
|
|
// the gtk code indicates that the callback can
|
|
// modify the position. how odd.
|
|
mPosition = sevent.position;
|
|
}
|
|
CalcBarBounds();
|
|
LayoutBar();
|
|
return result;
|
|
}
|
|
|
|
void nsScrollbar::CalcBarBounds(void)
|
|
{
|
|
float bar_start;
|
|
float bar_end;
|
|
|
|
if (mMaxRange == 0) {
|
|
bar_start = 0;
|
|
bar_end = 0;
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: max range is zero.\n"));
|
|
|
|
}
|
|
else {
|
|
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: position: %d max: %d thumb: %d\n",
|
|
mPosition, mMaxRange, mThumbSize));
|
|
bar_start = (float)mPosition / (float)mMaxRange;
|
|
bar_end = (float)mThumbSize / (float)mMaxRange;
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: start: %f end: %f\n", bar_start, bar_end));
|
|
|
|
}
|
|
|
|
if (mIsVertical == PR_TRUE) {
|
|
mBarBounds.x = 0;
|
|
mBarBounds.y = (int)(bar_start * mRequestedSize.height);
|
|
mBarBounds.width = mRequestedSize.width;
|
|
mBarBounds.height = (int)(bar_end * mRequestedSize.height);
|
|
}
|
|
else {
|
|
mBarBounds.x = (int)(bar_start * mRequestedSize.width);
|
|
mBarBounds.y = 0;
|
|
mBarBounds.width = (int)(bar_end * mRequestedSize.width);
|
|
mBarBounds.height = mRequestedSize.height;
|
|
}
|
|
if (mBarBounds.height == 0) {
|
|
mBarBounds.height = 1;
|
|
}
|
|
if (mBarBounds.width == 0) {
|
|
mBarBounds.width = 1;
|
|
}
|
|
|
|
PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: bar is (%s) %d %d %d %d\n",
|
|
((mIsVertical == PR_TRUE) ? "vertical" : "horizontal" ),
|
|
mBarBounds.x, mBarBounds.y, mBarBounds.width, mBarBounds.height));
|
|
}
|
|
|
|
void nsScrollbar::LayoutBar(void)
|
|
{
|
|
XMoveResizeWindow(mDisplay, mBar,
|
|
mBarBounds.x, mBarBounds.y,
|
|
mBarBounds.width, mBarBounds.height);
|
|
}
|
|
|
|
NS_IMETHODIMP nsScrollbar::Move(PRInt32 aX, PRInt32 aY)
|
|
{
|
|
return nsWidget::Move(aX, aY);
|
|
}
|