| /* |
| * Copyright (c) 1996, 2006, 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_Toolkit.h" |
| #include "awt_Checkbox.h" |
| #include "awt_Canvas.h" |
| #include "awt_Window.h" |
| |
| /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. |
| */ |
| |
| /***********************************************************************/ |
| // Struct for _SetLabel() method |
| struct SetLabelStruct { |
| jobject checkbox; |
| jstring label; |
| }; |
| // Struct for _SetState() method |
| struct SetStateStruct { |
| jobject checkbox; |
| jboolean state; |
| }; |
| |
| /************************************************************************ |
| * AwtCheckbox fields |
| */ |
| |
| /* java.awt.Checkbox field IDs */ |
| jfieldID AwtCheckbox::labelID; |
| jfieldID AwtCheckbox::groupID; |
| jfieldID AwtCheckbox::stateID; |
| |
| const int AwtCheckbox::CHECK_SIZE = 13; |
| |
| /************************************************************************ |
| * AwtCheckbox methods |
| */ |
| |
| AwtCheckbox::AwtCheckbox() { |
| |
| m_fLButtonDowned = FALSE; |
| } |
| |
| LPCTSTR AwtCheckbox::GetClassName() { |
| return TEXT("BUTTON"); /* System provided checkbox class (a type of button) */ |
| } |
| |
| AwtCheckbox* AwtCheckbox::Create(jobject peer, jobject parent) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jstring label = NULL; |
| jobject target = NULL; |
| AwtCheckbox *checkbox = NULL; |
| |
| try { |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return NULL; |
| } |
| |
| AwtComponent* awtParent; |
| JNI_CHECK_NULL_GOTO(parent, "null parent", done); |
| |
| awtParent = (AwtComponent*)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); |
| |
| checkbox = new AwtCheckbox(); |
| |
| { |
| DWORD style = WS_CHILD | WS_CLIPSIBLINGS | BS_OWNERDRAW; |
| LPCWSTR defaultLabelStr = L""; |
| LPCWSTR labelStr = defaultLabelStr; |
| DWORD exStyle = 0; |
| |
| if (GetRTL()) { |
| exStyle |= WS_EX_RIGHT; |
| if (GetRTLReadingOrder()) |
| exStyle |= WS_EX_RTLREADING; |
| } |
| |
| label = (jstring)env->GetObjectField(target, AwtCheckbox::labelID); |
| if (label != NULL) { |
| labelStr = JNU_GetStringPlatformChars(env, label, 0); |
| } |
| if (labelStr != 0) { |
| 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); |
| checkbox->CreateHWnd(env, labelStr, style, exStyle, |
| x, y, width, height, |
| awtParent->GetHWnd(), |
| reinterpret_cast<HMENU>(static_cast<INT_PTR>( |
| awtParent->CreateControlID())), |
| ::GetSysColor(COLOR_WINDOWTEXT), |
| ::GetSysColor(COLOR_BTNFACE), |
| peer); |
| |
| if (labelStr != defaultLabelStr) { |
| JNU_ReleaseStringPlatformChars(env, label, labelStr); |
| } |
| } else { |
| throw std::bad_alloc(); |
| } |
| } |
| } catch (...) { |
| env->DeleteLocalRef(label); |
| env->DeleteLocalRef(target); |
| throw; |
| } |
| |
| done: |
| env->DeleteLocalRef(label); |
| env->DeleteLocalRef(target); |
| |
| return checkbox; |
| } |
| |
| MsgRouting |
| AwtCheckbox::WmMouseUp(UINT flags, int x, int y, int button) |
| { |
| MsgRouting mrResult = AwtComponent::WmMouseUp(flags, x, y, button); |
| |
| if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) |
| { |
| return mrConsume; |
| } |
| |
| POINT p = {x, y}; |
| RECT rect; |
| ::GetClientRect(GetHWnd(), &rect); |
| |
| if (::PtInRect(&rect, p) && button == LEFT_BUTTON && m_fLButtonDowned) { |
| WmNotify(BN_CLICKED); |
| } |
| m_fLButtonDowned = FALSE; |
| return mrResult; |
| } |
| |
| MsgRouting |
| AwtCheckbox::WmMouseDown(UINT flags, int x, int y, int button) |
| { |
| m_fLButtonDowned = TRUE; |
| return AwtComponent::WmMouseDown(flags, x, y, button); |
| } |
| |
| MsgRouting |
| AwtCheckbox::WmNotify(UINT notifyCode) |
| { |
| if (notifyCode == BN_CLICKED) { |
| BOOL fChecked = !GetState(); |
| DoCallback("handleAction", "(Z)V", fChecked); |
| } |
| return mrDoDefault; |
| } |
| |
| BOOL AwtCheckbox::GetState() |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return NULL; |
| } |
| jobject target = GetTarget(env); |
| jboolean result = JNI_FALSE; |
| if (target != NULL) { |
| result = env->GetBooleanField(target, AwtCheckbox::stateID); |
| } |
| |
| env->DeleteLocalRef(target); |
| |
| return (BOOL)result; |
| } |
| |
| int AwtCheckbox::GetCheckSize() |
| { |
| /* using height of small icon for check mark size */ |
| return CHECK_SIZE; |
| } |
| |
| MsgRouting |
| AwtCheckbox::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| if (env->EnsureLocalCapacity(4) < 0) { |
| return mrConsume; |
| } |
| |
| jobject self = GetPeer(env); |
| jobject target = env->GetObjectField(self, AwtObject::targetID); |
| |
| HDC hDC = drawInfo.hDC; |
| RECT rect = drawInfo.rcItem; |
| int checkSize; |
| UINT nState; |
| SIZE size; |
| |
| jobject font = GET_FONT(target, self); |
| jstring str = (jstring)env->GetObjectField(target, AwtCheckbox::labelID); |
| size = AwtFont::getMFStringSize(hDC, font, str); |
| |
| jobject group = env->GetObjectField(target, AwtCheckbox::groupID); |
| if (group != NULL) |
| nState = DFCS_BUTTONRADIO; |
| else |
| nState = DFCS_BUTTONCHECK; |
| |
| if (GetState()) |
| nState |= DFCS_CHECKED; |
| else |
| nState &= ~DFCS_CHECKED; |
| |
| if (drawInfo.itemState & ODS_SELECTED) |
| nState |= DFCS_PUSHED; |
| |
| if (drawInfo.itemAction & ODA_DRAWENTIRE) { |
| VERIFY(::FillRect (hDC, &rect, GetBackgroundBrush())); |
| } |
| |
| /* draw check mark */ |
| checkSize = GetCheckSize(); |
| RECT boxRect; |
| |
| boxRect.left = (GetRTL()) ? rect.right - checkSize : rect.left; |
| boxRect.top = (rect.bottom - rect.top - checkSize)/2; |
| boxRect.right = boxRect.left + checkSize; |
| boxRect.bottom = boxRect.top + checkSize; |
| ::DrawFrameControl(hDC, &boxRect, DFC_BUTTON, nState); |
| |
| /* |
| * draw string |
| * |
| * 4 is a heuristic number |
| */ |
| rect.left = rect.left + checkSize + checkSize/4; |
| if (drawInfo.itemAction & ODA_DRAWENTIRE) { |
| BOOL bEnabled = isEnabled(); |
| |
| int x = (GetRTL()) ? rect.right - (checkSize + checkSize / 4 + size.cx) |
| : rect.left; |
| int y = (rect.top + rect.bottom - size.cy) / 2; |
| if (bEnabled) { |
| AwtComponent::DrawWindowText(hDC, font, str, x, y); |
| } else { |
| AwtComponent::DrawGrayText(hDC, font, str, x, y); |
| } |
| } |
| |
| /* Draw focus rect */ |
| RECT focusRect; |
| const int margin = 2; /* 2 is a heuristic number */ |
| |
| focusRect.left = (GetRTL()) ? rect.right - checkSize - checkSize / 4 - |
| 2 * margin - size.cx |
| : rect.left - margin; |
| focusRect.top = (rect.top+rect.bottom-size.cy)/2; |
| focusRect.right = (GetRTL()) ? rect.right - checkSize - checkSize / 4 + |
| margin |
| : focusRect.left + size.cx + 2 * margin; |
| focusRect.bottom = focusRect.top + size.cy; |
| |
| /* draw focus rect */ |
| if ((drawInfo.itemState & ODS_FOCUS) && |
| ((drawInfo.itemAction & ODA_FOCUS)|| |
| (drawInfo.itemAction &ODA_DRAWENTIRE))) { |
| VERIFY(::DrawFocusRect(hDC, &focusRect)); |
| } |
| /* erase focus rect */ |
| else if (!(drawInfo.itemState & ODS_FOCUS) && |
| (drawInfo.itemAction & ODA_FOCUS)) { |
| VERIFY(::DrawFocusRect(hDC, &focusRect)); |
| } |
| |
| /* Notify any subclasses */ |
| rect = drawInfo.rcItem; |
| DoCallback("handlePaint", "(IIII)V", rect.left, rect.top, |
| rect.right-rect.left, rect.bottom-rect.top); |
| |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(font); |
| env->DeleteLocalRef(str); |
| env->DeleteLocalRef(group); |
| |
| return mrConsume; |
| } |
| |
| MsgRouting AwtCheckbox::WmPaint(HDC) |
| { |
| /* Suppress peer notification, because it's handled in WmDrawItem. */ |
| return mrDoDefault; |
| } |
| |
| BOOL AwtCheckbox::IsFocusingMouseMessage(MSG *pMsg) { |
| return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP; |
| } |
| |
| BOOL AwtCheckbox::IsFocusingKeyMessage(MSG *pMsg) { |
| return (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) && |
| pMsg->wParam == VK_SPACE; |
| } |
| |
| MsgRouting AwtCheckbox::HandleEvent(MSG *msg, BOOL synthetic) |
| { |
| if (IsFocusingMouseMessage(msg)) { |
| SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_LBUTTONDOWN ? TRUE : FALSE)); |
| delete msg; |
| return mrConsume; |
| } |
| if (IsFocusingKeyMessage(msg)) { |
| SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_KEYDOWN ? TRUE : FALSE)); |
| if (msg->message == WM_KEYDOWN) { |
| m_fLButtonDowned = TRUE; |
| } else if (m_fLButtonDowned == TRUE) { |
| WmNotify(BN_CLICKED); |
| m_fLButtonDowned = TRUE; |
| } |
| delete msg; |
| return mrConsume; |
| } |
| return AwtComponent::HandleEvent(msg, synthetic); |
| } |
| |
| void AwtCheckbox::_SetLabel(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetLabelStruct *sls = (SetLabelStruct *)param; |
| jobject checkbox = sls->checkbox; |
| jstring label = sls->label; |
| |
| int badAlloc = 0; |
| AwtCheckbox *c = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(checkbox, done); |
| |
| c = (AwtCheckbox *)pData; |
| if (::IsWindow(c->GetHWnd())) |
| { |
| LPCTSTR labelStr = NULL; |
| |
| // By convension null label means empty string |
| if (label == NULL) |
| { |
| labelStr = TEXT(""); |
| } |
| else |
| { |
| labelStr = JNU_GetStringPlatformChars(env, label, JNI_FALSE); |
| } |
| |
| if (labelStr == NULL) |
| { |
| badAlloc = 1; |
| } |
| else |
| { |
| c->SetText(labelStr); |
| c->VerifyState(); |
| JNU_ReleaseStringPlatformChars(env, label, labelStr); |
| } |
| } |
| |
| done: |
| env->DeleteGlobalRef(checkbox); |
| if (label != NULL) |
| { |
| env->DeleteGlobalRef(label); |
| } |
| |
| delete sls; |
| |
| if (badAlloc) { |
| throw std::bad_alloc(); |
| } |
| } |
| |
| void AwtCheckbox::_SetCheckboxGroup(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject *jos = (jobject *)param; |
| jobject checkbox = jos[0]; |
| jobject group = jos[1]; |
| |
| AwtCheckbox *c = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(checkbox, done); |
| |
| c = (AwtCheckbox *)pData; |
| if (::IsWindow(c->GetHWnd())) |
| { |
| /* |
| #ifdef DEBUG |
| if (group != NULL) { |
| DASSERT(IsInstanceOf((HObject*)group, "java/awt/CheckboxGroup")); |
| } |
| #endif |
| */ |
| long style = c->GetStyle(); |
| if (group == NULL) { |
| style = style & ~BS_AUTORADIOBUTTON; |
| style = style | BS_AUTOCHECKBOX; |
| } else { |
| style = style & ~BS_AUTOCHECKBOX; |
| style = style | BS_AUTORADIOBUTTON; |
| } |
| c->SetStyle(style); |
| c->SendMessage(BM_SETSTYLE, (WPARAM)BS_OWNERDRAW, (LPARAM)TRUE); |
| c->VerifyState(); |
| } |
| |
| done: |
| env->DeleteGlobalRef(checkbox); |
| if (group != NULL) { |
| env->DeleteGlobalRef(group); |
| } |
| |
| delete[] jos; |
| } |
| |
| void AwtCheckbox::_SetState(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetStateStruct *sss = (SetStateStruct *)param; |
| jobject checkbox = sss->checkbox; |
| jboolean state = sss->state; |
| |
| AwtCheckbox *c = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(checkbox, done); |
| |
| c = (AwtCheckbox *)pData; |
| if (::IsWindow(c->GetHWnd())) |
| { |
| /* |
| * when multifont and group checkbox receive setState native |
| * method, it must be redraw to display correct check mark |
| */ |
| jobject target = env->GetObjectField(checkbox, AwtObject::targetID); |
| jobject group = env->GetObjectField(target, AwtCheckbox::groupID); |
| HWND hWnd = c->GetHWnd(); |
| if (group != NULL) { |
| RECT rect; |
| VERIFY(::GetWindowRect(hWnd, &rect)); |
| VERIFY(::ScreenToClient(hWnd, (LPPOINT)&rect)); |
| VERIFY(::ScreenToClient(hWnd, ((LPPOINT)&rect) + 1)); |
| VERIFY(::InvalidateRect(hWnd, &rect,TRUE)); |
| VERIFY(::UpdateWindow(hWnd)); |
| } else { |
| c->SendMessage(BM_SETCHECK, (WPARAM)(state ? BST_CHECKED : BST_UNCHECKED)); |
| VERIFY(::InvalidateRect(hWnd, NULL, FALSE)); |
| } |
| c->VerifyState(); |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(group); |
| } |
| |
| done: |
| env->DeleteGlobalRef(checkbox); |
| |
| delete sss; |
| } |
| |
| #ifdef DEBUG |
| void AwtCheckbox::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->EnsureLocalCapacity(2) < 0) { |
| return; |
| } |
| |
| jobject target = GetTarget(env); |
| |
| /* Check button style */ |
| DWORD style = ::GetWindowLong(GetHWnd(), GWL_STYLE); |
| DASSERT(style & BS_OWNERDRAW); |
| |
| /* Check label */ |
| int len = ::GetWindowTextLength(GetHWnd()); |
| LPTSTR peerStr; |
| try { |
| peerStr = new TCHAR[len+1]; |
| } catch (std::bad_alloc&) { |
| env->DeleteLocalRef(target); |
| throw; |
| } |
| |
| GetText(peerStr, len+1); |
| jstring label = (jstring)env->GetObjectField(target, AwtCheckbox::labelID); |
| DASSERT(_tcscmp(peerStr, JavaStringBuffer(env, label)) == 0); |
| delete [] peerStr; |
| |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(label); |
| } |
| #endif |
| |
| |
| /************************************************************************ |
| * Checkbox native methods |
| */ |
| |
| extern "C" { |
| |
| /* |
| * Class: sun_awt_windows_WButtonPeer |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_java_awt_Checkbox_initIDs(JNIEnv *env, jclass cls) |
| { |
| TRY; |
| |
| AwtCheckbox::labelID = |
| env->GetFieldID(cls, "label", "Ljava/lang/String;"); |
| AwtCheckbox::groupID = |
| env->GetFieldID(cls, "group", "Ljava/awt/CheckboxGroup;"); |
| AwtCheckbox::stateID = |
| env->GetFieldID(cls, "state", "Z"); |
| |
| DASSERT(AwtCheckbox::labelID != NULL); |
| DASSERT(AwtCheckbox::groupID != NULL); |
| DASSERT(AwtCheckbox::stateID != NULL); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| } /* extern "C" */ |
| |
| |
| /************************************************************************ |
| * WCheckboxPeer native methods |
| */ |
| |
| extern "C" { |
| |
| /* |
| * Class: sun_awt_windows_WCheckboxPeer |
| * Method: getCheckMarkSize |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WCheckboxPeer_getCheckMarkSize(JNIEnv *env, |
| jclass cls) |
| { |
| return (jint)AwtCheckbox::GetCheckSize(); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCheckboxPeer |
| * Method: setState |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WCheckboxPeer_setState(JNIEnv *env, jobject self, |
| jboolean state) |
| { |
| TRY; |
| |
| SetStateStruct *sss = new SetStateStruct; |
| sss->checkbox = env->NewGlobalRef(self); |
| sss->state = state; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtCheckbox::_SetState, sss); |
| // global refs and sss are deleted in _SetState() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCheckboxPeer |
| * Method: setCheckboxGroup |
| * Signature: (Ljava/awt/CheckboxGroup;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WCheckboxPeer_setCheckboxGroup(JNIEnv *env, jobject self, |
| jobject group) |
| { |
| TRY; |
| |
| jobject *jos = new jobject[2]; |
| jos[0] = env->NewGlobalRef(self); |
| jos[1] = env->NewGlobalRef(group); |
| |
| AwtToolkit::GetInstance().SyncCall(AwtCheckbox::_SetCheckboxGroup, jos); |
| // global refs and jos are deleted in _SetLabel() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCheckboxPeer |
| * Method: setLabel |
| * Signature: (Ljava/lang/String;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WCheckboxPeer_setLabel(JNIEnv *env, jobject self, |
| jstring label) |
| { |
| TRY; |
| |
| SetLabelStruct *sls = new SetLabelStruct; |
| sls->checkbox = env->NewGlobalRef(self); |
| sls->label = (label != NULL) ? (jstring)env->NewGlobalRef(label) : NULL; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtCheckbox::_SetLabel, sls); |
| // global refs and sls are deleted in _SetLabel() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCheckboxPeer |
| * Method: create |
| * Signature: (Lsun/awt/windows/WComponentPeer;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WCheckboxPeer_create(JNIEnv *env, jobject self, |
| jobject parent) |
| { |
| TRY; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_RETURN(parent); |
| AwtToolkit::CreateComponent(self, parent, |
| (AwtToolkit::ComponentFactory) |
| AwtCheckbox::Create); |
| JNI_CHECK_PEER_CREATION_RETURN(self); |
| |
| #ifdef DEBUG |
| ((AwtComponent*)JNI_GET_PDATA(self))->VerifyState(); |
| #endif |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| } /* extern "C" */ |