2011年12月8日 星期四

Concise's Anatomy: SWT native Toolbar (for Mac)

Concise 0.1 beta

One of the most significant change of Concise 0.1 beta is the Graphic User Interface.  It is now really "graphic."  Thanks to Joseph Wain's marvelous icons (http://glyphish.com/).  Besides, what makes the Mac-like toolbar possible is the new feature of SWT (the standard widget toolkit) 3.7.  Let's see how this works.


Shell.getToolBar() returns a ToolBar that appears in the title area of the Shell.  ToolItems added to that ToolBar will have the look and feel of the platform.

Well, I must say this isn't native enough.  The ToolBar returned from Shell.getToolBar() does feel like Leopard (Mac OS X 10.5) or Snow Leopard (Mac OS X 10.6).  As for Lion (Mac OS X 10.7), there is still room to improve.  Nonetheless, Shell.getToolBar() is enough to develop Mac-like user interface under careful design.  The result is shown in Concise 0.1 beta's user interface.

We may follow bug 222859 to see how to use SWT native ToolBar in your Mac (or cross-platform) application.  A test case provided by Felipe Heidrich is a good starting point.  Felipe Heidrich created two different type ToolBars which he called TRIM_FILL (regular toolBar) vs. getToolBar() (native app toolbar).



package tests;

import org.eclipse.swt.SWT;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class UnifiedToolbar {

public static void main(String[] args) {
 Display display = new Display();
 main1(display);
 main3(display);
 Shell shell = display.getShells()[0];
 while (!shell.isDisposed()) {
  if (!display.readAndDispatch())
   display.sleep();
 }
 display.dispose();
}
public static void main3(Display display) {
 Shell shell = new Shell(display, SWT.SHELL_TRIM );
 GridLayout layout = new GridLayout(1, false);
 layout.marginHeight = layout.marginWidth = 0;
 shell.setLayout(layout);

 ToolBar toolBar = shell.getToolBar();
 ToolItem item = new ToolItem (toolBar, SWT.PUSH);
 Image image = new Image(display, 30, 30);
 item.setImage(image);
 item = new ToolItem (toolBar, SWT.PUSH);
 item.setText("native app toolbar");
 
 Button b = new Button(shell, SWT.PUSH);
 b.setText("client");
 shell.setSize(300, 400);
 shell.open();
}


public static void main1(Display display) {
 Shell shell = new Shell(display, SWT.SHELL_TRIM);
 GridLayout layout = new GridLayout(1, false);
 layout.marginHeight = layout.marginWidth = 0;
 shell.setLayout(layout);
 
 ToolBar toolBar = new ToolBar(shell, SWT.FLAT);
 ToolItem item = new ToolItem (toolBar, SWT.PUSH);
 Image image = new Image(display, 30, 30);
 item.setImage(image);
 item = new ToolItem (toolBar, SWT.PUSH);
 item.setText("regular toolbar");
 toolBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 Composite composite = new Composite(shell, SWT.BORDER);
 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
 composite.setLayout(new GridLayout(1, false));
 Button b = new Button(composite, SWT.PUSH);
 b.setText("client");
 shell.setSize(300, 400);
 shell.open();
}

}

You may have discovered there's a blank room under the native app toolBar.  I don't know why.  But this "native" ToolBar does act like a Component which occupies a space whatever Layout (GridLayout(), FillLayout(), or ...) you're using.  Hence, I have come up with a idea by using FormLayout() and a Composite() to solve the strange situation.

The trick is to put the ToolBar into a Composite.  If your ToolBar = Shell.getToolBar(), the Composite will return 0 px in height.  Otherwise, the Composite's height is equal to ToolBar's actual height.  Here is my solution:

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;


public class NativeToolBar {

 public static void main(String[] args) {
  Display display = new Display();
  Shell shell = new Shell(display, SWT.SHELL_TRIM);
  shell.setLayout(new FormLayout());
  shell.setSize(300, 400);
  
  Composite cToolBar = new Composite(shell, SWT.EMBEDDED);
  cToolBar.setLayout(new FillLayout());
  ToolBar toolBar;
  if (System.getProperty("os.name").toLowerCase().contains("mac"))
   toolBar = shell.getToolBar();
  else
   toolBar = new ToolBar(cToolBar, SWT.FLAT);
  ToolItem item = new ToolItem(toolBar, SWT.PUSH);
  Image image = new Image(display, 30, 30);
  item.setImage(image);
  item = new ToolItem(toolBar, SWT.PUSH);
  item.setText("ToolBar");
  
  cToolBar.pack();
  FormData fd = new FormData();
  fd.left = new FormAttachment(0);
  fd.top = new FormAttachment(0);
  fd.right = new FormAttachment(0, shell.getClientArea().width);
  fd.bottom = new FormAttachment(0, cToolBar.getSize().y);
  cToolBar.setLayoutData(fd);
  
  Composite composite = new Composite(shell, SWT.BORDER);
  composite.setLayout(new GridLayout(1, false));
  fd = new FormData();
  fd.left = new FormAttachment(0);
  fd.top = new FormAttachment(cToolBar);
  fd.right = new FormAttachment(0, shell.getClientArea().width);
  fd.bottom = new FormAttachment(0, shell.getClientArea().height);
  composite.setLayoutData(fd);
  
  Button b = new Button(composite, SWT.PUSH);
  b.setText("client");
  
  
  shell.open();
  shell.layout();
  
  while (!shell.isDisposed()) {
   if (!display.readAndDispatch()) {
    display.sleep();
   }
  }
  
 } 
}

Note that this API is a work in progress, and is currently Cocoa-only, according to SWT official website.  We'd better keep a eye on the future New and Noteworthy announcements of SWT.

沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...