Detecting when the Tree View is visible


#1

Since Atom got Docks my package no-title-bar has had an issue that I can’t figure out how to resolve. Previously I added some horizontal space to the left of the tab-bar whenever the tree-view was hidden. This prevented the traffic lights from overlaying on top of the first tab in the tab-bar. This is how I did it:

atom-panel-container.left:empty + atom-workspace-axis.vertical
  .pane:nth-child(1)
  .tab-bar
{
  padding-left: 80px;
}

So we add some padding to the first pane’s tab-bar (this prevents adding the space whenever we have a split view) whenever we’ve got an empty left panel container directly followed by a vertical axis workspace. And this worked beautifully!

However it doesn’t work at all with Docks. No longer is the atom-panel-container.left empty. Instead it’s width is reduced to 0px and it’s got some elements in it:

<atom-panel-container class="left">
  <atom-dock class="left">
    <div class"atom-dock-inner left">...</div>
  </atom-dock>
</atom-panel-container>

Now if we make the tree-view visible, this changes slightly:

<atom-panel-container class="left">
  <atom-dock class="left">
    <div class"atom-dock-inner left atom-dock-open">...</div>
  </atom-dock>
</atom-panel-container>

Ah, see now, we’ve added the class atom-dock-open to an inner element. But this totally breaks the CSS I’ve been using to detect and add horizontal space to the tab-bar whenever the tree-view is hidden. I need something like:

atom-panel-container.left(but only when it contains atom-dock.left > .atom-dock-inner:not(.atom-dock-open)) + atom-workspace-axis.vertical
  .pane:nth-child(1)
  .tab-bar
{
  padding-left: 80px;
}

But of course there isn’t really a way to do that with CSS :frowning:

I’ve looked at this issue for a few days now and I really don’t see a way to resolve this. It’d be nice if Atom applied some class to the atom-panel-container element itself instead of just to an inner element of the container. Then I could key off of that very easily. Alas this is not the case. I’m starting to wonder if the only solution now is to do something with JavaScript… which would suck because up till now I’ve been able to solve this with simple CSS.


#2

So I came up with a JavaScript based solution using MutationObserver which is maybe overkill? I did a quick survey of the packages I have installed and those that come with Atom and no one else is using MutationObserver. Also the latest Atom blog post indicates that use of MutationObserver could be a potential performance drain. However I have no way how to do this otherwise.

  1. During package activation, install an observer on pane items: paneSub = atom.workspace.observePaneItems(handlePaneItem)
  2. In the handlePaneItem() function, look for an item where item.constructor.name === 'TreeView'.
  3. When we see that, install the MutationObserver like so:
    observer = new MutationObserver(mutationHandler)
    selector = 'atom-panel-container.left > atom-dock.left > .atom-dock-inner'
    element = document.querySelector(selector)
    observer.observe(element, { attributes: true })

We can also unhook the pane items observer now that the mutation observer is installed: paneSub.dispose().

Now, in the mutationHanlder() function we can detect when the Tree View is visible: isVisible = element.classList.contains('atom-dock-open')

This works no matter if the user toggles the Tree View via command, mouse, or keyboard shortcut. No other method I’ve discovered works as well as this.

Still, I think it would be preferable if this could be done with simple CSS instead. If only the atom-dock-open or some other class could be applied to a DOM element higher in the hierarchy :frowning: