blob: 67b2fa262a8caf4d866e3df64e20016812be1a88 [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 "awt.h"
#include "awt_MenuItem.h"
#include "awt_Menu.h"
#include "awt_MenuBar.h"
#include "awt_DesktopProperties.h"
#include <sun_awt_windows_WCheckboxMenuItemPeer.h>
// Begin -- Win32 SDK include files
#include <tchar.h>
#include <imm.h>
#include <ime.h>
// End -- Win32 SDK include files
//add for multifont menuitem
#include <java_awt_CheckboxMenuItem.h>
#include <java_awt_Toolkit.h>
#include <java_awt_event_InputEvent.h>
/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
*/
/***********************************************************************/
// struct for _SetLabel() method
struct SetLabelStruct {
jobject menuitem;
jstring label;
};
/************************************************************************
* AwtMenuItem fields
*/
HBITMAP AwtMenuItem::bmpCheck;
jobject AwtMenuItem::systemFont;
jfieldID AwtMenuItem::labelID;
jfieldID AwtMenuItem::enabledID;
jfieldID AwtMenuItem::fontID;
jfieldID AwtMenuItem::appContextID;
jfieldID AwtMenuItem::shortcutLabelID;
jfieldID AwtMenuItem::isCheckboxID;
jfieldID AwtMenuItem::stateID;
jmethodID AwtMenuItem::getDefaultFontMID;
// Added by waleed to initialize the RTL Flags
LANGID AwtMenuItem::m_idLang = LOWORD(GetKeyboardLayout(0));
UINT AwtMenuItem::m_CodePage =
AwtMenuItem::LangToCodePage(AwtMenuItem::m_idLang);
BOOL AwtMenuItem::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC ||
PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW;
BOOL AwtMenuItem::sm_rtlReadingOrder =
PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC;
/*
* This constant holds width of the default menu
* check-mark bitmap for default settings on XP/Vista,
* in pixels
*/
static const int SM_CXMENUCHECK_DEFAULT_ON_XP = 13;
static const int SM_CXMENUCHECK_DEFAULT_ON_VISTA = 15;
/************************************************************************
* AwtMenuItem methods
*/
AwtMenuItem::AwtMenuItem() {
m_peerObject = NULL;
m_menuContainer = NULL;
m_Id = (UINT)-1;
m_freeId = FALSE;
m_isCheckbox = FALSE;
}
AwtMenuItem::~AwtMenuItem()
{
}
void AwtMenuItem::RemoveCmdID()
{
if (m_freeId) {
AwtToolkit::GetInstance().RemoveCmdID( GetID() );
}
}
void AwtMenuItem::Dispose()
{
RemoveCmdID();
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (m_peerObject != NULL) {
JNI_SET_PDATA(m_peerObject, NULL);
env->DeleteGlobalRef(m_peerObject);
m_peerObject = NULL;
}
AwtObject::Dispose();
}
LPCTSTR AwtMenuItem::GetClassName() {
return TEXT("SunAwtMenuItem");
}
// Convert Language ID to CodePage
UINT AwtMenuItem::LangToCodePage(LANGID idLang)
{
TCHAR strCodePage[MAX_ACP_STR_LEN];
// use the LANGID to create a LCID
LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
// get the ANSI code page associated with this locale
if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
return _ttoi(strCodePage);
else
return GetACP();
}
BOOL AwtMenuItem::CheckMenuCreation(JNIEnv *env, jobject self, HMENU hMenu)
{
// fix for 5088782
// check if CreateMenu() returns not null value and if it does -
// create an InternalError or OutOfMemoryError based on GetLastError().
// This error is set to createError field of WObjectPeer and then
// checked and thrown in WMenuPeer or WMenuItemPeer constructor. We
// can't throw an error here because this code is invoked on Toolkit thread
// return TRUE if menu is created successfully, FALSE otherwise
if (hMenu == NULL)
{
DWORD dw = GetLastError();
jobject createError = NULL;
if (dw == ERROR_OUTOFMEMORY)
{
jstring errorMsg = JNU_NewStringPlatform(env, L"too many menu handles");
createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
"(Ljava/lang/String;)V",
errorMsg);
env->DeleteLocalRef(errorMsg);
}
else
{
TCHAR *buf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&buf, 0, NULL);
jstring s = JNU_NewStringPlatform(env, buf);
createError = JNU_NewObjectByName(env, "java/lang/InternalError",
"(Ljava/lang/String;)V", s);
LocalFree(buf);
env->DeleteLocalRef(s);
}
env->SetObjectField(self, AwtObject::createErrorID, createError);
if (createError != NULL)
{
env->DeleteLocalRef(createError);
}
return FALSE;
}
return TRUE;
}
/*
* Link the C++, Java peer together
*/
void AwtMenuItem::LinkObjects(JNIEnv *env, jobject peer)
{
m_peerObject = env->NewGlobalRef(peer);
JNI_SET_PDATA(peer, this);
}
AwtMenuItem* AwtMenuItem::Create(jobject peer, jobject menuPeer)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = NULL;
AwtMenuItem* item = NULL;
try {
if (env->EnsureLocalCapacity(1) < 0) {
return NULL;
}
PDATA pData;
JNI_CHECK_PEER_RETURN_NULL(menuPeer);
/* target is a java.awt.MenuItem */
target = env->GetObjectField(peer, AwtObject::targetID);
AwtMenu* menu = (AwtMenu *)pData;
item = new AwtMenuItem();
jboolean isCheckbox =
(jboolean)env->GetBooleanField(peer, AwtMenuItem::isCheckboxID);
if (isCheckbox) {
item->SetCheckbox();
}
item->LinkObjects(env, peer);
item->SetMenuContainer(menu);
item->SetNewID();
menu->AddItem(item);
} catch (...) {
env->DeleteLocalRef(target);
throw;
}
env->DeleteLocalRef(target);
return item;
}
MsgRouting AwtMenuItem::WmNotify(UINT notifyCode)
{
return mrDoDefault;
}
// This function returns a local reference
jobject
AwtMenuItem::GetFont(JNIEnv *env)
{
jobject self = GetPeer(env);
jobject target = env->GetObjectField(self, AwtObject::targetID);
jobject font = JNU_CallMethodByName(env, 0, target, "getFont_NoClientCode", "()Ljava/awt/Font;").l;
if (font == NULL) {
font = env->NewLocalRef(GetDefaultFont(env));
}
env->DeleteLocalRef(target);
return font;
}
jobject
AwtMenuItem::GetDefaultFont(JNIEnv *env) {
if (AwtMenuItem::systemFont == NULL) {
jclass cls = env->FindClass("sun/awt/windows/WMenuItemPeer");
DASSERT(cls != NULL);
AwtMenuItem::systemFont =
env->CallStaticObjectMethod(cls, AwtMenuItem::getDefaultFontMID);
DASSERT(AwtMenuItem::systemFont);
AwtMenuItem::systemFont = env->NewGlobalRef(AwtMenuItem::systemFont);
}
return AwtMenuItem::systemFont;
}
void
AwtMenuItem::DrawSelf(DRAWITEMSTRUCT& drawInfo)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->EnsureLocalCapacity(4) < 0) {
return;
}
// self is sun.awt.windows.WMenuItemPeer
jobject self = GetPeer(env);
// target is java.awt.MenuItem
jobject target = env->GetObjectField(self, AwtObject::targetID);
HDC hDC = drawInfo.hDC;
RECT rect = drawInfo.rcItem;
RECT textRect = rect;
SIZE size;
DWORD crBack,crText;
HBRUSH hbrBack;
jobject font = GetFont(env);
jstring text = GetJavaString(env);
size = AwtFont::getMFStringSize(hDC, font, text);
/* 4700350: If the font size is taller than the menubar, change to the
* default font. Otherwise, menu text is painted over the title bar and
* client area. -bchristi
*/
if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) {
env->DeleteLocalRef(font);
font = env->NewLocalRef(GetDefaultFont(env));
size = AwtFont::getMFStringSize(hDC, font, text);
}
/* Fix for bug 4257944 by ssi@sparc.spb.su
* check state of the parent
*/
AwtMenu* menu = GetMenuContainer();
DASSERT(menu != NULL && GetID() >= 0);
//Check whether the MenuItem is disabled.
BOOL bEnabled = (jboolean)env->GetBooleanField(target,
AwtMenuItem::enabledID);
if (menu != NULL) {
bEnabled = bEnabled && !menu->IsDisabledAndPopup();
}
if ((drawInfo.itemState) & (ODS_SELECTED)) {
// Set background and text colors for selected item
crBack = ::GetSysColor (COLOR_HIGHLIGHT);
// Disabled text must be drawn in gray.
crText = ::GetSysColor(bEnabled? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT);
} else {
// COLOR_MENUBAR is only defined on WindowsXP. Our binaries are
// built on NT, hence the below ifdef.
#ifndef COLOR_MENUBAR
#define COLOR_MENUBAR 30
#endif
// Set background and text colors for unselected item
if (IS_WINXP && IsTopMenu() && AwtDesktopProperties::IsXPStyle()) {
crBack = ::GetSysColor (COLOR_MENUBAR);
} else {
crBack = ::GetSysColor (COLOR_MENU);
}
// Disabled text must be drawn in gray.
crText = ::GetSysColor (bEnabled ? COLOR_MENUTEXT : COLOR_GRAYTEXT);
}
// Fill item rectangle with background color
hbrBack = ::CreateSolidBrush (crBack);
DASSERT(hbrBack);
VERIFY(::FillRect (hDC, &rect, hbrBack));
VERIFY(::DeleteObject (hbrBack));
// Set current background and text colors
::SetBkColor (hDC, crBack);
::SetTextColor (hDC, crText);
int nOldBkMode = ::SetBkMode(hDC, OPAQUE);
DASSERT(nOldBkMode != 0);
//draw check mark
int checkWidth = ::GetSystemMetrics(SM_CXMENUCHECK);
// Workaround for CR#6401956
if (IS_WINVISTA) {
AdjustCheckWidth(checkWidth);
}
if (IsCheckbox()) {
// means that target is a java.awt.CheckboxMenuItem
jboolean state =
(jboolean)env->GetBooleanField(target, AwtMenuItem::stateID);
if (state) {
DASSERT(drawInfo.itemState & ODS_CHECKED);
RECT checkRect;
::CopyRect(&checkRect, &textRect);
if (GetRTL())
checkRect.left = checkRect.right - checkWidth;
else
checkRect.right = checkRect.left + checkWidth;
DrawCheck(hDC, checkRect);
}
}
::SetBkMode(hDC, TRANSPARENT);
int x = 0;
//draw string
if (!IsTopMenu()){
textRect.left += checkWidth;
x = (GetRTL()) ? textRect.right - checkWidth - size.cx : textRect.left;
} else {
x = textRect.left = (textRect.left + textRect.right - size.cx) / 2;
}
int y = (textRect.top+textRect.bottom-size.cy)/2;
// Text must be drawn in emboss if the Menu is disabled and not selected.
BOOL bEmboss = !bEnabled && !(drawInfo.itemState & ODS_SELECTED);
if (bEmboss) {
::SetTextColor(hDC, GetSysColor(COLOR_BTNHILIGHT));
AwtFont::drawMFString(hDC, font, text, x + 1, y + 1, GetCodePage());
::SetTextColor(hDC, GetSysColor(COLOR_BTNSHADOW));
}
AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
jstring shortcutLabel =
(jstring)env->GetObjectField(self, AwtMenuItem::shortcutLabelID);
if (!IsTopMenu() && shortcutLabel != NULL) {
UINT oldAlign = 0;
if (GetRTL()){
oldAlign = ::SetTextAlign(hDC, TA_LEFT);
AwtFont::drawMFString(hDC, font, shortcutLabel, textRect.left, y,
GetCodePage());
} else {
oldAlign = ::SetTextAlign(hDC, TA_RIGHT);
AwtFont::drawMFString(hDC, font, shortcutLabel,
textRect.right - checkWidth, y,
GetCodePage());
}
::SetTextAlign(hDC, oldAlign);
}
VERIFY(::SetBkMode(hDC,nOldBkMode));
env->DeleteLocalRef(target);
env->DeleteLocalRef(text);
env->DeleteLocalRef(font);
env->DeleteLocalRef(shortcutLabel);
}
/*
* This function helps us to prevent check-mark's
* distortion appeared due to changing of default
* settings on Vista
*/
void AwtMenuItem::AdjustCheckWidth(int& checkWidth)
{
if (checkWidth == SM_CXMENUCHECK_DEFAULT_ON_VISTA) {
checkWidth = SM_CXMENUCHECK_DEFAULT_ON_XP;
}
}
void AwtMenuItem::DrawItem(DRAWITEMSTRUCT& drawInfo)
{
DASSERT(drawInfo.CtlType == ODT_MENU);
if (drawInfo.itemID != m_Id)
return;
DrawSelf(drawInfo);
}
void AwtMenuItem::MeasureSelf(HDC hDC, MEASUREITEMSTRUCT& measureInfo)
{
JNIEnv *env =(JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->EnsureLocalCapacity(4) < 0) {
return;
}
/* self is a sun.awt.windows.WMenuItemPeer */
jobject self = GetPeer(env);
/* font is a java.awt.Font */
jobject font = GetFont(env);
jstring text = GetJavaString(env);
SIZE size = AwtFont::getMFStringSize(hDC, font, text);
/* 4700350: If the font size is taller than the menubar, change to the
* default font. Otherwise, menu text is painted over the title bar and
* client area. -bchristi
*/
if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) {
jobject defFont = GetDefaultFont(env);
env->DeleteLocalRef(font);
font = env->NewLocalRef(defFont);
size = AwtFont::getMFStringSize(hDC, font, text);
}
jstring fontName =
(jstring)JNU_CallMethodByName(env, 0,font, "getName",
"()Ljava/lang/String;").l;
/* fontMetrics is a Hsun_awt_windows_WFontMetrics */
jobject fontMetrics = GetFontMetrics(env, font);
// int height = env->GetIntField(fontMetrics, AwtFont::heightID);
int height = (jint)JNU_CallMethodByName(env, 0, fontMetrics, "getHeight",
"()I").i;
measureInfo.itemHeight = height;
measureInfo.itemHeight += measureInfo.itemHeight/3;
// 3 is a heuristic number
measureInfo.itemWidth = size.cx;
if (!IsTopMenu()) {
int checkWidth = ::GetSystemMetrics(SM_CXMENUCHECK);
// Workaround for CR#6401956
if (IS_WINVISTA) {
AdjustCheckWidth(checkWidth);
}
measureInfo.itemWidth += checkWidth;
// Add in shortcut width, if one exists.
jstring shortcutLabel =
(jstring)env->GetObjectField(self, AwtMenuItem::shortcutLabelID);
if (shortcutLabel != NULL) {
size = AwtFont::getMFStringSize(hDC, font, shortcutLabel);
measureInfo.itemWidth += size.cx + checkWidth;
env->DeleteLocalRef(shortcutLabel);
}
}
env->DeleteLocalRef(text);
env->DeleteLocalRef(font);
env->DeleteLocalRef(fontName);
env->DeleteLocalRef(fontMetrics);
}
void AwtMenuItem::MeasureItem(HDC hDC, MEASUREITEMSTRUCT& measureInfo)
{
DASSERT(measureInfo.CtlType == ODT_MENU);
if (measureInfo.itemID != m_Id)
return;
MeasureSelf(hDC, measureInfo);
}
jobject AwtMenuItem::GetFontMetrics(JNIEnv *env, jobject font)
{
static jobject toolkit = NULL;
if (toolkit == NULL) {
if (env->PushLocalFrame(2) < 0)
return NULL;
jclass cls = env->FindClass("java/awt/Toolkit");
jobject toolkitLocal =
env->CallStaticObjectMethod(cls, AwtToolkit::getDefaultToolkitMID);
toolkit = env->NewGlobalRef(toolkitLocal);
DASSERT(!safe_ExceptionOccurred(env));
env->PopLocalFrame(0);
}
/*
JNU_PrintClass(env, "toolkit", toolkit);
JNU_PrintClass(env, "font", font);
jclass cls = env->FindClass("java/awt/Toolkit");
jmethodID mid = env->GetMethodID(cls, "getFontMetrics",
"(Ljava/awt/Font;)Ljava/awt/FontMetrics;");
jstring fontName =
(jstring)JNU_CallMethodByName(env, 0,font, "getName",
"()Ljava/lang/String;").l;
JNU_PrintString(env, "font name", fontName);
fprintf(stderr, "mid: %x\n", mid);
fprintf(stderr, "cached mid: %x\n", AwtToolkit::getFontMetricsMID);
DASSERT(!safe_ExceptionOccurred(env));
*/
jobject fontMetrics =
env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
DASSERT(!safe_ExceptionOccurred(env));
return fontMetrics;
}
BOOL AwtMenuItem::IsTopMenu()
{
return FALSE;
}
void AwtMenuItem::DrawCheck(HDC hDC, RECT rect)
{
if (bmpCheck == NULL) {
bmpCheck = ::LoadBitmap(AwtToolkit::GetInstance().GetModuleHandle(),
TEXT("CHECK_BITMAP"));
DASSERT(bmpCheck != NULL);
}
#define BM_SIZE 26 /* height and width of check.bmp */
// Square the rectangle, so the check is proportional.
int width = rect.right - rect.left;
int diff = max(rect.bottom - rect.top - width, 0) ;
int bottom = diff / 2;
rect.bottom -= bottom;
rect.top += diff - bottom;
HDC hdcBitmap = ::CreateCompatibleDC(hDC);
DASSERT(hdcBitmap != NULL);
HBITMAP hbmSave = (HBITMAP)::SelectObject(hdcBitmap, bmpCheck);
VERIFY(::StretchBlt(hDC, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
hdcBitmap, 0, 0, BM_SIZE, BM_SIZE, SRCCOPY));
::SelectObject(hdcBitmap, hbmSave);
VERIFY(::DeleteDC(hdcBitmap));
}
void AwtMenuItem::DoCommand()
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
// peer is sun.awt.windows.WMenuItemPeer
jobject peer = GetPeer(env);
if (IsCheckbox()) {
UINT nState = ::GetMenuState(GetMenuContainer()->GetHMenu(),
GetID(), MF_BYCOMMAND);
DASSERT(nState != 0xFFFFFFFF);
DoCallback("handleAction", "(Z)V", ((nState & MF_CHECKED) == 0));
} else {
DoCallback("handleAction", "(JI)V", TimeHelper::getMessageTimeUTC(),
(jint)AwtComponent::GetJavaModifiers());
}
}
void AwtMenuItem::SetLabel(LPCTSTR sb)
{
AwtMenu* menu = GetMenuContainer();
/* Fix for bug 4257944 by ssi@sparc.spb.su
* check parent
*/
if (menu == NULL) return;
DASSERT(menu != NULL && GetID() >= 0);
/*
* SetMenuItemInfo is replaced by this code for fix bug 4261935
*/
HMENU hMenu = menu->GetHMenu();
MENUITEMINFO mii, mii1;
// get full information about menu item
memset(&mii, 0, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID
| MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
::GetMenuItemInfo(hMenu, GetID(), FALSE, &mii);
mii.fType = MFT_OWNERDRAW;
mii.dwTypeData = (LPTSTR)(*sb);
// find index by menu item id
int nMenuItemCount = ::GetMenuItemCount(hMenu);;
int idx;
for (idx = 0; (idx < nMenuItemCount); idx++) {
memset(&mii1, 0, sizeof(MENUITEMINFO));
mii1.cbSize = sizeof mii1;
mii1.fMask = MIIM_ID;
::GetMenuItemInfo(hMenu, idx, TRUE, &mii1);
if (mii.wID == mii1.wID) break;
}
::RemoveMenu(hMenu, idx, MF_BYPOSITION);
::InsertMenuItem(hMenu, idx, TRUE, &mii);
// Redraw menu bar if it was affected.
if (menu->GetMenuBar() == menu) {
::DrawMenuBar(menu->GetOwnerHWnd());
}
}
void AwtMenuItem::Enable(BOOL isEnabled)
{
AwtMenu* menu = GetMenuContainer();
/* Fix for bug 4257944 by ssi@sparc.spb.su
* check state of the parent
*/
if (menu == NULL) return;
isEnabled = isEnabled && !menu->IsDisabledAndPopup();
DASSERT(menu != NULL && GetID() >= 0);
VERIFY(::EnableMenuItem(menu->GetHMenu(), GetID(),
MF_BYCOMMAND | (isEnabled ? MF_ENABLED : MF_GRAYED))
!= 0xFFFFFFFF);
// Redraw menu bar if it was affected.
if (menu->GetMenuBar() == menu) {
::DrawMenuBar(menu->GetOwnerHWnd());
}
}
void AwtMenuItem::SetState(BOOL isChecked)
{
AwtMenu* menu = GetMenuContainer();
/* Fix for bug 4257944 by ssi@sparc.spb.su
* check parent
*/
if (menu == NULL) return;
DASSERT(menu != NULL && GetID() >= 0);
VERIFY(::CheckMenuItem(menu->GetHMenu(), GetID(),
MF_BYCOMMAND | (isChecked ? MF_CHECKED : MF_UNCHECKED))
!= 0xFFFFFFFF);
// Redraw menu bar if it was affected.
if (menu->GetMenuBar() == menu) {
::DrawMenuBar(menu->GetOwnerHWnd());
}
}
LRESULT AwtMenuItem::WinThreadExecProc(ExecuteArgs * args)
{
switch( args->cmdId ) {
case MENUITEM_SETLABEL:
{
LPCTSTR sb = (LPCTSTR)args->param1;
DASSERT(!IsBadStringPtr(sb, 20));
this->SetLabel(sb);
}
break;
case MENUITEM_ENABLE:
{
BOOL isEnabled = (BOOL)args->param1;
this->Enable(isEnabled);
}
break;
case MENUITEM_SETSTATE:
{
BOOL isChecked = (BOOL)args->param1;
this->SetState(isChecked);
}
break;
default:
AwtObject::WinThreadExecProc(args);
break;
}
return 0L;
}
void AwtMenuItem::_SetLabel(void *param)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SetLabelStruct *sls = (SetLabelStruct *)param;
jobject self = sls->menuitem;
jstring label = sls->label;
int badAlloc = 0;
AwtMenuItem *m = NULL;
PDATA pData;
JNI_CHECK_PEER_GOTO(self, ret);
m = (AwtMenuItem *)pData;
// if (::IsWindow(m->GetOwnerHWnd()))
{
// fix for bug 4251036 MenuItem setLabel(null/"") behaves differently
// under Win32 and Solaris
jstring empty = NULL;
if (JNU_IsNull(env, label))
{
empty = JNU_NewStringPlatform(env, TEXT(""));
}
LPCTSTR labelPtr;
if (empty != NULL)
{
labelPtr = JNU_GetStringPlatformChars(env, empty, 0);
}
else
{
labelPtr = JNU_GetStringPlatformChars(env, label, 0);
}
if (labelPtr == NULL)
{
badAlloc = 1;
}
else
{
ExecuteArgs args;
args.cmdId = MENUITEM_SETLABEL;
args.param1 = (LPARAM)labelPtr;
m->WinThreadExecProc(&args);
if (empty != NULL)
{
JNU_ReleaseStringPlatformChars(env, empty, labelPtr);
}
else
{
JNU_ReleaseStringPlatformChars(env, label, labelPtr);
}
}
if (empty != NULL)
{
env->DeleteLocalRef(empty);
}
}
ret:
env->DeleteGlobalRef(self);
if (label != NULL)
{
env->DeleteGlobalRef(label);
}
delete sls;
if (badAlloc)
{
throw std::bad_alloc();
}
}
BOOL AwtMenuItem::IsSeparator() {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env->EnsureLocalCapacity(2) < 0) {
return FALSE;
}
jobject jitem = GetTarget(env);
jstring label =
(jstring)(env)->GetObjectField(jitem, AwtMenuItem::labelID);
LPCWSTR labelW = JNU_GetStringPlatformChars(env, label, NULL);
BOOL isSeparator = (labelW && (wcscmp(labelW, L"-") == 0));
JNU_ReleaseStringPlatformChars(env, label, labelW);
env->DeleteLocalRef(label);
env->DeleteLocalRef(jitem);
return isSeparator;
}
/************************************************************************
* MenuComponent native methods
*/
extern "C" {
JNIEXPORT void JNICALL
Java_java_awt_MenuComponent_initIDs(JNIEnv *env, jclass cls)
{
TRY;
AwtMenuItem::fontID = env->GetFieldID(cls, "font", "Ljava/awt/Font;");
AwtMenuItem::appContextID = env->GetFieldID(cls, "appContext", "Lsun/awt/AppContext;");
DASSERT(AwtMenuItem::fontID != NULL);
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* MenuItem native methods
*/
extern "C" {
JNIEXPORT void JNICALL
Java_java_awt_MenuItem_initIDs(JNIEnv *env, jclass cls)
{
TRY;
AwtMenuItem::labelID = env->GetFieldID(cls, "label", "Ljava/lang/String;");
AwtMenuItem::enabledID = env->GetFieldID(cls, "enabled", "Z");
DASSERT(AwtMenuItem::labelID != NULL);
DASSERT(AwtMenuItem::enabledID != NULL);
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* CheckboxMenuItem fields
*/
extern "C" {
JNIEXPORT void JNICALL
Java_java_awt_CheckboxMenuItem_initIDs(JNIEnv *env, jclass cls)
{
TRY;
AwtMenuItem::stateID = env->GetFieldID(cls, "state", "Z");
DASSERT(AwtMenuItem::stateID != NULL);
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* WMenuItemPeer native methods
*/
extern "C" {
/*
* Class: sun_awt_windows_WMenuItemPeer
* Method: _setLabel
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer_initIDs(JNIEnv *env, jclass cls)
{
TRY;
AwtMenuItem::isCheckboxID = env->GetFieldID(cls, "isCheckbox", "Z");
AwtMenuItem::shortcutLabelID = env->GetFieldID(cls, "shortcutLabel",
"Ljava/lang/String;");
AwtMenuItem::getDefaultFontMID =
env->GetStaticMethodID(cls, "getDefaultFont", "()Ljava/awt/Font;");
DASSERT(AwtMenuItem::isCheckboxID != NULL);
DASSERT(AwtMenuItem::shortcutLabelID != NULL);
DASSERT(AwtMenuItem::getDefaultFontMID != NULL);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WMenuItemPeer
* Method: _setLabel
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer__1setLabel(JNIEnv *env, jobject self,
jstring label)
{
TRY;
SetLabelStruct *sls = new SetLabelStruct;
sls->menuitem = env->NewGlobalRef(self);
sls->label = (label == NULL) ? NULL : (jstring)env->NewGlobalRef(label);
AwtToolkit::GetInstance().SyncCall(AwtMenuItem::_SetLabel, sls);
// global refs and sls are deleted in _SetLabel
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WMenuItemPeer
* Method: create
* Signature: (Lsun/awt/windows/WMenuPeer;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer_create(JNIEnv *env, jobject self,
jobject menu)
{
TRY;
JNI_CHECK_NULL_RETURN(menu, "null Menu");
AwtToolkit::CreateComponent(self, menu,
(AwtToolkit::ComponentFactory)
AwtMenuItem::Create);
PDATA pData;
JNI_CHECK_PEER_CREATION_RETURN(self);
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WMenuItemPeer
* Method: enable
* Signature: (Z)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer_enable(JNIEnv *env, jobject self,
jboolean on)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
AwtObject::WinThreadExec(self, AwtMenuItem::MENUITEM_ENABLE, (LPARAM)on );
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WMenuItemPeer
* Method: _dispose
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer__1dispose(JNIEnv *env, jobject self)
{
TRY_NO_HANG;
PDATA pData = JNI_GET_PDATA(self);
AwtObject::_Dispose(pData);
CATCH_BAD_ALLOC;
}
} /* extern "C" */
/************************************************************************
* WCheckboxMenuItemPeer native methods
*/
extern "C" {
/*
* Class: sun_awt_windows_WCheckboxMenuItemPeer
* Method: setState
* Signature: (Z)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WCheckboxMenuItemPeer_setState(JNIEnv *env, jobject self,
jboolean on)
{
TRY;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
AwtObject::WinThreadExec(self, AwtMenuItem::MENUITEM_SETSTATE, (LPARAM)on);
CATCH_BAD_ALLOC;
}
} /* extern "C" */