blob: 8c1621afec6f39a80461ecbb58a6dc7f76da1542 [file] [log] [blame]
/*
* Copyright (c) 1996, 2008, 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 <windowsx.h>
#include "awt_Toolkit.h"
#include "awt_Choice.h"
#include "awt_Canvas.h"
#include "awt_Dimension.h"
#include "awt_Container.h"
#include "ComCtl32Util.h"
#include <java_awt_Toolkit.h>
#include <java_awt_FontMetrics.h>
#include <java_awt_event_InputEvent.h>
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
/************************************************************************/
// Struct for _Reshape() method
struct ReshapeStruct {
jobject choice;
jint x, y;
jint width, height;
};
// Struct for _Select() method
struct SelectStruct {
jobject choice;
jint index;
};
// Struct for _AddItems() method
struct AddItemsStruct {
jobject choice;
jobjectArray items;
jint index;
};
// Struct for _Remove() method
struct RemoveStruct {
jobject choice;
jint index;
};
/************************************************************************/
/* Bug #4509045: set if SetDragCapture captured mouse */
BOOL AwtChoice::mouseCapture = FALSE;
/* Bug #4338368: consume the spurious MouseUp when the choice loses focus */
BOOL AwtChoice::skipNextMouseUp = FALSE;
BOOL AwtChoice::sm_isMouseMoveInList = FALSE;
static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8;
/*************************************************************************
* AwtChoice class methods
*/
AwtChoice::AwtChoice() {
m_hList = NULL;
m_listDefWindowProc = NULL;
}
LPCTSTR AwtChoice::GetClassName() {
return TEXT("COMBOBOX"); /* System provided combobox class */
}
void AwtChoice::Dispose() {
if (m_hList != NULL && m_listDefWindowProc != NULL) {
ComCtl32Util::GetInstance().UnsubclassHWND(m_hList, ListWindowProc, m_listDefWindowProc);
}
AwtComponent::Dispose();
}
AwtChoice* AwtChoice::Create(jobject peer, jobject parent) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = NULL;
AwtChoice* c = NULL;
RECT rc;
try {
if (env->EnsureLocalCapacity(1) < 0) {
return NULL;
}
AwtCanvas* awtParent;
JNI_CHECK_NULL_GOTO(parent, "null parent", done);
awtParent = (AwtCanvas*)JNI_GET_PDATA(parent);
JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
target = env->GetObjectField(peer, AwtObject::targetID);
JNI_CHECK_NULL_GOTO(target, "null target", done);
c = new AwtChoice();
{
DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL |
CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED;
DWORD exStyle = 0;
if (GetRTL()) {
exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
if (GetRTLReadingOrder())
exStyle |= WS_EX_RTLREADING;
}
/*
* In OWNER_DRAW, the size of the edit control part of the
* choice must be determinded in its creation, when the parent
* cannot get the choice's instance from its handle. So
* record the pair of the ID and the instance of the choice.
*/
UINT myId = awtParent->CreateControlID();
DASSERT(myId > 0);
c->m_myControlID = myId;
awtParent->PushChild(myId, c);
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);
jobject dimension = JNU_CallMethodByName(env, NULL, peer,
"preferredSize",
"()Ljava/awt/Dimension;").l;
DASSERT(!safe_ExceptionOccurred(env));
if (dimension != NULL && width == 0) {
width = env->GetIntField(dimension, AwtDimension::widthID);
}
c->CreateHWnd(env, L"", style, exStyle,
x, y, width, height,
awtParent->GetHWnd(),
reinterpret_cast<HMENU>(static_cast<INT_PTR>(myId)),
::GetSysColor(COLOR_WINDOWTEXT),
::GetSysColor(COLOR_WINDOW),
peer);
/* suppress inheriting parent's color. */
c->m_backgroundColorSet = TRUE;
c->UpdateBackground(env, target);
/* Bug 4255631 Solaris: Size returned by Choice.getSize() does not match
* actual size
* Fix: Set the Choice to its actual size in the component.
*/
::GetClientRect(c->GetHWnd(), &rc);
env->SetIntField(target, AwtComponent::widthID, (jint) rc.right);
env->SetIntField(target, AwtComponent::heightID, (jint) rc.bottom);
if (IS_WINXP) {
::SendMessage(c->GetHWnd(), CB_SETMINVISIBLE, (WPARAM) MINIMUM_NUMBER_OF_VISIBLE_ITEMS, 0);
}
env->DeleteLocalRef(dimension);
}
} catch (...) {
env->DeleteLocalRef(target);
throw;
}
done:
env->DeleteLocalRef(target);
return c;
}
// calculate height of drop-down list part of the combobox
// to show all the items up to a maximum of eight
int AwtChoice::GetDropDownHeight()
{
int itemHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)0,0);
int numItemsToShow = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0,0);
numItemsToShow = min(MINIMUM_NUMBER_OF_VISIBLE_ITEMS, numItemsToShow);
// drop-down height snaps to nearest line, so add a
// fudge factor of 1/2 line to ensure last line shows
return itemHeight*numItemsToShow + itemHeight/2;
}
// get the height of the field portion of the combobox
int AwtChoice::GetFieldHeight()
{
int fieldHeight;
int borderHeight;
fieldHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)-1, 0);
// add top and bottom border lines; border size is different for
// Win 4.x (3d edge) vs 3.x (1 pixel line)
borderHeight = ::GetSystemMetrics(SM_CYEDGE);
fieldHeight += borderHeight*2;
return fieldHeight;
}
// gets the total height of the combobox, including drop down
int AwtChoice::GetTotalHeight()
{
int dropHeight = GetDropDownHeight();
int fieldHeight = GetFieldHeight();
int totalHeight;
// border on drop-down portion is always non-3d (so don't use SM_CYEDGE)
int borderHeight = ::GetSystemMetrics(SM_CYBORDER);
// total height = drop down height + field height + top+bottom drop down border lines
totalHeight = dropHeight + fieldHeight +borderHeight*2;
return totalHeight;
}
// Recalculate and set the drop-down height for the Choice.
void AwtChoice::ResetDropDownHeight()
{
RECT rcWindow;
::GetWindowRect(GetHWnd(), &rcWindow);
// resize the drop down to accomodate added/removed items
int totalHeight = GetTotalHeight();
::SetWindowPos(GetHWnd(), NULL,
0, 0, rcWindow.right - rcWindow.left, totalHeight,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
}
/* Fix for the bug 4327666: set the capture for middle
and right mouse buttons, but leave left button alone */
void AwtChoice::SetDragCapture(UINT flags)
{
if ((flags & MK_LBUTTON) != 0) {
if ((::GetCapture() == GetHWnd()) && mouseCapture) {
/* On MK_LBUTTON ComboBox captures mouse itself
so we should release capture and clear flag to
prevent releasing capture by ReleaseDragCapture
*/
::ReleaseCapture();
mouseCapture = FALSE;
}
return;
}
// don't want to interfere with other controls
if (::GetCapture() == NULL) {
::SetCapture(GetHWnd());
mouseCapture = TRUE;
}
}
/* Fix for Bug 4509045: should release capture only if it is set by SetDragCapture */
void AwtChoice::ReleaseDragCapture(UINT flags)
{
if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0) && mouseCapture) {
::ReleaseCapture();
mouseCapture = FALSE;
}
}
void AwtChoice::Reshape(int x, int y, int w, int h)
{
// Choice component height is fixed (when rolled up)
// so vertically center the choice in it's bounding box
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
jobject parent = env->GetObjectField(target, AwtComponent::parentID);
RECT rc;
int fieldHeight = GetFieldHeight();
if ((parent != NULL && env->GetObjectField(parent, AwtContainer::layoutMgrID) != NULL) &&
fieldHeight > 0 && fieldHeight < h) {
y += (h - fieldHeight) / 2;
}
/* Fix for 4783342
* Choice should ignore reshape on height changes,
* as height is dependent on Font size only.
*/
AwtComponent* awtParent = GetParent();
BOOL bReshape = true;
if (awtParent != NULL) {
::GetWindowRect(GetHWnd(), &rc);
int oldW = rc.right - rc.left;
RECT parentRc;
::GetWindowRect(awtParent->GetHWnd(), &parentRc);
int oldX = rc.left - parentRc.left;
int oldY = rc.top - parentRc.top;
bReshape = (x != oldX || y != oldY || w != oldW);
}
if (bReshape)
{
int totalHeight = GetTotalHeight();
AwtComponent::Reshape(x, y, w, totalHeight);
}
/* Bug 4255631 Solaris: Size returned by Choice.getSize() does not match
* actual size
* Fix: Set the Choice to its actual size in the component.
*/
::GetClientRect(GetHWnd(), &rc);
env->SetIntField(target, AwtComponent::widthID, (jint)rc.right);
env->SetIntField(target, AwtComponent::heightID, (jint)rc.bottom);
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);
}
jobject AwtChoice::PreferredItemSize(JNIEnv *env)
{
jobject dimension = JNU_CallMethodByName(env, NULL, GetPeer(env),
"preferredSize",
"()Ljava/awt/Dimension;").l;
DASSERT(!safe_ExceptionOccurred(env));
if (dimension == NULL) {
return NULL;
}
/* This size is window size of choice and it's too big for each
* drop down item height.
*/
env->SetIntField(dimension, AwtDimension::heightID,
GetFontHeight(env));
return dimension;
}
void AwtChoice::SetFont(AwtFont* font)
{
AwtComponent::SetFont(font);
//Get the text metrics and change the height of each item.
HDC hDC = ::GetDC(GetHWnd());
DASSERT(hDC != NULL);
TEXTMETRIC tm;
HANDLE hFont = font->GetHFont();
VERIFY(::SelectObject(hDC, hFont) != NULL);
VERIFY(::GetTextMetrics(hDC, &tm));
long h = tm.tmHeight + tm.tmExternalLeading;
VERIFY(::ReleaseDC(GetHWnd(), hDC) != 0);
int nCount = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0, 0);
for(int i = 0; i < nCount; ++i) {
VERIFY(::SendMessage(GetHWnd(), CB_SETITEMHEIGHT, i, MAKELPARAM(h, 0)) != CB_ERR);
}
//Change the height of the Edit Box.
VERIFY(::SendMessage(GetHWnd(), CB_SETITEMHEIGHT, (UINT)-1,
MAKELPARAM(h, 0)) != CB_ERR);
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = GetTarget(env);
jint height = env->GetIntField(target, AwtComponent::heightID);
Reshape(env->GetIntField(target, AwtComponent::xID),
env->GetIntField(target, AwtComponent::yID),
env->GetIntField(target, AwtComponent::widthID),
h);
env->DeleteLocalRef(target);
}
static int lastClickX = -1;
static int lastClickY = -1;
LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
/*
* We don't pass the choice WM_LBUTTONDOWN message. As the result the choice's list
* doesn't forward mouse messages it captures. Below we do forward what we need.
*/
TRY;
DASSERT(::IsWindow(hwnd));
switch (message) {
case WM_LBUTTONDOWN: {
DWORD curPos = ::GetMessagePos();
lastClickX = GET_X_LPARAM(curPos);
lastClickY = GET_Y_LPARAM(curPos);
break;
}
case WM_MOUSEMOVE: {
RECT rect;
::GetClientRect(hwnd, &rect);
POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
if (::PtInRect(&rect, pt)) {
sm_isMouseMoveInList = TRUE;
}
POINT lastPt = {lastClickX, lastClickY};
::ScreenToClient(hwnd, &lastPt);
if (::PtInRect(&rect, lastPt)) {
break; // ignore when dragging inside the list
}
}
case WM_LBUTTONUP: {
lastClickX = -1;
lastClickY = -1;
AwtChoice *c = (AwtChoice *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (c != NULL) {
// forward the msg to the choice
c->WindowProc(message, wParam, lParam);
}
}
}
return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam);
CATCH_BAD_ALLOC_RET(0);
}
MsgRouting AwtChoice::WmNotify(UINT notifyCode)
{
if (notifyCode == CBN_SELCHANGE) {
int itemSelect = (int)SendMessage(CB_GETCURSEL);
if (itemSelect != CB_ERR){
DoCallback("handleAction", "(I)V", itemSelect);
}
} else if (notifyCode == CBN_DROPDOWN) {
if (m_hList == NULL) {
COMBOBOXINFO cbi;
cbi.cbSize = sizeof(COMBOBOXINFO);
::GetComboBoxInfo(GetHWnd(), &cbi);
m_hList = cbi.hwndList;
m_listDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(m_hList, ListWindowProc);
DASSERT(::GetWindowLongPtr(m_hList, GWLP_USERDATA) == NULL);
::SetWindowLongPtr(m_hList, GWLP_USERDATA, (LONG_PTR)this);
}
sm_isMouseMoveInList = FALSE;
// Clicking in the dropdown list steals focus from the proxy.
// So, set the focus-restore flag up.
SetRestoreFocus(TRUE);
} else if (notifyCode == CBN_CLOSEUP) {
SetRestoreFocus(FALSE);
}
return mrDoDefault;
}
MsgRouting
AwtChoice::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
{
DrawListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), drawInfo);
return mrConsume;
}
MsgRouting
AwtChoice::OwnerMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT& measureInfo)
{
MeasureListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), measureInfo);
return mrConsume;
}
/* Bug #4338368: when a choice loses focus, it triggers spurious MouseUp event,
* even if the focus was lost due to TAB key pressing
*/
MsgRouting
AwtChoice::WmKillFocus(HWND hWndGotFocus)
{
skipNextMouseUp = TRUE;
return AwtComponent::WmKillFocus(hWndGotFocus);
}
MsgRouting
AwtChoice::WmMouseUp(UINT flags, int x, int y, int button)
{
if (skipNextMouseUp) {
skipNextMouseUp = FALSE;
return mrDoDefault;
}
return AwtComponent::WmMouseUp(flags, x, y, button);
}
MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic)
{
if (IsFocusingMouseMessage(msg)) {
SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0);
delete msg;
return mrConsume;
}
// To simulate the native behavior, we close the list on WM_LBUTTONUP if
// WM_MOUSEMOVE has been dedected on the list since it has been dropped down.
if (msg->message == WM_LBUTTONUP && SendMessage(CB_GETDROPPEDSTATE, 0, 0) &&
sm_isMouseMoveInList)
{
SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
}
return AwtComponent::HandleEvent(msg, synthetic);
}
BOOL AwtChoice::InheritsNativeMouseWheelBehavior() {return true;}
void AwtChoice::_Reshape(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
ReshapeStruct *rs = (ReshapeStruct *)param;
jobject choice = rs->choice;
jint x = rs->x;
jint y = rs->y;
jint width = rs->width;
jint height = rs->height;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()))
{
c->Reshape(x, y, width, height);
c->VerifyState();
}
done:
env->DeleteGlobalRef(choice);
delete rs;
}
void AwtChoice::_Select(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SelectStruct *ss = (SelectStruct *)param;
jobject choice = ss->choice;
jint index = ss->index;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()))
{
c->SendMessage(CB_SETCURSEL, index);
// c->VerifyState();
}
done:
env->DeleteGlobalRef(choice);
delete ss;
}
void AwtChoice::_AddItems(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
AddItemsStruct *ais = (AddItemsStruct *)param;
jobject choice = ais->choice;
jobjectArray items = ais->items;
jint index = ais->index;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
JNI_CHECK_NULL_GOTO(items, "null items", done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()))
{
jsize i;
int itemCount = env->GetArrayLength(items);
if (itemCount > 0) {
c->SendMessage(WM_SETREDRAW, (WPARAM)FALSE, 0);
for (i = 0; i < itemCount; i++)
{
jstring item = (jstring)env->GetObjectArrayElement(items, i);
JNI_CHECK_NULL_GOTO(item, "null item", next_elem);
c->SendMessage(CB_INSERTSTRING, index + i, JavaStringBuffer(env, item));
env->DeleteLocalRef(item);
next_elem:
;
}
c->SendMessage(WM_SETREDRAW, (WPARAM)TRUE, 0);
InvalidateRect(c->GetHWnd(), NULL, TRUE);
c->ResetDropDownHeight();
c->VerifyState();
}
}
done:
env->DeleteGlobalRef(choice);
env->DeleteGlobalRef(items);
delete ais;
}
void AwtChoice::_Remove(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
RemoveStruct *rs = (RemoveStruct *)param;
jobject choice = rs->choice;
jint index = rs->index;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()))
{
c->SendMessage(CB_DELETESTRING, index, 0);
c->ResetDropDownHeight();
c->VerifyState();
}
done:
env->DeleteGlobalRef(choice);
delete rs;
}
void AwtChoice::_RemoveAll(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject choice = (jobject)param;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()))
{
c->SendMessage(CB_RESETCONTENT, 0, 0);
c->ResetDropDownHeight();
c->VerifyState();
}
done:
env->DeleteGlobalRef(choice);
}
void AwtChoice::_CloseList(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject choice = (jobject)param;
AwtChoice *c = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(choice, done);
c = (AwtChoice *)pData;
if (::IsWindow(c->GetHWnd()) && c->SendMessage(CB_GETDROPPEDSTATE, 0, 0)) {
c->SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
}
done:
env->DeleteGlobalRef(choice);
}
/************************************************************************
* WChoicePeer native methods
*/
extern "C" {
/*
* Class: sun_awt_windows_WChoicePeer
* Method: select
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_select(JNIEnv *env, jobject self,
jint index)
{
TRY;
SelectStruct *ss = new SelectStruct;
ss->choice = env->NewGlobalRef(self);
ss->index = index;
AwtToolkit::GetInstance().SyncCall(AwtChoice::_Select, ss);
// global refs and ss are removed in _Select
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: remove
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_remove(JNIEnv *env, jobject self,
jint index)
{
TRY;
RemoveStruct *rs = new RemoveStruct;
rs->choice = env->NewGlobalRef(self);
rs->index = index;
AwtToolkit::GetInstance().SyncCall(AwtChoice::_Remove, rs);
// global ref and rs are deleted in _Remove
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: removeAll
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_removeAll(JNIEnv *env, jobject self)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
AwtToolkit::GetInstance().SyncCall(AwtChoice::_RemoveAll, (void *)selfGlobalRef);
// selfGlobalRef is deleted in _RemoveAll
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: addItems
* Signature: ([Ljava/lang/String;I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_addItems(JNIEnv *env, jobject self,
jobjectArray items, jint index)
{
TRY;
AddItemsStruct *ais = new AddItemsStruct;
ais->choice = env->NewGlobalRef(self);
ais->items = (jobjectArray)env->NewGlobalRef(items);
ais->index = index;
AwtToolkit::GetInstance().SyncCall(AwtChoice::_AddItems, ais);
// global refs and ais are deleted in _AddItems
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: reshape
* Signature: (IIII)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_reshape(JNIEnv *env, jobject self,
jint x, jint y,
jint width, jint height)
{
TRY;
ReshapeStruct *rs = new ReshapeStruct;
rs->choice = env->NewGlobalRef(self);
rs->x = x;
rs->y = y;
rs->width = width;
rs->height = height;
AwtToolkit::GetInstance().SyncCall(AwtChoice::_Reshape, rs);
// global ref and rs are deleted in _Reshape
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: create
* Signature: (Lsun/awt/windows/WComponentPeer;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self,
jobject parent)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(parent);
AwtToolkit::CreateComponent(self, parent,
(AwtToolkit::ComponentFactory)
AwtChoice::Create);
JNI_CHECK_PEER_CREATION_RETURN(self);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WChoicePeer
* Method: closeList
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WChoicePeer_closeList(JNIEnv *env, jobject self)
{
TRY;
jobject selfGlobalRef = env->NewGlobalRef(self);
AwtToolkit::GetInstance().SyncCall(AwtChoice::_CloseList, (void *)selfGlobalRef);
// global ref is deleted in _CloseList
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* Diagnostic routines
*/
#ifdef DEBUG
void AwtChoice::VerifyState()
{
if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
return;
}
if (m_callbacksEnabled == FALSE) {
/* Component is not fully setup yet. */
return;
}
AwtComponent::VerifyState();
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->PushLocalFrame(1) < 0)
return;
jobject target = GetTarget(env);
// To avoid possibly running client code on the toolkit thread, don't
// do the following checks if we're running on the toolkit thread.
if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
// Compare number of items.
int nTargetItems = JNU_CallMethodByName(env, NULL, target,
"countItems", "()I").i;
DASSERT(!safe_ExceptionOccurred(env));
int nPeerItems = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0, 0);
DASSERT(nTargetItems == nPeerItems);
// Compare selection
int targetIndex = JNU_CallMethodByName(env, NULL, target,
"getSelectedIndex", "()I").i;
DASSERT(!safe_ExceptionOccurred(env));
int peerCurSel = (int)::SendMessage(GetHWnd(), CB_GETCURSEL, 0, 0);
DASSERT(targetIndex == peerCurSel);
}
env->PopLocalFrame(0);
}
#endif //DEBUG