かなり長い間、私はアプリケーションに取り組んできました。プログラミングは単なる趣味であるため、このプロジェクトはすでに時間がかかりすぎていますが、それは重要なことではありません。私は今、すべての「問題」を解決するのが非常に困難になっているところにいます。そして、私はコードをリファクタリングすることを考えています、しかしそれは「完全な」書き直しをもたらすでしょう。
問題と、現在どのように解決したかを説明します。基本的に私はデータを持っています、そして私はこのデータの上で物事を起こさせます(私はすべてのプログラムについてよく説明しましたか?)。何が起こるか:
データ->ビューアに表示を要求->ビューアは実際のデータに基づいてデータを表示ビューアはユーザー入力を返します->データ->「エグゼキュータ」に実行を要求->新しいデータ
今ではこれは非常にうまく機能していました。私はもともと「たとえば、コマンドプロンプトをqtやwindowsで変更するか、外部(C#)を使用して、このプログラムを呼び出すだけかもしれない」と考えていました。
しかし、プログラムが成長するにつれて、それはますます面倒になりました。最も重要なことは、データが何であるか、そしてさらに重要なことに、データがどこにあるかに応じて、データがさまざまな方法で表示されることです。そこで、ツリーに戻って、親の行が何であるかを「追跡」するために何らかの方法で追加しました。次に、一般の視聴者は、最も具体的な実際のウィジェットを検索します。最適な場所。
問題は、新しい「データ」を更新するときに始まります。ビューア、セーバーなど、すべてのアセットを確認する必要があります。チェックメカニズムを更新すると、多くのエラーが発生しました。今また?」
これで、これを完全に入れ替えることができます。そして、一般的なビューアを呼び出すツリーデータ構造の代わりに。OOの「内部」ツリー機能を使用します。ノードは子になります(新しいビューアまたは保存メカニズムが必要な場合は、新しい子が形成されます)。
これにより、ツリー内の場所をチェックする難しいチェックメカニズムが削除されます。ただし、他のすべてのワームの缶を開く可能性があります。そして、私はこれについていくつかのコメントが欲しいですか?ビューアを完全に分離しておく必要があります-データのチェックに問題がありますか?または、新しいアプローチの方が優れていますが、データと実行を1つのノードに結合します。(したがって、qtからcli / C#に変更したい場合は、ほとんど不可能になります)
最終的にどのような方法を追求する必要がありますか?また、他に何かできることはありますか?ビューアを分離したまま、表示するウィジェットを確認するためのチェックを行わないようにするには?
いくつかの「コード」と私のプログラムがどのように機能するかを示すためだけに編集してください。すでに言ったように、これが良いかどうかはわかりませんが、方法論のかなりのクラスターファックになっています。
これは、いくつかの「ゲームメーカープロジェクト」をマージすることを目的としています(GM:studioには奇妙なことにその機能がないため)。Gamemakerプロジェクトファイルは、単にxmlファイルのセットです。(他のxmlファイルへのリンクのみを含むメインxmlファイル、および各リソース(オブジェクト、スプライト、サウンド、ルームなど)のxmlファイル)。ただし、ブーストプロパティツリーやqtなどで実際に読み取ることができない「癖」がいくつかあります。1)ファイルの特定の部分で属性/子ノードの順序が非常に重要です。2)空白は無視されることがよくありますが、他の点では空白を保持することが非常に重要です。
そうは言っても、ノードがまったく同じであるポイントもたくさんあります。背景がどのように持つことができるか、<width>200</width>
そして部屋もそれを持つことができるように。しかし、ユーザーにとって、彼が話している幅は非常に重要です。
とにかく、「一般的なビューア」(AskGUIFn)には、これを処理するための次のtypedefがあります。
typedef int (AskGUIFn::*MemberFn)(const GMProject::pTree& tOut, const GMProject::pTree& tIn, int) const;
typedef std::vector<std::pair<boost::regex, MemberFn> > DisplaySubMap_Ty;
typedef std::map<RESOURCE_TYPES, std::pair<DisplaySubMap_Ty, MemberFn> > DisplayMap_Ty;
「GMProject::pTree」がツリーノードである場合、RESOURCE_TYPESは、現在のリソースの種類(スプライト、オブジェクトなど)を追跡するための定数です。「memberFn」は、ここでは単にウィジェットをロードするものになります。(もちろん、AskGUIFnだけが一般的なビューアーではありませんが、これは、他の「自動」-上書き、スキップ、名前変更-ハンドラーが失敗した場合にのみ開かれます)。
次に、これらのマップがどのように初期化されるかを示します(名前空間「MW」のすべてがqtウィジェットです)。
AskGUIFn::DisplayMap_Ty AskGUIFn::DisplayFunctionMap_INIT() {
DisplayMap_Ty t;
DisplaySubMap_Ty tmp;
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^instances "), &AskGUIFn::ExecuteFn<MW::RoomInstanceDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^code $"), &AskGUIFn::ExecuteFn<MW::RoomStringDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^(isometric|persistent|showcolour|enableViews|clearViewBackground) $"), &AskGUIFn::ExecuteFn<MW::ResourceBoolDialog>));
//etc etc etc
t[RT_ROOM] = std::pair<DisplaySubMap_Ty, MemberFn> (tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
tmp.clear();
//repeat above
t[RT_SPRITE] = std::pair<DisplaySubMap_Ty, MemberFn>(tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
//for each resource type.
次に、ツリーデータ構造が一般のビューアに表示を希望することを通知すると、ビューアは次の機能を実行します。
AskGUIFn::MemberFn AskGUIFn::FindFirstMatch() const {
auto map_loc(DisplayFunctionMap.find(res_type));
if (map_loc != DisplayFunctionMap.end()) {
std::string stack(CallStackSerialize());
for (auto iter(map_loc->second.first.begin()); iter != map_loc->second.first.end(); ++iter) {
if (boost::regex_search(stack, iter->first)) {
return iter->second;
}
}
return map_loc->second.second;
}
return BackupScreen;
}
そして、これは問題が率直になり始めたところです。関数はCallStackSerialize()
コールスタックに依存します。ただし、そのcall_stackは「ハンドラー」内に格納されます。すべてがハンドラーから始まるので、そこに保存しました。この「call_stack」をどこに保存すればよいのかよくわかりません。何が起こっているかを追跡する別のオブジェクトを導入しますか?親をノード自体と一緒に保存するルートを試してみました。(コールスタックの必要性を防ぎます)。しかし、それは私が望んでいたほどうまくいきませんでした。各ノードには、その子ノードを含むベクトルがあります。したがって、ポインタを使用して親のメモを指すことは問題外です...(PS:別の質問でこれを修正する必要があるかもしれません..)