<commit_before>{deprecate} = require 'grim'
_ = require 'underscore-plus'
path = require 'path'
{join} = path
{Model} = require 'theorist'
Q = require 'q'
Serializable = require 'serializable'
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
Grim = require 'grim'
fs = require 'fs-plus'
StackTraceParser = require 'stacktrace-parser'
TextEditor = require './text-editor'
PaneContainer = require './pane-container'
Pane = require './pane'
Panel = require './panel'
PanelElement = require './panel-element'
PanelContainer = require './panel-container'
PanelContainerElement = require './panel-container-element'
WorkspaceElement = require './workspace-element'
Task = require './task'

# Essential: Represents the state of the user interface for the entire window.
# An instance of this class is available via the `atom.workspace` global.
#
# Interact with this object to open files, be notified of current and future
# editors, and manipulate panes. To add panels, you'll need to use the
# {WorkspaceView} class for now until we establish APIs at the model layer.
#
# * `editor` {TextEditor} the new editor
#
module.exports =
class Workspace extends Model
  atom.deserializers.add(this)
  Serializable.includeInto(this)

  Object.defineProperty @::, 'activePaneItem',
    get: ->
      Grim.deprecate "Use ::getActivePaneItem() instead of the ::activePaneItem property"
      @getActivePaneItem()

  Object.defineProperty @::, 'activePane',
    get: ->
      Grim.deprecate "Use ::getActivePane() instead of the ::activePane property"
      @getActivePane()

  @properties
    paneContainer: null
    fullScreen: false
    destroyedItemURIs: -> []

  constructor: (params) ->
    super

    @emitter = new Emitter
    @openers = []

    @paneContainer ?= new PaneContainer()
    @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem)

    @panelContainers =
      top: new PanelContainer({location: 'top'})
      left: new PanelContainer({location: 'left'})
      right: new PanelContainer({location: 'right'})
      bottom: new PanelContainer({location: 'bottom'})
      modal: new PanelContainer({location: 'modal'})

    @subscribeToActiveItem()

    @addOpener (filePath) ->
      switch filePath
        when 'atom://.atom/stylesheet'
          atom.project.open(atom.styles.getUserStyleSheetPath())
        when 'atom://.atom/keymap'
          atom.project.open(atom.keymaps.getUserKeymapPath())
        when 'atom://.atom/config'
          atom.project.open(atom.config.getUserConfigPath())
        when 'atom://.atom/init-script'
          atom.project.open(atom.getUserInitScriptPath())

    atom.views.addViewProvider Workspace, (model) ->
      new WorkspaceElement().initialize(model)

    atom.views.addViewProvider PanelContainer, (model) ->
      new PanelContainerElement().initialize(model)

    atom.views.addViewProvider Panel, (model) ->
      new PanelElement().initialize(model)

  # Called by the Serializable mixin during deserialization
  deserializeParams: (params) ->
    for packageName in params.packagesWithActiveGrammars ? []
      atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()

    params.paneContainer = PaneContainer.deserialize(params.paneContainer)
    params

  # Called by the Serializable mixin during serialization.
  serializeParams: ->
    paneContainer: @paneContainer.serialize()
    fullScreen: atom.isFullScreen()
    packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()

  getPackageNamesWithActiveGrammars: ->
    packageNames = []
    addGrammar = ({includedGrammarScopes, packageName}={}) ->
      return unless packageName
      # Prevent cycles
      return if packageNames.indexOf(packageName) isnt -1

      packageNames.push(packageName)
      for scopeName in includedGrammarScopes ? []
        addGrammar(atom.grammars.grammarForScopeName(scopeName))

    editors = @getTextEditors()
    addGrammar(editor.getGrammar()) for editor in editors

    if editors.length > 0
      for grammar in atom.grammars.getGrammars() when grammar.injectionSelector
        addGrammar(grammar)

    _.uniq(packageNames)

  editorAdded: (editor) ->
    @emit 'editor-created', editor

  installShellCommands: ->
    require('./command-installer').installShellCommandsInteractively()

  subscribeToActiveItem: ->
    @updateWindowTitle()
    @updateDocumentEdited()
    atom.project.onDidChangePaths @updateWindowTitle

    @observeActivePaneItem (item) =>
      @updateWindowTitle()
      @updateDocumentEdited()

      @activeItemSubscriptions?.dispose()
      @activeItemSubscriptions = new CompositeDisposable

      if typeof item?.onDidChangeTitle is 'function'
        titleSubscription = item.onDidChangeTitle(@updateWindowTitle)
      else if typeof item?.on is 'function'
        titleSubscription = item.on('title-changed', @updateWindowTitle)
        unless typeof titleSubscription?.dispose is 'function'
          titleSubscription = new Disposable => item.off('title-changed', @updateWindowTitle)

      if typeof item?.onDidChangeModified is 'function'
        modifiedSubscription = item.onDidChangeModified(@updateDocumentEdited)
      else if typeof item?.on? is 'function'
        modifiedSubscription = item.on('modified-status-changed', @updateDocumentEdited)
        unless typeof modifiedSubscription?.dispose is 'function'
          modifiedSubscription = new Disposable => item.off('modified-status-changed', @updateDocumentEdited)

      @activeItemSubscriptions.add(titleSubscription) if titleSubscription?
      @activeItemSubscriptions.add(modifiedSubscription) if modifiedSubscription?

  # Updates the application's title and proxy icon based on whichever file is
  # open.
  updateWindowTitle: =>
    appName = 'Atom'
    if projectPath = atom.project?.getPaths()[0]
      if item = @getActivePaneItem()
        document.title = "#{item.getTitle?() ? 'untitled'} - #{projectPath} - #{appName}"
        atom.setRepresentedFilename(item.getPath?() ? projectPath)
      else
        document.title = "#{projectPath} - #{appName}"
        atom.setRepresentedFilename(projectPath)
    else
      document.title = "untitled - #{appName}"
      atom.setRepresentedFilename('')

  # On OS X, fades the application window's proxy icon when the current file
  # has been modified.
  updateDocumentEdited: =>
    modified = @getActivePaneItem()?.isModified?() ? false
    atom.setDocumentEdited(modified)

  ###
  Section: Event Subscription<commit_msg>Use the right project path for document title<commit_after>{deprecate} = require 'grim'
_ = require 'underscore-plus'
path = require 'path'
{join} = path
{Model} = require 'theorist'
Q = require 'q'
Serializable = require 'serializable'
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
Grim = require 'grim'
fs = require 'fs-plus'
StackTraceParser = require 'stacktrace-parser'
TextEditor = require './text-editor'
PaneContainer = require './pane-container'
Pane = require './pane'
Panel = require './panel'
PanelElement = require './panel-element'
PanelContainer = require './panel-container'
PanelContainerElement = require './panel-container-element'
WorkspaceElement = require './workspace-element'
Task = require './task'

# Essential: Represents the state of the user interface for the entire window.
# An instance of this class is available via the `atom.workspace` global.
#
# Interact with this object to open files, be notified of current and future
# editors, and manipulate panes. To add panels, you'll need to use the
# {WorkspaceView} class for now until we establish APIs at the model layer.
#
# * `editor` {TextEditor} the new editor
#
module.exports =
class Workspace extends Model
  atom.deserializers.add(this)
  Serializable.includeInto(this)

  Object.defineProperty @::, 'activePaneItem',
    get: ->
      Grim.deprecate "Use ::getActivePaneItem() instead of the ::activePaneItem property"
      @getActivePaneItem()

  Object.defineProperty @::, 'activePane',
    get: ->
      Grim.deprecate "Use ::getActivePane() instead of the ::activePane property"
      @getActivePane()

  @properties
    paneContainer: null
    fullScreen: false
    destroyedItemURIs: -> []

  constructor: (params) ->
    super

    @emitter = new Emitter
    @openers = []

    @paneContainer ?= new PaneContainer()
    @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem)

    @panelContainers =
      top: new PanelContainer({location: 'top'})
      left: new PanelContainer({location: 'left'})
      right: new PanelContainer({location: 'right'})
      bottom: new PanelContainer({location: 'bottom'})
      modal: new PanelContainer({location: 'modal'})

    @subscribeToActiveItem()

    @addOpener (filePath) ->
      switch filePath
        when 'atom://.atom/stylesheet'
          atom.project.open(atom.styles.getUserStyleSheetPath())
        when 'atom://.atom/keymap'
          atom.project.open(atom.keymaps.getUserKeymapPath())
        when 'atom://.atom/config'
          atom.project.open(atom.config.getUserConfigPath())
        when 'atom://.atom/init-script'
          atom.project.open(atom.getUserInitScriptPath())

    atom.views.addViewProvider Workspace, (model) ->
      new WorkspaceElement().initialize(model)

    atom.views.addViewProvider PanelContainer, (model) ->
      new PanelContainerElement().initialize(model)

    atom.views.addViewProvider Panel, (model) ->
      new PanelElement().initialize(model)

  # Called by the Serializable mixin during deserialization
  deserializeParams: (params) ->
    for packageName in params.packagesWithActiveGrammars ? []
      atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()

    params.paneContainer = PaneContainer.deserialize(params.paneContainer)
    params

  # Called by the Serializable mixin during serialization.
  serializeParams: ->
    paneContainer: @paneContainer.serialize()
    fullScreen: atom.isFullScreen()
    packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()

  getPackageNamesWithActiveGrammars: ->
    packageNames = []
    addGrammar = ({includedGrammarScopes, packageName}={}) ->
      return unless packageName
      # Prevent cycles
      return if packageNames.indexOf(packageName) isnt -1

      packageNames.push(packageName)
      for scopeName in includedGrammarScopes ? []
        addGrammar(atom.grammars.grammarForScopeName(scopeName))

    editors = @getTextEditors()
    addGrammar(editor.getGrammar()) for editor in editors

    if editors.length > 0
      for grammar in atom.grammars.getGrammars() when grammar.injectionSelector
        addGrammar(grammar)

    _.uniq(packageNames)

  editorAdded: (editor) ->
    @emit 'editor-created', editor

  installShellCommands: ->
    require('./command-installer').installShellCommandsInteractively()

  subscribeToActiveItem: ->
    @updateWindowTitle()
    @updateDocumentEdited()
    atom.project.onDidChangePaths @updateWindowTitle

    @observeActivePaneItem (item) =>
      @updateWindowTitle()
      @updateDocumentEdited()

      @activeItemSubscriptions?.dispose()
      @activeItemSubscriptions = new CompositeDisposable

      if typeof item?.onDidChangeTitle is 'function'
        titleSubscription = item.onDidChangeTitle(@updateWindowTitle)
      else if typeof item?.on is 'function'
        titleSubscription = item.on('title-changed', @updateWindowTitle)
        unless typeof titleSubscription?.dispose is 'function'
          titleSubscription = new Disposable => item.off('title-changed', @updateWindowTitle)

      if typeof item?.onDidChangeModified is 'function'
        modifiedSubscription = item.onDidChangeModified(@updateDocumentEdited)
      else if typeof item?.on? is 'function'
        modifiedSubscription = item.on('modified-status-changed', @updateDocumentEdited)
        unless typeof modifiedSubscription?.dispose is 'function'
          modifiedSubscription = new Disposable => item.off('modified-status-changed', @updateDocumentEdited)

      @activeItemSubscriptions.add(titleSubscription) if titleSubscription?
      @activeItemSubscriptions.add(modifiedSubscription) if modifiedSubscription?

  # Updates the application's title and proxy icon based on whichever file is
  # open.
  updateWindowTitle: =>
    appName = 'Atom'
    projectPaths = atom.project?.getPaths() ? []
    if item = @getActivePaneItem()
      itemPath = item.getPath?()
      itemTitle = item.getTitle?()
      projectPath = _.find projectPaths, (projectPath) ->
        itemPath is projectPath or itemPath?.startsWith(projectPath + path.sep)
    itemTitle ?= "untitled"
    projectPath ?= projectPaths[0]

    if item? and projectPath?
      document.title = "#{itemTitle} - #{projectPath} - #{appName}"
      atom.setRepresentedFilename(itemPath ? projectPath)
    else if projectPath?
      document.title = "#{projectPath} - #{appName}"
      atom.setRepresentedFilename(projectPath)
    else
      document.title = "#{itemTitle} - #{appName}"
      atom.setRepresentedFilename("")

  # On OS X, fades the application window's proxy icon when the current file
  # has been modified.
  updateDocumentEdited: =>
    modified = @getActivePaneItem()?.isModified?() ? false
    atom.setDocumentEdited(modified)

  ###
  Section: Event Subscription
{'fraction_non_alphanumeric': 0.10768533212423487, 'fraction_numerical': 0.0004534119247336205, 'mean_word_length': 3.867230599485105, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 46, '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': '6774508', 'n_tokens_mistral': 3764, 'n_tokens_neox': 3671, 'n_words': 902}