[M1 Mac, Big Sur 11.6.8, clang 13.0.0, FLTK 1.3.8, NO IDE]
[C++] 138の続きです。
Fl_File_Browserをダブルクリックして上下層のディレクトリをブラウズできるようにしました。
Fl_File_Chooser::directory関数がポインタ演算を使っていてとても読みにくくメンテナンス性も低くなるため、この関数は使わないようにしました。ポインタ演算はかなりハード寄りの表現なので、オープンソースでは使わない方がいいように思います。
extern Fl_Input *dirInput;
extern FileChooser* chooser;
extern const char* dir_; // FileChooser内カレントディレクトリ
char selectPath[FL_PATH_MAX]; // 選択ファイルパス
vector<string> split(const string& str, char delim){
std::istringstream iss(str);
string tmp;
vector<string> res;
while (getline(iss, tmp, delim)) res.push_back(tmp);
return res;
}
void FileBrowserCB()
{
char *dirName;
const char* delim2 = "/";
// クリックしたディレクトリ名を取得
dirName = (char *)FileBrowser->Fl_Browser::text(FileBrowser->Fl_Browser::value());
cout << "dirName " << dirName << endl;
if (!dirName) return;
string dirNameStr = string(dirName);
// ディレクトリ名を絶対パスに変換
if (dirNameStr.compare("../") == 0){ // "../"をクリックした場合は上層へ移行
string dirStr = string(dir_);
cout << "dirStr " << dirStr << endl;
vector<string> dirStrList = split(dirStr);
dirStrList.pop_back();
std::ostringstream os;
std::copy(dirStrList.begin(), dirStrList.end(), std::ostream_iterator<std::string>(os, delim2));
std::string dirUpper = os.str();
cout << "dirUpper " << dirUpper << endl;
strcat(selectPath, dirUpper.c_str());
} else {
strcat(selectPath, dir_);
strcat(selectPath, dirName);
}
cout << "selectPath " << selectPath << endl;
if (Fl::event_clicks()) {
cout << "ダブルクリックしました" << endl;
// 選択したディレクトリの内容を表示し、カレントディレクトリdir_を更新
if (std::filesystem::is_directory(selectPath)){
FileBrowser->load(selectPath);
char* dir_0 = new char[strlen(selectPath) + 1];
strcpy(dir_0, selectPath);
dir_ = dir_0;
}
if (string(dir_).compare("/") == 0){
cout << "この階層が上限です" << endl;
return;
}
cout << "ダブルクリック後 dir_ " << dir_ << endl;
selectPath[0] = '\0';
return;
}
//選択ディレクトリ名を表示
inputFileName->value("");
inputFileName->value(selectPath);
// カレントディレクトリdir_確認
cout << "dir_ " << dir_ << endl;
selectPath[0] = '\0';
}
void btnOKCB(Fl_Return_Button*, void*)
{
const char* dir = inputFileName->value();
dirInput->value(dir);
chooser->Fl_Window::hide();
}