all files / ui/ SurfaceManager.js

82.35% Statements 28/34
78.26% Branches 18/23
77.78% Functions 7/9
87.5% Lines 28/32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110          206× 206× 206×       206× 206×                           1870× 1870×                   1665× 1436×                               295×                 12× 12×           12× 12× 12× 12× 12×           557× 557× 557×       557×                 557× 557×   557× 557×   344× 344×            
import { platform } from '../util'
 
class SurfaceManager {
 
  constructor(editorSession) {
    this.editorSession = editorSession
    this.surfaces = {}
    this._state = {
      focusedSurfaceId: null,
      selection: null,
    }
    editorSession.onUpdate('selection', this._onSelectionChanged, this)
    editorSession.onPostRender(this._recoverDOMSelection, this)
  }
 
  dispose() {
    this.editorSession.off(this)
  }
 
  /**
   * Get Surface instance
   *
   * @param {String} name Name under which the surface is registered
   * @return {ui/Surface} The surface instance
   */
  getSurface(name) {
    Eif (name) {
      return this.surfaces[name]
    }
  }
 
  /**
   * Get the currently focused Surface.
   *
   * @return {ui/Surface} Surface instance
   */
  getFocusedSurface() {
    if (this._state.focusedSurfaceId) {
      return this.getSurface(this._state.focusedSurfaceId)
    }
  }
 
  getSurfaces() {
    // HACK: not yet. we would need a polyfill
    // return Object.values(this.surfaces)
    return Object.keys(this.surfaces).map(key => this.surfaces[key])
  }
 
  /**
   * Register a surface
   *
   * @param surface {ui/Surface} A new surface instance to register
   */
  registerSurface(surface) {
    this.surfaces[surface.getId()] = surface
  }
 
  /**
   * Unregister a surface
   *
   * @param surface {ui/Surface} A surface instance to unregister
   */
  unregisterSurface(surface) {
    surface.off(this)
    let surfaceId = surface.getId()
    // TODO: this is not working, has side-effects
    // with inline-nodes (see #985)
    // if (surface === this.getFocusedSurface()) {
    //   this.editorSession.setSelection(null)
    // }
    let registeredSurface = this.surfaces[surfaceId]
    Eif (registeredSurface === surface) {
      let focusedSurface = this.getFocusedSurface()
      delete this.surfaces[surfaceId]
      if (surface && focusedSurface === surface) {
        this._state.focusedSurfaceId = null
      }
    }
  }
 
  _onSelectionChanged(selection) {
    const state = this._state
    state.selection = selection
    state.focusedSurfaceId = selection.surfaceId
    // HACK: removing DOM selection *and* blurring when having a CustomSelection
    // otherwise we will receive events on the wrong surface
    // instead of bubbling up to GlobalEventManager
    Iif (selection && selection.isCustomSelection() && platform.inBrowser) {
      window.getSelection().removeAllRanges()
      window.document.activeElement.blur()
    }
  }
 
  _recoverDOMSelection() {
    // at the end of the update flow, make sure the surface is focused
    // and displays the right DOM selection.
    let info = this.editorSession.getChangeInfo() || {}
    Iif (info.skipSelectionRerender) return
 
    let focusedSurface = this.getFocusedSurface()
    if (focusedSurface && !focusedSurface.isDisabled()) {
      // console.log('Rendering selection on surface', focusedSurface.getId(), this.editorSession.getSelection().toString());
      focusedSurface.focus()
      focusedSurface.rerenderDOMSelection()
    }
  }
}
 
export default SurfaceManager