blob: 5188c85984fe055af99494a0982957168328e2b6 [file] [log] [blame]
/*
* Copyright (c) 1996, 2014, 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_List.h"
#include "awt_Canvas.h"
#include "awt_Dimension.h"
#include "awt_Toolkit.h"
#include "awt_Window.h"
#include "ComCtl32Util.h"
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
/***********************************************************************/
// struct for _AddItems() method
struct AddItemsStruct {
jobject list;
jobjectArray items;
jint index;
jint width;
};
// struct for _DelItems() method
struct DelItemsStruct {
jobject list;
jint start, end;
};
// struct for _IsSelected(), _Select(), _Deselect() and _MakeVisible() methods
struct SelectElementStruct {
jobject list;
jint index;
};
// struct for _SetMultipleSelections() method
struct SetMultipleSelectionsStruct {
jobject list;
jboolean on;
};
/************************************************************************
* AwtList methods
*/
AwtList::AwtList() {
isMultiSelect = FALSE;
isWrapperPrint = FALSE;
}
AwtList::~AwtList()
{
}
LPCTSTR AwtList::GetClassName() {
return TEXT("LISTBOX");
}
/* Create a new AwtList object and window. */
AwtList* AwtList::Create(jobject peer, jobject parent)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = NULL;
AwtList* 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 is Hjava_awt_List * */
target = env->GetObjectField(peer, AwtObject::targetID);
JNI_CHECK_NULL_GOTO(target, "null target", done);
c = new AwtList();
{
/*
* NOTE: WS_CLIPCHILDREN is excluded so that repaint requests
* from Java will pass through the wrap to the native listbox.
*/
DWORD wrapStyle = WS_CHILD | WS_CLIPSIBLINGS;
DWORD wrapExStyle = 0;
DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL |
LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_OWNERDRAWFIXED;
DWORD exStyle = WS_EX_CLIENTEDGE;
/*
* NOTE: WS_VISIBLE is always set for the listbox. Listbox
* visibility is controlled by toggling the wrap's WS_VISIBLE bit.
*/
style |= WS_VISIBLE;
if (GetRTL()) {
exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
if (GetRTLReadingOrder())
exStyle |= WS_EX_RTLREADING;
}
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, exStyle,
x, y, width, height,
awtParent->GetHWnd(),
NULL,
::GetSysColor(COLOR_WINDOWTEXT),
::GetSysColor(COLOR_WINDOW),
peer
);
/* suppress inheriting awtParent's color. */
c->m_backgroundColorSet = TRUE;
c->UpdateBackground(env, target);
}
} catch (...) {
env->DeleteLocalRef(target);
throw;
}
done:
env->DeleteLocalRef(target);
return c;
}
void AwtList::SetDragCapture(UINT flags)
{
// don't want to interfere with other controls
if (::GetCapture() == NULL) {
::SetCapture(GetListHandle());
}
}
void AwtList::ReleaseDragCapture(UINT flags)
{
if ((::GetCapture() == GetListHandle()) && ((flags & ALL_MK_BUTTONS) == 0)) {
::ReleaseCapture();
}
}
void AwtList::Reshape(int x, int y, int w, int h)
{
AwtComponent::Reshape(x, y, w, h);
/*
HWND hList = GetListHandle();
if (hList != NULL) {
long flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS;
/*
* Fix for bug 4046446.
* /
SetWindowPos(hList, 0, 0, 0, w, h, flags);
}
*/
}
//Netscape : Override the AwtComponent method so we can set the item height
//for each item in the list. Modified by echawkes to avoid race condition.
void AwtList::SetFont(AwtFont* font)
{
DASSERT(font != NULL);
if (font->GetAscent() < 0)
{
AwtFont::SetupAscent(font);
}
HANDLE hFont = font->GetHFont();
SendListMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0));
HDC hDC = ::GetDC(GetHWnd());
TEXTMETRIC tm;
VERIFY(::SelectObject(hDC, hFont) != NULL);
VERIFY(::GetTextMetrics(hDC, &tm));
::ReleaseDC(GetHWnd(), hDC);
long h = tm.tmHeight + tm.tmExternalLeading;
// Listbox is LBS_OWNERDRAWFIXED so the items have the same height
VERIFY(SendListMessage(LB_SETITEMHEIGHT, 0, MAKELPARAM(h, 0)) != LB_ERR);
VERIFY(::RedrawWindow(GetHWnd(), NULL, NULL, RDW_INVALIDATE |RDW_FRAME |RDW_ERASE));
}
void AwtList::SetMultiSelect(BOOL ms) {
if (ms == isMultiSelect) {
return;
}
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
/* Copy current box's contents to string array */
const int nCount = GetCount();
LPTSTR * strings = new LPTSTR[nCount];
int i;
for(i = 0; i < nCount; i++) {
LRESULT len = SendListMessage(LB_GETTEXTLEN, i);
LPTSTR text = NULL;
try {
text = new TCHAR[len + 1];
} catch (std::bad_alloc&) {
// free char * already allocated
for (int j = 0; j < i; j++) {
delete [] strings[j];
}
delete [] strings;
throw;
}
VERIFY(SendListMessage(LB_GETTEXT, i, (LPARAM)text) != LB_ERR);
strings[i] = text;
}
// index for selected item after multi-select mode change
int toSelect = SendListMessage(LB_GETCURSEL);
if (!isMultiSelect)
{
// MSDN: for single-select lists LB_GETCURSEL returns
// index of selected item or LB_ERR if no item is selected
if (toSelect == LB_ERR)
{
toSelect = -1;
}
}
else
{
// MSDN: for multi-select lists LB_GETCURSEL returns index
// of the focused item or 0 if no items are selected; if
// some item has focus and is not selected then LB_GETCURSEL
// return its index, so we need IsItemSelected too
if ((toSelect == LB_ERR) ||
(SendListMessage(LB_GETSELCOUNT) == 0) ||
(IsItemSelected(toSelect) == 0))
{
toSelect = -1;
}
}
isMultiSelect = ms;
HWND parentHWnd = GetParent()->GetHWnd();
/* Save old list box's attributes */
RECT rect;
GetWindowRect(GetListHandle(), &rect);
MapWindowPoints(0, parentHWnd, (LPPOINT)&rect, 2);
HANDLE font = (HANDLE)SendListMessage(WM_GETFONT);
LRESULT itemHeight = SendListMessage(LB_GETITEMHEIGHT, 0);
DWORD style = ::GetWindowLong(GetListHandle(), GWL_STYLE) | WS_VSCROLL | WS_HSCROLL;
if (isMultiSelect) {
style |= LBS_MULTIPLESEL;
} else {
style &= ~LBS_MULTIPLESEL;
}
DWORD exStyle = ::GetWindowLong(GetListHandle(), GWL_EXSTYLE);
jobject peer = GetPeer(env);
UnsubclassHWND();
AwtToolkit::DestroyComponentHWND(m_hwnd);
CreateHWnd(env, L"", style, exStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
parentHWnd,
NULL,
::GetSysColor(COLOR_WINDOWTEXT),
::GetSysColor(COLOR_WINDOW),
peer);
SendListMessage(WM_SETFONT, (WPARAM)font, (LPARAM)FALSE);
SendListMessage(LB_SETITEMHEIGHT, 0, MAKELPARAM(itemHeight, 0));
SendListMessage(LB_RESETCONTENT);
for (i = 0; i < nCount; i++) {
InsertString(i, strings[i]);
delete [] strings[i];
}
delete[] strings;
if (toSelect != -1) {
Select(toSelect);
}
AdjustHorizontalScrollbar();
}
/*
* There currently is no good place to cache java.awt.Dimension field
* ids. If this method gets called a lot, one such place should be found.
* -- br 07/18/97.
*/
jobject AwtList::PreferredItemSize(JNIEnv *env)
{
jobject peer = GetPeer(env);
jobject dimension = JNU_CallMethodByName(env, NULL, peer, "preferredSize",
"(I)Ljava/awt/Dimension;",
1).l;
DASSERT(!safe_ExceptionOccurred(env));
if (dimension == NULL) {
return NULL;
}
/* This size is too big for each item height. */
(env)->SetIntField(dimension, AwtDimension::heightID, GetFontHeight(env));
return dimension;
}
// Every time something gets added to the list, we increase the max width
// of items that have ever been added. If it surpasses the width of the
// listbox, we show the scrollbar. When things get deleted, we shrink
// the scroll region back down and hide the scrollbar, if needed.
void AwtList::AdjustHorizontalScrollbar()
{
// The border width is added to the horizontal extent to ensure that we
// can view all of the text when we move the horz. scrollbar to the end.
int cxBorders = GetSystemMetrics( SM_CXBORDER ) * 2;
RECT rect;
VERIFY(::GetClientRect(GetListHandle(), &rect));
LRESULT iHorzExt = SendListMessage(LB_GETHORIZONTALEXTENT, 0, 0L ) - cxBorders;
if ( (m_nMaxWidth > rect.left) // if strings wider than listbox
|| (iHorzExt != m_nMaxWidth) ) // or scrollbar not needed anymore.
{
SendListMessage(LB_SETHORIZONTALEXTENT, m_nMaxWidth + cxBorders, 0L);
}
}
// This function goes through all strings in the list to find the width,
// in pixels, of the longest string in the list.
void AwtList::UpdateMaxItemWidth()
{
m_nMaxWidth = 0;
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->EnsureLocalCapacity(2) < 0)
return;
HDC hDC = ::GetDC(GetHWnd());
jobject self = GetPeer(env);
DASSERT(self);
/* target is java.awt.List */
jobject target = env->GetObjectField(self, AwtObject::targetID);
jobject font = GET_FONT(target, self);
int nCount = GetCount();
for ( int i=0; i < nCount; i++ )
{
jstring jstr = GetItemString( env, target, i );
SIZE size = AwtFont::getMFStringSize( hDC, font, jstr );
if ( size.cx > m_nMaxWidth )
m_nMaxWidth = size.cx;
env->DeleteLocalRef( jstr );
}
// free up the shared DC and release local refs
::ReleaseDC(GetHWnd(), hDC);
env->DeleteLocalRef( target );
env->DeleteLocalRef( font );
// Now adjust the horizontal scrollbar extent
AdjustHorizontalScrollbar();
}
MsgRouting
AwtList::WmSize(UINT type, int w, int h)
{
AdjustHorizontalScrollbar();
return AwtComponent::WmSize(type, w, h);
}
MsgRouting
AwtList::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
{
AwtComponent::DrawListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), drawInfo);
return mrConsume;
}
MsgRouting
AwtList::OwnerMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT& measureInfo)
{
AwtComponent::MeasureListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), measureInfo);
return mrConsume;
}
MsgRouting
AwtList::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{
if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
retVal = HTCLIENT;
return mrConsume;
}
return AwtComponent::WmNcHitTest(x, y, retVal);
}
MsgRouting
AwtList::WmMouseUp(UINT flags, int x, int y, int button)
{
MsgRouting result = mrDoDefault;
// if this list is in the modal blocked window, this message should be consumed,
// however AwtComponent::WmMouseUp must be called anyway
if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
result = mrConsume;
} else {
if (button == LEFT_BUTTON) {
WmCommand(0, GetListHandle(), LBN_SELCHANGE);
}
}
MsgRouting compResult = AwtComponent::WmMouseUp(flags, x, y, button);
return (result == mrConsume) ? result : compResult;
}
MsgRouting
AwtList::WmMouseDown(UINT flags, int x, int y, int button)
{
MsgRouting mrResult = AwtComponent::WmMouseDown(flags, x, y, button);
if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd()))))
{
return mrConsume;
}
/*
* As we consume WM_LBUTONDOWN the list won't trigger ActionEvent by double click.
* We trigger it ourselves. (see also 6240202)
*/
int clickCount = GetClickCount();
if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0) {
WmCommand(0, GetListHandle(), LBN_DBLCLK);
}
return mrResult;
}
MsgRouting
AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush)
{
DASSERT(ctlColor == CTLCOLOR_LISTBOX);
DASSERT(hCtrl == GetListHandle());
::SetBkColor(hDC, GetBackgroundColor());
::SetTextColor(hDC, GetColor());
retBrush = GetBackgroundBrush();
return mrConsume;
}
BOOL AwtList::IsFocusingMouseMessage(MSG *pMsg)
{
return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
}
MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic)
{
if (IsFocusingMouseMessage(msg)) {
LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, msg->lParam));
if (item != LB_ERR) {
if (isMultiSelect) {
if (IsItemSelected(item)) {
Deselect(item);
} else {
Select(item);
}
} else {
Select(item);
}
}
delete msg;
return mrConsume;
}
if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) {
WmNotify(LBN_DBLCLK);
}
return AwtComponent::HandleEvent(msg, synthetic);
}
// Fix for 4665745.
// Override WmPrint to catch when the list control (not wrapper) should
// operate WM_PRINT to be compatible with the "smooth scrolling" feature.
MsgRouting AwtList::WmPrint(HDC hDC, LPARAM flags)
{
if (!isWrapperPrint &&
(flags & PRF_CLIENT) &&
(GetStyleEx() & WS_EX_CLIENTEDGE))
{
int nOriginalDC = ::SaveDC(hDC);
DASSERT(nOriginalDC != 0);
// Save a copy of the DC for WmPrintClient
VERIFY(::SaveDC(hDC));
DefWindowProc(WM_PRINT, (WPARAM) hDC,
(flags & (PRF_CLIENT | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
VERIFY(::RestoreDC(hDC, nOriginalDC));
flags &= ~PRF_CLIENT;
}
return AwtComponent::WmPrint(hDC, flags);
}
MsgRouting
AwtList::WmNotify(UINT notifyCode)
{
if (notifyCode == LBN_SELCHANGE || notifyCode == LBN_DBLCLK) {
/* Fixed an asserion failure when clicking on an empty List. */
int nCurrentSelection = SendListMessage(LB_GETCURSEL);
if (nCurrentSelection != LB_ERR && GetCount() > 0) {
if (notifyCode == LBN_SELCHANGE) {
DoCallback("handleListChanged", "(I)V", nCurrentSelection);
}
else if (notifyCode == LBN_DBLCLK) {
DoCallback("handleAction", "(IJI)V", nCurrentSelection,
TimeHelper::getMessageTimeUTC(),
(jint)AwtComponent::GetJavaModifiers());
}
}
}
return mrDoDefault;
}
BOOL AwtList::InheritsNativeMouseWheelBehavior() {return true;}
jint AwtList::_GetMaxWidth(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject self = (jobject)param;
jint result = 0;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList *)pData;
if (::IsWindow(l->GetHWnd()))
{
result = l->GetMaxWidth();
}
ret:
env->DeleteGlobalRef(self);
return result;
}
void AwtList::_UpdateMaxItemWidth(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject self = (jobject)param;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList *)pData;
if (::IsWindow(l->GetHWnd()))
{
l->UpdateMaxItemWidth();
}
ret:
env->DeleteGlobalRef(self);
}
void AwtList::_AddItems(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
AddItemsStruct *ais = (AddItemsStruct *)param;
jobject self = ais->list;
jobjectArray items = ais->items;
jint index = ais->index;
jint width = ais->width;
int badAlloc = 0;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
JNI_CHECK_NULL_GOTO(items, "null items", ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
int itemCount = env->GetArrayLength(items);
if (itemCount > 0)
{
AwtList* l = (AwtList*)pData;
l->SendListMessage(WM_SETREDRAW, (WPARAM)FALSE, 0);
for (jsize i=0; i < itemCount; i++)
{
LPTSTR itemPtr = NULL;
jstring item = (jstring)env->GetObjectArrayElement(items, i);
if (env->ExceptionCheck()) goto ret;
if (item == NULL) goto next_item;
itemPtr = (LPTSTR)JNU_GetStringPlatformChars(env, item, 0);
if (itemPtr == NULL)
{
badAlloc = 1;
}
else
{
l->InsertString(index+i, itemPtr);
JNU_ReleaseStringPlatformChars(env, item, itemPtr);
}
env->DeleteLocalRef(item);
next_item:
;
}
l->SendListMessage(WM_SETREDRAW, (WPARAM)TRUE, 0);
l->InvalidateList(NULL, TRUE);
l->CheckMaxWidth(width);
}
}
ret:
env->DeleteGlobalRef(self);
env->DeleteGlobalRef(items);
delete ais;
if (badAlloc)
{
throw std::bad_alloc();
}
}
void AwtList::_DelItems(void *param)
{ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
DelItemsStruct *dis = (DelItemsStruct *)param;
jobject self = dis->list;
jint start = dis->start;
jint end = dis->end;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
int count = l->GetCount();
if (start == 0 && end == count)
{
l->SendListMessage(LB_RESETCONTENT);
}
else
{
for (int i = start; i <= end; i++)
{
l->SendListMessage(LB_DELETESTRING, start);
}
}
l->UpdateMaxItemWidth();
}
ret:
env->DeleteGlobalRef(self);
delete dis;
}
void AwtList::_Select(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SelectElementStruct *ses = (SelectElementStruct *)param;
jobject self = ses->list;
jint index = ses->index;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
l->Select(index);
}
ret:
env->DeleteGlobalRef(self);
delete ses;
}
void AwtList::_Deselect(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SelectElementStruct *ses = (SelectElementStruct *)param;
jobject self = ses->list;
jint index = ses->index;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
l->Deselect(index);
}
ret:
env->DeleteGlobalRef(self);
delete ses;
}
void AwtList::_MakeVisible(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SelectElementStruct *ses = (SelectElementStruct *)param;
jobject self = ses->list;
jint index = ses->index;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
l->SendListMessage(LB_SETTOPINDEX, index);
}
ret:
env->DeleteGlobalRef(self);
delete ses;
}
jboolean AwtList::_IsSelected(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SelectElementStruct *ses = (SelectElementStruct *)param;
jobject self = ses->list;
jint index = ses->index;
jboolean result = JNI_FALSE;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
result = l->IsItemSelected(index);
}
ret:
env->DeleteGlobalRef(self);
delete ses;
return result;
}
void AwtList::_SetMultipleSelections(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SetMultipleSelectionsStruct *sms = (SetMultipleSelectionsStruct *)param;
jobject self = sms->list;
jboolean on = sms->on;
AwtList *l = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
l = (AwtList*)pData;
if (::IsWindow(l->GetHWnd()))
{
AwtToolkit::GetInstance().SendMessage(WM_AWT_LIST_SETMULTISELECT,
(WPARAM)self, on);
}
ret:
env->DeleteGlobalRef(self);
delete sms;
}
/************************************************************************
* WListPeer native methods
*
* This class seems to have numerous bugs in it, but they are all bugs
* which were present before conversion to JNI. -br.
*/
extern "C" {
/*
* Class: sun_awt_windows_WListPeer
* Method: getMaxWidth
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_windows_WListPeer_getMaxWidth(JNIEnv *env, jobject self)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
return (jint)AwtToolkit::GetInstance().SyncCall(
(void *(*)(void *))AwtList::_GetMaxWidth,
(void *)selfGlobalRef);
// selfGlobalRef is deleted in _GetMaxWidth
CATCH_BAD_ALLOC_RET(0);
}
/*
* Class: sun_awt_windows_WListPeer
* Method: updateMaxItemWidth
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_updateMaxItemWidth(JNIEnv *env, jobject self)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
AwtToolkit::GetInstance().SyncCall(AwtList::_UpdateMaxItemWidth,
(void *)selfGlobalRef);
// selfGlobalRef is deleted in _UpdateMaxItemWidth
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: addItems
* Signature: ([Ljava/lang/String;II)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_addItems(JNIEnv *env, jobject self,
jobjectArray items, jint index, jint width)
{
TRY;
AddItemsStruct *ais = new AddItemsStruct;
ais->list = env->NewGlobalRef(self);
ais->items = (jobjectArray)env->NewGlobalRef(items);
ais->index = index;
ais->width = width;
AwtToolkit::GetInstance().SyncCall(AwtList::_AddItems, ais);
// global refs and ais are deleted in _AddItems()
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: delItems
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_delItems(JNIEnv *env, jobject self,
jint start, jint end)
{
TRY;
DelItemsStruct *dis = new DelItemsStruct;
dis->list = env->NewGlobalRef(self);
dis->start = start;
dis->end = end;
AwtToolkit::GetInstance().SyncCall(AwtList::_DelItems, dis);
// global ref and dis are deleted in _DelItems
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: select
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_select(JNIEnv *env, jobject self,
jint pos)
{
TRY;
SelectElementStruct *ses = new SelectElementStruct;
ses->list = env->NewGlobalRef(self);
ses->index = pos;
AwtToolkit::GetInstance().SyncCall(AwtList::_Select, ses);
// global ref and ses are deleted in _Select
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: deselect
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_deselect(JNIEnv *env, jobject self,
jint pos)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
SelectElementStruct *ses = new SelectElementStruct;
ses->list = env->NewGlobalRef(self);
ses->index = pos;
AwtToolkit::GetInstance().SyncCall(AwtList::_Deselect, ses);
// global ref and ses are deleted in _Deselect
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: makeVisible
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_makeVisible(JNIEnv *env, jobject self,
jint pos)
{
TRY;
SelectElementStruct *ses = new SelectElementStruct;
ses->list = env->NewGlobalRef(self);
ses->index = pos;
AwtToolkit::GetInstance().SyncCall(AwtList::_MakeVisible, ses);
// global ref and ses are deleted in _MakeVisible
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: setMultipleSelections
* Signature: (Z)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_setMultipleSelections(JNIEnv *env, jobject self,
jboolean on)
{
TRY;
SetMultipleSelectionsStruct *sms = new SetMultipleSelectionsStruct;
sms->list = env->NewGlobalRef(self);
sms->on = on;
AwtToolkit::GetInstance().SyncCall(AwtList::_SetMultipleSelections, sms);
// global ref and sms are deleted in AwtList::_SetMultipleSelections
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: create
* Signature: (Lsun/awt/windows/WComponentPeer;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WListPeer_create(JNIEnv *env, jobject self,
jobject parent)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(parent);
AwtToolkit::CreateComponent(self, parent,
(AwtToolkit::ComponentFactory)AwtList::Create);
JNI_CHECK_PEER_CREATION_RETURN(self);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WListPeer
* Method: isSelected
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WListPeer_isSelected(JNIEnv *env, jobject self,
jint index)
{
TRY;
SelectElementStruct *ses = new SelectElementStruct;
ses->list = env->NewGlobalRef(self);
ses->index = index;
return (jboolean)AwtToolkit::GetInstance().SyncCall(
(void *(*)(void *))AwtList::_IsSelected, ses);
// global ref and ses are deleted in _IsSelected
CATCH_BAD_ALLOC_RET(FALSE);
}
} /* extern "C" */