CLabel で鏡文字

ども。さぶいですね。
手がかじかんでうまくタイプできなくなって,あぁさぶいんだと気付いた
whitypig です。


鏡文字なラベルを作ってみました。
ソースコードを載っけたので長いですよ。

なぜにこんなものが必要だったか?

秘密。いま作っているものの中で必要だったからです。
鏡像というのかな? 一般的には。
要は,x --> -x, y --> y な変換をしているだけです。
そして,その名は,MirrorCLabel です。

ソースコード

以下 MirrorCLabel.java

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.widgets.Composite;

/**
 * CLabel の鏡文字版
 *
 * @author whitypig
 * @version 1.0
 */
public class MirrorCLabel extends CLabel implements PaintListener {

  private String string;
  private Transform transform;

  /**
   * コンストラクタ
   *
   * @param parent 親 Composite
   * @param style SWT.LEFT, SWT.CENTER, or SWT.RIGHT でも無視される。
   */
  public MirrorCLabel(Composite parent, int style, String string) {
    super(parent, style);
    this.string = string;
    // x --> -x, y --> y に変換
    this.transform = new Transform(getDisplay(), -1, 0, 0, 1, 0, 0);
    setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
    addPaintListener(this);
  }

  public MirrorCLabel(Composite parent, int style) {
    super(parent, style);
    this.string = null;
    // x --> -x, y --> y に変換
    this.transform = new Transform(getDisplay(), -1, 0, 0, 1, 0, 0);
    setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
    addPaintListener(this);
  }

  @Override
  public void setText(String s) {
    this.string = s;
    redraw();
    update();
  }

// Implementation of org.eclipse.swt.events.PaintListener

  /**
   * ラベルの中央に,this.string を描く。
   *
   * @param paintEvent a <code>PaintEvent</code> value
   */
  public final void paintControl(final PaintEvent paintEvent) {
    if (string == null) { return; }
    GC gc = paintEvent.gc;
    // 文字列の幅,高さを調べる
    Point p = gc.stringExtent(string);
    gc.setForeground(getForeground());
    gc.setTransform(transform);
    // ラベルの中央に。
    gc.drawString(string, -1 * ((paintEvent.width + p.x) / 2), (paintEvent.height - p.y) / 2);
  }

}

とりあえず,ラベルの中央にテキストを表示するようにしています。
今のところ,オレ的にはそれしか必要ないからだぜ。

写真デモ

こんなん見せられてもわからんと思うので,デモ。
わかりやすく,まず文字列を表示して,3秒後に文字列を別のに変更します。
まずは,最初の状態。


んで,3秒後にこうなります。


3秒後にラベルのテキストを変更するのは,MirrorCLabel とは関係ございません。
以下が,デモのソースコード

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public final class MirrorCLabelDemo {

  public static void main(final String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setSize(400, 400);
    shell.setText("Mirror CLabel Demo");
    GridLayout gridLayout = new GridLayout();
    gridLayout.numColumns = 3;
    shell.setLayout(gridLayout);
    Font font = new Font(display, "Meiryo", 16, SWT.BOLD);
    // ラベル用の GridData
    GridData gd1 = new GridData(GridData.FILL_BOTH);
    gd1.grabExcessHorizontalSpace = true;
    gd1.grabExcessVerticalSpace = true;
    gd1.heightHint = 150;
    gd1.widthHint = 200;
    GridData gd2 = new GridData(GridData.FILL_BOTH);
    gd2.grabExcessHorizontalSpace = true;
    gd2.grabExcessVerticalSpace = true;
    gd2.heightHint = 150;
    gd2.widthHint = 200;
    GridData gd3 = new GridData(GridData.FILL_BOTH);
    gd3.grabExcessHorizontalSpace = true;
    gd3.grabExcessVerticalSpace = true;
    gd3.heightHint = 150;
    gd3.widthHint = 200;

    // MirrorCLabel を作っていきます。
    final MirrorCLabel l1 = new MirrorCLabel(shell, SWT.BORDER);
    l1.setSize(200, 100);
    l1.setFont(font);
    l1.setText("おはようございます");
    l1.setLayoutData(gd1);
    final MirrorCLabel l2 = new MirrorCLabel(shell, SWT.BORDER);
    l2.setFont(font);
    l2.setText("こんにちは");
    l2.setLayoutData(gd2);
    final MirrorCLabel l3 = new MirrorCLabel(shell, SWT.BORDER);
    l3.setFont(font);
    l3.setText("こんばんは");
    l3.setLayoutData(gd3);

    // 3秒後に ラベルのテキストを変更してみる
    Runnable timer = new Runnable() {
        public void run() {
          l1.setText("ちゅーっす!!");
          l2.setText("おつかれーす!!");
          l3.setText("あざーす!!");
        }
      };
    display.timerExec(3000, timer);

    shell.pack();
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
    font.dispose();
    display.dispose();
  }

}

まとめ。

パフォーマンス的にはどうなんだろう。
あと,コードについて,つっこみお願いします。
慣習とかよく知らないので。