mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Use StyleManager and StylesElement to manage all stylesheet elements
For now, loading remains in the theme manager, but all application of stylesheets is routed through atom.styles.
This commit is contained in:
@@ -14,6 +14,7 @@ fs = require 'fs-plus'
|
||||
|
||||
{$} = require './space-pen-extensions'
|
||||
WindowEventHandler = require './window-event-handler'
|
||||
StylesElement = require './styles-element'
|
||||
|
||||
# Essential: Atom global for dealing with packages, themes, menus, and the window.
|
||||
#
|
||||
@@ -202,8 +203,8 @@ class Atom extends Model
|
||||
@keymap = @keymaps # Deprecated
|
||||
@commands = new CommandRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager({resourcePath})
|
||||
@contextMenu = new ContextMenuManager({resourcePath, devMode})
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@clipboard = new Clipboard()
|
||||
@@ -221,6 +222,8 @@ class Atom extends Model
|
||||
|
||||
@windowEventHandler = new WindowEventHandler
|
||||
|
||||
document.head.appendChild(new StylesElement)
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
@@ -31,14 +31,25 @@ class StyleManager
|
||||
updated = true
|
||||
else
|
||||
styleElement = document.createElement('style')
|
||||
styleElement.sourcePath = sourcePath if sourcePath?
|
||||
styleElement.group = group if group?
|
||||
styleElement.setAttribute('source-path', sourcePath) if sourcePath?
|
||||
styleElement.setAttribute('group', group) if group?
|
||||
|
||||
styleElement.textContent = source
|
||||
|
||||
if updated
|
||||
@emitter.emit 'did-update-style-element', styleElement
|
||||
else
|
||||
@addStyleElement(styleElement, params)
|
||||
|
||||
new Disposable => @removeStyleElement(styleElement)
|
||||
|
||||
addStyleElement: (styleElement, params) ->
|
||||
sourcePath = params?.sourcePath
|
||||
group = params?.group
|
||||
|
||||
if group?
|
||||
for existingElement, index in @styleElements
|
||||
if existingElement.group is group
|
||||
if existingElement.getAttribute('group') is group
|
||||
insertIndex = index + 1
|
||||
else
|
||||
break if insertIndex?
|
||||
@@ -46,22 +57,26 @@ class StyleManager
|
||||
|
||||
@styleElements.splice(insertIndex, 0, styleElement)
|
||||
@styleElementsBySourcePath[sourcePath] ?= styleElement if sourcePath?
|
||||
|
||||
if updated
|
||||
@emitter.emit 'did-update-style-element', styleElement
|
||||
else
|
||||
@emitter.emit 'did-add-style-element', styleElement
|
||||
|
||||
new Disposable => @removeStyleElement(styleElement, params)
|
||||
@emitter.emit 'did-add-style-element', styleElement
|
||||
|
||||
removeStyleElement: (styleElement, params) ->
|
||||
index = @styleElements.indexOf(styleElement)
|
||||
unless index is -1
|
||||
@styleElements.splice(index, 1)
|
||||
sourcePath = params?.sourcePath
|
||||
delete @styleElementsBySourcePath[sourcePath] if sourcePath?
|
||||
if sourcePath = styleElement.getAttribute('source-path')
|
||||
delete @styleElementsBySourcePath[sourcePath]
|
||||
@emitter.emit 'did-remove-style-element', styleElement
|
||||
|
||||
clear: ->
|
||||
@styleElements = []
|
||||
@styleElementsBySourcePath = {}
|
||||
getSnapshot: ->
|
||||
@styleElements.slice()
|
||||
|
||||
restoreSnapshot: (styleElementsToRestore) ->
|
||||
for styleElement in @getStyleElements()
|
||||
@removeStyleElement(styleElement) unless styleElement in styleElementsToRestore
|
||||
|
||||
existingStyleElements = @getStyleElements()
|
||||
for styleElement in styleElementsToRestore
|
||||
unless styleElement in existingStyleElements
|
||||
sourcePath = styleElement.getAttribute('source-path')
|
||||
group = styleElement.getAttribute('group')
|
||||
@addStyleElement(styleElement, {sourcePath, group})
|
||||
|
||||
@@ -8,14 +8,13 @@ class StylesElement extends HTMLElement
|
||||
@subscriptions.add atom.styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this))
|
||||
|
||||
styleElementAdded: (styleElement) ->
|
||||
{group} = styleElement
|
||||
styleElementClone = styleElement.cloneNode(true)
|
||||
styleElementClone.group = group
|
||||
@styleElementClonesByOriginalElement.set(styleElement, styleElementClone)
|
||||
|
||||
group = styleElement.getAttribute('group')
|
||||
if group?
|
||||
for child in @children
|
||||
if child.group is group and child.nextSibling?.group isnt group
|
||||
if child.getAttribute('group') is group and child.nextSibling?.getAttribute('group') isnt group
|
||||
insertBefore = child.nextSibling
|
||||
break
|
||||
|
||||
|
||||
@@ -19,10 +19,42 @@ class ThemeManager
|
||||
|
||||
constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) ->
|
||||
@emitter = new Emitter
|
||||
@styleSheetDisposablesBySourcePath = {}
|
||||
@lessCache = null
|
||||
@initialLoadComplete = false
|
||||
@packageManager.registerPackageActivator(this, ['theme'])
|
||||
|
||||
atom.styles.onDidAddStyleElement @styleElementAdded.bind(this)
|
||||
atom.styles.onDidRemoveStyleElement @styleElementRemoved.bind(this)
|
||||
atom.styles.onDidUpdateStyleElement @styleElementUpdated.bind(this)
|
||||
|
||||
styleElementAdded: (element) ->
|
||||
sheet = @styleSheetForElement(element)
|
||||
@emit 'stylesheet-added', sheet
|
||||
@emitter.emit 'did-add-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
styleElementRemoved: (element) ->
|
||||
sheet = @styleSheetForElement(element)
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
styleElementUpdated: (element) ->
|
||||
sheet = @styleSheetForElement(element)
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheet-added', sheet
|
||||
@emitter.emit 'did-add-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
styleSheetForElement: (element) ->
|
||||
@stylesElement ?= document.head.querySelector('atom-styles')
|
||||
@stylesElement.styleElementClonesByOriginalElement.get(element)?.sheet
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
@@ -188,7 +220,6 @@ class ThemeManager
|
||||
if fullPath = @resolveStylesheet(stylesheetPath)
|
||||
content = @loadStylesheet(fullPath)
|
||||
@applyStylesheet(fullPath, content, type)
|
||||
new Disposable => @removeStylesheet(fullPath)
|
||||
else
|
||||
throw new Error("Could not find a file at path '#{stylesheetPath}'")
|
||||
|
||||
@@ -204,8 +235,7 @@ class ThemeManager
|
||||
|
||||
@userStylesheetPath = userStylesheetPath
|
||||
@userStylesheetFile = new File(userStylesheetPath)
|
||||
@userStylesheetFile.on 'contents-changed moved removed', =>
|
||||
@loadUserStylesheet()
|
||||
@userStylesheetFile.on 'contents-changed moved removed', => @loadUserStylesheet()
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, true)
|
||||
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
|
||||
|
||||
@@ -219,7 +249,7 @@ class ThemeManager
|
||||
@requireStylesheet(nativeStylesheetPath)
|
||||
|
||||
stylesheetElementForId: (id) ->
|
||||
document.head.querySelector("""style[id="#{id}"]""")
|
||||
document.head.querySelector("atom-styles style[source-path=\"#{id}\"]")
|
||||
|
||||
resolveStylesheet: (stylesheetPath) ->
|
||||
if path.extname(stylesheetPath).length > 0
|
||||
@@ -256,40 +286,10 @@ class ThemeManager
|
||||
"""
|
||||
|
||||
removeStylesheet: (stylesheetPath) ->
|
||||
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
|
||||
element = @stylesheetElementForId(@stringToId(fullPath))
|
||||
if element?
|
||||
{sheet} = element
|
||||
element.remove()
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
@styleSheetDisposablesBySourcePath[stylesheetPath]?.dispose()
|
||||
|
||||
applyStylesheet: (path, text, type='bundled') ->
|
||||
styleId = @stringToId(path)
|
||||
styleElement = @stylesheetElementForId(styleId)
|
||||
|
||||
if styleElement?
|
||||
@emit 'stylesheet-removed', styleElement.sheet
|
||||
@emitter.emit 'did-remove-stylesheet', styleElement.sheet
|
||||
styleElement.textContent = text
|
||||
else
|
||||
styleElement = document.createElement('style')
|
||||
styleElement.setAttribute('class', type)
|
||||
styleElement.setAttribute('id', styleId)
|
||||
styleElement.textContent = text
|
||||
|
||||
elementToInsertBefore = _.last(document.head.querySelectorAll("style.#{type}"))?.nextElementSibling
|
||||
if elementToInsertBefore?
|
||||
document.head.insertBefore(styleElement, elementToInsertBefore)
|
||||
else
|
||||
document.head.appendChild(styleElement)
|
||||
|
||||
@emit 'stylesheet-added', styleElement.sheet
|
||||
@emitter.emit 'did-add-stylesheet', styleElement.sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
@styleSheetDisposablesBySourcePath[path] = atom.styles.addStyleSheet(text, sourcePath: path, group: type)
|
||||
|
||||
###
|
||||
Section: Private
|
||||
@@ -358,17 +358,3 @@ class ThemeManager
|
||||
themePaths.push(path.join(themePath, Package.stylesheetsDir))
|
||||
|
||||
themePaths.filter (themePath) -> fs.isDirectorySync(themePath)
|
||||
|
||||
updateGlobalEditorStyle: (property, value) ->
|
||||
unless styleNode = @stylesheetElementForId('global-editor-styles')
|
||||
@applyStylesheet('global-editor-styles', 'atom-text-editor {}')
|
||||
styleNode = @stylesheetElementForId('global-editor-styles')
|
||||
|
||||
{sheet} = styleNode
|
||||
editorRule = sheet.cssRules[0]
|
||||
editorRule.style[property] = value
|
||||
|
||||
@emit 'stylesheet-updated', sheet
|
||||
@emitter.emit 'did-update-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
@@ -8,8 +8,11 @@ WorkspaceView = null
|
||||
|
||||
module.exports =
|
||||
class WorkspaceElement extends HTMLElement
|
||||
globalTextEditorStyleSheet: null
|
||||
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@initializeGlobalTextEditorStyleSheet()
|
||||
@initializeContent()
|
||||
@observeScrollbarStyle()
|
||||
@observeTextEditorFontConfig()
|
||||
@@ -22,6 +25,10 @@ class WorkspaceElement extends HTMLElement
|
||||
detachedCallback: ->
|
||||
@model.destroy()
|
||||
|
||||
initializeGlobalTextEditorStyleSheet: ->
|
||||
atom.styles.addStyleSheet('atom-text-editor {}', sourcePath: 'global-text-editor-styles')
|
||||
@globalTextEditorStyleSheet = document.head.querySelector('style[source-path="global-text-editor-styles"]').sheet
|
||||
|
||||
initializeContent: ->
|
||||
@classList.add 'workspace'
|
||||
@setAttribute 'tabindex', -1
|
||||
@@ -46,9 +53,9 @@ class WorkspaceElement extends HTMLElement
|
||||
@classList.add("scrollbars-visible-when-scrolling")
|
||||
|
||||
observeTextEditorFontConfig: ->
|
||||
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize
|
||||
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily
|
||||
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight
|
||||
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight.bind(this)
|
||||
|
||||
createSpacePenShim: ->
|
||||
WorkspaceView ?= require './workspace-view'
|
||||
@@ -68,13 +75,18 @@ class WorkspaceElement extends HTMLElement
|
||||
@__spacePenView.setModel(@model)
|
||||
|
||||
setTextEditorFontSize: (fontSize) ->
|
||||
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
|
||||
@updateGlobalEditorStyle('font-size', fontSize + 'px')
|
||||
|
||||
setTextEditorFontFamily: (fontFamily) ->
|
||||
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
|
||||
@updateGlobalEditorStyle('font-family', fontFamily)
|
||||
|
||||
setTextEditorLineHeight: (lineHeight) ->
|
||||
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
|
||||
@updateGlobalEditorStyle('line-height', lineHeight)
|
||||
|
||||
updateGlobalEditorStyle: (property, value) ->
|
||||
editorRule = @globalTextEditorStyleSheet.cssRules[0]
|
||||
editorRule.style[property] = value
|
||||
atom.themes.emitter.emit 'did-update-stylesheet', @globalTextEditorStyleSheet
|
||||
|
||||
handleFocus: (event) ->
|
||||
@model.getActivePane().activate()
|
||||
|
||||
Reference in New Issue
Block a user