« Magic Mouse 購入 | トップページ | 検査データの印刷 »

2009年11月13日 (金)

JSheet 導入

Sheet

Mac OS X のダイアログは,タイトルバーのところからアニメーションで降りてくる。これを,「シート」と呼ぶらしい。Mac OS X らしい微妙に半透明のダイアログで素敵である。
 Quaqua には JSheet というクラスがあって,Mac OS X のシートっぽいことが Java でもできる。JSheet を継承した MyJSheet を作って,いくつかダイアログを,シートに置き換えてみた。Mac っぽくなっていい感じになった。JSheet が出てくるスピードは,デフォルトだと遅めなので,default コマンドで 0.05 にセットしている。

$ defaults write NSGlobalDomain NSWindowResizeTime 0.05

client/MyJSheet.java

package open.dolphin.client;

import ch.randelshofer.quaqua.*;
import java.awt.*;
import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * JOptionPane を quaqua の JSheet で置き換える
 * Sheet の表示スピード調節:e.g. defaults write NSGlobalDomain NSWindowResizeTime 0.05 (default=0.2)
 * @author pinus
 */
public class MyJSheet extends JSheet {
  static int answer;

  public MyJSheet(Frame frame) {
    super(frame);
  }
  public MyJSheet(Dialog dialog) {
    super(dialog);
  }

  // JOptionPane.showConfirmDialog 互換
  public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) {
    return showOptionDialog(parentComponent, message, title, optionType, messageType, null, null, null);
  }

  // JOptionPane.showMessageDialog 互換
  public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) {
    showOptionDialog(parentComponent, message, title, JOptionPane.DEFAULT_OPTION, messageType, null, null, null);
  }

  // JOptionPane.showOptionDialog 互換
  public static int showOptionDialog(Component parentComponent, Object message, String title,
      int optionType, int messageType, Icon icon, final Object[] options, Object initialValue) {

    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, options, initialValue);
    pane.setInitialValue(initialValue);
    JSheet sheet = createDialog(pane, parentComponent);
    pane.selectInitialValue();
    sheet.addSheetListener(new SheetListener(){
      public void optionSelected(SheetEvent e) {
        answer = e.getOption();
      }
    });
    sheet.show();
    sheet.dispose();
    return answer;
  }

  // dialog = jop.createDialog を dialog = MyJSheet.createDialog(jop, parent) と置き換えるだけで JSheet になる
  public static MyJSheet createDialog(final JOptionPane pane, Component parentComponent) {
    Window window = getWindowForComponent(parentComponent);
    final MyJSheet sheet;
    if (window instanceof Frame) {
      sheet = new MyJSheet((Frame) window);
    } else {
      sheet = new MyJSheet((Dialog) window);
    }
    JComponent contentPane = (JComponent) sheet.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(pane, BorderLayout.NORTH);
    sheet.setResizable(false);
    sheet.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentShown(ComponentEvent ce) {
        // reset value to ensure closing works properly
        pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
        Object object = pane.getInitialValue();
        if (object instanceof Component) {
          ((Component) object).requestFocusInWindow();
        }
      }
    });
    pane.addPropertyChangeListener(new PropertyChangeListener() {

      public void propertyChange(PropertyChangeEvent event) {
        if (sheet.isVisible() && event.getSource() == pane &&
            (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) &&
            event.getNewValue() != null &&
            event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
          sheet.setVisible(false);
          sheet.fireOptionSelected(pane);
        }
      }
    });
    sheet.pack();
    return sheet;
  }

  /**
   * その component に既に JSheet が表示されているかどうか
   * @param parentComponent
   * @return
   */
  public static boolean isAlreadyShown(Component parentComponent) {
    Window window = getWindowForComponent(parentComponent);
    Window[] windowList = window.getOwnedWindows();
    for (Window w : windowList) {
      if (w instanceof MyJSheet && w.isVisible()) {
        // すでに JSheet が表示されている
        return true;
      }
    }
    return false;
  }

  private static Window getWindowForComponent(Component parentComponent) {
    if (parentComponent == null) {
      return JOptionPane.getRootFrame();
    }
    if (parentComponent instanceof Frame || parentComponent instanceof Dialog) {
      return (Window) parentComponent;
    }
    return getWindowForComponent(parentComponent.getParent());
  }
}

« Magic Mouse 購入 | トップページ | 検査データの印刷 »

OpenDolphin」カテゴリの記事