|
Java example source code file (awt_Scrollbar.cpp)
This example Java source code file (awt_Scrollbar.cpp) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The awt_Scrollbar.cpp Java example source code
/*
* Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "awt_Toolkit.h"
#include "awt_Scrollbar.h"
#include "awt_Canvas.h"
#include "awt_Window.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
/***********************************************************************/
// struct for _SetValues() method
struct SetValuesStruct {
jobject scrollbar;
jint value;
jint visible;
jint min, max;
};
/************************************************************************
* AwtScrollbar fields
*/
jfieldID AwtScrollbar::lineIncrementID;
jfieldID AwtScrollbar::pageIncrementID;
jfieldID AwtScrollbar::orientationID;
BOOL AwtScrollbar::ms_isInsideMouseFilter = FALSE;
int AwtScrollbar::ms_instanceCounter = 0;
HHOOK AwtScrollbar::ms_hMouseFilter;
/************************************************************************
* AwtScrollbar methods
*/
AwtScrollbar::AwtScrollbar() {
m_orientation = SB_HORZ;
m_lineIncr = 0;
m_pageIncr = 0;
m_prevCallback = NULL;
m_prevCallbackPos = 0;
ms_instanceCounter++;
/*
* Fix for 4515085.
* Use the hook to process WM_LBUTTONUP message.
*/
if (AwtScrollbar::ms_instanceCounter == 1) {
AwtScrollbar::ms_hMouseFilter =
::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)AwtScrollbar::MouseFilter,
0, AwtToolkit::MainThread());
}
}
AwtScrollbar::~AwtScrollbar()
{
}
void AwtScrollbar::Dispose()
{
if (--ms_instanceCounter == 0) {
::UnhookWindowsHookEx(ms_hMouseFilter);
}
AwtComponent::Dispose();
}
LPCTSTR
AwtScrollbar::GetClassName() {
return TEXT("SCROLLBAR"); /* System provided scrollbar class */
}
/* Create a new AwtScrollbar object and window. */
AwtScrollbar *
AwtScrollbar::Create(jobject peer, jobject parent)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = NULL;
AwtScrollbar* c = NULL;
try {
if (env->EnsureLocalCapacity(1) < 0) {
return NULL;
}
PDATA pData;
AwtCanvas* awtParent;
JNI_CHECK_PEER_GOTO(parent, done);
awtParent = (AwtCanvas*)pData;
JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
target = env->GetObjectField(peer, AwtObject::targetID);
JNI_CHECK_NULL_GOTO(target, "null target", done);
c = new AwtScrollbar();
{
jint orientation =
env->GetIntField(target, AwtScrollbar::orientationID);
c->m_orientation = (orientation == java_awt_Scrollbar_VERTICAL) ?
SB_VERT : SB_HORZ;
c->m_lineIncr =
env->GetIntField(target, AwtScrollbar::lineIncrementID);
c->m_pageIncr =
env->GetIntField(target, AwtScrollbar::pageIncrementID);
DWORD style = WS_CHILD | WS_CLIPSIBLINGS |
c->m_orientation;/* Note: SB_ and SBS_ are the same here */
jint x = env->GetIntField(target, AwtComponent::xID);
jint y = env->GetIntField(target, AwtComponent::yID);
jint width = env->GetIntField(target, AwtComponent::widthID);
jint height = env->GetIntField(target, AwtComponent::heightID);
c->CreateHWnd(env, L"", style, 0,
x, y, width, height,
awtParent->GetHWnd(),
reinterpret_cast<HMENU>(static_cast(
awtParent->CreateControlID())),
::GetSysColor(COLOR_SCROLLBAR),
::GetSysColor(COLOR_SCROLLBAR),
peer);
c->m_backgroundColorSet = TRUE;
/* suppress inheriting parent's color. */
c->UpdateBackground(env, target);
}
} catch (...) {
env->DeleteLocalRef(target);
throw;
}
done:
env->DeleteLocalRef(target);
return c;
}
LRESULT CALLBACK
AwtScrollbar::MouseFilter(int nCode, WPARAM wParam, LPARAM lParam)
{
if (((UINT)wParam == WM_LBUTTONUP || (UINT)wParam == WM_MOUSEMOVE) &&
ms_isInsideMouseFilter != TRUE &&
nCode >= 0)
{
HWND hwnd = ((PMOUSEHOOKSTRUCT)lParam)->hwnd;
AwtComponent *comp = AwtComponent::GetComponent(hwnd);
if (comp != NULL && comp->IsScrollbar()) {
MSG msg;
LPMSG lpMsg = (LPMSG)&msg;
UINT msgID = (UINT)wParam;
ms_isInsideMouseFilter = TRUE;
// Peek the message to get wParam containing the message's flags.
// <::PeekMessage> will call this hook again. To prevent recursive
// processing the <ms_isInsideMouseFilter> flag is used.
// Calling <::PeekMessage> is not so good desision but is the only one
// found to get those flags (used further in Java event creation).
// WARNING! If you are about to add new hook of WM_MOUSE type make
// it ready for recursive call, otherwise modify this one.
if (::PeekMessage(lpMsg, hwnd, msgID, msgID, PM_NOREMOVE)) {
comp->WindowProc(msgID, lpMsg->wParam, lpMsg->lParam);
}
ms_isInsideMouseFilter = FALSE;
}
}
return ::CallNextHookEx(AwtScrollbar::ms_hMouseFilter, nCode, wParam, lParam);
}
LRESULT
AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// Delegate real work to super
LRESULT retValue = AwtComponent::WindowProc(message, wParam, lParam);
// After-hooks for workarounds
switch (message) {
// Work around a windows bug described in KB article Q73839.
// Need to update focus indicator on scrollbar if thumb
// proportion or thumb position was changed.
case WM_SIZE:
case SBM_SETSCROLLINFO:
case SBM_SETRANGE:
case SBM_SETRANGEREDRAW:
if (AwtComponent::sm_focusOwner == GetHWnd()) {
UpdateFocusIndicator();
}
break;
}
return retValue;
}
MsgRouting
AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{
if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
retVal = HTCLIENT;
return mrConsume;
}
return AwtComponent::WmNcHitTest(x, y, retVal);
}
// Fix for a race condition when the WM_LBUTTONUP is picked by the AWT
// message loop before(!) the windows internal message loop for the
// scrollbar is started in response to WM_LBUTTONDOWN. See KB article
// Q102552.
//
// Note that WM_LBUTTONUP is processed by the windows internal message
// loop. May be we can synthesize a MOUSE_RELEASED event but that
// seems kludgey, so we'd better left this as is for now.
MsgRouting
AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button)
{
// We pass the WM_LBUTTONDOWN up to Java, but we process it
// immediately as well to avoid the race. Later when this press
// event returns to us wrapped into a WM_AWT_HANDLE_EVENT we
// ignore it in the HandleEvent below. This means that we can not
// consume the mouse press in the Java world.
MsgRouting usualRoute = AwtComponent::WmMouseDown(flags, x, y, button);
if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
return mrConsume;
}
if (button == LEFT_BUTTON)
return mrDoDefault; // Force immediate processing to avoid the race.
else
return usualRoute;
}
MsgRouting
AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
{
// SCROLLBAR control doesn't cause activation on mouse/key events,
// so we can safely (for synthetic focus) pass them to the system proc.
if (IsFocusingMouseMessage(msg)) {
// Left button press was already routed to default window
// procedure in the WmMouseDown above. Propagating synthetic
// press seems like a bad idea as internal message loop
// doesn't know how to unwrap synthetic release.
delete msg;
return mrConsume;
}
return AwtComponent::HandleEvent(msg, synthetic);
}
// Work around a windows bug descrbed in KB article Q73839. Reset
// focus on scrollbars to update focus indicator. The article advises
// to disable/enable the scrollbar.
void
AwtScrollbar::UpdateFocusIndicator()
{
if (IsFocusable()) {
// todo: doesn't work
SendMessage((WPARAM)ESB_DISABLE_BOTH);
SendMessage((WPARAM)ESB_ENABLE_BOTH);
}
}
// In a windows app one would call SetScrollInfo from WM_[HV]SCROLL
// handler directly. Since we call SetScrollInfo from Java world
// after scroll handler is over next WM_[HV]SCROLL event can be
// delivered before SetScrollInfo was called in response to the
// previous one and thus we would fire exactly the same event which
// will only contribute to the growth of the backlog of scroll events.
const char * const AwtScrollbar::SbNlineDown = "lineDown";
const char * const AwtScrollbar::SbNlineUp = "lineUp";
const char * const AwtScrollbar::SbNpageDown = "pageDown";
const char * const AwtScrollbar::SbNpageUp = "pageUp";
const char * const AwtScrollbar::SbNdrag = "drag";
const char * const AwtScrollbar::SbNdragEnd = "dragEnd";
const char * const AwtScrollbar::SbNwarp = "warp";
inline void
AwtScrollbar::DoScrollCallbackCoalesce(const char* methodName, int newPos)
{
if (methodName == m_prevCallback && newPos == m_prevCallbackPos) {
DTRACE_PRINTLN2("AwtScrollbar: ignoring duplicate callback %s(%d)",
methodName, newPos);
}
else {
DoCallback(methodName, "(I)V", newPos);
m_prevCallback = methodName;
m_prevCallbackPos = newPos;
}
}
MsgRouting
AwtScrollbar::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
{
int minVal, maxVal; // scrollbar range
int minPos, maxPos; // thumb positions (max depends on visible amount)
int curPos, newPos;
// For drags we have old (static) and new (dynamic) thumb positions
int dragP = (scrollCode == SB_THUMBTRACK
|| scrollCode == SB_THUMBPOSITION);
int thumbPos;
SCROLLINFO si;
si.cbSize = sizeof si;
si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
// From, _Win32 Programming_, by Rector and Newcommer, p. 185:
// "In some of the older documentation on Win32 scroll bars,
// including that published by Microsoft, you may read that
// you *cannot* obtain the scroll position while in a handler.
// The SIF_TRACKPOS flag was added after this documentation
// was published. Beware of this older documentation; it may
// have other obsolete features."
if (dragP) {
si.fMask |= SIF_TRACKPOS;
}
VERIFY(::GetScrollInfo(GetHWnd(), SB_CTL, &si));
curPos = si.nPos;
minPos = minVal = si.nMin;
// Upper bound of the range. Note that adding 1 here is safe
// and won't cause a wrap, since we have substracted 1 in the
// SetValues above.
maxVal = si.nMax + 1;
// Meaningful maximum position is maximum - visible.
maxPos = maxVal - si.nPage;
// XXX: Documentation for SBM_SETRANGE says that scrollbar
// range is limited by MAXLONG, which is 2**31, but when a
// scroll range is greater than that, thumbPos is reported
// incorrectly due to integer arithmetic wrap(s).
thumbPos = dragP ? si.nTrackPos : curPos;
// NB: Beware arithmetic wrap when calculating newPos
switch (scrollCode) {
case SB_LINEUP:
if ((__int64)curPos - m_lineIncr > minPos)
newPos = curPos - m_lineIncr;
else
newPos = minPos;
if (newPos != curPos)
DoScrollCallbackCoalesce(SbNlineUp, newPos);
break;
case SB_LINEDOWN:
if ((__int64)curPos + m_lineIncr < maxPos)
newPos = curPos + m_lineIncr;
else
newPos = maxPos;
if (newPos != curPos)
DoScrollCallbackCoalesce(SbNlineDown, newPos);
break;
case SB_PAGEUP:
if ((__int64)curPos - m_pageIncr > minPos)
newPos = curPos - m_pageIncr;
else
newPos = minPos;
if (newPos != curPos)
DoScrollCallbackCoalesce(SbNpageUp, newPos);
break;
case SB_PAGEDOWN:
if ((__int64)curPos + m_pageIncr < maxPos)
newPos = curPos + m_pageIncr;
else
newPos = maxPos;
if (newPos != curPos)
DoScrollCallbackCoalesce(SbNpageDown, newPos);
break;
case SB_TOP:
if (minPos != curPos)
DoScrollCallbackCoalesce(SbNwarp, minPos);
break;
case SB_BOTTOM:
if (maxPos != curPos)
DoScrollCallbackCoalesce(SbNwarp, maxPos);
break;
case SB_THUMBTRACK:
if (thumbPos != curPos)
DoScrollCallbackCoalesce(SbNdrag, thumbPos);
break;
case SB_THUMBPOSITION:
DoScrollCallbackCoalesce(SbNdragEnd, thumbPos);
break;
case SB_ENDSCROLL:
// reset book-keeping info
m_prevCallback = NULL;
break;
}
return mrDoDefault;
}
MsgRouting
AwtScrollbar::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
{
return WmVScroll(scrollCode, pos, hScrollbar);
}
void AwtScrollbar::_SetValues(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SetValuesStruct *svs = (SetValuesStruct *)param;
jobject self = svs->scrollbar;
SCROLLINFO si;
si.cbSize = sizeof si;
si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
si.nMin = svs->min;
si.nMax = svs->max - 1;
si.nPage = svs->visible;
si.nPos = svs->value;
AwtScrollbar *sb = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
sb = (AwtScrollbar *)pData;
if (::IsWindow(sb->GetHWnd()))
{
BOOL update_p = ::IsWindowEnabled(sb->GetHWnd()); // don't redraw if disabled
DTRACE_PRINTLN5("AwtScrollbar::SetValues(val = %d, vis = %d,"//(ctd.)
" min = %d, max = %d)%s",
svs->value, svs->visible, svs->min, svs->max,
update_p ? "" : " - NOT redrawing");
::SetScrollInfo(sb->GetHWnd(), SB_CTL, &si, update_p);
}
ret:
env->DeleteGlobalRef(self);
delete svs;
}
/************************************************************************
* Scrollbar native methods
*/
extern "C" {
/*
* Class: java_awt_Scrollbar
* Method: initIDs
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_java_awt_Scrollbar_initIDs(JNIEnv *env, jclass cls)
{
TRY;
AwtScrollbar::lineIncrementID = env->GetFieldID(cls, "lineIncrement", "I");
AwtScrollbar::pageIncrementID = env->GetFieldID(cls, "pageIncrement", "I");
AwtScrollbar::orientationID = env->GetFieldID(cls, "orientation", "I");
DASSERT(AwtScrollbar::lineIncrementID != NULL);
DASSERT(AwtScrollbar::pageIncrementID != NULL);
DASSERT(AwtScrollbar::orientationID != NULL);
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* WScrollbarPeer native methods
*/
extern "C" {
/*
* Class: sun_awt_windows_WScrollbarPeer
* Method: setValues
* Signature: (IIII)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setValues(JNIEnv *env, jobject self,
jint value, jint visible,
jint minimum, jint maximum)
{
TRY;
SetValuesStruct *svs = new SetValuesStruct;
svs->scrollbar = env->NewGlobalRef(self);
svs->value = value;
svs->visible = visible;
svs->min = minimum;
svs->max = maximum;
AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetValues, svs);
// global ref and svs are deleted in _SetValues
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WScrollbarPeer
* Method: setLineIncrement
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setLineIncrement(JNIEnv *env, jobject self,
jint increment)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
AwtScrollbar* c = (AwtScrollbar*)pData;
c->SetLineIncrement(increment);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WScrollbarPeer
* Method: setPageIncrement
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setPageIncrement(JNIEnv *env, jobject self,
jint increment)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
AwtScrollbar* c = (AwtScrollbar*)pData;
c->SetPageIncrement(increment);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WScrollbarPeer
* Method: create
* Signature: (Lsun/awt/windows/WComponentPeer;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_create(JNIEnv *env, jobject self,
jobject parent)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(parent);
AwtToolkit::CreateComponent(self, parent,
(AwtToolkit::ComponentFactory)
AwtScrollbar::Create);
JNI_CHECK_PEER_CREATION_RETURN(self);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WScrollbarPeer
* Method: getScrollbarSize
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_windows_WScrollbarPeer_getScrollbarSize(JNIEnv *env, jclass clazz, jint orientation)
{
if (orientation == java_awt_Scrollbar_VERTICAL) {
return ::GetSystemMetrics(SM_CXVSCROLL);
} else {
return ::GetSystemMetrics(SM_CYHSCROLL);
}
}
} /* extern "C" */
Other Java examples (source code examples)
Here is a short list of links related to this Java awt_Scrollbar.cpp source code file:
|