| <html> |
| |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> |
| <meta name="ProgId" content="FrontPage.Editor.Document"> |
| <meta name="Author" content="Carolyn MacLeod"> |
| <title>Appendix D: Spinner for Motif</title> |
| </head> |
| |
| <body> |
| <h2>Appendix D: Spinner for Motif</h2> |
| This appendix contains the source code for the Motif version of the <i>Spinner</i> natives in spinner.c, and the shell file and makefile for building the Motif Shared Object Library |
| libspinner.so. |
| <h3><strong>spinner.c</strong></h3> |
| <pre> |
| /* |
| * (c) Copyright IBM Corp. 2000, 2001. |
| * All Rights Reserved. |
| */ |
| |
| #include <jni.h> |
| #include <Xm/XmAll.h> |
| #include <pthread.h> |
| #include <stdio.h> |
| |
| #define ARROW_WIDTH 19 |
| #define SPACING 2 |
| |
| static jobject javaClass; |
| static jmethodID mid; |
| static pthread_key_t envKey; |
| |
| int Callback(Widget handle, XtPointer clientData, XmAnyCallbackStruct * callData) { |
| JNIEnv *env = (JNIEnv *) pthread_getspecific(envKey); |
| if (env != NULL) { |
| /* If an exception has already occurred, |
| * allow the stack to unwind so that the |
| * exception will be thrown in Java. */ |
| if ((*env)->ExceptionOccurred(env)) return 0; |
| switch (callData->reason) { |
| //case XmCR_SPIN_NEXT: |
| //case XmCR_SPIN_PRIOR: |
| case XmCR_OK: |
| ((*env)->CallStaticVoidMethod(env, javaClass, mid, handle)); |
| return 0; |
| } |
| } |
| return 0; |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: createControl |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL Java_spinner_Spinner_createControl |
| (JNIEnv *env, jclass that, jint handleParent) |
| { |
| Widget handleSpinBox; |
| Arg argList[10]; |
| int n = 0; |
| XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++; |
| XtSetArg(argList[n], XmNarrowLayout, XmARROWS_END); n++; |
| handleSpinBox = XmCreateSimpleSpinBox((Widget) handleParent, NULL, argList, n); |
| if (handleSpinBox == 0) return 0; |
| XtManageChild(handleSpinBox); |
| XtAddCallback(handleSpinBox, XmNvalueChangedCallback, (XtCallbackProc) Callback, NULL); |
| if (javaClass == 0) { |
| javaClass = (*env)->NewGlobalRef(env, (jobject) that); |
| mid = (*env)->GetStaticMethodID(env, (jobject) that, "widgetSelected", "(I)V"); |
| pthread_key_create(&envKey, NULL); |
| } |
| pthread_setspecific(envKey, env); |
| return (jint) handleSpinBox; |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: computeSize |
| * Signature: (I[I)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_computeSize |
| (JNIEnv *env, jclass that, jint handleSpinBox, jintArray result) |
| { |
| Dimension width, height; |
| Arg argList[10]; |
| int n; |
| Widget handleText; |
| XmFontList fontList; |
| Dimension sbShadowThickness, textMarginWidth, textMarginHeight, textShadowThickness; |
| int max, digits; |
| char text [64]; |
| XmString xmString; |
| |
| jint *result1 = NULL; |
| result1 = (*env)->GetIntArrayElements(env, result, NULL); |
| |
| n = 0; |
| XtSetArg(argList[n], XmNtextField, &handleText); n++; |
| XtSetArg(argList[n], XmNmaximumValue, &max); n++; |
| XtSetArg(argList[n], XmNshadowThickness, &sbShadowThickness); n++; |
| XtGetValues((Widget) handleSpinBox, argList, n); |
| |
| n = 0; |
| XtSetArg(argList[n], XmNfontList, &fontList); n++; |
| XtSetArg(argList[n], XmNmarginWidth, &textMarginWidth); n++; |
| XtSetArg(argList[n], XmNmarginHeight, &textMarginHeight); n++; |
| XtSetArg(argList[n], XmNshadowThickness, &textShadowThickness); n++; |
| XtGetValues(handleText, argList, n); |
| |
| if (max > 0) { |
| digits = 0; |
| while (max > 0) { |
| text[digits] = '0'; |
| max /= 10; |
| digits++; |
| } |
| text [digits] = 0; |
| xmString = XmStringParseText( |
| (XtPointer) text, |
| (XtPointer *) NULL, |
| XmFONTLIST_DEFAULT_TAG, |
| XmCHARSET_TEXT, |
| (XmParseTable) NULL, |
| 0, |
| (XtPointer) 0); |
| width = XmStringWidth(fontList, xmString); |
| height = XmStringHeight(fontList, xmString); |
| XmStringFree(xmString); |
| } else { |
| width = 200; |
| height = 50; |
| } |
| |
| // Add in the margins. |
| width += textMarginWidth * 2 + textShadowThickness * 2 + sbShadowThickness * 2 + ARROW_WIDTH + SPACING; |
| height += textMarginHeight * 2 + textShadowThickness * 2 + sbShadowThickness * 2; |
| result1 [0] = width; |
| result1 [1] = height; |
| (*env)->ReleaseIntArrayElements(env, result, result1, 0); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: resizeControl |
| * Signature: (IIIII)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_resizeControl |
| (JNIEnv *env, jclass that, jint handleSpinBox, jint x, jint y, jint width, jint height) |
| { |
| Arg arg; |
| Widget handleText; |
| XtSetArg(arg, XmNtextField, &handleText); |
| XtGetValues((Widget) handleSpinBox, &arg, 1); |
| XtResizeWidget((Widget) handleSpinBox, width, height, 0); |
| XtResizeWidget(handleText, width - ARROW_WIDTH, height, 0); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: setPosition |
| * Signature: (II)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_setPosition |
| (JNIEnv *env, jclass that, jint handle, jint position) |
| { |
| Arg arg; |
| XtSetArg(arg, XmNposition, position); |
| XtSetValues((Widget) handle, &arg, 1); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: getPosition |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL Java_spinner_Spinner_getPosition |
| (JNIEnv *env, jclass that, jint handle) |
| { |
| Arg arg; |
| int pos; |
| XtSetArg(arg, XmNposition, &pos); |
| XtGetValues((Widget) handle, &arg, 1); |
| return (jint) pos; |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: setMaximum |
| * Signature: (II)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_setMaximum |
| (JNIEnv *env, jclass that, jint handle, jint max) |
| { |
| Arg arg; |
| XtSetArg(arg, XmNmaximumValue, max); |
| XtSetValues((Widget) handle, &arg, 1); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: getMaximum |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL Java_spinner_Spinner_getMaximum |
| (JNIEnv *env, jclass that, jint handle) |
| { |
| Arg arg; |
| int max; |
| XtSetArg(arg, XmNmaximumValue, &max); |
| XtGetValues((Widget) handle, &arg, 1); |
| return (jint) max; |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: setMinimum |
| * Signature: (II)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_setMinimum |
| (JNIEnv *env, jclass that, jint handle, jint min) |
| { |
| Arg arg; |
| XtSetArg(arg, XmNminimumValue, min); |
| XtSetValues((Widget) handle, &arg, 1); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: getMinimum |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL Java_spinner_Spinner_getMinimum |
| (JNIEnv *env, jclass that, jint handle) |
| { |
| Arg arg; |
| int min; |
| XtSetArg(arg, XmNminimumValue, &min); |
| XtGetValues((Widget) handle, &arg, 1); |
| return (jint) min; |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: setFont |
| * Signature: (II)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_setFont |
| (JNIEnv *env, jclass that, jint handle, jint fontList) |
| { |
| Arg arg; |
| Widget handleText; |
| XtSetArg(arg, XmNtextField, &handleText); |
| XtGetValues((Widget) handle, &arg, 1); |
| XtSetArg(arg, XmNfontList, (XmFontList) fontList); |
| XtSetValues(handleText, &arg, 1); |
| } |
| |
| /* |
| * Class: spinner_Spinner |
| * Method: setFocus |
| * Signature: (I)V |
| */ |
| JNIEXPORT void JNICALL Java_spinner_Spinner_setFocus |
| (JNIEnv *env, jclass that, jint handle) |
| { |
| Arg arg; |
| Widget handleText; |
| XtSetArg(arg, XmNtextField, &handleText); |
| XtGetValues((Widget) handle, &arg, 1); |
| XSetInputFocus(XtDisplay(handleText), XtWindow(handleText), RevertToParent, CurrentTime); |
| } |
| </pre> |
| <p> |
| <h3><strong>build.csh</strong></h3> |
| <pre> |
| #!/bin/csh |
| |
| setenv IVE_HOME /bluebird/teamswt/swt-builddir/ive/bin |
| setenv MOTIF_HOME /bluebird/teamswt/swt-builddir/motif21 |
| setenv X_HOME /usr/X11R6 |
| set path=($IVE_HOME $path) |
| setenv LD_LIBRARY_PATH .:$IVE_HOME |
| |
| make -f makefile.mak</pre> |
| <p> |
| <h3><strong>makefile.mak</strong></h3> |
| <pre> |
| # Makefile for module 'libspinner.so' |
| # assumes IVE_HOME, MOTIF_HOME, and X_HOME are set in the environment |
| |
| # NOTE: |
| # We use the VPATH directive to allow the generic UNIX source files to be |
| # located in a single directory. IX make does not understand VPATH so |
| # you must use a 'make' which does understand it (like LINUX make) |
| VPATH= ../:../../common |
| |
| DLLPREFIX=spinner |
| DLLNAME=lib$(DLLPREFIX).so |
| |
| CFLAGS=-fpic -O -s -DLINUX -DMOTIF -I./ -I../ -I$(IVE_HOME)/include -I$(MOTIF_HOME)/include -I$(X_HOME)/include |
| LFLAGS=-L$(MOTIF_HOME)/lib -lXm -L/usr/lib -L/usr/X11R6/lib -rpath . -x -shared -lX11 -lm -lXext -lXt |
| OBJS = spinner.o |
| |
| all: $(DLLNAME) |
| |
| $(DLLNAME): $(OBJS) |
| ld $(LFLAGS) -o $(DLLNAME) $(OBJS) |
| |
| clean: |
| rm -f *.o |
| rm -f $(DLLNAME) |
| </pre> |
| </body> |
| |
| </html> |