こんにちは、高木です。
今回はgeometry_managerクラスにconfigureコマンドに相当するconfigureメンバー関数を追加していくことにします。最初に考えないといけないのは、configureコマンドと基本コマンドはconfigureがあるかないかの違いだけでシンタックスがそっくりだということです。コピペでベタベタに実装することもできますが、ここは共通の下請け関数を作ってあげることにしましょう。
というわけで、geometry_managerクラスに次のような下請け関数を追加しました。privateメンバーでもいい気がしたのですが、念のためprotectedにしています。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
protected: // windows列をコマンドに設定する。 static tcl::interpreter set_window_parameters(std::vector<Tcl_Obj*>& args, std::initializer_list<window> windows) { Tcl_Interp* interp = nullptr; std::for_each(windows.begin(), windows.end(), [&args, &interp](auto w) { // 各ウィンドウが所属しているインタープリターの一致判定 if (interp == nullptr) interp = w.get().interpreter().get(); else if (interp != w.get().interpreter().get()) throw std::runtime_error("異なるインタープリターに所属するウィジェットが混在している"); args.push_back(w.get().path().get()); }); return interp; } // オプション列をコマンドに設定する。 static void set_options(std::vector<Tcl_Obj*>& args, std::initializer_list<tcl::obj> options) { std::for_each(options.begin(), options.end(), [&args](auto option) { args.push_back(option.get()); }); } |
次に、これらの下請け関数を使って、前回作った基本コマンドのメンバー関数を書き換えます。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// 基本コマンド int operator()(std::initializer_list<window> windows, std::initializer_list<tcl::obj> options) const { std::vector<Tcl_Obj*> args{ this->type_.get() }; auto interp = set_window_parameters(args, windows); set_options(args, options); return interp.evaluate(args); } // オプション無し int operator()(std::initializer_list<window> windows) const { return operator()(windows, {}); } // ウィジェト1つ、オプションあり int operator()(const window& w, std::initializer_list<tcl::obj> options) const { std::vector<Tcl_Obj*> args{ this->type_.get(), w.get().path().get() }; auto interp = w.get().interpreter(); set_options(args, options); return interp.evaluate(args); } // ウィジェット1つ、オプション無し int operator()(const window& w) const { return operator()(w, {}); } |
あとは同じようにしてconfigureメンバー関数も作っていきます。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// configureコマンド int configure(std::initializer_list<window> windows, std::initializer_list<tcl::obj> options) const { auto command = tcl::obj(u8"configure"); std::vector<Tcl_Obj*> args{ this->type_.get(), command.get() }; auto interp = set_window_parameters(args, windows); set_options(args, options); return interp.evaluate(args); } // configureウィジェト1つ、オプションあり int configure(const window& w, std::initializer_list<tcl::obj> options) const { auto command = tcl::obj(u8"configure"); std::vector<Tcl_Obj*> args{ this->type_.get(), command.get(), w.get().path().get() }; auto interp = w.get().interpreter(); set_options(args, options); return interp.evaluate(args); } // configureウィジェット1つ、オプション無し int configure(const window& w) const { return configure(w, {}); } |
これでconfigureコマンドを作ることができました。
次回はforgetなど他のコマンドも作り込んでいく予定です。