Wicket 8 の AjaxButton 、Link など

Wicket 8 になるとこれまでよりもシリアライズ化された Consumer などによりラムダ記述は、
前に投稿した 
Wicket8 の LambdaModel - Oboe吹きプログラマの黙示録 の他に、

AjaxButton 、FeedBackPanel 、Link なども簡潔に書けるようになってくる。

AjaxButton には、

// onSubmit と onError の BiConsumer
onSubmit(String id, SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onSubmit
  , SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onError)

// あるいは、onSubmit だけ
onSubmit(String id, SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onSubmit)

このおかげて、

queue(AjaxButton.onSubmit("submit", (b, t)->{
   /* onSubmit の処理 */
}, (b, t)->{
   /* onError の処理 */
});

// あるいは、
queue(AjaxButton.onSubmit("submit", (b, t)->{
   /* onSubmit の処理 */
});

と書ける。

FeedBackPanel でセットする IFeedbackMessageFilter メッセージも、setFilter は、

boolean feedbackError_flg = false;
final FeedbackPanel feedback = new FeedbackPanel("feedback");
feedback.setOutputMarkupId(true);
feedback.setFilter(e->feedbackError_flg);
queue(feedback);

と書いて

queue(AjaxButton.onSubmit("send", (b, t)->{
  feedbackError_flg = false;

  /* エラーで、feedbackError_flg を true 、error("Error message"); */
  t.add(feedback);
}));

とすることができる。

リンクの onClick も、Link.onClick で、シリアライズConsumerで、

queue(Link.onClick("bklink", k->{
   setResponsePage(HomePage.class);
}));

と書くことができる。

Consumer を Inject

Google guice で、List をインジェクションする時によく使うのが、com.google.inject.TypeLiteral 

Java8 lambda の Consumer をインジェクションすることをやれば、条件分岐によるメソッド実行を
一括管理の記述ができると思った。

まず、分岐ではなく、ただの Consumer をインジェクションする例。

Injector injector =
Guice.createInjector(new AbstractModule(){
   @Override
   protected void configure(){
      binder().bind(new TypeLiteral<Consumer<?>>(){})
      .toInstance(e->{
         System.out.println(e);
      });
   }
});

Injector で生成されるクラスのメソッドで、Consumer を実行

@Inject Consumer<String> consumer;
public void exec(){
   consumer.accept("accept! on Foo::exec()");
}


AbstractModule の configure の中で if 文を書くか、if 文による ModuleインスタンスGuice.createInjector
に渡す方法を考えるかもしれないが、
あまり整理できると思えない。

今のところ、Mapを使用することぐらいしか思いつかない。

Map<String, Consumer<String>> map = new HashMap<>();
map.put("1", e->{
   System.out.println("Test 1 : " + e);
});
map.put("2", e->{
   System.out.println("Test 2 : " + e);
});

String key = "2";

Injector injector = Guice.createInjector(new AbstractModule(){
   @Override
   protected void configure(){
      binder().bind(new TypeLiteral<Consumer<String>>(){}).toInstance(map.get(key));
   }
});

条件毎の実装クラス定義を作らなくて済むだけでもありがたいのかも知れない。

NULLインジェクション

いつも、Google guice 使用を書いていて思うのが、NULLインジェクションが発生するとき、
@Nullable をつけて、Module の configure で、toProvider を書かなくてはならないのが
煩わしい。

   binder().bind(Integer.class).toProvider(Providers.of(null));
   @Inject @Nullable private Integer i;

com.google.inject.Inject のオプション @Inject(optional=true) だけではダメで、
@Nullable が必要なのだ。
明示的であり、NULL 発生で落ちるのが解るから、toProviderと@Nullable を使うのだと言えば、それで納得なんだけど。。。

結局、optional がない javax.inject.Inject の方をいつも使っている。

JavaFX CSS で @CHARSET記述は不要である

JavaFXCSS を書いていると、ついHTMLのCSS を書いていた時の癖で @CHARSET "UTF-8"; を書いてしまう。

でも、これを書いてしまうと、com.sun.javafx.css.parser.CSSParser は、CSS parseエラーになり思いとおりの
スタイルが適用されなくなる。

docs.oracle.com

@Rule の章をよく読むべし。

JavaFX の ウィンドウフレームを無くす

JavaFX の ウィンドウフレームを無くしたい場合、Application の start(Stage) で渡される javafx.stage.Stage を

javafx.stage.StageStyle の StageStyle.TRANSPARENT を指定すれば、ウィンドウフレーム無しの透過
StageStyle.UNDECORATED なら、ウィンドウフレーム無しで背景はし白色で塗りつぶしになる。

public class MainApp extends Application{
   /* @see javafx.application.Application#start(javafx.stage.Stage) */
   @Override
   public void start(Stage primaryStage) throws Exception{
      primaryStage.initStyle(StageStyle.TRANSPARENT);

JavaFX で、外部フォント

JavaFX で、外部フォントを指定する場合の書き方

CSS に書く場合 @font-faceで fontファミリ-ttfを定義、→ -fx-font-family で指定

@font-face{
    font-family: meiryo;
  /** ttf ファイル参照 **/
    src: url("file://c:/home/test/meiryo.ttf");
}

Pane{
   -fx-font-family: meiryo;
}


ttc ファイルがあって ttf が存在しない場合、

UniteTTC というツールを使えば、ttc を分割して ttf を抽出できる。

java.time.format.FormatStyle を確認

java.time.format.FormatStyle で Locale に従った日付表記を試してみる。

    LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(new Locale("ja", "JP")));
    LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).withLocale(new Locale("ja", "JP")));
    LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(new Locale("ja", "JP")));
    LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(new Locale("ja", "JP")));

4通りある。
これを、 Locale( 言語、国 ) を指定して標準出力してみると、、

--- FormatStyle.FULL ---
ja JP → 2017年3月8日
en US → Wednesday, March 8, 2017
en UK → Wednesday, March 8, 2017
zh CN → 2017年3月8日 星期三
zh TW → 2017年3月8日 星期三
ko KR → 2017년 3월 8일 수요일
ru RU → 8 марта 2017 г.
--- FormatStyle.LONG ---
ja JP → 2017/03/08
en US → March 8, 2017
en UK → March 8, 2017
zh CN → 2017年3月8日
zh TW → 2017年3月8日
ko KR → 2017년 3월 8일 (수)
ru RU → 8 марта 2017 г.
--- FormatStyle.MEDIUM ---
ja JP → 2017/03/08
en US → Mar 8, 2017
en UK → Mar 8, 2017
zh CN → 2017-3-8
zh TW → 2017/3/8
ko KR → 2017. 3. 8
ru RU → 08.03.2017
--- FormatStyle.SHORT ---
ja JP → 17/03/08
en US → 3/8/17
en UK → 3/8/17
zh CN → 17-3-8
zh TW → 2017/3/8
ko KR → 17. 3. 8
ru RU → 08.03.17

en US(米国)も en UK も 変わらない。

FormatStyle.MEDIUM と FormatStyle.SHORT → 中国と 微妙な扱いの台湾、違う!!
(この差にあまり触れたくない)