How to close current and select left tab?

We want to improve our workflow a little bit and need to forcly select the left tab after closing the current tab.

In other words closing the active tab (in brackets) should lead to the given result:

[A] B C -> [B] C
A [B] C -> [A] C
A B [C] -> A [B]

I already have played around with the improved TABCLOSE / TABSELECT keywords of the Go command but unfortunately I haven't found any obvious solution. It seems that after a TABCLOSE the most recent tab (left or right) is automatically activated. Therefore a TABSELECT can not be reliable used. On the other hand the scripting interface doesn't provide the tab index as property (to keep it in mind for later selection)?

I guess there is an easy solution and I am not seeing that in the moment ...

Thank you very much for any help!

You can loop over the existing tabs by looking at the tab collections of a lister object to get their index.

But I'm not sure what the experience is like, when a tab is closed, the previously active tab gets activated automatically by DO and then another tab gets activated by a script. That could end up in some nervous GUI magic. Maybe preventing the actual tab to close from closing (can be done in OnTabClose()), activating the desired previous tab by index first and then closing the tab to be closed is a better approach. The tab to close does not have focus anymore, so closing it should not result in automatic switching of tabs by DO.

Ok, thanks for the hint. I gave that a short try but unfortunately the "Go TABCLOSE " command ignores the index instead the active tab is closed. On the other hand the == operator doesn't work for the source tab object and the objects from the lister collection (seems to be different tab objects). I have to build a string using the default value of the tab object as workaround to allow a text comparison.

Use Go TABCLOSE PATH=n to close the tab at index n.

(The examples in the manual for "Go TABCLOSE n" were missing the explicit PATH=, which is wrong. "Go TABCLOSE n" is interpreted as "Go TABCLOSE=n". "Go n TABCLOSE" would work, while "Go PATH=n TABCLOSE" or "Go TABCLOSE PATH=n" mean the same thing but in a clearer way. I've done an edit to the manual to correct this.)

In a script you can also pass the tab object itself to close that tab (this is given to the TABCLOSE arg, not the PATH arg, unlike the index).

I think this does what you want. Most of the code is just to handle the case where you close the leftmost tab.

Function OnClick(ClickData)
	Set cmd = ClickData.Func.Command
	Set tab = ClickData.Func.SourceTab
	If tab.right Then
		Set tabs = tab.lister.tabsright
	Else
		Set tabs = tab.lister.tabsleft
	End If
	If tab <> tabs(0) Then
	    cmd.AddLine "Go TABSELECT=-1"
	Else
	    cmd.AddLine "Go TABSELECT=+1"
	End If
	cmd.AddLine "Go TABCLOSE=" & tab
	cmd.Run
End Function

I think you can also try calling command.SetSourceTab( tabToClose ); and then command.RunCommand("Go TABCLOSE"); if the index in conbination with TABCLOSE does not work.

Comparing tab-"objects" I tend to do like this, which string-compares without much hassle.

if (sibTab+""==""+tab){ //same }

EDIT: Leos post popped in right before "submitting".. clearing the TABCLOSE issue, thanks! o)

Yes, thanks so much for your help. Leo's version looks much cleaner than mine (see below). I will translate Leo's version to JScript and use it...

function findTab(tabs, tab) {
	for (i = 0; i < tabs.Count; i++) {
		if ("" + tabs(i) == "" + tab) {
			return i;
		}
	}
	return -1;
}

function indexOfTab(tab) {
	if (tab.right) {
		return findTab(tab.lister.tabsright, tab);
	} else {
		return findTab(tab.lister.tabsleft, tab);
	}
}

function closeTab(tab, command) {
	var index = indexOfTab(tab);
	if (index >= 0) {
		command.RunCommand(
			"Go TABSELECT " 
			+ (index > 0 ? index - 1 : index + 1)
			+ (tab.source ? "" : " OPENINDUAL")
		);
		command.RunCommand(
			"Go TABCLOSE " 
			+ tab
			+ (tab.source ? "" : " OPENINDUAL")
		);
	}
}

function OnClick(clickData) {
	closeTab(clickData.func.sourcetab, clickData.func.command);
}

Here is the JScript version that also can be used for dual display lister.

function closeTab(tab, cmd) {
	var tabs = tab.right ? tab.lister.tabsright : tab.lister.tabsleft;
	var dual = !tab.source ? " OPENINDUAL" : "";
	if ("" + tab == "" + tabs(0)) {
		cmd.AddLine("Go TABSELECT=+1" + dual);
	} else {
		cmd.AddLine("Go TABSELECT=-1" + dual);
	}
	cmd.AddLine("Go TABCLOSE=" + tab + dual);
	cmd.Run;
}

function OnClick(clickData) {
	closeTab(clickData.func.sourcetab, clickData.func.command);
//	closeTab(clickData.func.desttab, clickData.func.command);
}

So you use a button to close tabs from now on? Isn't that inconvenient a bit?

No, our configuration doesn't rely on buttons (see screenshot). We have hotkeys for everything. :slight_smile:

The script is bound to CTRL+W and CTRL+ALT+W to close active tab of source / destination splitter.


I meant "we do not use action buttons at all" but obviously we have a lot of drive and folder buttons. :slight_smile:

Here is a litle event based version, it should work with standard hotkeys and commands and also works by mouse.
Save as "Event.GUI_ActivateLeftTabOnClose.js" to "script addins" and try it if you are in an adventurous mood. o)

Your sentence "to close active tab of source / destination splitter.." made me wonder if there's something missing
in this solution for you. Well, at least I had a little finger exercise then. o)

///////////////////////////////////////////////////////////////////////////////
function OnInit(data){
	data.name = "Event.GUI: ActivateLeftTabOnClose";
	data.default_enable = true;
}
///////////////////////////////////////////////////////////////////////////////
function OnCloseTab(data) {
	var cmd = DOpus.Create.Command();
	cmd.SetSourceTab(data.tab);
	CloseTab(data.tab, cmd);
	return true;
}
///////////////////////////////////////////////////////////////////////////////
function CloseTab(tab, command) {
	var index = GetIndexOfTab(tab);
	if (index===null) return;
	command.RunCommand("Go NOSCRIPT TABSELECT " + (index>0?index-1:index+1));
	command.RunCommand("Go NOSCRIPT TABCLOSE  " + tab );
}
///////////////////////////////////////////////////////////////////////////////
function GetIndexOfTab(tab){
	var tabs = tab.lister.tabsleft;
	if (tab.right) tabs = tab.lister.tabsright;
	for (var i=0;i<tabs.count;i++)
		if (tabs(i)+""==""+tab) return i;
	return null;
}

Actually I'm already trying around with this. Interesting, thank you for bringing this together using events.

Be cautious, I managed to create some endless loops with the OnCloseTab() event, when not using "Go NOSCRIPT..". Thank gods (I mean Jon and Leo o), the NOSCRIPT kicks in here too, though it's not mentioned in the docs.

Using +1 and -1 for the TABSELECT thing did not work out for me, when trying it with the event, especially when closing inactive tabs by mouse, weird things happened (like all tabs dissapearing, then coming back alltogether when opening a new one). Edgy stuff! o)

May I ask what your impression is? Did you try my version for some time, does it work or did you write your own, adjusted mine?
If this is something that's working stable, then it might be worth to be added to the add-ins section, what do you think?

I have used that for some time (I have 2-3 freezes but can't say if it were related to a script). Finally I switched over to a dedicated command because it is more obvious in our configuration.

function closeTab(tab, cmd) {
	if (tab.lock == "off") {
		var tabs = tab.right ? tab.lister.tabsright : tab.lister.tabsleft;
		var dual = !tab.source ? " OPENINDUAL" : "";
		if ("" + tab == "" + tabs(0)) {
			cmd.AddLine("Go TABSELECT=+1" + dual);
		} else {
			cmd.AddLine("Go TABSELECT=-1" + dual);
		}
		cmd.AddLine("Go TABCLOSE=" + tab + dual);
		cmd.AddLine("Set SOURCE=Focus");
		cmd.Run();
	}
}

function OnClick(clickData) {
	closeTab(clickData.func.sourcetab, clickData.func.command);
}

I uploaded another version of the event-based prototype we did back in january, maybe you like to give it another try. While using it over the last couple of month I came across weird situations when closing tabs, that were not active or not connected to the source file-display. These topcis have been addressed and since then, I found it to work stable.
ActivateLeftTabOnClose: Event: ActivateLeftTabOnClose (switch to left instead of previously used tab)

I modified tbone's script a bit to perform ActivateRightTabOnClose instead, in case anyone prefers having the right adjacent tab focused upon closing a tab instead the most recent (default) or the left adjacent tab.
Event.GUI_ActivateRightTabOnClose.js.txt (8.4 KB)