// This is a script for Directory Opus. // See https://www.gpsoft.com.au/DScripts/redirect.asp?page=scripts for development information. // Called by Directory Opus to initialize the script function OnInit(initData) { initData.name = "Keep Selection"; initData.version = "1.0.2"; initData.copyright = "(c) 2023 Christian Arellano García"; // initData.url = "https://resource.dopus.com/c/buttons-scripts/16"; initData.desc = "Script Add-in to keep selection and focused item while navigating through folders"; initData.default_enable = true; initData.min_version = "13.0"; initData.config.debug = false; initData.config.ignored_paths = DOpus.Create.Vector(); initData.config.restore_mode = DOpus.Create.Vector(2, 'focus only', 'selected only', 'both selection and focus'); initData.config.max_paths = 2; initData.config.sel_first_if = true; initData.config_desc = DOpus.Create.Map('debug', 'Toggle debug mode', 'ignored_paths', 'Paths ignored by the script', 'restore_mode', 'Choose between restoring only the item with focus, the entire selection or both', 'max_paths', 'Maximum number of paths to be remembered', 'sel_first_if', 'Wheter to select first item or not when the path is not remembered'); } var cmd = DOpus.Create.Command(); // Called before a new folder is read in a tab function OnBeforeFolderChange(BFCD) { if (BFCD.initial) return; if (Script.config.max_paths < 2) return; Log("===OnBeforeFolderChange ON==="); Log("restore_mode : " + Script.config.restore_mode); var tab = BFCD.tab; Log("OBFC=>tab : " + tab.path + "\t\t---Type:" + DOpus.FSUtil.PathType(tab.path)); if (DOpus.FSUtil.PathType(tab.path) === 'shell') return; if (VectorExists(Script.config.ignored_paths, tab.path)) { Log("OBFC=>" + tab.path + ' is on the ignore paths list'); return; } var focus_item = (tab.GetFocusItem() != null && Script.config.restore_mode !== 1) ? String(tab.GetFocusItem()) : false; Log("OBFC=>Focused item : " + focus_item); Log("OBFC=>Selected : " + tab.selected.count); if (tab.selected.count == 0 && !focus_item) { Log("OBFC=>" + tab.path + ' will not be saved'); return; } var items = DOpus.Create.Vector(); if (Script.config.restore_mode > 0) { for (var i = 0; i < tab.selected.count; i++) { if (tab.selected(i) != focus_item) items.push_back(String(tab.selected(i))); } } //if focus only is set and exists selected items but not focus item, give focus to first selected if (!focus_item && Script.config.restore_mode == 0) focus_item = String(tab.selected(0)); items.push_back(focus_item); items.push_back(String(tab.path)); Log('OBFC=>Saving : ' + tab.path + "\t\t---Vector size:" + items.count); if (tab.lister.vars.Exists('paths')) { var paths = tab.lister.vars.Get('paths') //a vector // try { // Log(paths.count); // Log(DOpus.TypeOf(paths.front)); // Log(paths.front.count); // Log(paths.front.back); // if (paths.front.back == items.back) { // Log('OBFC=>last path is the same as current'); // paths.erase(0); // } // } // catch (e) { // Log('OBFC=>failed to compare with last path'); // }; paths.insert(0, items); if (paths.count > Script.config.max_paths) paths.resize(Script.config.max_paths); } else { var paths = DOpus.Create.Vector(); paths.push_back(items); } Log("OBFC=>paths length : " + paths.count); tab.lister.vars.Set('paths', paths); Log("===OnBeforeFolderChange OFF===:"); } // Called after a new folder is read in a tab function OnAfterFolderChange(AFCD) { if (!AFCD.result) return; Log("===OnAfterFolderChange ON==="); if (!AFCD.tab.lister.vars.Exists('paths')) { Log("OAFC=>var paths doesnt exists"); return; } var tab = AFCD.tab; if (Script.config.debug == true) showSavedPaths(tab.lister.vars.Get('paths')); Log("restore_mode : " + Script.config.restore_mode); Log("OAFC=>tab : " + tab.path + "\t\t---Type:" + DOpus.FSUtil.PathType(tab.path)); if (DOpus.FSUtil.PathType(tab.path) === 'shell') return; // cmd.RunCommand('Select NONE'); if (VectorExists(Script.config.ignored_paths, tab.path)) { Log('OAFC=>' + tab.path + ' is on the ignore paths list'); return; } cmd.ClearFiles(); cmd.SetSourceTab(tab); var items = VectorExistSub(tab.lister.vars.Get('paths'), String(tab.path)); if (items == null) { Log('OAFC=>' + tab.path + ' is not saved in paths'); //since we have to disable select first item in folder in preferences if (Script.config.sel_first_if) { Log('OAFC=>Selected : first item selected cause sel_first_if is enabled'); cmd.RunCommand('Select FIRST'); } //select first item for easy keyboard navigation afterwards return; } var focus = items.back; if (focus) { Log('OAFC=>Focus : ' + items.back); cmd.AddFile(items.back); cmd.RunCommand('Select FROMSCRIPT SETFOCUS'); } items.pop_back(); if (items.count > 0 && Script.config.restore_mode > 0) { cmd.SetFiles(items); Log('OAFC=>Selected : ' + cmd.filecount); if (focus) //no need for set focus cmd.RunCommand('Select FROMSCRIPT'); else cmd.RunCommand('Select FROMSCRIPT SETFOCUS'); } Log("===OnAfterFolderChange OFF===:"); } function Log(scriptCmd) { if (Script.config.debug == true) DOpus.Output(scriptCmd); } function VectorExists(vector, value) { for (var i = 0; i < vector.count; i++) if (vector(i) == value) return true; return false; }; function VectorExistSub(vector, value) { for (var i = 0; i < vector.count; i++) { sub = vector(i); if (sub.count == 0) continue; if (sub.back == value) { sub.pop_back(); Log('OAFC=>Founded : ' + value + '\t\t---Items saved: ' + sub.count); vector.erase(i); return sub; }; } return null; } function showSavedPaths(vector) { Log('============================'); for (var i = 0; i < vector.count; i++) { if (vector(i).count == 0) Log('SavedPaths : malformed path in position ' + i); else Log('SavedPaths : ' + vector(i).back); } Log('============================'); }