Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIEventHandler の登録 API を整理する #142

Open
lriki opened this issue May 3, 2020 · 0 comments
Open

UIEventHandler の登録 API を整理する #142

lriki opened this issue May 3, 2020 · 0 comments
Labels
proposal 実装済みの機能を変更する場合に使用する。

Comments

@lriki
Copy link
Collaborator

lriki commented May 3, 2020

[2021/1/6] やっぱり現状維持にしてみる

Builder パターンの導入を始めたので、そっちで対応してみる。C++ から使うときはほとんどこのケースで足りる。

auto button = UIButton::Builder()
    .onClicked(handler)
    .build();

新しめの UI フレームワークは Builder パターンないしそれに近い、副作用の少ない方法で UI要素を構築するケースが多い。これで十分な感じ。

connectXX は主に Binding を作るとき、「これはイベントハンドラの登録関数です」を強調するのに使うことにしてみる。

イベント名は過去形?

ネイティブに近いフレームワークは過去形が多い傾向。
ただ過去形に統一しすぎると MouseDowned とかなじみ無い名前になる。

タイミングを区別するなら WPF の "Preview" Prefix のようなものを付ける、でいいかも。

Proposal

connectOnXXXX 及び onXXXX のインターフェイスを変更する。
例えば UIButton の Clicked イベントであれば、

Ref<EventConnection> connectOnClicked(Ref<UIEventHandler> handler);
virtual void onClicked(UIEventArgs* e) override;

UIButton* onClicked(Ref<UIEventHandler> handler, Ref<EventConnection>* outConnection = nullptr);
virtual void onClickedEvent(UIEventArgs* e) override;

ただし、on~ は他のモジュールでも使用している仮想関数実装の命名規則でもあるため、上記そのまま適用は難しいかもしれない。

候補としては、

  • setOnClicked
    • Ruby や C# binding で使うときに on_clicked や OnClicked となるため、他モジュールの命名規則と衝突する。
  • setClickedHandler
    • まだちょっと長いかも…。特にスクリプト系 Binding から見た時。
  • setClicked
    • 落としどころかも?通常プロパティと区別するため、イベント名には名詞を使わないように注意する必要がある。

Motivation

現在、ユーザープログラムから、イベントをハンドリングする方法は次の2通り。

  • A. connectOnXXXX にコールバックを登録する
  • B. コントロールを継承して仮想関数 onXXXX を実装する

ユーザープログラムから見ると、このうち A は非常によく使い、B はあまり使わない。
(A はコントロールを利用するための API であるが、B はコントロールをカスタマイズするための API)

そのため以下のような不満が出てきた。

  • A のほうが頻繁に使うのにタイプ量が多い
  • 戻り値が決まっているので Builder パターンのようなメソッドチェインが組めない
  • EventConnection はほとんどのケースで使用しないが、そうすると VisualStudio でインテリセンスの警告が出る → C26444

Note

on~ を採用しているものはそれなりにある。ただ、signal ではなく普通のプロパティとして単一のハンドラをセットするケースが多い印象。

C# の Event や、signal-slot の仕組みで作られているものは on~ ではないことが多いみたい。

WPF

  • MouseEnter += _handler

Material-UI

  • onClick = _handler

onClick の呼び出し元は handleClick.
ただ仮想関数という考え方ではない。

一番根っこは div の onClick にローカル定義した関数をセットしているだけ。
<div ... onClick={handleClick} ...>

JavaScript

Flutter

  • onPressed: _handler

Unity(UIElements)

  • clicked += _handler
    ※ onClick もあるが、Obsolete としてマークされている。また、コンストラクタでもハンドラを受け取れる。

これらはすべて C# の event として実装されている。

  • Button.clicked
  • ListView.onSelectionChanged

仮想関数は次のような命名になっている。

  • Clickable.OnMouseDown()
  • Clickable.OnMouseMove()

UE4

  • (BP) On Clicked
  • (Slate) OnClicked(_handler)

イベントと仮想関数の命名規則に区別はない。

  • OnMouseButtonDown()
  • OnPaint()
  • OnClicked
  • OnAcceptDrop
  • OnPaintHandler

Kivy

  • (.kv) on_press: _handler
  • (.py) on_press=_handler (コンストラクタ名前付き引数)
  • (.py) b.bind(on_press=anim_btn)

イベントと仮想関数の命名規則に区別はない。

  • on_touch_down()
  • on_touch_move()
  • on_touch_up()
  • on_press:
  • on_release:

Qt

  • (QWidgets) connect(a, SIGNAL(valueChanged()), b, SLOT(_handler));
  • (QML) onClicked: _handler

Android

  • setOnClickListener(_handler)

UIKit

  • button.addTarget(self, action: #selector(_handler),

GTK

  • g_signal_connect (button, "clicked", G_CALLBACK (_handler), (gpointer) "button");

Rust azul

let button = Button::with_label("+1").dom().with_id("button")
      .with_callback(On::MouseUp, Callback(update_counter));

Rust gtk

button.connect_clicked(move |_| { ... });

Rust iced

Button::new(&mut self.reset_button, Text::new("reset"))
    .on_press(Message::Reset),

OrbTk iced

self.on_mouse_up(move |p| { ... });

Note

現時点で Event<> な変数は次の通り。

canUndoChanged;
canRedoChanged;

m_onCollisionEnter;
m_onCollisionLeave;
m_onCollisionStay;
m_onUIEvent;
m_onChecked;
m_onUnchecked;

m_onActivated;
m_onDeactivated;

m_onSubmit;
DragStarted;
DragDelta;
DragCompleted;
DragCanceled;

m_onItemSubmitted;
m_onGenerateTreeItem;

m_onCanExecuteChanged;
m_onCanExecuteEvent;
m_onExecuteEvent;

m_onClosed;
m_onImGuiLayer;

m_onClick;
m_onItemClick;
m_onSelectionChanged;
m_onSelectedTabChanged;

m_onRender

onGenerateTreeItem, onRender あたりは他の名前にし辛いかも。

  • (C++) setRender(...)
  • (C#) Render += ...
  • (Ruby) render = ...

onUIEvent は動詞でもないケースなので、Ruby とかだと普通の変数と区別ができなくなる。
スクリプト系だとこのあたりの視認性が悪くなるのはマイナス。

@lriki lriki added the proposal 実装済みの機能を変更する場合に使用する。 label May 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal 実装済みの機能を変更する場合に使用する。
Projects
None yet
Development

No branches or pull requests

1 participant