2015-01-07 7 views
6

reactive-bananaを使用してマルチモーダルエディタを構築しています。ほとんどの場合、完璧になっています。私のシナリオを拡張するために、エディタはマッピングソフトウェアの一部であるか、非常に単純なベクトルグラフィックスエディタと考えることができます。現在のところ、選択モードポリゴン作成モードの2つの状態があります。選択モードでは、ユーザーは以前に作成したポリゴンをマウスの右ボタンで選択することができます(理論的には選択モードになります)。または、マウスの左ボタンで新しいポリゴンの作成を開始できます。リアクティブバナナで1つのスイッチを実行

マウスの左ボタンを押すと、選択モードからポリゴン作成モードに切り替わります。このモードでは、マウスの左ボタンは、ユーザーが元の頂点に戻るまで「新しい頂点を追加」を意味します。この時点で、それらはポリゴンを閉じているので、選択モードに戻ります。

私はこれをいくつかの方法で実装しましたが、最近イベントスイッチがこれを非常に優雅にしていることに気付きました。私が持つことができます。

createSectorMode :: Frameworks t 
       => HadoomGUI 
       -> SectorBuilder 
       -> Point V2 Double 
       -> Moment t (Behavior t Diagram) 
createSectorMode HadoomGUI{..} initialSectorBuilder firstVertex = 
    do mouseClicked <- registerMouseClicked guiMap 
    ... 

これに伴い

defaultMode :: Frameworks t => HadoomGUI -> Moment t (Behavior t Diagram) 
defaultMode [email protected]{..} = 
    do mouseMoved <- registerMotionNotify guiMap 
    mouseClicked <- registerMouseClicked guiMap 
    let lmbClicked = ... 
     gridCoords = ... 
     diagram = ... 
    switchToCreateSector <- execute ((\m -> 
             FrameworksMoment 
              (=<< trimB =<< createSectorMode gui emptySectorBuilder m)) <$> 
             (gridCoords <@ lmbClicked)) 
    return (switchB diagram switchToCreateSector) 

確かに動作します - 単一のマウスクリックのために。一度地図をクリックすると、直前の状態からセクタ作成モードに切り替わりますが、を再度にクリックすると、defaultModeはクリックイベントを受信し、新しいポリゴン作成モードに切り替わり、前の状態。

私がしたいことは、defaultModeに一度だけ戻ってくる可能性があります。基本的にはBehavior t Diagram()の「スワップ」をcreateSectorModeとしたいと思います。

私はreactive-bananaが動的イベントのガベージコレクションに問題があることを理解していますが、私は今のところそれに喜んでいます。上記の公式は、今までに書いたものよりもはるかに正確です。たとえば、変数が1つしかなく、その内容に基づいてさまざまなイベントをフィルタリングしています。私がこれを持っている問題は、それが大きすぎるということです。切り替えを行うと、私はできる範囲でイベントを開催できます。

答えて

3

問題は幾分オープンになっていますので、私は明確な答えを出すことはできません。しかし、私は確かに私の意見を与えることができます。 ;-)

しかし、私はどうなるのか、おそらくモード内で動作から切り替え間のモードを分離することです。私たちは一瞬FRPを忘れた場合は、あなたのプログラムが少し自分自身を再帰的に呼び出す関数のペアのようになります。

defaultMode = ... `andthen` sectorMode 
sectorMode = ... `andthen` defaultMode 

それは、ビット「順次」プログラムのように書かれている、「最初にこのモードを行う、そしてそれを行いますモード"。私はそこに何も間違っているとは思わないが、デフォルトのAPI反応バナナ、特にswitchBはそのスタイルをとてもうまくサポートしていない。あなたは、イベントの最初の発生を通過させるが、残りの部分を破棄し

once :: Event t a -> Event t a 

コンビネータを書くことができる(個人的に)言及しました。これは実際にあなたがシーケンシャルスタイルに必要なものです。

あなたはいつもデフォルトモードに戻りますが、私はおそらく、それぞれのモードに切り替える必要があることを示すイベントがある別のアプローチを試みます。スイッチング自体は「外部」エンティティによって処理されます。考え方は、上のプログラムで明示的な再帰をいくつかの高次コンビネータによって避けることです。擬似コードでは、これは次のようになります。

modeManager = switchB initialMode changeMode 
changeMode = defaultModeSwitch `union` sectorModeSwitch 

詳細については少し不明ですが、実際には、まったく動作するかどうかは完全にはわかりませんが、おそらくまだonceコンビネータが必要です。

とにかく、これは切り替えの仕方に関するちょっとしたアイデアです。私は、スイッチングがさまざまなモードを扱う正しい方法であることに完全に同意します。

+0

ありがとう、これは私が考慮しなかった興味深いアプローチです。古い「モード」がまだ切り離されることを依頼しても、まだイベントを受信して​​いるという問題があるのに、「一度」必要ですか?私はこれと遊びをして、私が見つけたものを確かめるでしょう。 – ocharles

+0

どちらの場合も、古いモードはイベントを受信して​​います。破棄して結果を無視し、代わりに新しいモードを作成するだけです。これはおそらく、それぞれのモードが新しいモードに置き換えられることを一度だけ伝えることができるようにするためには、まだ 'once'が必要であることを意味します。 –

+0

これはガベージコレクションが将来対応するのに役立つとは思わないでしょうか? – ocharles

関連する問題