<commit_before>BrowserIpc = require('remote').require('ipc')
RendererIpc = require('ipc')

{$, View} = require 'atom'
_ = require 'underscore-plus'
TabView = require './tab-view'

module.exports =
class TabBarView extends View
  @content: ->
    @ul tabindex: -1, class: "list-inline tab-bar inset-panel"

  initialize: (@pane) ->
    @command 'tabs:close-tab', => @closeTab()
    @command 'tabs:close-other-tabs', => @closeOtherTabs()
    @command 'tabs:close-tabs-to-right', => @closeTabsToRight()

    @on 'dragstart', '.sortable', @onDragStart
    @on 'dragend', '.sortable', @onDragEnd
    @on 'dragleave', @onDragLeave
    @on 'dragover', @onDragOver
    @on 'drop', @onDrop

    @paneContainer = @pane.getContainer()
    @addTabForItem(item) for item in @pane.getItems()

    @subscribe @paneContainer, 'pane:removed', (pane) =>
      @unsubscribe() if pane is @pane

    @subscribe @pane, 'pane:item-added', (e, item, index) =>
      @addTabForItem(item, index)
      true

    @subscribe @pane, 'pane:item-moved', (e, item, index) =>
      @moveItemTabToIndex(item, index)
      true

    @subscribe @pane, 'pane:item-removed', (e, item) =>
      @removeTabForItem(item)
      true

    @subscribe @pane, 'pane:active-item-changed', =>
      @updateActiveTab()
      true

    @updateActiveTab()

    @on 'mousedown', '.tab', ({target, which, ctrlKey}) =>
      tab = $(target).closest('.tab').view()
      if which is 3 or (which is 1 and ctrlKey is true)
        @find('.right-clicked').removeClass('right-clicked')
        tab.addClass('right-clicked')
        false
      else if which is 2
        @pane.destroyItem(tab.item)
        false

    @on 'dblclick', ({target}) =>
      if target is @[0]
        @pane.trigger('application:new-file')
        false

    @on 'click', '.tab .close-icon', ({target}) =>
      tab = $(target).closest('.tab').view()
      @pane.destroyItem(tab.item)
      false

    @on 'click', '.tab', ({target, which}) =>
      tab = $(target).closest('.tab').view()
      if which is 1 and not target.classList.contains('close-icon')
        @pane.showItem(tab.item)
        @pane.focus()
        false

    RendererIpc.on('tab:dropped', @onDropOnOtherWindow)

    @pane.prepend(this)

  beforeRemove: ->
    RendererIpc.removeListener('tab:dropped', @onDropOnOtherWindow)

  addTabForItem: (item, index) ->
    @insertTabAtIndex(new TabView(item, @pane), index)

  moveItemTabToIndex: (item, index) ->
    tab = @tabForItem(item)
    tab.detach()
    @insertTabAtIndex(tab, index)

  insertTabAtIndex: (tab, index) ->
    followingTab = @tabAtIndex(index) if index?
    if followingTab
      tab.insertBefore(followingTab)
    else
      @append(tab)
    tab.updateTitle()

  removeTabForItem: (item) ->
    @tabForItem(item).remove()
    tab.updateTitle() for tab in @getTabs()

  getTabs: ->
    @children('.tab').toArray().map (elt) -> $(elt).view()

  tabAtIndex: (index) ->
    @children(".tab:eq(#{index})").view()

  tabForItem: (item) ->
    _.detect @getTabs(), (tab) -> tab.item is item

  setActiveTab: (tabView) ->
    if tabView? and not tabView.hasClass('active')
      @find(".tab.active").removeClass('active')
      tabView.addClass('active')

  updateActiveTab: ->
    @setActiveTab(@tabForItem(@pane.activeItem))

  closeTab: (tab) ->
    tab ?= @children('.right-clicked').view()
    @pane.destroyItem(tab.item)

  closeOtherTabs: ->
    tabs = @getTabs()
    active = @children('.right-clicked').view()
    return unless active?
    @closeTab tab for tab in tabs when tab isnt active

  closeTabsToRight: ->
    tabs = @getTabs()
    active = @children('.right-clicked').view()
    index = tabs.indexOf(active)
    return if index is -1
    @closeTab tab for tab, i in tabs when i > index

  getProcessId: ->
    @processId ?= atom.getCurrentWindow().getProcessId()

  getRoutingId: ->
    @routingId ?= atom.getCurrentWindow().getRoutingId()

  onDragStart: (event) =>
    event.originalEvent.dataTransfer.setData 'atom-event', 'true'

    el = $(event.target).closest('.sortable')
    el.addClass 'is-dragging'
    event.originalEvent.dataTransfer.setData 'sortable-index', el.index()

    pane = $(event.target).closest('.pane')
    paneIndex = @paneContainer.indexOfPane(pane)
    event.originalEvent.dataTransfer.setData 'from-pane-index', paneIndex
    event.originalEvent.dataTransfer.setData 'from-process-id', @getProcessId()
    event.originalEvent.dataTransfer.setData 'from-routing-id', @getRoutingId()

    item = @pane.getItems()[el.index()]
    if item.getPath?
      event.originalEvent.dataTransfer.setData 'text/uri-list', 'file://' + item.getPath()
      event.originalEvent.dataTransfer.setData 'text/plain', item.getPath()

  onDragLeave: (event) =>
    @removePlaceholderElement()

  onDragEnd: (event) =>
    @find('.is-dragging').removeClass('is-dragging')
    @removeDropTargetClasses()
    @removePlaceholderElement()

  onDragOver: (event) =>
    unless event.originalEvent.dataTransfer.getData('atom-event') is 'true'
      event.preventDefault()
      event.stopPropagation()
      return

    event.preventDefault()
    newDropTargetIndex = @getDropTargetIndex(event)
    return unless newDropTargetIndex?

    @removeDropTargetClasses()

    tabBar = @getTabBar(event.target)
    sortableObjects = tabBar.find(".sortable")

    if newDropTargetIndex < sortableObjects.length
      el = sortableObjects.eq(newDropTargetIndex).addClass 'is-drop-target'
      @getPlaceholderElement().insertBefore(el)
    else
      el = sortableObjects.eq(newDropTargetIndex - 1).addClass 'drop-target-is-after'
      @getPlaceholderElement().insertAfter(el)

  onDropOnOtherWindow: (fromItemIndex, fromPaneIndex) =>
    if fromPane = @paneContainer.paneAtIndex(fromPaneIndex)
      if item = fromPane.itemAtIndex(fromItemIndex)
        fromPane.removeItem(item)

    @clearDropTarget()

  clearDropTarget: ->
    @find(".is-dragging").removeClass 'is-dragging'
    @removeDropTargetClasses()
    @removePlaceholderElement()

  onDrop: (event) =>
    event.preventDefault()
    event.stopPropagation()
    {dataTransfer} = event.originalEvent

    return unless dataTransfer.getData('atom-event') is 'true'

    fromProcessId = parseInt(dataTransfer.getData('from-process-id'))
    fromRoutingId = parseInt(dataTransfer.getData('from-routing-id'))
    fromIndex     = parseInt(dataTransfer.getData('sortable-index'))
    fromPaneIndex = parseInt(dataTransfer.getData('from-pane-index'))

    @clearDropTarget()

    if fromProcessId is @getProcessId()
      fromPane = @paneContainer.paneAtIndex(fromPaneIndex)
      toIndex = @getDropTargetIndex(event)
      toPane = $(event.target).closest('.pane').view()
      {item} = fromPane.find(".tab-bar .sortable:eq(#{fromIndex})").view() ? {}
      @moveItemBetweenPanes(fromPane, fromIndex, toPane, toIndex, item) if item?
    else
      if droppedPath = dataTransfer.getData('text/plain')<commit_msg>Check that event is from correct pane<commit_after>BrowserIpc = require('remote').require('ipc')
RendererIpc = require('ipc')

{$, View} = require 'atom'
_ = require 'underscore-plus'
TabView = require './tab-view'

module.exports =
class TabBarView extends View
  @content: ->
    @ul tabindex: -1, class: "list-inline tab-bar inset-panel"

  initialize: (@pane) ->
    @command 'tabs:close-tab', => @closeTab()
    @command 'tabs:close-other-tabs', => @closeOtherTabs()
    @command 'tabs:close-tabs-to-right', => @closeTabsToRight()

    @on 'dragstart', '.sortable', @onDragStart
    @on 'dragend', '.sortable', @onDragEnd
    @on 'dragleave', @onDragLeave
    @on 'dragover', @onDragOver
    @on 'drop', @onDrop

    @paneContainer = @pane.getContainer()
    @addTabForItem(item) for item in @pane.getItems()

    @subscribe @paneContainer, 'pane:removed', (pane) =>
      @unsubscribe() if pane is @pane

    @subscribe @pane, 'pane:item-added', (e, item, index) =>
      @addTabForItem(item, index)
      true

    @subscribe @pane, 'pane:item-moved', (e, item, index) =>
      @moveItemTabToIndex(item, index)
      true

    @subscribe @pane, 'pane:item-removed', (e, item) =>
      @removeTabForItem(item)
      true

    @subscribe @pane, 'pane:active-item-changed', =>
      @updateActiveTab()
      true

    @updateActiveTab()

    @on 'mousedown', '.tab', ({target, which, ctrlKey}) =>
      tab = $(target).closest('.tab').view()
      if which is 3 or (which is 1 and ctrlKey is true)
        @find('.right-clicked').removeClass('right-clicked')
        tab.addClass('right-clicked')
        false
      else if which is 2
        @pane.destroyItem(tab.item)
        false

    @on 'dblclick', ({target}) =>
      if target is @[0]
        @pane.trigger('application:new-file')
        false

    @on 'click', '.tab .close-icon', ({target}) =>
      tab = $(target).closest('.tab').view()
      @pane.destroyItem(tab.item)
      false

    @on 'click', '.tab', ({target, which}) =>
      tab = $(target).closest('.tab').view()
      if which is 1 and not target.classList.contains('close-icon')
        @pane.showItem(tab.item)
        @pane.focus()
        false

    RendererIpc.on('tab:dropped', @onDropOnOtherWindow)

    @pane.prepend(this)

  beforeRemove: ->
    RendererIpc.removeListener('tab:dropped', @onDropOnOtherWindow)

  addTabForItem: (item, index) ->
    @insertTabAtIndex(new TabView(item, @pane), index)

  moveItemTabToIndex: (item, index) ->
    tab = @tabForItem(item)
    tab.detach()
    @insertTabAtIndex(tab, index)

  insertTabAtIndex: (tab, index) ->
    followingTab = @tabAtIndex(index) if index?
    if followingTab
      tab.insertBefore(followingTab)
    else
      @append(tab)
    tab.updateTitle()

  removeTabForItem: (item) ->
    @tabForItem(item).remove()
    tab.updateTitle() for tab in @getTabs()

  getTabs: ->
    @children('.tab').toArray().map (elt) -> $(elt).view()

  tabAtIndex: (index) ->
    @children(".tab:eq(#{index})").view()

  tabForItem: (item) ->
    _.detect @getTabs(), (tab) -> tab.item is item

  setActiveTab: (tabView) ->
    if tabView? and not tabView.hasClass('active')
      @find(".tab.active").removeClass('active')
      tabView.addClass('active')

  updateActiveTab: ->
    @setActiveTab(@tabForItem(@pane.activeItem))

  closeTab: (tab) ->
    tab ?= @children('.right-clicked').view()
    @pane.destroyItem(tab.item)

  closeOtherTabs: ->
    tabs = @getTabs()
    active = @children('.right-clicked').view()
    return unless active?
    @closeTab tab for tab in tabs when tab isnt active

  closeTabsToRight: ->
    tabs = @getTabs()
    active = @children('.right-clicked').view()
    index = tabs.indexOf(active)
    return if index is -1
    @closeTab tab for tab, i in tabs when i > index

  getProcessId: ->
    @processId ?= atom.getCurrentWindow().getProcessId()

  getRoutingId: ->
    @routingId ?= atom.getCurrentWindow().getRoutingId()

  onDragStart: (event) =>
    event.originalEvent.dataTransfer.setData 'atom-event', 'true'

    el = $(event.target).closest('.sortable')
    el.addClass 'is-dragging'
    event.originalEvent.dataTransfer.setData 'sortable-index', el.index()

    pane = $(event.target).closest('.pane')
    paneIndex = @paneContainer.indexOfPane(pane)
    event.originalEvent.dataTransfer.setData 'from-pane-index', paneIndex
    event.originalEvent.dataTransfer.setData 'from-process-id', @getProcessId()
    event.originalEvent.dataTransfer.setData 'from-routing-id', @getRoutingId()

    item = @pane.getItems()[el.index()]
    if item.getPath?
      event.originalEvent.dataTransfer.setData 'text/uri-list', 'file://' + item.getPath()
      event.originalEvent.dataTransfer.setData 'text/plain', item.getPath()

  onDragLeave: (event) =>
    @removePlaceholderElement()

  onDragEnd: (event) =>
    @find('.is-dragging').removeClass('is-dragging')
    @removeDropTargetClasses()
    @removePlaceholderElement()

  onDragOver: (event) =>
    unless event.originalEvent.dataTransfer.getData('atom-event') is 'true'
      event.preventDefault()
      event.stopPropagation()
      return

    event.preventDefault()
    newDropTargetIndex = @getDropTargetIndex(event)
    return unless newDropTargetIndex?

    @removeDropTargetClasses()

    tabBar = @getTabBar(event.target)
    sortableObjects = tabBar.find(".sortable")

    if newDropTargetIndex < sortableObjects.length
      el = sortableObjects.eq(newDropTargetIndex).addClass 'is-drop-target'
      @getPlaceholderElement().insertBefore(el)
    else
      el = sortableObjects.eq(newDropTargetIndex - 1).addClass 'drop-target-is-after'
      @getPlaceholderElement().insertAfter(el)

  onDropOnOtherWindow: (fromItemIndex, fromPaneIndex) =>
    fromPane = @paneContainer.paneAtIndex(fromPaneIndex)
    return unless @pane.is(fromPane)

    if itemToRemove = fromPane.itemAtIndex(fromItemIndex)
      fromPane.removeItem(itemToRemove)

    @clearDropTarget()

  clearDropTarget: ->
    @find(".is-dragging").removeClass 'is-dragging'
    @removeDropTargetClasses()
    @removePlaceholderElement()

  onDrop: (event) =>
    event.preventDefault()
    event.stopPropagation()
    {dataTransfer} = event.originalEvent

    return unless dataTransfer.getData('atom-event') is 'true'

    fromProcessId = parseInt(dataTransfer.getData('from-process-id'))
    fromRoutingId = parseInt(dataTransfer.getData('from-routing-id'))
    fromIndex     = parseInt(dataTransfer.getData('sortable-index'))
    fromPaneIndex = parseInt(dataTransfer.getData('from-pane-index'))

    @clearDropTarget()

    if fromProcessId is @getProcessId()
      fromPane = @paneContainer.paneAtIndex(fromPaneIndex)
      toIndex = @getDropTargetIndex(event)
      toPane = $(event.target).closest('.pane').view()
      {item} = fromPane.find(".tab-bar .sortable:eq(#{fromIndex})").view() ? {}
      @moveItemBetweenPanes(fromPane, fromIndex, toPane, toIndex, item) if item?
    else
      if droppedPath = dataTransfer.getData('text/plain')
{'fraction_non_alphanumeric': 0.15271891387112996, 'fraction_numerical': 0.0011493427196322104, 'mean_word_length': 3.5601048149361283, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4703651', 'n_tokens_mistral': 4579, 'n_tokens_neox': 4490, 'n_words': 849}