| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | 
 | <html> | 
 | <head> | 
 |    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
 |    <title>SWT: The Standard Widget Toolkit</title> | 
 | <link rel="stylesheet" href="../default_style.css"> | 
 | </head> | 
 | <body> | 
 | 		<div align="right"> | 
 | 			<font face="Times New Roman, Times, serif" size="2">Copyright  | 
 |   © 2001 Object Technology International, Inc.</font> | 
 |   | 
 |  | 
 | 			<table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" > | 
 | 				<tr> | 
 | 					<td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse | 
 | Corner Article</font></font></b></td> | 
 | 				</tr> | 
 | 			</table> | 
 | 		</div> | 
 | 		<h1> | 
 | <img SRC="idea.jpg" height=86 width=120 align=CENTER></h1> | 
 | 		<center> | 
 | <h1> | 
 | SWT: The Standard Widget Toolkit</h1></center> | 
 |  | 
 | <center> | 
 | <h3> | 
 | PART 1: Implementation Strategy for Java™ Natives</h3></center> | 
 |  | 
 | <center><i>The first in a series of articles about the design ideas behind | 
 | SWT.</i></center> | 
 |  | 
 | <blockquote><b>Summary</b> | 
 | <br>SWT is the software component that delivers native widget functionality | 
 | for the Eclipse platform in an operating system independent manner.  | 
 | It is analogous to AWT/Swing in Java with a difference - SWT uses a rich set of native | 
 | widgets.  Even in an ideal situation, industrial strength cross platform | 
 | widget libraries are very difficult to write and maintain.  This is | 
 | due to the inherent complexity of widget systems and the many subtle differences | 
 | between platforms.  There are several basic approaches that have helped | 
 | significantly to reduce the complexity of the problem and deliver high | 
 | quality libraries.  This article discusses one of them, the low level | 
 | implementation techniques used to implement SWT on different platforms.  | 
 | Examples are drawn from the Windows® and Motif implementations. | 
 |  | 
 | <p><b>By Steve Northover, OTI</b> | 
 | <br> | 
 |   <font size="-1">March 22, 2001</font> </p> | 
 |  | 
 | </blockquote> | 
 |  | 
 | <p> | 
 | <hr WIDTH="100%"> | 
 | <h3> | 
 | Portable and Native - It Can't Be Done!</h3> | 
 | Developers demand portable graphics and widgets to allow them to build | 
 | user interfaces that are competitive with shrink-wrapped applications built | 
 | using platform specific tools.  They need access to platform specific | 
 | features, with well defined API boundaries. SWT delivers this functionality | 
 | using a small and consistent API.  This API is implemented on different | 
 | platforms using a combination of Java code and JNI natives specific to | 
 | each platform. | 
 | <p>SWT is implemented entirely in one language: Java.  How can this | 
 | be true when SWT uses native widgets that provide an API in C?  The | 
 | answer is that Java provides a native interface to C (JNI) that is used | 
 | by SWT to invoke the operating system from Java code.  JNI is the | 
 | standard mechanism used by all Java programs to invoke code written in | 
 | C. SWT goes one step further by enforcing a<i> one-to-one mapping</i> between | 
 | Java native methods and operating system calls.  The fact that this | 
 | mapping is strictly enforced is one of the most critical factors in the | 
 | success of SWT. | 
 | <h3> | 
 | A Tale of Two Implementations</h3> | 
 | Let's take a look at the implementation of SWT <i>Text</i> widget on two | 
 | different platforms.  The <i>Text</i> widget provides the ability | 
 | to set the selection.  SWT application code that uses this API might | 
 | look something like this: | 
 | <p><tt>    /* Select positions 2 to 5 */</tt> | 
 | <br><tt>    text.setText ("0123456780");</tt> | 
 | <br><tt>    text.setSelection (2, 5);</tt> | 
 | <p>The method signature for <b>setSelection</b> in class <i>Text</i> looks | 
 | like this: | 
 | <p><tt>    /**</tt> | 
 | <br><tt>    * Sets the selection.</tt> | 
 | <br><tt>    * <p></tt> | 
 | <br><tt>    * Indexing is zero based.  The range of | 
 | a selection is from 0..N</tt> | 
 | <br><tt>    * where N is the number of characters in the | 
 | widget.</tt> | 
 | <br><tt>    */</tt> | 
 | <br><tt>    public void setSelection (int start, int end)</tt> | 
 | <p>Here is the Windows implementation of <b>setSelection</b>: | 
 | <p><tt>    public void setSelection (int start, int end) | 
 | {</tt> | 
 | <br><tt>        OS.SendMessage (handle, | 
 | OS.EM_SETSEL, start, end);</tt> | 
 | <br><tt>    }</tt> | 
 | <p>What are <b>SendMessage</b> and <b>EM_SETSEL</b>?  Windows programmers | 
 | recognize this right away.  It's <b>SendMessage</b>, the mechanism | 
 | that is used to talk to Windows controls. <b>EM_SETSEL</b> is the message | 
 | that tells the text control to set the selection.  It's not easy reading, | 
 | but it is familiar to a Windows programmer.  The rest of us get to | 
 | read the Microsoft® Developer Network (MSDN) Library! | 
 | <p>Here is the Java code for the SWT class <i>OS</i> on Windows: | 
 | <p><tt>    class OS {</tt> | 
 | <br><tt>        public static final | 
 | int EM_SETSEL = 0xB1;</tt> | 
 | <br><tt>        public static final | 
 | native int SendMessage (int hWnd, int Msg, int wParam, int lParam);</tt> | 
 | <br><tt>        ...</tt> | 
 | <br><tt>    }</tt> | 
 | <p>How is the <b>SendMessage</b> native implemented?  Here is the | 
 | C code on Windows: | 
 | <p><tt>    JNIEXPORT jint JNICALL Java_org_eclipse_swt_internal_win32_OS_SendMessage__IIII</tt> | 
 | <br><tt>      (JNIEnv *env, jclass that, jint | 
 | hWnd, jint Msg, jint wParam, jint lParam)</tt> | 
 | <br><tt>    {</tt> | 
 | <br><tt>        return (jint) SendMessage((HWND)hWnd, | 
 | Msg, wParam, lParam);</tt> | 
 | <br><tt>    }</tt> | 
 | <p>Notice that <i>the only thing this native does</i> is pass the Java | 
 | call straight on through to the Windows API. But what about other operating | 
 | systems?  Does the fact that <b>setSelection</b> is implemented in | 
 | terms of the Windows API mean that SWT is not portable?  While it | 
 | is true that the Windows implementation of <i>Text</i> is not portable, | 
 | application code that uses <i>Text</i> is.  How is this achieved?  | 
 | SWT provides a different <i>Text</i> class for each platform, but the signature | 
 | of every public method is the same.  Java code that calls SWT does | 
 | not know or care which <i>Text</i> class is referenced at run time.  | 
 | <b>SendMessage</b> | 
 | is not SWT API. | 
 | <p>Here is the implementation of <b>setSelection</b> on Motif (Java and | 
 | JNI C): | 
 | <p><tt>    public void setSelection (int start, int end) | 
 | {</tt> | 
 | <br><tt>        int xDisplay = OS.XtDisplay | 
 | (handle);</tt> | 
 | <br><tt>        if (xDisplay == 0) return;</tt> | 
 | <br><tt>        OS.XmTextSetSelection | 
 | (handle, start, end, OS.XtLastTimestampProcessed (xDisplay));</tt> | 
 | <br><tt>        OS.XmTextSetInsertionPosition | 
 | (handle, end);</tt> | 
 | <br><tt>    }</tt> | 
 | <p><tt>    class OS {</tt> | 
 | <br><tt>        public static final | 
 | native void XmTextSetSelection (int widget, int first, int last, int time);</tt> | 
 | <br><tt>        public static final | 
 | native int XtLastTimestampProcessed (int display);</tt> | 
 | <br><tt>        public static final | 
 | native void XmTextSetInsertionPosition (int widget, int position);</tt> | 
 | <br><tt>        public static final | 
 | native int XtDisplay (int widget);</tt> | 
 | <br><tt>        ...</tt> | 
 | <br><tt>    }</tt> | 
 | <p><tt>    JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_motif_OS_XmTextSetSelection</tt> | 
 | <br><tt>      (JNIEnv *env, jclass that, jint | 
 | widget, jint first, jint last, jint time)</tt> | 
 | <br><tt>    {</tt> | 
 | <br><tt>        XmTextSetSelection((Widget)widget, | 
 | first, last, time);</tt> | 
 | <br><tt>    }</tt> | 
 | <p><tt>    ...</tt> | 
 | <p>What are <b>XtDisplay</b>, <b>XmTextSetSelection</b>, <b>XtLastTimestampProcessed</b> | 
 | and <b>XmTextSetInsertionPosition</b>?  They don't mean much to a | 
 | Windows programmer, but they are familiar to anyone who has ever programmed | 
 | Motif.  Now it's the Windows programmer's turn to consult the Motif | 
 | man pages! | 
 | <p>The example code above was taken directly from SWT but has been simplified | 
 | by removing range and error checking code for the sake of the example.  | 
 | However, the code that is doing the real work - setting the selection - | 
 | is identical to that found in the product. | 
 | <h3> | 
 | One to One Mapping - No Custom Natives</h3> | 
 | Take a moment to review the Java and C code for <b>setSelection</b> in | 
 | the previous section.  Wouldn't it be easier to implement one <i>Text</i> | 
 | class for all SWT platforms and hide the platform differences in the natives?  | 
 | Such an implementation might look like this: | 
 | <p><tt>    public void setSelection (int start, int end) | 
 | {</tt> | 
 | <br><tt>        nativeSetSelection (start, | 
 | end)</tt> | 
 | <br><tt>    }</tt> | 
 | <br><tt>    static final native void nativeSetSelection (int | 
 | start, int end);</tt> | 
 | <p><tt>    JNIEXPORT void JNICALL Java_org_eclipse_swt_widgets_text_nativeSetSelection</tt> | 
 | <br><tt>      (JNIEnv *env, jclass that, jobject | 
 | widget, jint first, jint last)</tt> | 
 | <br><tt>    {</tt> | 
 | <br><tt>    #ifdef WINDOWS</tt> | 
 | <br><tt>        HWND hWnd = SWTGetHandleFromJavaWidget | 
 | (widget);</tt> | 
 | <br><tt>        SendMessage(hWnd, Msg, | 
 | wParam, lParam);</tt> | 
 | <br><tt>    #endif</tt> | 
 | <br><tt>    #ifdef MOTIF</tt> | 
 | <br><tt>        Widget *w = SWTGetHandleFromJavaWidget | 
 | (widget);</tt> | 
 | <br><tt>        Display xDisplay = XtDisplay | 
 | (w);</tt> | 
 | <br><tt>        if (xDisplay == NULL) | 
 | return;</tt> | 
 | <br><tt>        XmTextSetSelection (w, | 
 | start, end, XtLastTimestampProcessed (xDisplay));</tt> | 
 | <br><tt>        XmTextSetInsertionPosition | 
 | (w, end);</tt> | 
 | <br><tt>    #endif</tt> | 
 | <br><tt>    }</tt> | 
 | <p>Isn't this easier than having a different <i>Text</i> class on each | 
 | platform?  The answer is a resounding "<i>No</i>".  Why?  | 
 | In the case of the <i>Text</i> widget, the code to set the selection is | 
 | pretty simple but even this causes problems.  Before we get into the | 
 | discussion, consider this: | 
 | <ul> | 
 | <li> | 
 | The non-public native interface must be identical on all platforms.  | 
 | This means there needs to be an implementation of <b>nativeSetSelection</b> | 
 | everywhere.  We also still need to provide the public SWT API.  | 
 | So we need to implement <b>setSelection</b> everywhere. Why would we want | 
 | to write two portable APIs instead of just one?  One API is hard enough | 
 | to specify and maintain!</li> | 
 |  | 
 | <li> | 
 | Java is a powerful high level language with features that promote robust | 
 | code and program stability.  It contains reusable class libraries | 
 | for high level data types such as hash tables and vectors as well as efficient | 
 | primitive types. Why use C?</li> | 
 | </ul> | 
 | Calling the operating system directly from Java helps with debugging. The | 
 | following problem occurred in an early version of SWT for Windows:  | 
 | when the selection was set in the text widget, sometimes the widget did | 
 | not scroll to show the i-beam.  Where was the problem?  The code | 
 | that demonstrated the problem was complicated, but it was clear from stepping | 
 | through the Java code and consulting the MSDN Library that the Java implementation | 
 | of <b>setSelection</b> was correct.  In fact, because of the <i>one-to-one | 
 | mapping</i> between our Java natives and C, it was possible to write a | 
 | simple C example to help isolate the problem and submit a bug report to | 
 | Microsoft.  Why was this so easy?  Because, as we have said before, | 
 | nothing extra ever happens in an SWT native. The Java call is passed right | 
 | on through to the operating system.  This means that C code is guaranteed | 
 | to exhibit the same behavior.  This is great news for debugging and | 
 | maintenance. | 
 | <p>Performance problems are legendary in widget toolkits and finding them | 
 | is a black art.  Where is the performance problem?  Is it in | 
 | the Java code or the natives?  Fortunately, SWT natives can't be the | 
 | problem. We are guaranteed that once we are in a native, the limiting factor | 
 | is the speed of the operating system - something beyond our control.  | 
 | This is great news for performance tuning: look at the Java code.  | 
 | In fact, one quickly develops a sense of which operating system operations | 
 | are expensive and which are cheap. Best of all, this knowledge is accurate.  | 
 | A C program that makes the same sequence of operating system calls will | 
 | exhibit the same performance characteristics.  This is a feature of | 
 | the one-to-one mapping. | 
 | <p>What happens when you try to debug a segment fault (or GP)?  It's | 
 | easy enough to step into a Java method and examine arguments but not possible | 
 | to step into a native.  Fortunately, nothing special happens in SWT | 
 | natives so it's easy enough to isolate the code that is causing the problem.  | 
 | While on the subject of GPs, wouldn't it make sense for SWT natives to | 
 | check their parameters before making the operating system call?  It's | 
 | tempting to check for NULL or -1 to avoid the crash.  On the surface, | 
 | this seems to make sense - after all, who wants to GP?  The answer, | 
 | of course, is that this would violate the one-to-one mapping and would | 
 | mean that an equivalent C program would not crash in the same place.  | 
 | That's bad news for debugging and isolating a problem. | 
 | <p>For someone implementing and maintaining SWT, the one-to-one mapping | 
 | is extremely valuable.  For example, a Windows programmer knows right | 
 | away how <b>setSelection</b> works, just by looking at the Java code.  | 
 | Everyone else needs to read the MSDN Library.  It's not light reading, | 
 | but the information is there.  The same thing is true for a Motif | 
 | programmer for SWT on Motif, and for the other supported operating systems.  | 
 | In fact, it's clear exactly how existing features work and new features | 
 | are to be implemented.  The critial point here is that the documentation | 
 | for the operating system applies to all SWT natives because they are a | 
 | one-to-one mapping. | 
 | <p>Adding new native features to SWT is a straightforward and well defined | 
 | process. For example, implementing drag and drop and integrating it with | 
 | the widgets was not difficult, despite the fact that these are two independent | 
 | services.  Why was this so easy?  Nothing is hidden in the C | 
 | code.  All of the operating system resources needed to implement SWT | 
 | are manifested as simple Java objects making it easy to understand how | 
 | SWT works and to make changes.  This allows SWT to be customized to | 
 | support new platform dependent widgets and operating system services as | 
 | they become available. | 
 | <p>One last point: JNI is rich and powerful.  It allows you to allocate | 
 | Java objects in C, get and set Java fields, invoke new VMs and throw exceptions.  | 
 | The operating system, on the other hand, is typically more primitive.  | 
 | For example, most operating system calls that access memory require you | 
 | to allocate the buffer and pass in the size.  Java arrays know their | 
 | size, so why do we need to pass it in?  JNI allows us to allocate | 
 | objects in C, so why not allocate buffers in the C code?  Wouldn't | 
 | it be better to try and "fix" the operating system API to make it more | 
 | Java friendly?  The answer again is "<i>No</i>".  Any deviation | 
 | from the one-to-one rule means that our Java code no longer behaves the | 
 | same as the equivalent C code.  For example, allocating objects in | 
 | JNI could introduce a hidden performance problem for Java code inside a | 
 | tight loop.  Also, it may make sense to allocate one large buffer | 
 | and pass in a smaller size, or reuse a buffer.  It's tempting to use | 
 | JNI | 
 | features to attempt to "fix" the operating system API but this is a huge | 
 | mistake. | 
 | <h3> | 
 | Conclusion</h3>All of the natives in SWT are implemented using this simple and consistent strategy.  There is no C code to hide the low level details of the operating system such as the event loop, callbacks or the thread model.  No code reaches back into Java from C to get a field or invoke a method.  Nothing is magic - everything is coded in Java using the terminology and documentation of the operating system.  Why is this such a big deal?  Some might claim that all SWT does is use JNI to invoke the operating system - nothing fancy. But that's the whole point.  Without a simple set of rules and a sense of restraint - a characteristic of SWT - it's just too easy for a widget toolkit to collapse under its own weight.<br>  | 
 |  | 
 | <p><small>Java and all Java-based trademarks and logos are trademarks or registered | 
 | trademarks of Sun Microsystems, Inc. in the United States, other countries, or | 
 | both.</small></p> | 
 | <p><small>Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.</small></p> | 
 |  | 
 | </body> | 
 | </html> |