[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[albireo-dev] Re: AwtEnvironment & customizability

Hi Gordon,

I wrote:
> I'll therefore try to move out to a separate class LookAndFeelHandler all
> the policy, i.e. all the calls that should be customizable and deal with
> look&feel.

Done now, through the appended patch.

One thing I'm not comfortable with is that the default L&F choice is
LAFChoiceNativeSystemForceGtk, which is exactly the same as you did.

The reason is that on the Linux system I happen to be using (openSUSE with KDE
desktop), the Gtk look&feel of Swing is not well supported: At the beginning
I get an error message in the console:
/opt/gnome/share/themes/Qt/gtk-2.0/gtkrc:5: Engine "qtengine" is unsupported, ignoring

and the resulting look is
  - very ugly,
  - different from the look of the Eclipse/JFace GUI.
(See attached screenshots.)

On RedHat Linux machines with GNOME desktop the JDK is configured to launch
in Gtk look&feel by default, and I haven't heard complaints that it looks
bad. So in this case I have no objection against using Gtk look&feel by
default.

But when the JDK does not open it up by default, I'd prefer to respect that
choice. You wrote in comments:

           // Java makes metal the system look and feel if running under a
           // non-gnome Linux desktop. Fix that here, if the RCP itself is
           // running
           // with the GTK windowing system set.

but in some cases it is not a fix - it makes things worse.

So I'm for changing the default from
  LAFChoiceNativeSystemForceGtk
to
  LAFChoiceNativeSystem.

In view of the bug that you found and reported
  https://bugs.eclipse.org/bugs/show_bug.cgi?id=126931
I think we must even make it
  LAFChoiceNativeSystemAvoidGtk
when running under JDK 1.6.

I just retested this bug, by running our sample application under JDK 1.6.
First try: the application showed a window that terminated immediately.
Second try: the application showed its window,
            the AWT part was empty instead of showing a JTable,
            a message "Xlib: unexpected async reply (sequence 0x6b2)!"
            appeared in the console,
            and my entire display was blocked (moving the mouse worked,
            but clicking anywhere did not show any reaction - the worst
            thing that can happen to a user under X).

Bruno


Index: src/org/eclipse/albireo/core/AwtEnvironment.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/core/AwtEnvironment.java,v
retrieving revision 1.2
diff -c -3 -r1.2 AwtEnvironment.java
*** src/org/eclipse/albireo/core/AwtEnvironment.java	23 Jan 2008 20:49:32 -0000	1.2
--- src/org/eclipse/albireo/core/AwtEnvironment.java	25 Jan 2008 15:36:24 -0000
***************
*** 17,26 ****
  import java.util.HashMap;
  import java.util.Map;
  
- import javax.swing.UIManager;
  import javax.swing.UnsupportedLookAndFeelException;
  
- import org.eclipse.albireo.internal.Platform;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Event;
--- 17,24 ----
***************
*** 48,54 ****
   * {@link #getInstance(Display)} method.
   */
  public final class AwtEnvironment {
-     private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$
  
      // Map from Display to AwtEnvironment.
      // This does not need to be a WeakHashMap: Display instances don't go away
--- 46,51 ----
***************
*** 127,161 ****
          try {
              EventQueue.invokeAndWait(new Runnable() {
                  public void run() {
!                     setSystemLookAndFeel();
                  }
              });
          } catch (InterruptedException e) {
              SWT.error(SWT.ERROR_FAILED_EXEC, e);
          } catch (InvocationTargetException e) {
!             SWT.error(SWT.ERROR_FAILED_EXEC, e);
          }
  
          this.display = display;
      }
  
!     protected void setSystemLookAndFeel() {
          assert EventQueue.isDispatchThread(); // On AWT event thread
  
          if (!isLookAndFeelInitialized) {
              isLookAndFeelInitialized = true;
              try {
!                 String systemLaf = UIManager.getSystemLookAndFeelClassName();
!                 String xplatLaf = UIManager.getCrossPlatformLookAndFeelClassName();
! 
!                 // Java makes metal the system look and feel if running under a
!                 // non-gnome Linux desktop. Fix that here, if the RCP itself is
!                 // running
!                 // with the GTK windowing system set.
!                 if (xplatLaf.equals(systemLaf) && Platform.isGtk()) {
!                     systemLaf = GTK_LOOK_AND_FEEL_NAME;
!                 }
!                 UIManager.setLookAndFeel(systemLaf);
              } catch (ClassNotFoundException e) {
                  SWT.error(SWT.ERROR_NOT_IMPLEMENTED, e);
              } catch (InstantiationException e) {
--- 124,148 ----
          try {
              EventQueue.invokeAndWait(new Runnable() {
                  public void run() {
!                     setLookAndFeel();
                  }
              });
          } catch (InterruptedException e) {
              SWT.error(SWT.ERROR_FAILED_EXEC, e);
          } catch (InvocationTargetException e) {
!             SWT.error(SWT.ERROR_FAILED_EXEC, e.getTargetException());
          }
  
          this.display = display;
      }
  
!     static private void setLookAndFeel() {
          assert EventQueue.isDispatchThread(); // On AWT event thread
  
          if (!isLookAndFeelInitialized) {
              isLookAndFeelInitialized = true;
              try {
!                 LookAndFeelHandler.getInstance().setLookAndFeel();
              } catch (ClassNotFoundException e) {
                  SWT.error(SWT.ERROR_NOT_IMPLEMENTED, e);
              } catch (InstantiationException e) {
*** /dev/null	2006-05-02 08:46:16.000000000 +0200
--- src/org/eclipse/albireo/core/LookAndFeelHandler.java	2008-01-25 16:38:07.000000000 +0100
***************
*** 0 ****
--- 1,160 ----
+ /*******************************************************************************
+  * Copyright (c) 2007-2008 SAS Institute Inc., ILOG S.A.
+  * All rights reserved. This program and the accompanying materials
+  * are made available under the terms of the Eclipse Public License v1.0
+  * which accompanies this distribution, and is available at
+  * http://www.eclipse.org/legal/epl-v10.html
+  *
+  * Contributors:
+  *     SAS Institute Inc. - initial API and implementation
+  *     ILOG S.A. - initial API and implementation
+  *******************************************************************************/
+ package org.eclipse.albireo.core;
+ 
+ import java.awt.EventQueue;
+ 
+ import javax.swing.UIManager;
+ import javax.swing.UnsupportedLookAndFeelException;
+ 
+ import org.eclipse.albireo.internal.Platform;
+ 
+ /**
+  * This class deals with the customization of the look&feel
+  * of Swing components embedded inside SWT.
+  * <p>
+  * It is customizable through the "replaceable singleton" design pattern.
+  */
+ public class LookAndFeelHandler {
+ 
+     // ========================================================================
+     // Accessors
+ 
+     /**
+      * This look&amp;feel choice denotes the default Swing look&amp;feel.
+      * It may be platform dependent.
+      */
+     public static final String LAFChoiceSwingDefault = "swing.defaultlaf";
+ 
+     /**
+      * This look&amp;feel choice denotes the cross-platform Swing
+      * look&amp;feel.
+      * It is not platform dependent.
+      * @see javax.swing.UIManager#getCrossPlatformLookAndFeelClassName()
+      */
+     public static final String LAFChoiceCrossPlatform = "swing.crossplatformlaf";
+ 
+     /**
+      * This look&amp;feel choice denotes the Swing look&amp;feel
+      * that best approximates the system look&amp;feel.
+      * It is platform dependent.
+      * @see javax.swing.UIManager#getSystemLookAndFeelClassName()
+      */
+     public static final String LAFChoiceNativeSystem = "swing.systemlaf";
+ 
+     /**
+      * This look&amp;feel choice denotes the Swing look&amp;feel
+      * that best approximates the system look&amp;feel, except that
+      * the Gtk look&amp;feel is used instead of the cross-platform
+      * look&amp;feel if SWT is based on Gtk.
+      * (This typically affects Linux systems with KDE desktop.)
+      * It is platform dependent.
+      */
+     public static final String LAFChoiceNativeSystemForceGtk = "swing.systemlaf+gtk";
+ 
+     /**
+      * This look&amp;feel choice denotes the Swing look&amp;feel
+      * that best approximates the system look&amp;feel, except that
+      * the Gtk look&amp;feel is avoided.
+      * (This typically affects Linux systems with Gtk desktop.)
+      * It is platform dependent.
+      */
+     public static final String LAFChoiceNativeSystemNoGtk = "swing.systemlaf-gtk";
+ 
+     private String lafChoice = LAFChoiceNativeSystemForceGtk;
+ 
+     /**
+      * Returns the look&amp;feel choice. It can be a class name or one
+      * the shorthands defined in this class.
+      */
+     public String getLAFChoice() {
+         return lafChoice;
+     }
+ 
+     /**
+      * Specifies which look&amp;feel should be used.
+      * @param choice Either a class name, such as
+      *               <code>"javax.swing.plaf.metal.MetalLookAndFeel"</code>,
+      *               <code>"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"</code>,
+      *               <code>"com.sun.java.swing.plaf.gtk.GTKLookAndFeel"</code>,
+      *               <code>"com.sun.java.swing.plaf.motif.MotifLookAndFeel"</code>,
+      *               <code>"apple.laf.AquaLookAndFeel"</code>,
+      *               or one of the shorthands
+      *               {@link #LAFChoiceSwingDefault},
+      *               {@link #LAFChoiceCrossPlatform},
+      *               {@link #LAFChoiceNativeSystem},
+      *               {@link #LAFChoiceNativeSystemForceGtk},
+      *               {@link #LAFChoiceNativeSystemNoGtk}.
+      */
+     public void setLAFChoice(String choice) {
+         lafChoice = choice;
+     }
+ 
+     // ========================================================================
+     // Overridable API
+ 
+     private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$
+ 
+     /**
+      * Sets the desired look&amp;feel.
+      * @see #setLAFChoice(String)
+      */
+     public void setLookAndFeel()
+         throws ClassNotFoundException,
+                InstantiationException,
+                IllegalAccessException,
+                UnsupportedLookAndFeelException {
+         assert EventQueue.isDispatchThread(); // On AWT event thread
+ 
+         String laf = getLAFChoice();
+         if (LAFChoiceSwingDefault.equals(laf)) {
+             return;
+         } else if (LAFChoiceCrossPlatform.equals(laf)) {
+             laf = UIManager.getCrossPlatformLookAndFeelClassName();
+         } else if (LAFChoiceNativeSystem.equals(laf)) {
+             laf = UIManager.getSystemLookAndFeelClassName();
+         } else if (LAFChoiceNativeSystemForceGtk.equals(laf)) {
+             laf = UIManager.getSystemLookAndFeelClassName();
+             if (Platform.isGtk()
+                 && laf.equals(UIManager.getCrossPlatformLookAndFeelClassName())) {
+                 laf = GTK_LOOK_AND_FEEL_NAME;
+             }
+         } else if (LAFChoiceNativeSystemNoGtk.equals(laf)) {
+             laf = UIManager.getSystemLookAndFeelClassName();
+             if (GTK_LOOK_AND_FEEL_NAME.equals(laf))
+                 laf = UIManager.getCrossPlatformLookAndFeelClassName();
+         }
+ 
+         UIManager.setLookAndFeel(laf);
+     }
+ 
+     // ========================================================================
+     // Singleton design pattern
+ 
+     private static LookAndFeelHandler theHandler = new LookAndFeelHandler();
+ 
+     /**
+      * Returns the currently active singleton of this class.
+      */
+     public static LookAndFeelHandler getInstance() {
+         return theHandler;
+     }
+ 
+     /**
+      * Replaces the singleton of this class.
+      * @param instance An instance of this class or of a customized subclass.
+      */
+     public static void setInstance(LookAndFeelHandler instance) {
+         theHandler = instance;
+     }
+ 
+ }

PNG image

PNG image