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:
Nathan Sobo
2014-10-14 10:08:46 -06:00
parent 79598aaae9
commit 65e077abd1
8 changed files with 106 additions and 90 deletions

View File

@@ -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
###

View File

@@ -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})

View File

@@ -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

View File

@@ -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'

View File

@@ -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()