1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt_MenuBar.h" 27 #include "awt_Frame.h" 28 29 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. 30 */ 31 32 /***********************************************************************/ 33 // struct for _AddMenu() method 34 struct AddMenuStruct { 35 jobject menubar; 36 jobject menu; 37 }; 38 /************************************************************************ 39 * AwtMenuBar fields 40 */ 41 42 jmethodID AwtMenuBar::getMenuMID; 43 jmethodID AwtMenuBar::getMenuCountMID; 44 45 46 /************************************************************************ 47 * AwtMenuBar methods 48 */ 49 50 51 AwtMenuBar::AwtMenuBar() { 52 m_frame = NULL; 53 } 54 55 AwtMenuBar::~AwtMenuBar() 56 { 57 } 58 59 void AwtMenuBar::Dispose() 60 { 61 m_frame = NULL; 62 63 AwtMenu::Dispose(); 64 } 65 66 LPCTSTR AwtMenuBar::GetClassName() { 67 return TEXT("SunAwtMenuBar"); 68 } 69 70 /* Create a new AwtMenuBar object and menu. */ 71 AwtMenuBar* AwtMenuBar::Create(jobject self, jobject framePeer) 72 { 73 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 74 75 jobject target = NULL; 76 AwtMenuBar* menuBar = NULL; 77 78 try { 79 if (env->EnsureLocalCapacity(1) < 0) { 80 return NULL; 81 } 82 83 /* target is a java.awt.MenuBar */ 84 target = env->GetObjectField(self, AwtObject::targetID); 85 JNI_CHECK_NULL_GOTO(target, "null target", done); 86 87 menuBar = new AwtMenuBar(); 88 89 SetLastError(0); 90 HMENU hMenu = ::CreateMenu(); 91 // fix for 5088782 92 if (!CheckMenuCreation(env, self, hMenu)) 93 { 94 env->DeleteLocalRef(target); 95 return NULL; 96 } 97 98 menuBar->SetHMenu(hMenu); 99 100 menuBar->LinkObjects(env, self); 101 if (framePeer != NULL) { 102 PDATA pData; 103 JNI_CHECK_PEER_GOTO(framePeer, done); 104 menuBar->m_frame = (AwtFrame *)pData; 105 } else { 106 menuBar->m_frame = NULL; 107 } 108 } catch (...) { 109 env->DeleteLocalRef(target); 110 throw; 111 } 112 113 done: 114 if (target != NULL) { 115 env->DeleteLocalRef(target); 116 } 117 118 return menuBar; 119 } 120 121 HWND AwtMenuBar::GetOwnerHWnd() 122 { 123 AwtFrame *myFrame = m_frame; 124 if (myFrame == NULL) 125 return NULL; 126 else 127 return myFrame->GetHWnd(); 128 } 129 130 void AwtMenuBar::SendDrawItem(AwtMenuItem* awtMenuItem, 131 DRAWITEMSTRUCT& drawInfo) 132 { 133 awtMenuItem->DrawItem(drawInfo); 134 } 135 136 void AwtMenuBar::SendMeasureItem(AwtMenuItem* awtMenuItem, 137 HDC hDC, MEASUREITEMSTRUCT& measureInfo) 138 { 139 awtMenuItem->MeasureItem(hDC, measureInfo); 140 } 141 142 int AwtMenuBar::CountItem(jobject menuBar) 143 { 144 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 145 jint nCount = env->CallIntMethod(menuBar, AwtMenuBar::getMenuCountMID); 146 DASSERT(!safe_ExceptionOccurred(env)); 147 148 return nCount; 149 } 150 151 AwtMenuItem* AwtMenuBar::GetItem(jobject target, long index) 152 { 153 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 154 if (env->EnsureLocalCapacity(2) < 0) { 155 return NULL; 156 } 157 158 jobject menu = env->CallObjectMethod(target, AwtMenuBar::getMenuMID,index); 159 if (!menu) return NULL; // menu item was removed concurrently 160 DASSERT(!safe_ExceptionOccurred(env)); 161 162 jobject menuItemPeer = GetPeerForTarget(env, menu); 163 PDATA pData; 164 JNI_CHECK_PEER_GOTO(menuItemPeer, done); 165 166 AwtMenuItem* awtMenuItem = (AwtMenuItem*)pData; 167 168 done: 169 env->DeleteLocalRef(menu); 170 env->DeleteLocalRef(menuItemPeer); 171 172 return awtMenuItem; 173 } 174 175 void AwtMenuBar::DrawItem(DRAWITEMSTRUCT& drawInfo) 176 { 177 DASSERT(drawInfo.CtlType == ODT_MENU); 178 AwtMenu::DrawItems(drawInfo); 179 } 180 181 void AwtMenuBar::MeasureItem(HDC hDC, 182 MEASUREITEMSTRUCT& measureInfo) 183 { 184 DASSERT(measureInfo.CtlType == ODT_MENU); 185 AwtMenu::MeasureItem(hDC, measureInfo); 186 } 187 188 void AwtMenuBar::AddItem(AwtMenuItem* item) 189 { 190 AwtMenu::AddItem(item); 191 HWND hOwnerWnd = GetOwnerHWnd(); 192 if (hOwnerWnd != NULL) { 193 VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE)); 194 } 195 } 196 197 void AwtMenuBar::DeleteItem(UINT index) 198 { 199 AwtMenu::DeleteItem(index); 200 HWND hOwnerWnd = GetOwnerHWnd(); 201 if (hOwnerWnd != NULL) { 202 VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE)); 203 } 204 RedrawMenuBar(); 205 } 206 207 /** 208 * If the menu changes after the system has created the window, 209 * this function must be called to draw the changed menu bar. 210 */ 211 void AwtMenuBar::RedrawMenuBar() { 212 VERIFY(::DrawMenuBar(GetOwnerHWnd())); 213 } 214 215 LRESULT AwtMenuBar::WinThreadExecProc(ExecuteArgs * args) 216 { 217 switch( args->cmdId ) { 218 case MENUBAR_DELITEM: 219 this->DeleteItem(static_cast<UINT>(args->param1)); 220 break; 221 222 default: 223 AwtMenu::WinThreadExecProc(args); 224 break; 225 } 226 return 0L; 227 } 228 229 void AwtMenuBar::_AddMenu(void *param) 230 { 231 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 232 233 AddMenuStruct *ams = (AddMenuStruct *)param; 234 jobject self = ams->menubar; 235 jobject menu = ams->menu; 236 237 AwtMenuBar *m = NULL; 238 239 PDATA pData; 240 JNI_CHECK_PEER_GOTO(self, ret); 241 JNI_CHECK_NULL_GOTO(menu, "null menu", ret); 242 m = (AwtMenuBar *)pData; 243 if (::IsWindow(m->GetOwnerHWnd())) 244 { 245 /* The menu was already created and added during peer creation -- redraw */ 246 m->RedrawMenuBar(); 247 } 248 ret: 249 env->DeleteGlobalRef(self); 250 if (menu != NULL) { 251 env->DeleteGlobalRef(menu); 252 } 253 254 delete ams; 255 } 256 257 /************************************************************************ 258 * MenuBar native methods 259 */ 260 261 extern "C" { 262 263 /* 264 * Class: java_awt_MenuBar 265 * Method: initIDs 266 * Signature: ()V 267 */ 268 JNIEXPORT void JNICALL 269 Java_java_awt_MenuBar_initIDs(JNIEnv *env, jclass cls) 270 { 271 TRY; 272 273 AwtMenuBar::getMenuCountMID = env->GetMethodID(cls, "getMenuCountImpl", "()I"); 274 DASSERT(AwtMenuBar::getMenuCountMID != NULL); 275 CHECK_NULL(AwtMenuBar::getMenuCountMID); 276 277 AwtMenuBar::getMenuMID = env->GetMethodID(cls, "getMenuImpl", 278 "(I)Ljava/awt/Menu;"); 279 DASSERT(AwtMenuBar::getMenuMID != NULL); 280 281 CATCH_BAD_ALLOC; 282 } 283 284 } /* extern "C" */ 285 286 287 /************************************************************************ 288 * WMenuBarPeer native methods 289 */ 290 291 extern "C" { 292 293 /* 294 * Class: sun_awt_windows_WMenuBarPeer 295 * Method: addMenu 296 * Signature: (Ljava/awt/Menu;)V 297 */ 298 JNIEXPORT void JNICALL 299 Java_sun_awt_windows_WMenuBarPeer_addMenu(JNIEnv *env, jobject self, 300 jobject menu) 301 { 302 TRY; 303 304 AddMenuStruct *ams = new AddMenuStruct; 305 ams->menubar = env->NewGlobalRef(self); 306 ams->menu = env->NewGlobalRef(menu); 307 308 AwtToolkit::GetInstance().SyncCall(AwtMenuBar::_AddMenu, ams); 309 // global refs and ams are deleted in _AddMenu() 310 311 CATCH_BAD_ALLOC; 312 } 313 314 /* 315 * Class: sun_awt_windows_WMenuBarPeer 316 * Method: delMenu 317 * Signature: (I)V 318 */ 319 JNIEXPORT void JNICALL 320 Java_sun_awt_windows_WMenuBarPeer_delMenu(JNIEnv *env, jobject self, 321 jint index) 322 { 323 TRY; 324 325 PDATA pData; 326 JNI_CHECK_PEER_RETURN(self); 327 AwtObject::WinThreadExec(self, AwtMenuBar::MENUBAR_DELITEM, (LPARAM)index); 328 329 CATCH_BAD_ALLOC; 330 } 331 332 /* 333 * Class: sun_awt_windows_WMenuBarPeer 334 * Method: create 335 * Signature: (Lsun/awt/windows/WFramePeer;)V 336 */ 337 JNIEXPORT void JNICALL 338 Java_sun_awt_windows_WMenuBarPeer_create(JNIEnv *env, jobject self, 339 jobject frame) 340 { 341 TRY; 342 343 AwtToolkit::CreateComponent(self, frame, 344 (AwtToolkit::ComponentFactory) 345 AwtMenuBar::Create); 346 PDATA pData; 347 JNI_CHECK_PEER_CREATION_RETURN(self); 348 349 CATCH_BAD_ALLOC; 350 } 351 352 } /* extern "C" */