annotate src/windows/native/sun/windows/awt_Choice.cpp @ 3261:a06412e13bf7

6962318: Update copyright year Reviewed-by: xdono
author ohair
date Tue, 28 Dec 2010 15:53:50 -0800
parents 3a2355dcef13
children 997f464f8446
rev   line source
duke@0 1 /*
ohair@3261 2 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
ohair@2362 7 * published by the Free Software Foundation. Oracle designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
ohair@2362 9 * by Oracle in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
ohair@2362 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2362 22 * or visit www.oracle.com if you need additional information or have any
ohair@2362 23 * questions.
duke@0 24 */
duke@0 25
ant@1058 26 #include <windowsx.h>
ant@1058 27
duke@0 28 #include "awt_Toolkit.h"
duke@0 29 #include "awt_Choice.h"
duke@0 30 #include "awt_Canvas.h"
duke@0 31
duke@0 32 #include "awt_Dimension.h"
duke@0 33 #include "awt_Container.h"
duke@0 34
ant@1058 35 #include "ComCtl32Util.h"
ant@1058 36
duke@0 37 #include <java_awt_Toolkit.h>
duke@0 38 #include <java_awt_FontMetrics.h>
duke@0 39 #include <java_awt_event_InputEvent.h>
duke@0 40
duke@0 41 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
duke@0 42 */
duke@0 43
duke@0 44 /************************************************************************/
duke@0 45 // Struct for _Reshape() method
duke@0 46 struct ReshapeStruct {
duke@0 47 jobject choice;
duke@0 48 jint x, y;
duke@0 49 jint width, height;
duke@0 50 };
duke@0 51 // Struct for _Select() method
duke@0 52 struct SelectStruct {
duke@0 53 jobject choice;
duke@0 54 jint index;
duke@0 55 };
duke@0 56 // Struct for _AddItems() method
duke@0 57 struct AddItemsStruct {
duke@0 58 jobject choice;
duke@0 59 jobjectArray items;
duke@0 60 jint index;
duke@0 61 };
duke@0 62 // Struct for _Remove() method
duke@0 63 struct RemoveStruct {
duke@0 64 jobject choice;
duke@0 65 jint index;
duke@0 66 };
duke@0 67
duke@0 68 /************************************************************************/
duke@0 69
duke@0 70 /* Bug #4509045: set if SetDragCapture captured mouse */
duke@0 71
duke@0 72 BOOL AwtChoice::mouseCapture = FALSE;
duke@0 73
duke@0 74 /* Bug #4338368: consume the spurious MouseUp when the choice loses focus */
duke@0 75
duke@0 76 BOOL AwtChoice::skipNextMouseUp = FALSE;
ant@1058 77
ant@1058 78 BOOL AwtChoice::sm_isMouseMoveInList = FALSE;
ant@1058 79
dcherepanov@1062 80 static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8;
dcherepanov@1062 81
duke@0 82 /*************************************************************************
duke@0 83 * AwtChoice class methods
duke@0 84 */
duke@0 85
duke@0 86 AwtChoice::AwtChoice() {
ant@1058 87 m_hList = NULL;
ant@1058 88 m_listDefWindowProc = NULL;
dcherepanov@3074 89 m_selectedItem = -1;
duke@0 90 }
duke@0 91
duke@0 92 LPCTSTR AwtChoice::GetClassName() {
duke@0 93 return TEXT("COMBOBOX"); /* System provided combobox class */
duke@0 94 }
duke@0 95
ant@1058 96 void AwtChoice::Dispose() {
ant@1058 97 if (m_hList != NULL && m_listDefWindowProc != NULL) {
ant@1058 98 ComCtl32Util::GetInstance().UnsubclassHWND(m_hList, ListWindowProc, m_listDefWindowProc);
ant@1058 99 }
ant@1058 100 AwtComponent::Dispose();
ant@1058 101 }
ant@1058 102
duke@0 103 AwtChoice* AwtChoice::Create(jobject peer, jobject parent) {
duke@0 104
duke@0 105
duke@0 106 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 107
duke@0 108 jobject target = NULL;
duke@0 109 AwtChoice* c = NULL;
duke@0 110 RECT rc;
duke@0 111
duke@0 112 try {
duke@0 113 if (env->EnsureLocalCapacity(1) < 0) {
duke@0 114 return NULL;
duke@0 115 }
duke@0 116 AwtCanvas* awtParent;
duke@0 117
duke@0 118 JNI_CHECK_NULL_GOTO(parent, "null parent", done);
duke@0 119
duke@0 120 awtParent = (AwtCanvas*)JNI_GET_PDATA(parent);
duke@0 121 JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
duke@0 122
duke@0 123 target = env->GetObjectField(peer, AwtObject::targetID);
duke@0 124 JNI_CHECK_NULL_GOTO(target, "null target", done);
duke@0 125
duke@0 126 c = new AwtChoice();
duke@0 127
duke@0 128 {
duke@0 129 DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL |
duke@0 130 CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED;
duke@0 131 DWORD exStyle = 0;
duke@0 132 if (GetRTL()) {
duke@0 133 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
duke@0 134 if (GetRTLReadingOrder())
duke@0 135 exStyle |= WS_EX_RTLREADING;
duke@0 136 }
duke@0 137
duke@0 138 /*
duke@0 139 * In OWNER_DRAW, the size of the edit control part of the
duke@0 140 * choice must be determinded in its creation, when the parent
duke@0 141 * cannot get the choice's instance from its handle. So
duke@0 142 * record the pair of the ID and the instance of the choice.
duke@0 143 */
duke@0 144 UINT myId = awtParent->CreateControlID();
duke@0 145 DASSERT(myId > 0);
duke@0 146 c->m_myControlID = myId;
duke@0 147 awtParent->PushChild(myId, c);
duke@0 148
duke@0 149 jint x = env->GetIntField(target, AwtComponent::xID);
duke@0 150 jint y = env->GetIntField(target, AwtComponent::yID);
duke@0 151 jint width = env->GetIntField(target, AwtComponent::widthID);
duke@0 152 jint height = env->GetIntField(target, AwtComponent::heightID);
duke@0 153
duke@0 154 jobject dimension = JNU_CallMethodByName(env, NULL, peer,
duke@0 155 "preferredSize",
duke@0 156 "()Ljava/awt/Dimension;").l;
duke@0 157 DASSERT(!safe_ExceptionOccurred(env));
duke@0 158
duke@0 159 if (dimension != NULL && width == 0) {
duke@0 160 width = env->GetIntField(dimension, AwtDimension::widthID);
duke@0 161 }
duke@0 162 c->CreateHWnd(env, L"", style, exStyle,
duke@0 163 x, y, width, height,
duke@0 164 awtParent->GetHWnd(),
duke@0 165 reinterpret_cast<HMENU>(static_cast<INT_PTR>(myId)),
duke@0 166 ::GetSysColor(COLOR_WINDOWTEXT),
duke@0 167 ::GetSysColor(COLOR_WINDOW),
duke@0 168 peer);
duke@0 169
duke@0 170 /* suppress inheriting parent's color. */
duke@0 171 c->m_backgroundColorSet = TRUE;
duke@0 172 c->UpdateBackground(env, target);
duke@0 173
duke@0 174 /* Bug 4255631 Solaris: Size returned by Choice.getSize() does not match
duke@0 175 * actual size
duke@0 176 * Fix: Set the Choice to its actual size in the component.
duke@0 177 */
duke@0 178 ::GetClientRect(c->GetHWnd(), &rc);
duke@0 179 env->SetIntField(target, AwtComponent::widthID, (jint) rc.right);
duke@0 180 env->SetIntField(target, AwtComponent::heightID, (jint) rc.bottom);
duke@0 181
dcherepanov@1062 182 if (IS_WINXP) {
dcherepanov@1062 183 ::SendMessage(c->GetHWnd(), CB_SETMINVISIBLE, (WPARAM) MINIMUM_NUMBER_OF_VISIBLE_ITEMS, 0);
dcherepanov@1062 184 }
dcherepanov@1062 185
duke@0 186 env->DeleteLocalRef(dimension);
duke@0 187 }
duke@0 188 } catch (...) {
duke@0 189 env->DeleteLocalRef(target);
duke@0 190 throw;
duke@0 191 }
duke@0 192
duke@0 193 done:
duke@0 194 env->DeleteLocalRef(target);
duke@0 195
duke@0 196 return c;
duke@0 197 }
duke@0 198
duke@0 199 // calculate height of drop-down list part of the combobox
duke@0 200 // to show all the items up to a maximum of eight
duke@0 201 int AwtChoice::GetDropDownHeight()
duke@0 202 {
duke@0 203 int itemHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)0,0);
duke@0 204 int numItemsToShow = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0,0);
dcherepanov@1062 205 numItemsToShow = min(MINIMUM_NUMBER_OF_VISIBLE_ITEMS, numItemsToShow);
duke@0 206 // drop-down height snaps to nearest line, so add a
duke@0 207 // fudge factor of 1/2 line to ensure last line shows
duke@0 208 return itemHeight*numItemsToShow + itemHeight/2;
duke@0 209 }
duke@0 210
duke@0 211 // get the height of the field portion of the combobox
duke@0 212 int AwtChoice::GetFieldHeight()
duke@0 213 {
duke@0 214 int fieldHeight;
duke@0 215 int borderHeight;
duke@0 216 fieldHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)-1, 0);
duke@0 217 // add top and bottom border lines; border size is different for
duke@0 218 // Win 4.x (3d edge) vs 3.x (1 pixel line)
art@862 219 borderHeight = ::GetSystemMetrics(SM_CYEDGE);
duke@0 220 fieldHeight += borderHeight*2;
duke@0 221 return fieldHeight;
duke@0 222 }
duke@0 223
duke@0 224 // gets the total height of the combobox, including drop down
duke@0 225 int AwtChoice::GetTotalHeight()
duke@0 226 {
duke@0 227 int dropHeight = GetDropDownHeight();
duke@0 228 int fieldHeight = GetFieldHeight();
duke@0 229 int totalHeight;
duke@0 230
duke@0 231 // border on drop-down portion is always non-3d (so don't use SM_CYEDGE)
duke@0 232 int borderHeight = ::GetSystemMetrics(SM_CYBORDER);
duke@0 233 // total height = drop down height + field height + top+bottom drop down border lines
duke@0 234 totalHeight = dropHeight + fieldHeight +borderHeight*2;
duke@0 235 return totalHeight;
duke@0 236 }
duke@0 237
duke@0 238 // Recalculate and set the drop-down height for the Choice.
duke@0 239 void AwtChoice::ResetDropDownHeight()
duke@0 240 {
duke@0 241 RECT rcWindow;
duke@0 242
duke@0 243 ::GetWindowRect(GetHWnd(), &rcWindow);
duke@0 244 // resize the drop down to accomodate added/removed items
duke@0 245 int totalHeight = GetTotalHeight();
duke@0 246 ::SetWindowPos(GetHWnd(), NULL,
duke@0 247 0, 0, rcWindow.right - rcWindow.left, totalHeight,
duke@0 248 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
duke@0 249 }
duke@0 250
duke@0 251 /* Fix for the bug 4327666: set the capture for middle
duke@0 252 and right mouse buttons, but leave left button alone */
duke@0 253 void AwtChoice::SetDragCapture(UINT flags)
duke@0 254 {
duke@0 255 if ((flags & MK_LBUTTON) != 0) {
duke@0 256 if ((::GetCapture() == GetHWnd()) && mouseCapture) {
duke@0 257 /* On MK_LBUTTON ComboBox captures mouse itself
duke@0 258 so we should release capture and clear flag to
duke@0 259 prevent releasing capture by ReleaseDragCapture
duke@0 260 */
duke@0 261 ::ReleaseCapture();
duke@0 262 mouseCapture = FALSE;
duke@0 263 }
duke@0 264 return;
duke@0 265 }
ant@1058 266
duke@0 267 // don't want to interfere with other controls
duke@0 268 if (::GetCapture() == NULL) {
duke@0 269 ::SetCapture(GetHWnd());
duke@0 270 mouseCapture = TRUE;
duke@0 271 }
duke@0 272 }
duke@0 273
duke@0 274 /* Fix for Bug 4509045: should release capture only if it is set by SetDragCapture */
duke@0 275 void AwtChoice::ReleaseDragCapture(UINT flags)
duke@0 276 {
duke@0 277 if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0) && mouseCapture) {
duke@0 278 ::ReleaseCapture();
duke@0 279 mouseCapture = FALSE;
duke@0 280 }
duke@0 281 }
duke@0 282
duke@0 283 void AwtChoice::Reshape(int x, int y, int w, int h)
duke@0 284 {
duke@0 285 // Choice component height is fixed (when rolled up)
duke@0 286 // so vertically center the choice in it's bounding box
duke@0 287 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 288 jobject target = GetTarget(env);
duke@0 289 jobject parent = env->GetObjectField(target, AwtComponent::parentID);
duke@0 290 RECT rc;
duke@0 291
duke@0 292 int fieldHeight = GetFieldHeight();
duke@0 293 if ((parent != NULL && env->GetObjectField(parent, AwtContainer::layoutMgrID) != NULL) &&
duke@0 294 fieldHeight > 0 && fieldHeight < h) {
duke@0 295 y += (h - fieldHeight) / 2;
duke@0 296 }
duke@0 297
duke@0 298 /* Fix for 4783342
duke@0 299 * Choice should ignore reshape on height changes,
duke@0 300 * as height is dependent on Font size only.
duke@0 301 */
duke@0 302 AwtComponent* awtParent = GetParent();
duke@0 303 BOOL bReshape = true;
duke@0 304 if (awtParent != NULL) {
duke@0 305 ::GetWindowRect(GetHWnd(), &rc);
duke@0 306 int oldW = rc.right - rc.left;
duke@0 307 RECT parentRc;
duke@0 308 ::GetWindowRect(awtParent->GetHWnd(), &parentRc);
duke@0 309 int oldX = rc.left - parentRc.left;
duke@0 310 int oldY = rc.top - parentRc.top;
duke@0 311 bReshape = (x != oldX || y != oldY || w != oldW);
duke@0 312 }
duke@0 313
duke@0 314 if (bReshape)
duke@0 315 {
duke@0 316 int totalHeight = GetTotalHeight();
duke@0 317 AwtComponent::Reshape(x, y, w, totalHeight);
duke@0 318 }
duke@0 319
duke@0 320 /* Bug 4255631 Solaris: Size returned by Choice.getSize() does not match
duke@0 321 * actual size
duke@0 322 * Fix: Set the Choice to its actual size in the component.
duke@0 323 */
duke@0 324 ::GetClientRect(GetHWnd(), &rc);
duke@0 325 env->SetIntField(target, AwtComponent::widthID, (jint)rc.right);
duke@0 326 env->SetIntField(target, AwtComponent::heightID, (jint)rc.bottom);
duke@0 327
duke@0 328 env->DeleteLocalRef(target);
duke@0 329 env->DeleteLocalRef(parent);
duke@0 330 }
duke@0 331
duke@0 332 jobject AwtChoice::PreferredItemSize(JNIEnv *env)
duke@0 333 {
duke@0 334 jobject dimension = JNU_CallMethodByName(env, NULL, GetPeer(env),
duke@0 335 "preferredSize",
duke@0 336 "()Ljava/awt/Dimension;").l;
duke@0 337 DASSERT(!safe_ExceptionOccurred(env));
duke@0 338 if (dimension == NULL) {
duke@0 339 return NULL;
duke@0 340 }
duke@0 341 /* This size is window size of choice and it's too big for each
duke@0 342 * drop down item height.
duke@0 343 */
duke@0 344 env->SetIntField(dimension, AwtDimension::heightID,
duke@0 345 GetFontHeight(env));
duke@0 346 return dimension;
duke@0 347 }
duke@0 348
duke@0 349 void AwtChoice::SetFont(AwtFont* font)
duke@0 350 {
duke@0 351 AwtComponent::SetFont(font);
duke@0 352
duke@0 353 //Get the text metrics and change the height of each item.
duke@0 354 HDC hDC = ::GetDC(GetHWnd());
duke@0 355 DASSERT(hDC != NULL);
duke@0 356 TEXTMETRIC tm;
duke@0 357
duke@0 358 HANDLE hFont = font->GetHFont();
duke@0 359 VERIFY(::SelectObject(hDC, hFont) != NULL);
duke@0 360 VERIFY(::GetTextMetrics(hDC, &tm));
duke@0 361 long h = tm.tmHeight + tm.tmExternalLeading;
duke@0 362 VERIFY(::ReleaseDC(GetHWnd(), hDC) != 0);
duke@0 363
duke@0 364 int nCount = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0, 0);
duke@0 365 for(int i = 0; i < nCount; ++i) {
duke@0 366 VERIFY(::SendMessage(GetHWnd(), CB_SETITEMHEIGHT, i, MAKELPARAM(h, 0)) != CB_ERR);
duke@0 367 }
duke@0 368 //Change the height of the Edit Box.
duke@0 369 VERIFY(::SendMessage(GetHWnd(), CB_SETITEMHEIGHT, (UINT)-1,
duke@0 370 MAKELPARAM(h, 0)) != CB_ERR);
duke@0 371
duke@0 372 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 373 jobject target = GetTarget(env);
duke@0 374 jint height = env->GetIntField(target, AwtComponent::heightID);
duke@0 375
duke@0 376 Reshape(env->GetIntField(target, AwtComponent::xID),
duke@0 377 env->GetIntField(target, AwtComponent::yID),
duke@0 378 env->GetIntField(target, AwtComponent::widthID),
duke@0 379 h);
duke@0 380
duke@0 381 env->DeleteLocalRef(target);
duke@0 382 }
duke@0 383
ant@1058 384 static int lastClickX = -1;
ant@1058 385 static int lastClickY = -1;
ant@1058 386
ant@1058 387 LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message,
ant@1058 388 WPARAM wParam, LPARAM lParam)
ant@1058 389 {
ant@1058 390 /*
ant@1058 391 * We don't pass the choice WM_LBUTTONDOWN message. As the result the choice's list
ant@1058 392 * doesn't forward mouse messages it captures. Below we do forward what we need.
ant@1058 393 */
ant@1058 394
ant@1058 395 TRY;
ant@1058 396
ant@1058 397 DASSERT(::IsWindow(hwnd));
ant@1058 398
ant@1058 399 switch (message) {
ant@1058 400 case WM_LBUTTONDOWN: {
ant@1058 401 DWORD curPos = ::GetMessagePos();
ant@1058 402 lastClickX = GET_X_LPARAM(curPos);
ant@1058 403 lastClickY = GET_Y_LPARAM(curPos);
ant@1058 404 break;
ant@1058 405 }
ant@1058 406 case WM_MOUSEMOVE: {
ant@1058 407 RECT rect;
ant@1058 408 ::GetClientRect(hwnd, &rect);
ant@1058 409
ant@1058 410 POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
ant@1058 411 if (::PtInRect(&rect, pt)) {
ant@1058 412 sm_isMouseMoveInList = TRUE;
ant@1058 413 }
ant@1058 414
ant@1058 415 POINT lastPt = {lastClickX, lastClickY};
ant@1058 416 ::ScreenToClient(hwnd, &lastPt);
ant@1058 417 if (::PtInRect(&rect, lastPt)) {
ant@1058 418 break; // ignore when dragging inside the list
ant@1058 419 }
ant@1058 420 }
ant@1058 421 case WM_LBUTTONUP: {
ant@1058 422 lastClickX = -1;
ant@1058 423 lastClickY = -1;
ant@1058 424
ant@1058 425 AwtChoice *c = (AwtChoice *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ant@1058 426 if (c != NULL) {
ant@1058 427 // forward the msg to the choice
ant@1058 428 c->WindowProc(message, wParam, lParam);
ant@1058 429 }
ant@1058 430 }
ant@1058 431 }
ant@1058 432 return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam);
ant@1058 433
ant@1058 434 CATCH_BAD_ALLOC_RET(0);
ant@1058 435 }
duke@0 436
duke@0 437
duke@0 438 MsgRouting AwtChoice::WmNotify(UINT notifyCode)
duke@0 439 {
duke@0 440 if (notifyCode == CBN_SELCHANGE) {
dcherepanov@3074 441 int selectedItem = (int)SendMessage(CB_GETCURSEL);
dcherepanov@3074 442 if (selectedItem != CB_ERR && m_selectedItem != selectedItem){
dcherepanov@3074 443 m_selectedItem = selectedItem;
dcherepanov@3074 444 DoCallback("handleAction", "(I)V", selectedItem);
duke@0 445 }
ant@1058 446 } else if (notifyCode == CBN_DROPDOWN) {
ant@1058 447
ant@1058 448 if (m_hList == NULL) {
ant@1058 449 COMBOBOXINFO cbi;
ant@1058 450 cbi.cbSize = sizeof(COMBOBOXINFO);
ant@1058 451 ::GetComboBoxInfo(GetHWnd(), &cbi);
ant@1058 452 m_hList = cbi.hwndList;
ant@1058 453 m_listDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(m_hList, ListWindowProc);
ant@1058 454 DASSERT(::GetWindowLongPtr(m_hList, GWLP_USERDATA) == NULL);
ant@1058 455 ::SetWindowLongPtr(m_hList, GWLP_USERDATA, (LONG_PTR)this);
ant@1058 456 }
ant@1058 457 sm_isMouseMoveInList = FALSE;
ant@1058 458
ant@1058 459 // Clicking in the dropdown list steals focus from the proxy.
ant@1058 460 // So, set the focus-restore flag up.
ant@1058 461 SetRestoreFocus(TRUE);
ant@1058 462 } else if (notifyCode == CBN_CLOSEUP) {
ant@1058 463 SetRestoreFocus(FALSE);
duke@0 464 }
duke@0 465 return mrDoDefault;
duke@0 466 }
duke@0 467
duke@0 468 MsgRouting
duke@0 469 AwtChoice::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
duke@0 470 {
duke@0 471 DrawListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), drawInfo);
duke@0 472 return mrConsume;
duke@0 473 }
duke@0 474
duke@0 475 MsgRouting
duke@0 476 AwtChoice::OwnerMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT& measureInfo)
duke@0 477 {
duke@0 478 MeasureListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), measureInfo);
duke@0 479 return mrConsume;
duke@0 480 }
duke@0 481
duke@0 482 /* Bug #4338368: when a choice loses focus, it triggers spurious MouseUp event,
duke@0 483 * even if the focus was lost due to TAB key pressing
duke@0 484 */
duke@0 485
duke@0 486 MsgRouting
duke@0 487 AwtChoice::WmKillFocus(HWND hWndGotFocus)
duke@0 488 {
duke@0 489 skipNextMouseUp = TRUE;
ant@1058 490 return AwtComponent::WmKillFocus(hWndGotFocus);
duke@0 491 }
duke@0 492
duke@0 493 MsgRouting
duke@0 494 AwtChoice::WmMouseUp(UINT flags, int x, int y, int button)
duke@0 495 {
duke@0 496 if (skipNextMouseUp) {
duke@0 497 skipNextMouseUp = FALSE;
duke@0 498 return mrDoDefault;
duke@0 499 }
duke@0 500 return AwtComponent::WmMouseUp(flags, x, y, button);
duke@0 501 }
duke@0 502
duke@0 503 MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic)
duke@0 504 {
ant@1058 505 if (IsFocusingMouseMessage(msg)) {
ant@1058 506 SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0);
ant@1058 507 delete msg;
ant@1058 508 return mrConsume;
ant@1058 509 }
ant@1058 510 // To simulate the native behavior, we close the list on WM_LBUTTONUP if
ant@1058 511 // WM_MOUSEMOVE has been dedected on the list since it has been dropped down.
ant@1058 512 if (msg->message == WM_LBUTTONUP && SendMessage(CB_GETDROPPEDSTATE, 0, 0) &&
ant@1058 513 sm_isMouseMoveInList)
duke@0 514 {
ant@1058 515 SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
duke@0 516 }
duke@0 517 return AwtComponent::HandleEvent(msg, synthetic);
duke@0 518 }
duke@0 519
duke@0 520 BOOL AwtChoice::InheritsNativeMouseWheelBehavior() {return true;}
duke@0 521
duke@0 522 void AwtChoice::_Reshape(void *param)
duke@0 523 {
duke@0 524 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 525
duke@0 526 ReshapeStruct *rs = (ReshapeStruct *)param;
duke@0 527 jobject choice = rs->choice;
duke@0 528 jint x = rs->x;
duke@0 529 jint y = rs->y;
duke@0 530 jint width = rs->width;
duke@0 531 jint height = rs->height;
duke@0 532
duke@0 533 AwtChoice *c = NULL;
duke@0 534
duke@0 535 PDATA pData;
duke@0 536 JNI_CHECK_PEER_GOTO(choice, done);
duke@0 537
duke@0 538 c = (AwtChoice *)pData;
duke@0 539 if (::IsWindow(c->GetHWnd()))
duke@0 540 {
duke@0 541 c->Reshape(x, y, width, height);
duke@0 542 c->VerifyState();
duke@0 543 }
duke@0 544
duke@0 545 done:
duke@0 546 env->DeleteGlobalRef(choice);
duke@0 547
duke@0 548 delete rs;
duke@0 549 }
duke@0 550
duke@0 551 void AwtChoice::_Select(void *param)
duke@0 552 {
duke@0 553 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 554
duke@0 555 SelectStruct *ss = (SelectStruct *)param;
duke@0 556 jobject choice = ss->choice;
duke@0 557 jint index = ss->index;
duke@0 558
duke@0 559 AwtChoice *c = NULL;
duke@0 560
duke@0 561 PDATA pData;
duke@0 562 JNI_CHECK_PEER_GOTO(choice, done);
duke@0 563
duke@0 564 c = (AwtChoice *)pData;
duke@0 565 if (::IsWindow(c->GetHWnd()))
duke@0 566 {
duke@0 567 c->SendMessage(CB_SETCURSEL, index);
duke@0 568 // c->VerifyState();
duke@0 569 }
duke@0 570
duke@0 571 done:
duke@0 572 env->DeleteGlobalRef(choice);
duke@0 573
duke@0 574 delete ss;
duke@0 575 }
duke@0 576
duke@0 577 void AwtChoice::_AddItems(void *param)
duke@0 578 {
duke@0 579 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 580
duke@0 581 AddItemsStruct *ais = (AddItemsStruct *)param;
duke@0 582 jobject choice = ais->choice;
duke@0 583 jobjectArray items = ais->items;
duke@0 584 jint index = ais->index;
duke@0 585
duke@0 586 AwtChoice *c = NULL;
duke@0 587
duke@0 588 PDATA pData;
duke@0 589 JNI_CHECK_PEER_GOTO(choice, done);
duke@0 590 JNI_CHECK_NULL_GOTO(items, "null items", done);
duke@0 591
duke@0 592 c = (AwtChoice *)pData;
duke@0 593 if (::IsWindow(c->GetHWnd()))
duke@0 594 {
duke@0 595 jsize i;
duke@0 596 int itemCount = env->GetArrayLength(items);
duke@0 597 if (itemCount > 0) {
duke@0 598 c->SendMessage(WM_SETREDRAW, (WPARAM)FALSE, 0);
duke@0 599 for (i = 0; i < itemCount; i++)
duke@0 600 {
duke@0 601 jstring item = (jstring)env->GetObjectArrayElement(items, i);
duke@0 602 JNI_CHECK_NULL_GOTO(item, "null item", next_elem);
duke@0 603 c->SendMessage(CB_INSERTSTRING, index + i, JavaStringBuffer(env, item));
duke@0 604 env->DeleteLocalRef(item);
duke@0 605 next_elem:
duke@0 606 ;
duke@0 607 }
duke@0 608 c->SendMessage(WM_SETREDRAW, (WPARAM)TRUE, 0);
duke@0 609 InvalidateRect(c->GetHWnd(), NULL, TRUE);
duke@0 610 c->ResetDropDownHeight();
duke@0 611 c->VerifyState();
duke@0 612 }
duke@0 613 }
duke@0 614
duke@0 615 done:
duke@0 616 env->DeleteGlobalRef(choice);
duke@0 617 env->DeleteGlobalRef(items);
duke@0 618
duke@0 619 delete ais;
duke@0 620 }
duke@0 621
duke@0 622 void AwtChoice::_Remove(void *param)
duke@0 623 {
duke@0 624 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 625
duke@0 626 RemoveStruct *rs = (RemoveStruct *)param;
duke@0 627 jobject choice = rs->choice;
duke@0 628 jint index = rs->index;
duke@0 629
duke@0 630 AwtChoice *c = NULL;
duke@0 631
duke@0 632 PDATA pData;
duke@0 633 JNI_CHECK_PEER_GOTO(choice, done);
duke@0 634
duke@0 635 c = (AwtChoice *)pData;
duke@0 636 if (::IsWindow(c->GetHWnd()))
duke@0 637 {
duke@0 638 c->SendMessage(CB_DELETESTRING, index, 0);
duke@0 639 c->ResetDropDownHeight();
duke@0 640 c->VerifyState();
duke@0 641 }
duke@0 642
duke@0 643 done:
duke@0 644 env->DeleteGlobalRef(choice);
duke@0 645
duke@0 646 delete rs;
duke@0 647 }
duke@0 648
duke@0 649 void AwtChoice::_RemoveAll(void *param)
duke@0 650 {
duke@0 651 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 652
duke@0 653 jobject choice = (jobject)param;
duke@0 654
duke@0 655 AwtChoice *c = NULL;
duke@0 656
duke@0 657 PDATA pData;
duke@0 658 JNI_CHECK_PEER_GOTO(choice, done);
duke@0 659
duke@0 660 c = (AwtChoice *)pData;
duke@0 661 if (::IsWindow(c->GetHWnd()))
duke@0 662 {
duke@0 663 c->SendMessage(CB_RESETCONTENT, 0, 0);
duke@0 664 c->ResetDropDownHeight();
duke@0 665 c->VerifyState();
duke@0 666 }
duke@0 667
duke@0 668 done:
duke@0 669 env->DeleteGlobalRef(choice);
duke@0 670 }
duke@0 671
ant@1058 672 void AwtChoice::_CloseList(void *param)
ant@1058 673 {
ant@1058 674 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
ant@1058 675
ant@1058 676 jobject choice = (jobject)param;
ant@1058 677
ant@1058 678 AwtChoice *c = NULL;
ant@1058 679
ant@1058 680 PDATA pData;
ant@1058 681 JNI_CHECK_PEER_GOTO(choice, done);
ant@1058 682
ant@1058 683 c = (AwtChoice *)pData;
ant@1058 684 if (::IsWindow(c->GetHWnd()) && c->SendMessage(CB_GETDROPPEDSTATE, 0, 0)) {
ant@1058 685 c->SendMessage(CB_SHOWDROPDOWN, FALSE, 0);
ant@1058 686 }
ant@1058 687
ant@1058 688 done:
ant@1058 689 env->DeleteGlobalRef(choice);
ant@1058 690 }
ant@1058 691
duke@0 692 /************************************************************************
duke@0 693 * WChoicePeer native methods
duke@0 694 */
duke@0 695
duke@0 696 extern "C" {
duke@0 697
duke@0 698 /*
duke@0 699 * Class: sun_awt_windows_WChoicePeer
duke@0 700 * Method: select
duke@0 701 * Signature: (I)V
duke@0 702 */
duke@0 703 JNIEXPORT void JNICALL
duke@0 704 Java_sun_awt_windows_WChoicePeer_select(JNIEnv *env, jobject self,
duke@0 705 jint index)
duke@0 706 {
duke@0 707 TRY;
duke@0 708
duke@0 709 SelectStruct *ss = new SelectStruct;
duke@0 710 ss->choice = env->NewGlobalRef(self);
duke@0 711 ss->index = index;
duke@0 712
duke@0 713 AwtToolkit::GetInstance().SyncCall(AwtChoice::_Select, ss);
duke@0 714 // global refs and ss are removed in _Select
duke@0 715
duke@0 716 CATCH_BAD_ALLOC;
duke@0 717 }
duke@0 718
duke@0 719 /*
duke@0 720 * Class: sun_awt_windows_WChoicePeer
duke@0 721 * Method: remove
duke@0 722 * Signature: (I)V
duke@0 723 */
duke@0 724 JNIEXPORT void JNICALL
duke@0 725 Java_sun_awt_windows_WChoicePeer_remove(JNIEnv *env, jobject self,
duke@0 726 jint index)
duke@0 727 {
duke@0 728 TRY;
duke@0 729
duke@0 730 RemoveStruct *rs = new RemoveStruct;
duke@0 731 rs->choice = env->NewGlobalRef(self);
duke@0 732 rs->index = index;
duke@0 733
duke@0 734 AwtToolkit::GetInstance().SyncCall(AwtChoice::_Remove, rs);
duke@0 735 // global ref and rs are deleted in _Remove
duke@0 736
duke@0 737 CATCH_BAD_ALLOC;
duke@0 738 }
duke@0 739
duke@0 740 /*
duke@0 741 * Class: sun_awt_windows_WChoicePeer
duke@0 742 * Method: removeAll
duke@0 743 * Signature: ()V
duke@0 744 */
duke@0 745 JNIEXPORT void JNICALL
duke@0 746 Java_sun_awt_windows_WChoicePeer_removeAll(JNIEnv *env, jobject self)
duke@0 747 {
duke@0 748 TRY;
duke@0 749
duke@0 750 jobject selfGlobalRef = env->NewGlobalRef(self);
duke@0 751
duke@0 752 AwtToolkit::GetInstance().SyncCall(AwtChoice::_RemoveAll, (void *)selfGlobalRef);
duke@0 753 // selfGlobalRef is deleted in _RemoveAll
duke@0 754
duke@0 755 CATCH_BAD_ALLOC;
duke@0 756 }
duke@0 757
duke@0 758 /*
duke@0 759 * Class: sun_awt_windows_WChoicePeer
duke@0 760 * Method: addItems
duke@0 761 * Signature: ([Ljava/lang/String;I)V
duke@0 762 */
duke@0 763 JNIEXPORT void JNICALL
duke@0 764 Java_sun_awt_windows_WChoicePeer_addItems(JNIEnv *env, jobject self,
duke@0 765 jobjectArray items, jint index)
duke@0 766 {
duke@0 767 TRY;
duke@0 768
duke@0 769 AddItemsStruct *ais = new AddItemsStruct;
duke@0 770 ais->choice = env->NewGlobalRef(self);
duke@0 771 ais->items = (jobjectArray)env->NewGlobalRef(items);
duke@0 772 ais->index = index;
duke@0 773
duke@0 774 AwtToolkit::GetInstance().SyncCall(AwtChoice::_AddItems, ais);
duke@0 775 // global refs and ais are deleted in _AddItems
duke@0 776
duke@0 777 CATCH_BAD_ALLOC;
duke@0 778 }
duke@0 779
duke@0 780 /*
duke@0 781 * Class: sun_awt_windows_WChoicePeer
duke@0 782 * Method: reshape
duke@0 783 * Signature: (IIII)V
duke@0 784 */
duke@0 785 JNIEXPORT void JNICALL
duke@0 786 Java_sun_awt_windows_WChoicePeer_reshape(JNIEnv *env, jobject self,
duke@0 787 jint x, jint y,
duke@0 788 jint width, jint height)
duke@0 789 {
duke@0 790 TRY;
duke@0 791
duke@0 792 ReshapeStruct *rs = new ReshapeStruct;
duke@0 793 rs->choice = env->NewGlobalRef(self);
duke@0 794 rs->x = x;
duke@0 795 rs->y = y;
duke@0 796 rs->width = width;
duke@0 797 rs->height = height;
duke@0 798
duke@0 799 AwtToolkit::GetInstance().SyncCall(AwtChoice::_Reshape, rs);
duke@0 800 // global ref and rs are deleted in _Reshape
duke@0 801
duke@0 802 CATCH_BAD_ALLOC;
duke@0 803 }
duke@0 804
duke@0 805 /*
duke@0 806 * Class: sun_awt_windows_WChoicePeer
duke@0 807 * Method: create
duke@0 808 * Signature: (Lsun/awt/windows/WComponentPeer;)V
duke@0 809 */
duke@0 810 JNIEXPORT void JNICALL
duke@0 811 Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self,
duke@0 812 jobject parent)
duke@0 813 {
duke@0 814 TRY;
duke@0 815
duke@0 816 PDATA pData;
duke@0 817 JNI_CHECK_PEER_RETURN(parent);
duke@0 818 AwtToolkit::CreateComponent(self, parent,
duke@0 819 (AwtToolkit::ComponentFactory)
duke@0 820 AwtChoice::Create);
duke@0 821 JNI_CHECK_PEER_CREATION_RETURN(self);
duke@0 822
duke@0 823 CATCH_BAD_ALLOC;
duke@0 824 }
duke@0 825
ant@1058 826 /*
ant@1058 827 * Class: sun_awt_windows_WChoicePeer
ant@1058 828 * Method: closeList
ant@1058 829 * Signature: ()V
ant@1058 830 */
ant@1058 831 JNIEXPORT void JNICALL
ant@1058 832 Java_sun_awt_windows_WChoicePeer_closeList(JNIEnv *env, jobject self)
ant@1058 833 {
ant@1058 834 TRY;
ant@1058 835
ant@1058 836 jobject selfGlobalRef = env->NewGlobalRef(self);
ant@1058 837
ant@1058 838 AwtToolkit::GetInstance().SyncCall(AwtChoice::_CloseList, (void *)selfGlobalRef);
ant@1058 839 // global ref is deleted in _CloseList
ant@1058 840
ant@1058 841 CATCH_BAD_ALLOC;
ant@1058 842 }
duke@0 843 } /* extern "C" */
duke@0 844
duke@0 845
duke@0 846 /************************************************************************
duke@0 847 * Diagnostic routines
duke@0 848 */
duke@0 849
duke@0 850 #ifdef DEBUG
duke@0 851
duke@0 852 void AwtChoice::VerifyState()
duke@0 853 {
duke@0 854 if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
duke@0 855 return;
duke@0 856 }
duke@0 857
duke@0 858 if (m_callbacksEnabled == FALSE) {
duke@0 859 /* Component is not fully setup yet. */
duke@0 860 return;
duke@0 861 }
duke@0 862
duke@0 863 AwtComponent::VerifyState();
duke@0 864 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
duke@0 865 if (env->PushLocalFrame(1) < 0)
duke@0 866 return;
duke@0 867
duke@0 868 jobject target = GetTarget(env);
duke@0 869
duke@0 870 // To avoid possibly running client code on the toolkit thread, don't
duke@0 871 // do the following checks if we're running on the toolkit thread.
duke@0 872 if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
duke@0 873 // Compare number of items.
duke@0 874 int nTargetItems = JNU_CallMethodByName(env, NULL, target,
duke@0 875 "countItems", "()I").i;
duke@0 876 DASSERT(!safe_ExceptionOccurred(env));
duke@0 877 int nPeerItems = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0, 0);
duke@0 878 DASSERT(nTargetItems == nPeerItems);
duke@0 879
duke@0 880 // Compare selection
duke@0 881 int targetIndex = JNU_CallMethodByName(env, NULL, target,
duke@0 882 "getSelectedIndex", "()I").i;
duke@0 883 DASSERT(!safe_ExceptionOccurred(env));
duke@0 884 int peerCurSel = (int)::SendMessage(GetHWnd(), CB_GETCURSEL, 0, 0);
duke@0 885 DASSERT(targetIndex == peerCurSel);
duke@0 886 }
duke@0 887 env->PopLocalFrame(0);
duke@0 888 }
duke@0 889 #endif //DEBUG