blob: 0064344497033a029dacf4103ccf5fa4ea55cccc [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#ifdef HEADLESS
27 #error This file should not be included in headless library
28#endif
29
30#include "awt_p.h"
31#include "java_awt_List.h"
32#include "java_awt_AWTEvent.h"
33#include "sun_awt_motif_MListPeer.h"
34#include "sun_awt_motif_MComponentPeer.h"
35#include "java_awt_event_MouseWheelEvent.h"
36#include "canvas.h"
37
38#include "awt_Component.h"
39
40#include "multi_font.h"
41#include <jni.h>
42#include <jni_util.h>
43
44extern struct MComponentPeerIDs mComponentPeerIDs;
45extern struct ComponentIDs componentIDs;
46extern AwtGraphicsConfigDataPtr
47 copyGraphicsConfigToPeer(JNIEnv *env, jobject this);
48
49
50/*
51 * client_data = MListPeer instance
52 */
53static void
54Slist_callback(Widget w, XtPointer client_data, XtPointer call_data)
55{
56 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
57 XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
58
59 switch (cbs->reason) {
60 case XmCR_DEFAULT_ACTION: {
61 ConvertEventTimeAndModifiers converted;
62
63 awt_util_convertEventTimeAndModifiers(cbs->event, &converted);
64
65 if (cbs->event->type == KeyPress) {
66 /* When Default action comes from keyboard, no notification
67 * is given by motif that a selection has been made, even
68 * though, internally, the item will now be selected regardless
69 * of whether or not it was previously selected. ( on mouse
70 * generated DEFAULT ACTIONS the XmCR_BROWSE_SELECT is
71 * generated first ).
72 */
73 JNU_CallMethodByName(env, NULL, (jobject) client_data
74 ,"handleListChanged"
75 ,"(I)V"
76 ,(cbs->item_position - 1));
77 if ((*env)->ExceptionOccurred(env)) {
78 (*env)->ExceptionDescribe(env);
79 (*env)->ExceptionClear(env);
80 }
81 }
82
83 JNU_CallMethodByName(env, NULL, (jobject) client_data
84 ,"action"
85 ,"(IJI)V"
86 ,(cbs->item_position - 1)
87 ,converted.when
88 ,converted.modifiers);
89 if ((*env)->ExceptionOccurred(env)) {
90 (*env)->ExceptionDescribe(env);
91 (*env)->ExceptionClear(env);
92 }
93 break;
94 }
95 case XmCR_BROWSE_SELECT:
96 JNU_CallMethodByName(env, NULL, (jobject) client_data
97 ,"handleListChanged"
98 ,"(I)V"
99 ,(cbs->item_position - 1));
100 if ((*env)->ExceptionOccurred(env)) {
101 (*env)->ExceptionDescribe(env);
102 (*env)->ExceptionClear(env);
103 }
104 break;
105
106 case XmCR_MULTIPLE_SELECT:
107 JNU_CallMethodByName(env, NULL, (jobject) client_data
108 ,"handleListChanged"
109 ,"(I)V"
110 ,(cbs->item_position - 1));
111 if ((*env)->ExceptionOccurred(env)) {
112 (*env)->ExceptionDescribe(env);
113 (*env)->ExceptionClear(env);
114 }
115 break;
116
117 default:
118 break;
119 }
120}
121
122/*
123 * Class: sun_awt_motif_MListPeer
124 * Method: create
125 * Signature: (Lsun/awt/motif/MComponentPeer;)V
126 */
127JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_create
128 (JNIEnv *env, jobject this, jobject parent)
129{
130 Cardinal argc;
131#define MAX_ARGC 40
132 Arg args[MAX_ARGC];
133 struct ComponentData *wdata;
134 struct ListData *sdata;
135 Pixel bg;
136 jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this);
137 AwtGraphicsConfigDataPtr adata;
138
139 AWT_LOCK();
140
141 adata = copyGraphicsConfigToPeer(env, this);
142
143 if (JNU_IsNull(env, parent)) {
144 JNU_ThrowNullPointerException(env, "NullPointerException");
145 AWT_UNLOCK();
146
147 return;
148 }
149 wdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,parent,mComponentPeerIDs.pData);
150
151 if (wdata == NULL) {
152 JNU_ThrowNullPointerException(env, "NullPointerException");
153 AWT_UNLOCK();
154 return;
155 }
156 sdata = (struct ListData *) calloc(1, sizeof(struct ListData));
157
158 JNU_SetLongFieldFromPtr(env,this,mComponentPeerIDs.pData,sdata);
159 if (sdata == NULL) {
160 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
161 AWT_UNLOCK();
162 return;
163 }
164 XtVaGetValues(wdata->widget, XmNbackground, &bg, NULL);
165 argc = 0;
166 XtSetArg(args[argc], XmNrecomputeSize, False);
167 argc++;
168 XtSetArg(args[argc], XmNbackground, bg);
169 argc++;
170 XtSetArg(args[argc], XmNlistSizePolicy, XmCONSTANT);
171 argc++;
172 XtSetArg(args[argc], XmNx, 0);
173 argc++;
174 XtSetArg(args[argc], XmNy, 0);
175 argc++;
176 XtSetArg(args[argc], XmNmarginTop, 0);
177 argc++;
178 XtSetArg(args[argc], XmNmarginBottom, 0);
179 argc++;
180 XtSetArg(args[argc], XmNmarginLeft, 0);
181 argc++;
182 XtSetArg(args[argc], XmNmarginRight, 0);
183 argc++;
184 XtSetArg(args[argc], XmNmarginHeight, 0);
185 argc++;
186 XtSetArg(args[argc], XmNmarginWidth, 0);
187 argc++;
188 XtSetArg(args[argc], XmNlistMarginHeight, 0);
189 argc++;
190 XtSetArg(args[argc], XmNlistMarginWidth, 0);
191 argc++;
192 XtSetArg(args[argc], XmNscrolledWindowMarginWidth, 0);
193 argc++;
194 XtSetArg(args[argc], XmNscrolledWindowMarginHeight, 0);
195 argc++;
196 XtSetArg(args[argc], XmNuserData, (XtPointer) globalRef);
197 argc++;
198 XtSetArg (args[argc], XmNscreen,
199 ScreenOfDisplay(awt_display,
200 adata->awt_visInfo.screen));
201 argc++;
202
203 DASSERT(!(argc > MAX_ARGC));
204 sdata->list = XmCreateScrolledList(wdata->widget,
205 "slist",
206 args,
207 argc);
208
209 sdata->comp.widget = XtParent(sdata->list);
210 XtSetMappedWhenManaged(sdata->comp.widget, False);
211 XtAddCallback(sdata->list,
212 XmNdefaultActionCallback,
213 Slist_callback,
214 (XtPointer) globalRef);
215 XtAddEventHandler(sdata->list, FocusChangeMask,
216 True, awt_canvas_event_handler, globalRef);
217
218 awt_addWidget(sdata->list, sdata->comp.widget, globalRef,
219 java_awt_AWTEvent_KEY_EVENT_MASK |
220 java_awt_AWTEvent_MOUSE_EVENT_MASK |
221 java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK);
222
223 XtManageChild(sdata->list);
224 XtManageChild(sdata->comp.widget);
225
226 AWT_UNLOCK();
227}
228
229/*
230 * Class: sun_awt_motif_MListPeer
231 * Method: setMultipleSelections
232 * Signature: (Z)V
233 */
234JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_setMultipleSelections
235 (JNIEnv *env, jobject this, jboolean v)
236{
237 struct ListData *sdata;
238 jobject globalRef;
239 int32_t selPos;
240 Boolean selected;
241
242 AWT_LOCK();
243
244 sdata = (struct ListData *)
245 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
246 if (sdata == NULL) {
247 JNU_ThrowNullPointerException(env, "NullPointerException");
248 AWT_UNLOCK();
249 return;
250 }
251 globalRef = (jobject)
252 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.jniGlobalRef);
253 if (v == JNI_FALSE) {
254 XtVaSetValues(sdata->list,
255 XmNselectionPolicy, XmBROWSE_SELECT,
256 NULL);
257 XtRemoveCallback(sdata->list,
258 XmNmultipleSelectionCallback,
259 Slist_callback,
260 (XtPointer) globalRef);
261 XtAddCallback(sdata->list,
262 XmNbrowseSelectionCallback,
263 Slist_callback,
264 (XtPointer) globalRef);
265
266 // If we change the selection mode from multiple to single
267 // we need to decide what the item should be selected:
268 // If a selected item has the location cursor, only that
269 // item will remain selected. If no selected item has the
270 // location cursor, all items will be deselected.
271 selPos = XmListGetKbdItemPos(sdata->list);
272 selected = XmListPosSelected(sdata->list, selPos);
273 XmListDeselectAllItems(sdata->list);
274 if (selected) {
275 Java_sun_awt_motif_MListPeer_select(env, this, selPos-1);
276 }
277
278 } else {
279 XtVaSetValues(sdata->list,
280 XmNselectionPolicy, XmMULTIPLE_SELECT,
281 NULL);
282 XtRemoveCallback(sdata->list,
283 XmNbrowseSelectionCallback,
284 Slist_callback,
285 (XtPointer) globalRef);
286 XtAddCallback(sdata->list,
287 XmNmultipleSelectionCallback,
288 Slist_callback,
289 (XtPointer) globalRef);
290 }
291 AWT_UNLOCK();
292}
293
294/*
295 * Class: sun_awt_motif_MListPeer
296 * Method: setBackground
297 * Signature: (Ljava/awt/Color;)V
298 */
299
300JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_setBackground
301 (JNIEnv *env, jobject this, jobject c)
302{
303 struct ListData *ldata;
304 Pixel color;
305
306 if (JNU_IsNull(env, c)) {
307 JNU_ThrowNullPointerException(env, "NullPointerException");
308 return;
309 }
310 AWT_LOCK();
311 ldata = (struct ListData *)
312 JNU_GetLongFieldAsPtr(env,this, mComponentPeerIDs.pData);
313 if (ldata == NULL || ldata->list == NULL) {
314 JNU_ThrowNullPointerException(env, "NullPointerException");
315 AWT_UNLOCK();
316 return;
317 }
318 color = awtJNI_GetColor(env, c);
319 XtVaSetValues(ldata->list,
320 XmNbackground, color,
321 NULL);
322 AWT_FLUSH_UNLOCK();
323}
324
325/*
326 * Class: sun_awt_motif_MListPeer
327 * Method: isSelected
328 * Signature: (I)Z
329 */
330JNIEXPORT jboolean JNICALL Java_sun_awt_motif_MListPeer_isSelected
331 (JNIEnv *env, jobject this, jint pos)
332{
333 struct ListData *sdata;
334
335 AWT_LOCK();
336
337 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
338 if (sdata == NULL) {
339 JNU_ThrowNullPointerException(env, "NullPointerException");
340 AWT_UNLOCK();
341 return JNI_FALSE;
342 }
343 pos++;
344 if (XmListPosSelected(sdata->list, pos) == True) {
345 AWT_UNLOCK();
346 return JNI_TRUE;
347 } else {
348 AWT_UNLOCK();
349 return JNI_FALSE;
350 }
351}
352
353/*
354 * Class: sun_awt_motif_MListPeer
355 * Method: addItem
356 * Signature: (Ljava/lang/String;I)V
357 */
358JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_addItem
359 (JNIEnv *env, jobject this, jstring item, jint index)
360{
361 XmString im;
362 struct ListData *sdata;
363 jobject font;
364
365 /*
366 * Note:
367 * There used to be code in this function to fix:
368 * 4067355 size of listbox depends on when pack() is called (solaris)
369 * The fix (for jdk1.1.7) involved unmapping the List widget before the add
370 * is done and resizing/remapping it after the add. This causes significant
371 * performance degradation if addItem() is called a lot. A bug was filed
372 * on this performance problem: 4117288
373 * The fix was backed out after testing that:
374 * - the problem reported in 4067355 was no longer reproducible
375 * - the performance problem is gone
376 */
377
378 AWT_LOCK();
379 if (JNU_IsNull(env, item)) {
380 JNU_ThrowNullPointerException(env, "NullPointerException");
381 AWT_UNLOCK();
382 return;
383 }
384 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
385 if (sdata == NULL) {
386 JNU_ThrowNullPointerException(env, "NullPointerException");
387 AWT_UNLOCK();
388 return;
389 }
390 font = awtJNI_GetFont(env, this);
391
392 if (awtJNI_IsMultiFont(env, font)) {
393 im = awtJNI_MakeMultiFontString(env, item, font);
394 } else {
395 char *temp;
396
397 temp = (char *) JNU_GetStringPlatformChars(env, item, NULL);
398 im = XmStringCreateLocalized(temp);
399 JNU_ReleaseStringPlatformChars(env, item, (const char *)temp);
400 }
401
402 /* motif uses 1-based indeces for the list operations with 0 */
403 /* referring to the last item on the list. Thus if index is -1 */
404 /* then we'll get the right effect of adding to the end of the */
405 /* list. */
406 index++;
407
408 XmListAddItemUnselected(sdata->list, im, index);
409 XmStringFree(im);
410
411 AWT_UNLOCK();
412}
413
414/*
415 * Class: sun_awt_motif_MListPeer
416 * Method: delItems
417 * Signature: (II)V
418 */
419JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_delItems
420 (JNIEnv *env, jobject this, jint start, jint end)
421{
422 struct ListData *sdata;
423 Boolean was_mapped;
424 jobject target;
425 Position width, height;
426 int32_t itemCount;
427
428 AWT_LOCK();
429 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
430 if (JNU_IsNull(env, target)) {
431 JNU_ThrowNullPointerException(env, "NullPointerException");
432 AWT_UNLOCK();
433 return;
434 }
435 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
436 if (sdata == NULL) {
437 JNU_ThrowNullPointerException(env, "NullPointerException");
438 AWT_UNLOCK();
439 return;
440 }
441 /* [jk] catch bogus indexes (Sun bug) */
442 XtVaGetValues(sdata->list, XmNitemCount, &itemCount, NULL);
443 if (itemCount == 0) {
444 AWT_UNLOCK();
445 return;
446 }
447 if (start > itemCount) {
448 start = itemCount;
449 }
450 if (end > itemCount) {
451 end = itemCount;
452 }
453 start++;
454 end++;
455
456 XtVaGetValues(sdata->comp.widget, XmNmappedWhenManaged, &was_mapped, NULL);
457
458 /* If it was visible, then make it invisible while we update */
459 if (was_mapped) {
460 XtSetMappedWhenManaged(sdata->comp.widget, False);
461 }
462
463 if (start == end) {
464 XmListDeletePos(sdata->list, start);
465 } else {
466 XmListDeleteItemsPos(sdata->list, end - start + 1, start);
467 }
468
469 width = (*env)->GetIntField(env, target, componentIDs.width);
470 height = (*env)->GetIntField(env, target, componentIDs.height);
471 XtVaSetValues(sdata->comp.widget,
472 XmNwidth, (width > 1) ? width-1 : 1,
473 XmNheight, (height > 1) ? height-1 : 1,
474 NULL);
475 XtVaSetValues(sdata->comp.widget,
476 XmNwidth, (width > 0) ? width : 1,
477 XmNheight, (height > 0) ? height : 1,
478 NULL);
479 /* If it was visible, then make it visible again once updated */
480 if (was_mapped) {
481 XtSetMappedWhenManaged(sdata->comp.widget, True);
482 }
483
484
485 AWT_UNLOCK();
486}
487
488/*
489 * Class: sun_awt_motif_MListPeer
490 * Method: pSelect
491 * Signature: (I)V
492 */
493JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_select
494 (JNIEnv *env, jobject this, jint pos)
495{
496 struct ListData *sdata;
497
498 AWT_LOCK();
499 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
500 if (sdata == NULL) {
501 JNU_ThrowNullPointerException(env, "NullPointerException");
502 AWT_UNLOCK();
503 return;
504 }
505 pos++;
506 XmListSelectPos(sdata->list, pos, False);
507 AWT_UNLOCK();
508}
509
510/*
511 * Class: sun_awt_motif_MListPeer
512 * Method: pDeselect
513 * Signature: (I)V
514 */
515JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_deselect
516 (JNIEnv *env, jobject this, jint pos)
517{
518 struct ListData *sdata;
519
520 AWT_LOCK();
521 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
522 if (sdata == NULL) {
523 JNU_ThrowNullPointerException(env, "NullPointerException");
524 AWT_UNLOCK();
525 return;
526 }
527 pos++;
528 XmListDeselectPos(sdata->list, pos);
529 AWT_UNLOCK();
530}
531
532/*
533 * Class: sun_awt_motif_MListPeer
534 * Method: makeVisible
535 * Signature: (I)V
536 */
537JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_makeVisible
538 (JNIEnv *env, jobject this, jint pos)
539{
540 int32_t top, visible;
541 struct ListData *sdata;
542
543 AWT_LOCK();
544 sdata = (struct ListData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
545 if (sdata == NULL) {
546 JNU_ThrowNullPointerException(env, "NullPointerException");
547 AWT_UNLOCK();
548 return;
549 }
550 XtVaGetValues(sdata->list,
551 XmNtopItemPosition, &top,
552 XmNvisibleItemCount, &visible,
553 NULL);
554 pos++;
555 if (pos < top) {
556 XmListSetPos(sdata->list, pos);
557 } else {
558 XmListSetBottomPos(sdata->list, pos);
559 }
560
561 AWT_UNLOCK();
562}
563
564/*
565 * Class: sun_awt_motif_MListPeer
566 * Method: nativeHandleMouseWheel
567 * Signature: (III)V
568 */
569JNIEXPORT void JNICALL Java_sun_awt_motif_MListPeer_nativeHandleMouseWheel
570 (JNIEnv *env, jobject this, jint scrollType, jint scrollAmt, jint wheelAmt)
571{
572 struct ListData *ldata;
573 Widget list = NULL;
574 Widget scroll = NULL;
575
576 AWT_LOCK();
577 ldata = (struct ListData *)
578 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
579 if (ldata == NULL || ldata->comp.widget == NULL) {
580 JNU_ThrowNullPointerException(env, "NullPointerException");
581 AWT_UNLOCK();
582 return;
583 }
584 // get the List widget
585 list = ldata->list;
586 if (list == NULL) {
587 AWT_UNLOCK();
588 return;
589 }
590
591 // get the ScrolledWindow
592 scroll = XtParent(list);
593 if (scroll == NULL) {
594 AWT_UNLOCK();
595 return;
596 }
597
598 awt_util_do_wheel_scroll(scroll, scrollType, scrollAmt, wheelAmt);
599 AWT_UNLOCK();
600}