mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge remote-tracking branch 'origin/master' into vim-core-changes
Conflicts: src/app/pane.coffee
This commit is contained in:
@@ -2406,3 +2406,13 @@ describe "EditSession", ->
|
||||
editSession.joinLine()
|
||||
expect(editSession.lineForBufferRow(9)).toBe ' }; return sort(Array.apply(this, arguments)); };'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[9, 3], [9, 49]]
|
||||
|
||||
describe ".shouldPromptToSave()", ->
|
||||
it "returns false when an edit session's buffer is in use by more than one session", ->
|
||||
expect(editSession.shouldPromptToSave()).toBeFalsy()
|
||||
buffer.setText('changed')
|
||||
expect(editSession.shouldPromptToSave()).toBeTruthy()
|
||||
editSession2 = project.buildEditSession('sample.js', autoIndent: false)
|
||||
expect(editSession.shouldPromptToSave()).toBeFalsy()
|
||||
editSession2.destroy()
|
||||
expect(editSession.shouldPromptToSave()).toBeTruthy()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
RootView = require 'root-view'
|
||||
EditSession = require 'edit-session'
|
||||
Buffer = require 'text-buffer'
|
||||
Editor = require 'editor'
|
||||
@@ -2036,6 +2037,25 @@ describe "Editor", ->
|
||||
runs ->
|
||||
expect(editor.getText()).toBe(originalPathText)
|
||||
|
||||
|
||||
describe ".pixelPositionForBufferPosition(position)", ->
|
||||
describe "when the editor is detached", ->
|
||||
it "returns top and left values of 0", ->
|
||||
expect(editor.isOnDom()).toBeFalsy()
|
||||
expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0
|
||||
|
||||
describe "when the editor is invisible", ->
|
||||
it "returns top and left values of 0", ->
|
||||
editor.attachToDom()
|
||||
editor.hide()
|
||||
expect(editor.isVisible()).toBeFalsy()
|
||||
expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0
|
||||
|
||||
describe "when the editor is attached and visible", ->
|
||||
it "returns the top and left pixel positions", ->
|
||||
editor.attachToDom()
|
||||
expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 40, left: 70
|
||||
|
||||
describe "when clicking in the gutter", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom()
|
||||
@@ -2488,3 +2508,47 @@ describe "Editor", ->
|
||||
|
||||
editor.trigger(keydownEvent('escape'))
|
||||
expect(testEventHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the editor is attached but invisible", ->
|
||||
describe "when the editor's text is changed", ->
|
||||
it "redraws the editor when it is next shown", ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
editor.getPane().showItem(view)
|
||||
expect(editor.isVisible()).toBeFalsy()
|
||||
|
||||
editor.setText('hidden changes')
|
||||
editor.setCursorBufferPosition([0,4])
|
||||
|
||||
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
|
||||
editor.on 'editor:display-updated', displayUpdatedHandler
|
||||
editor.getPane().showItem(editor.getModel())
|
||||
expect(editor.isVisible()).toBeTruthy()
|
||||
|
||||
waitsFor ->
|
||||
displayUpdatedHandler.callCount is 1
|
||||
|
||||
runs ->
|
||||
expect(editor.renderedLines.find('.line').text()).toBe 'hidden changes'
|
||||
|
||||
it "redraws the editor when it is next reattached", ->
|
||||
editor.attachToDom()
|
||||
editor.hide()
|
||||
editor.setText('hidden changes')
|
||||
editor.setCursorBufferPosition([0,4])
|
||||
editor.detach()
|
||||
|
||||
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
|
||||
editor.on 'editor:display-updated', displayUpdatedHandler
|
||||
editor.show()
|
||||
editor.attachToDom()
|
||||
|
||||
waitsFor ->
|
||||
displayUpdatedHandler.callCount is 1
|
||||
|
||||
runs ->
|
||||
expect(editor.renderedLines.find('.line').text()).toBe 'hidden changes'
|
||||
|
||||
78
spec/app/image-view-spec.coffee
Normal file
78
spec/app/image-view-spec.coffee
Normal file
@@ -0,0 +1,78 @@
|
||||
ImageView = require 'image-view'
|
||||
ImageEditSession = require 'image-edit-session'
|
||||
|
||||
describe "ImageView", ->
|
||||
[view, path] = []
|
||||
|
||||
beforeEach ->
|
||||
path = project.resolve('binary-file.png')
|
||||
view = new ImageView()
|
||||
view.attachToDom()
|
||||
view.parent().height(100)
|
||||
|
||||
it "displays the image for a path", ->
|
||||
view.setModel(new ImageEditSession(path))
|
||||
expect(view.image.attr('src')).toBe path
|
||||
|
||||
it "centers the image in the editor", ->
|
||||
imageLoaded = false
|
||||
view.image.load =>
|
||||
imageLoaded = true
|
||||
view.setModel(new ImageEditSession(path))
|
||||
|
||||
waitsFor ->
|
||||
imageLoaded
|
||||
|
||||
runs ->
|
||||
expect(view.image.width()).toBe 10
|
||||
expect(view.image.height()).toBe 10
|
||||
expect(view.image.css('left')).toBe "#{(view.width() - view.image.outerWidth()) / 2}px"
|
||||
expect(view.image.css('top')).toBe "#{(view.height() - view.image.outerHeight()) / 2}px"
|
||||
|
||||
describe "image-view:zoom-in", ->
|
||||
it "increases the image size by 10%", ->
|
||||
imageLoaded = false
|
||||
view.image.load =>
|
||||
imageLoaded = true
|
||||
view.setModel(new ImageEditSession(path))
|
||||
|
||||
waitsFor ->
|
||||
imageLoaded
|
||||
|
||||
runs ->
|
||||
view.trigger 'image-view:zoom-in'
|
||||
expect(view.image.width()).toBe 11
|
||||
expect(view.image.height()).toBe 11
|
||||
|
||||
describe "image-view:zoom-out", ->
|
||||
it "decreases the image size by 10%", ->
|
||||
imageLoaded = false
|
||||
view.image.load =>
|
||||
imageLoaded = true
|
||||
view.setModel(new ImageEditSession(path))
|
||||
|
||||
waitsFor ->
|
||||
imageLoaded
|
||||
|
||||
runs ->
|
||||
view.trigger 'image-view:zoom-out'
|
||||
expect(view.image.width()).toBe 9
|
||||
expect(view.image.height()).toBe 9
|
||||
|
||||
describe "image-view:reset-zoom", ->
|
||||
it "restores the image to the original size", ->
|
||||
imageLoaded = false
|
||||
view.image.load =>
|
||||
imageLoaded = true
|
||||
view.setModel(new ImageEditSession(path))
|
||||
|
||||
waitsFor ->
|
||||
imageLoaded
|
||||
|
||||
runs ->
|
||||
view.trigger 'image-view:zoom-in'
|
||||
expect(view.image.width()).not.toBe 10
|
||||
expect(view.image.height()).not.toBe 10
|
||||
view.trigger 'image-view:reset-zoom'
|
||||
expect(view.image.width()).toBe 10
|
||||
expect(view.image.height()).toBe 10
|
||||
@@ -110,7 +110,8 @@ describe "PaneContainer", ->
|
||||
expect(pane1.activeItem).toEqual item3
|
||||
|
||||
describe "when there is no active pane", ->
|
||||
it "attaches a new pane with the reconstructed last pane item", ->
|
||||
it "attaches a new pane with the reconstructed last pane item and focuses it", ->
|
||||
container.attachToDom()
|
||||
pane1.remove()
|
||||
pane2.remove()
|
||||
item3 = pane3.activeItem
|
||||
@@ -120,6 +121,7 @@ describe "PaneContainer", ->
|
||||
container.reopenItem()
|
||||
|
||||
expect(container.getActivePane().activeItem).toEqual item3
|
||||
expect(container.getActivePane().activeView).toMatchSelector ':focus'
|
||||
|
||||
it "does not reopen an item that is already open", ->
|
||||
item3 = pane3.activeItem
|
||||
|
||||
@@ -257,6 +257,13 @@ describe "Pane", ->
|
||||
expect(pane2.getItems()).toEqual [view3, editSession1]
|
||||
expect(editSession1.destroyed).toBeFalsy()
|
||||
|
||||
describe "when the item is a jQuery object", ->
|
||||
it "preserves data by detaching instead of removing", ->
|
||||
view1.data('preservative', 1234)
|
||||
pane.moveItemToPane(view1, pane2, 1)
|
||||
pane2.showItemAtIndex(1)
|
||||
expect(pane2.activeView.data('preservative')).toBe 1234
|
||||
|
||||
describe "core:close", ->
|
||||
it "destroys the active item and does not bubble the event", ->
|
||||
containerCloseHandler = jasmine.createSpy("containerCloseHandler")
|
||||
|
||||
@@ -354,3 +354,31 @@ describe "RootView", ->
|
||||
rootView.open(require.resolve('fixtures/sample.txt'))
|
||||
expect(count).toBe 1
|
||||
expect(callbackBuffer).toBe rootView.getActiveView().getBuffer()
|
||||
|
||||
describe ".eachPane(callback)", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
|
||||
it "invokes the callback for all existing panes", ->
|
||||
count = 0
|
||||
callbackPane = null
|
||||
callback = (pane) ->
|
||||
callbackPane = pane
|
||||
count++
|
||||
rootView.eachPane(callback)
|
||||
expect(count).toBe 1
|
||||
expect(callbackPane).toBe rootView.getActivePane()
|
||||
|
||||
it "invokes the callback for new panes", ->
|
||||
count = 0
|
||||
callbackPane = null
|
||||
callback = (pane) ->
|
||||
callbackPane = pane
|
||||
count++
|
||||
|
||||
rootView.eachPane(callback)
|
||||
count = 0
|
||||
callbackPane = null
|
||||
rootView.getActiveView().splitRight()
|
||||
expect(count).toBe 1
|
||||
expect(callbackPane).toBe rootView.getActivePane()
|
||||
|
||||
@@ -198,3 +198,31 @@ describe "Window", ->
|
||||
expect(deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined()
|
||||
expect(deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined()
|
||||
expect(deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined()
|
||||
|
||||
describe "drag and drop", ->
|
||||
buildDragEvent = (type, files) ->
|
||||
dataTransfer =
|
||||
files: files
|
||||
data: {}
|
||||
setData: (key, value) -> @data[key] = value
|
||||
getData: (key) -> @data[key]
|
||||
|
||||
event = $.Event(type)
|
||||
event.originalEvent = { dataTransfer }
|
||||
event.preventDefault = ->
|
||||
event.stopPropagation = ->
|
||||
event
|
||||
|
||||
describe "when a file is dragged to window", ->
|
||||
it "opens it", ->
|
||||
spyOn(atom, "open")
|
||||
event = buildDragEvent("drop", [ {path: "/fake1"}, {path: "/fake2"} ])
|
||||
window.onDrop(event)
|
||||
expect(atom.open.callCount).toBe 2
|
||||
|
||||
describe "when a non-file is dragged to window", ->
|
||||
it "does nothing", ->
|
||||
spyOn(atom, "open")
|
||||
event = buildDragEvent("drop", [])
|
||||
window.onDrop(event)
|
||||
expect(atom.open).not.toHaveBeenCalled()
|
||||
|
||||
@@ -156,6 +156,7 @@ class EditSession
|
||||
saveAs: (path) -> @buffer.saveAs(path)
|
||||
getFileExtension: -> @buffer.getExtension()
|
||||
getPath: -> @buffer.getPath()
|
||||
getBuffer: -> @buffer
|
||||
getUri: -> @getPath()
|
||||
isBufferRowBlank: (bufferRow) -> @buffer.isRowBlank(bufferRow)
|
||||
nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow)
|
||||
@@ -167,7 +168,7 @@ class EditSession
|
||||
scanInBufferRange: (args...) -> @buffer.scanInRange(args...)
|
||||
backwardsScanInBufferRange: (args...) -> @buffer.backwardsScanInRange(args...)
|
||||
isModified: -> @buffer.isModified()
|
||||
hasEditors: -> @buffer.hasEditors()
|
||||
shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors()
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition, options) -> @displayBuffer.screenPositionForBufferPosition(bufferPosition, options)
|
||||
bufferPositionForScreenPosition: (screenPosition, options) -> @displayBuffer.bufferPositionForScreenPosition(screenPosition, options)
|
||||
|
||||
@@ -442,6 +442,13 @@ class Editor extends View
|
||||
@subscribe $(window), "resize.editor-#{@id}", => @requestDisplayUpdate()
|
||||
@focus() if @isFocused
|
||||
|
||||
if pane = @getPane()
|
||||
@active = @is(pane.activeView)
|
||||
@subscribe pane, 'pane:active-item-changed', (event, item) =>
|
||||
wasActive = @active
|
||||
@active = @is(pane.activeView)
|
||||
@redraw() if @active and not wasActive
|
||||
|
||||
@resetDisplay()
|
||||
|
||||
@trigger 'editor:attached', [this]
|
||||
@@ -771,6 +778,7 @@ class Editor extends View
|
||||
|
||||
requestDisplayUpdate: ->
|
||||
return if @pendingDisplayUpdate
|
||||
return unless @isVisible()
|
||||
@pendingDisplayUpdate = true
|
||||
_.nextTick =>
|
||||
@updateDisplay()
|
||||
@@ -779,6 +787,10 @@ class Editor extends View
|
||||
updateDisplay: (options={}) ->
|
||||
return unless @attached and @activeEditSession
|
||||
return if @activeEditSession.destroyed
|
||||
unless @isVisible()
|
||||
@redrawOnReattach = true
|
||||
return
|
||||
|
||||
@updateRenderedLines()
|
||||
@highlightCursorLine()
|
||||
@updateCursorViews()
|
||||
@@ -916,9 +928,8 @@ class Editor extends View
|
||||
|
||||
if intactRanges.length == 0
|
||||
@renderedLines.empty()
|
||||
else
|
||||
else if currentLine = renderedLines.firstChild
|
||||
domPosition = 0
|
||||
currentLine = renderedLines.firstChild
|
||||
for intactRange in intactRanges
|
||||
while intactRange.domStart > domPosition
|
||||
currentLine = killLine(currentLine)
|
||||
@@ -1079,7 +1090,7 @@ class Editor extends View
|
||||
@pixelPositionForScreenPosition(@screenPositionForBufferPosition(position))
|
||||
|
||||
pixelPositionForScreenPosition: (position) ->
|
||||
return { top: 0, left: 0 } unless @isOnDom()
|
||||
return { top: 0, left: 0 } unless @isOnDom() and @isVisible()
|
||||
{row, column} = Point.fromObject(position)
|
||||
actualRow = Math.floor(row)
|
||||
|
||||
|
||||
42
src/app/image-edit-session.coffee
Normal file
42
src/app/image-edit-session.coffee
Normal file
@@ -0,0 +1,42 @@
|
||||
fsUtils = require 'fs-utils'
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports=
|
||||
class ImageEditSession
|
||||
registerDeserializer(this)
|
||||
|
||||
@canOpen: (path) ->
|
||||
_.indexOf([
|
||||
'.gif'
|
||||
'.jpeg'
|
||||
'.jpg'
|
||||
'.png'
|
||||
], fsUtils.extension(path), true) >= 0
|
||||
|
||||
@deserialize: (state) ->
|
||||
if fsUtils.exists(state.path)
|
||||
project.buildEditSession(state.path)
|
||||
else
|
||||
console.warn "Could not build edit session for path '#{state.path}' because that file no longer exists"
|
||||
|
||||
constructor: (@path) ->
|
||||
|
||||
serialize: ->
|
||||
deserializer: 'ImageEditSession'
|
||||
path: @path
|
||||
|
||||
getViewClass: ->
|
||||
require 'image-view'
|
||||
|
||||
getTitle: ->
|
||||
if path = @getPath()
|
||||
fsUtils.base(path)
|
||||
else
|
||||
'untitled'
|
||||
|
||||
getUri: -> @path
|
||||
|
||||
getPath: -> @path
|
||||
|
||||
isEqual: (other) ->
|
||||
other instanceof ImageEditSession and @getUri() is other.getUri()
|
||||
80
src/app/image-view.coffee
Normal file
80
src/app/image-view.coffee
Normal file
@@ -0,0 +1,80 @@
|
||||
ScrollView = require 'scroll-view'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class ImageView extends ScrollView
|
||||
@content: ->
|
||||
@div class: 'image-view', tabindex: -1, =>
|
||||
@img outlet: 'image'
|
||||
|
||||
initialize: (imageEditSession) ->
|
||||
super
|
||||
|
||||
requireStylesheet 'image-view'
|
||||
|
||||
@image.load =>
|
||||
@originalHeight = @image.height()
|
||||
@originalWidth = @image.width()
|
||||
@loaded = true
|
||||
@centerImage()
|
||||
@setPath(imageEditSession?.getPath())
|
||||
|
||||
@subscribe $(window), 'resize', _.debounce((=> @centerImage()), 300)
|
||||
@command 'image-view:zoom-in', => @zoomIn()
|
||||
@command 'image-view:zoom-out', => @zoomOut()
|
||||
@command 'image-view:reset-zoom', => @resetZoom()
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
|
||||
if pane = @getPane()
|
||||
@active = @is(pane.activeView)
|
||||
@subscribe pane, 'pane:active-item-changed', (event, item) =>
|
||||
wasActive = @active
|
||||
@active = @is(pane.activeView)
|
||||
@centerImage() if @active and not wasActive
|
||||
|
||||
centerImage: ->
|
||||
return unless @loaded and @isVisible()
|
||||
|
||||
@image.css
|
||||
'top': Math.max((@height() - @image.outerHeight()) / 2, 0)
|
||||
'left': Math.max((@width() - @image.outerWidth()) / 2, 0)
|
||||
@image.show()
|
||||
|
||||
setPath: (path) ->
|
||||
if path?
|
||||
if @image.attr('src') isnt path
|
||||
@loaded = false
|
||||
@image.hide().attr('src', path)
|
||||
else
|
||||
@image.hide()
|
||||
|
||||
setModel: (imageEditSession) ->
|
||||
@setPath(imageEditSession?.getPath())
|
||||
|
||||
getPane: ->
|
||||
@parent('.item-views').parent('.pane').view()
|
||||
|
||||
adjustSize: (factor) ->
|
||||
return unless @loaded and @isVisible()
|
||||
|
||||
newWidth = @image.width() * factor
|
||||
newHeight = @image.height() * factor
|
||||
@image.width(newWidth)
|
||||
@image.height(newHeight)
|
||||
@centerImage()
|
||||
|
||||
zoomOut: ->
|
||||
@adjustSize(0.9)
|
||||
|
||||
zoomIn: ->
|
||||
@adjustSize(1.1)
|
||||
|
||||
resetZoom: ->
|
||||
return unless @loaded and @isVisible()
|
||||
|
||||
@image.width(@originalWidth)
|
||||
@image.height(@originalHeight)
|
||||
@centerImage()
|
||||
@@ -35,3 +35,9 @@
|
||||
|
||||
'.editor !important, .editor.mini !important':
|
||||
'escape': 'editor:consolidate-selections'
|
||||
|
||||
'.image-view':
|
||||
'meta-+': 'image-view:zoom-in'
|
||||
'meta-=': 'image-view:zoom-in'
|
||||
'meta--': 'image-view:zoom-out'
|
||||
'meta-0': 'image-view:reset-zoom'
|
||||
|
||||
@@ -55,7 +55,9 @@ class PaneContainer extends View
|
||||
activePane.showItem(deserialize(lastItemState))
|
||||
true
|
||||
else
|
||||
@append(new Pane(deserialize(lastItemState)))
|
||||
newPane = new Pane(deserialize(lastItemState))
|
||||
@append(newPane)
|
||||
newPane.focus()
|
||||
|
||||
itemDestroyed: (item) ->
|
||||
state = item.serialize?()
|
||||
|
||||
@@ -58,7 +58,7 @@ class Pane extends View
|
||||
|
||||
return if @attached
|
||||
@attached = true
|
||||
@trigger 'pane:attached'
|
||||
@trigger 'pane:attached', [this]
|
||||
|
||||
makeActive: ->
|
||||
for pane in @getContainer().getPanes() when pane isnt this
|
||||
@@ -148,7 +148,7 @@ class Pane extends View
|
||||
|
||||
@autosaveItem(item)
|
||||
|
||||
if promptToSave && item.isModified?()
|
||||
if item.shouldPromptToSave?()
|
||||
@promptToSaveItem(item, reallyDestroyItem)
|
||||
else
|
||||
reallyDestroyItem()
|
||||
@@ -214,7 +214,9 @@ class Pane extends View
|
||||
@trigger 'pane:item-moved', [item, newIndex]
|
||||
|
||||
moveItemToPane: (item, pane, index) ->
|
||||
@isMovingItem = true
|
||||
@removeItem(item)
|
||||
@isMovingItem = false
|
||||
pane.addItem(item, index)
|
||||
|
||||
itemForUri: (uri) ->
|
||||
@@ -235,8 +237,12 @@ class Pane extends View
|
||||
delete @viewsByClassName[viewClass.name]
|
||||
|
||||
if @items.length > 0
|
||||
viewToRemove?.remove()
|
||||
if @isMovingItem and item is viewToRemove
|
||||
viewToRemove?.detach()
|
||||
else
|
||||
viewToRemove?.remove()
|
||||
else
|
||||
viewToRemove?.detach() if @isMovingItem and item is viewToRemove
|
||||
@remove()
|
||||
|
||||
viewForItem: (item) ->
|
||||
|
||||
@@ -4,6 +4,7 @@ $ = require 'jquery'
|
||||
Range = require 'range'
|
||||
Buffer = require 'text-buffer'
|
||||
EditSession = require 'edit-session'
|
||||
ImageEditSession = require 'image-edit-session'
|
||||
EventEmitter = require 'event-emitter'
|
||||
Directory = require 'directory'
|
||||
BufferedProcess = require 'buffered-process'
|
||||
@@ -85,7 +86,10 @@ class Project
|
||||
setSoftWrap: (@softWrap) ->
|
||||
|
||||
buildEditSession: (filePath, editSessionOptions={}) ->
|
||||
@buildEditSessionForBuffer(@bufferForPath(filePath), editSessionOptions)
|
||||
if ImageEditSession.canOpen(filePath)
|
||||
new ImageEditSession(filePath)
|
||||
else
|
||||
@buildEditSessionForBuffer(@bufferForPath(filePath), editSessionOptions)
|
||||
|
||||
buildEditSessionForBuffer: (buffer, editSessionOptions) ->
|
||||
options = _.extend(@defaultEditSessionOptions(), editSessionOptions)
|
||||
|
||||
@@ -162,6 +162,10 @@ class RootView extends View
|
||||
indexOfPane: (pane) ->
|
||||
@panes.indexOfPane(pane)
|
||||
|
||||
eachPane: (callback) ->
|
||||
callback(pane) for pane in @getPanes()
|
||||
@on 'pane:attached', (e, pane) -> callback(pane)
|
||||
|
||||
eachEditor: (callback) ->
|
||||
callback(editor) for editor in @getEditors()
|
||||
@on 'editor:attached', (e, editor) -> callback(editor)
|
||||
|
||||
@@ -142,6 +142,7 @@ class SelectList extends View
|
||||
|
||||
cancelled: ->
|
||||
@miniEditor.setText('')
|
||||
@miniEditor.updateDisplay()
|
||||
|
||||
cancel: ->
|
||||
@list.empty()
|
||||
|
||||
@@ -70,7 +70,7 @@ class Buffer
|
||||
path: @getPath()
|
||||
text: @getText() if @isModified()
|
||||
|
||||
hasEditors: -> @refcount > 1
|
||||
hasMultipleEditors: -> @refcount > 1
|
||||
|
||||
subscribeToFile: ->
|
||||
@file.on "contents-changed", =>
|
||||
|
||||
@@ -25,12 +25,6 @@ window.setUpEnvironment = ->
|
||||
$(document).on 'keydown', keymap.handleKeyEvent
|
||||
keymap.bindDefaultKeys()
|
||||
|
||||
ignoreEvents = (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
$(document).on 'dragover', ignoreEvents
|
||||
$(document).on 'drop', ignoreEvents
|
||||
|
||||
requireStylesheet 'reset'
|
||||
requireStylesheet 'atom'
|
||||
requireStylesheet 'overlay'
|
||||
@@ -50,6 +44,7 @@ window.startup = ->
|
||||
console.warn "Failed to install `atom` binary"
|
||||
|
||||
handleWindowEvents()
|
||||
handleDragDrop()
|
||||
config.load()
|
||||
keymap.loadBundledKeymaps()
|
||||
atom.loadThemes()
|
||||
@@ -93,6 +88,18 @@ window.handleWindowEvents = ->
|
||||
$(window).command 'window:close', => confirmClose()
|
||||
$(window).command 'window:reload', => reload()
|
||||
|
||||
window.handleDragDrop = ->
|
||||
$(document).on 'dragover', (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
$(document).on 'drop', onDrop
|
||||
|
||||
window.onDrop = (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
for file in e.originalEvent.dataTransfer.files
|
||||
atom.open(file.path)
|
||||
|
||||
window.deserializeWindowState = ->
|
||||
RootView = require 'root-view'
|
||||
Project = require 'project'
|
||||
|
||||
@@ -39,13 +39,13 @@ class CommandPanelView extends View
|
||||
@command 'core:move-up', => @navigateBackwardInHistory()
|
||||
@command 'core:move-down', => @navigateForwardInHistory()
|
||||
|
||||
rootView.command 'command-panel:toggle', => @toggle()
|
||||
rootView.command 'command-panel:toggle-preview', => @togglePreview()
|
||||
rootView.command 'command-panel:find-in-file', => @attach('/')
|
||||
rootView.command 'command-panel:find-in-project', => @attach('Xx/')
|
||||
rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true)
|
||||
rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
@subscribeToCommand rootView, 'command-panel:toggle', => @toggle()
|
||||
@subscribeToCommand rootView, 'command-panel:toggle-preview', => @togglePreview()
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-file', => @attach('/')
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-project', => @attach('Xx/')
|
||||
@subscribeToCommand rootView, 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
@subscribeToCommand rootView, 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true)
|
||||
@subscribeToCommand rootView, 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@on 'click', '.expand', @onExpandAll
|
||||
@on 'click', '.collapse', @onCollapseAll
|
||||
@@ -65,8 +65,6 @@ class CommandPanelView extends View
|
||||
|
||||
destroy: ->
|
||||
@previewList.destroy()
|
||||
rootView.off "command-panel:toggle-preview command-panel:find-in-file command-panel:find-in-project \
|
||||
command-panel:repeat-relative-address command-panel:repeat-relative-address-in-reverse command-panel:set-selection-as-regex-address"
|
||||
@remove()
|
||||
|
||||
toggle: ->
|
||||
|
||||
@@ -14,10 +14,20 @@ class MarkdownPreviewView extends ScrollView
|
||||
|
||||
initialize: (@buffer) ->
|
||||
super
|
||||
|
||||
@fetchRenderedMarkdown()
|
||||
@on 'core:move-up', => @scrollUp()
|
||||
@on 'core:move-down', => @scrollDown()
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
@subscribe @buffer, 'saved', =>
|
||||
@fetchRenderedMarkdown()
|
||||
pane = @getPane()
|
||||
pane.showItem(this) if pane? and pane isnt rootView.getActivePane()
|
||||
|
||||
getPane: ->
|
||||
@parent('.item-views').parent('.pane').view()
|
||||
|
||||
serialize: ->
|
||||
deserializer: 'MarkdownPreviewView'
|
||||
path: @buffer.getPath()
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
EditSession = require 'edit-session'
|
||||
MarkdownPreviewView = require 'markdown-preview/lib/markdown-preview-view'
|
||||
MarkdownPreviewView = require './markdown-preview-view'
|
||||
|
||||
module.exports =
|
||||
activate: ->
|
||||
rootView.command 'markdown-preview:show', '.editor', => @show()
|
||||
rootView.on 'core:save', ".pane", => @show() if @previewExists()
|
||||
|
||||
show: ->
|
||||
activePane = rootView.getActivePane()
|
||||
@@ -16,17 +15,19 @@ module.exports =
|
||||
console.warn("Can not render markdown for '#{editSession.getUri() ? 'untitled'}'")
|
||||
return
|
||||
|
||||
if nextPane = activePane.getNextPane()
|
||||
if preview = nextPane.itemForUri("markdown-preview:#{editSession.getPath()}")
|
||||
nextPane.showItem(preview)
|
||||
preview.fetchRenderedMarkdown()
|
||||
else
|
||||
nextPane.showItem(new MarkdownPreviewView(editSession.buffer))
|
||||
{previewPane, previewItem} = @getExistingPreview(editSession)
|
||||
if previewItem?
|
||||
previewPane.showItem(previewItem)
|
||||
previewItem.fetchRenderedMarkdown()
|
||||
else if nextPane = activePane.getNextPane()
|
||||
nextPane.showItem(new MarkdownPreviewView(editSession.buffer))
|
||||
else
|
||||
activePane.splitRight(new MarkdownPreviewView(editSession.buffer))
|
||||
activePane.focus()
|
||||
|
||||
previewExists: ->
|
||||
nextPane = rootView.getActivePane().getNextPane()
|
||||
item = rootView.getActivePane().activeItem
|
||||
nextPane?.itemForUri("markdown-preview:#{item.getPath?()}")
|
||||
getExistingPreview: (editSession) ->
|
||||
uri = "markdown-preview:#{editSession.getPath()}"
|
||||
for previewPane in rootView.getPanes()
|
||||
previewItem = previewPane.itemForUri(uri)
|
||||
return {previewPane, previewItem} if previewItem?
|
||||
{}
|
||||
|
||||
@@ -62,7 +62,7 @@ describe "MarkdownPreview package", ->
|
||||
pane.focus()
|
||||
|
||||
MarkdownPreviewView.prototype.fetchRenderedMarkdown.reset()
|
||||
pane.trigger("core:save")
|
||||
pane.activeItem.buffer.trigger 'saved'
|
||||
expect(MarkdownPreviewView.prototype.fetchRenderedMarkdown).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a preview item has already been created for the edit session's uri", ->
|
||||
@@ -86,12 +86,30 @@ describe "MarkdownPreview package", ->
|
||||
expect(pane1).toMatchSelector(':has(:focus)')
|
||||
|
||||
describe "when a buffer is saved", ->
|
||||
it "updates the existing preview item", ->
|
||||
rootView.getActiveView().trigger 'markdown-preview:show'
|
||||
[pane1, pane2] = rootView.getPanes()
|
||||
preview = pane2.activeItem
|
||||
pane1.focus()
|
||||
describe "when the preview is in the same pane", ->
|
||||
it "updates the preview but does not make it active", ->
|
||||
rootView.getActiveView().trigger 'markdown-preview:show'
|
||||
[pane1, pane2] = rootView.getPanes()
|
||||
pane2.moveItemToPane(pane2.activeItem, pane1, 1)
|
||||
pane1.showItemAtIndex(1)
|
||||
pane1.showItemAtIndex(0)
|
||||
preview = pane1.itemAtIndex(1)
|
||||
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
pane1.trigger("core:save")
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
pane1.activeItem.buffer.trigger 'saved'
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
expect(pane1.activeItem).not.toBe preview
|
||||
|
||||
describe "when the preview is not in the same pane", ->
|
||||
it "updates the preview and makes it active", ->
|
||||
rootView.getActiveView().trigger 'markdown-preview:show'
|
||||
[pane1, pane2] = rootView.getPanes()
|
||||
preview = pane2.activeItem
|
||||
pane2.showItem($$ -> @div id: 'view', tabindex: -1, 'View')
|
||||
expect(pane2.activeItem).not.toBe preview
|
||||
pane1.focus()
|
||||
|
||||
preview.fetchRenderedMarkdown.reset()
|
||||
pane1.activeItem.buffer.trigger 'saved'
|
||||
expect(preview.fetchRenderedMarkdown).toHaveBeenCalled()
|
||||
expect(pane2.activeItem).toBe preview
|
||||
|
||||
@@ -5,12 +5,8 @@ $ = require 'jquery'
|
||||
module.exports =
|
||||
class StatusBarView extends View
|
||||
@activate: ->
|
||||
rootView.eachEditor (editor) =>
|
||||
@appendToEditorPane(rootView, editor) if editor.attached
|
||||
|
||||
@appendToEditorPane: (rootView, editor) ->
|
||||
if pane = editor.getPane()
|
||||
pane.append(new StatusBarView(rootView, editor))
|
||||
rootView.eachPane (pane) =>
|
||||
pane.append(new StatusBarView(rootView, pane))
|
||||
|
||||
@content: ->
|
||||
@div class: 'status-bar', =>
|
||||
@@ -26,41 +22,46 @@ class StatusBarView extends View
|
||||
@span class: 'cursor-position', outlet: 'cursorPosition'
|
||||
@span class: 'grammar-name', outlet: 'grammarName'
|
||||
|
||||
initialize: (rootView, @editor) ->
|
||||
initialize: (rootView, @pane) ->
|
||||
@updatePathText()
|
||||
@editor.on 'editor:path-changed', =>
|
||||
@subscribe @pane, 'pane:active-item-changed', =>
|
||||
@subscribeToBuffer()
|
||||
@updatePathText()
|
||||
|
||||
@updateCursorPositionText()
|
||||
@subscribe @editor, 'cursor:moved', => @updateCursorPositionText()
|
||||
@subscribe @grammarName, 'click', => @editor.trigger 'grammar-selector:show'
|
||||
@subscribe @editor, 'editor:grammar-changed', => @updateGrammarText()
|
||||
@subscribe @pane, 'cursor:moved', => @updateCursorPositionText()
|
||||
@subscribe @grammarName, 'click', => @pane.activeView.trigger 'grammar-selector:show'
|
||||
@subscribe @pane, 'editor:grammar-changed', => @updateGrammarText()
|
||||
|
||||
if git?
|
||||
@subscribe git, 'status-changed', (path, status) =>
|
||||
@updateStatusBar() if path is @buffer?.getPath()
|
||||
@updateStatusBar() if path is @getActiveItemPath()
|
||||
@subscribe git, 'statuses-changed', =>
|
||||
@updateStatusBar()
|
||||
|
||||
@subscribeToBuffer()
|
||||
|
||||
getActiveItemPath: ->
|
||||
@pane.activeItem?.getPath?()
|
||||
|
||||
subscribeToBuffer: ->
|
||||
@buffer?.off '.status-bar'
|
||||
@buffer = @editor.getBuffer()
|
||||
@buffer.on 'modified-status-changed.status-bar', (isModified) => @updateBufferHasModifiedText(isModified)
|
||||
@buffer.on 'saved.status-bar', => @updateStatusBar()
|
||||
if @buffer = @pane.activeItem.getBuffer?()
|
||||
@buffer.on 'modified-status-changed.status-bar', (isModified) => @updateBufferHasModifiedText(isModified)
|
||||
@buffer.on 'saved.status-bar', => @updateStatusBar()
|
||||
|
||||
@updateStatusBar()
|
||||
|
||||
updateStatusBar: ->
|
||||
@updateGrammarText()
|
||||
@updateBranchText()
|
||||
@updateBufferHasModifiedText(@buffer.isModified())
|
||||
@updateBufferHasModifiedText(@buffer?.isModified())
|
||||
@updateStatusText()
|
||||
@updateCursorPositionText()
|
||||
|
||||
updateGrammarText: ->
|
||||
grammar = @editor.getGrammar()
|
||||
if grammar is syntax.nullGrammar
|
||||
@grammarName.text('').hide()
|
||||
grammar = @pane.activeView.getGrammar?()
|
||||
if not grammar? or grammar is syntax.nullGrammar
|
||||
@grammarName.hide()
|
||||
else
|
||||
@grammarName.text(grammar.name).show()
|
||||
|
||||
@@ -73,7 +74,7 @@ class StatusBarView extends View
|
||||
@isModified = false
|
||||
|
||||
updateBranchText: ->
|
||||
path = @editor.getPath()
|
||||
path = @getActiveItemPath()
|
||||
@branchArea.hide()
|
||||
return unless path
|
||||
|
||||
@@ -82,7 +83,7 @@ class StatusBarView extends View
|
||||
@branchArea.show() if head
|
||||
|
||||
updateStatusText: ->
|
||||
path = @editor.getPath()
|
||||
path = @getActiveItemPath()
|
||||
@gitStatusIcon.removeClass()
|
||||
return unless path
|
||||
|
||||
@@ -113,17 +114,24 @@ class StatusBarView extends View
|
||||
@gitStatusIcon.text('')
|
||||
else if git.isStatusNew(status)
|
||||
@gitStatusIcon.addClass('new-status-icon')
|
||||
@gitStatusIcon.text("+#{@buffer.getLineCount()}")
|
||||
if @buffer?
|
||||
@gitStatusIcon.text("+#{@buffer.getLineCount()}")
|
||||
else
|
||||
@gitStatusIcon.text('')
|
||||
else if git.isPathIgnored(path)
|
||||
@gitStatusIcon.addClass('ignored-status-icon')
|
||||
@gitStatusIcon.text('')
|
||||
|
||||
updatePathText: ->
|
||||
if path = @editor.getPath()
|
||||
@currentPath.text(project.relativize(path))
|
||||
if path = @getActiveItemPath()
|
||||
@currentPath.text(project.relativize(path)).show()
|
||||
else if title = @pane.activeItem.getTitle?()
|
||||
@currentPath.text(title).show()
|
||||
else
|
||||
@currentPath.text('untitled')
|
||||
@currentPath.hide()
|
||||
|
||||
updateCursorPositionText: ->
|
||||
{ row, column } = @editor.getCursorBufferPosition()
|
||||
@cursorPosition.text("#{row + 1},#{column + 1}")
|
||||
if position = @pane.activeView.getCursorBufferPosition?()
|
||||
@cursorPosition.text("#{position.row + 1},#{position.column + 1}").show()
|
||||
else
|
||||
@cursorPosition.hide()
|
||||
|
||||
@@ -3,6 +3,7 @@ _ = require 'underscore'
|
||||
RootView = require 'root-view'
|
||||
StatusBar = require 'status-bar/lib/status-bar-view'
|
||||
fsUtils = require 'fs-utils'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
describe "StatusBar", ->
|
||||
[editor, statusBar, buffer] = []
|
||||
@@ -102,7 +103,9 @@ describe "StatusBar", ->
|
||||
|
||||
describe "when the associated editor's cursor position changes", ->
|
||||
it "updates the cursor position in the status bar", ->
|
||||
rootView.attachToDom()
|
||||
editor.setCursorScreenPosition([1, 2])
|
||||
editor.updateDisplay()
|
||||
expect(statusBar.cursorPosition.text()).toBe '2,3'
|
||||
|
||||
describe "git branch label", ->
|
||||
@@ -192,7 +195,6 @@ describe "StatusBar", ->
|
||||
editor.activeEditSession.languageMode.grammar = syntax.nullGrammar
|
||||
editor.activeEditSession.trigger 'grammar-changed'
|
||||
expect(statusBar.find('.grammar-name')).toBeHidden()
|
||||
expect(statusBar.find('.grammar-name').text()).toBe ''
|
||||
editor.reloadGrammar()
|
||||
expect(statusBar.find('.grammar-name')).toBeVisible()
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'JavaScript'
|
||||
@@ -209,3 +211,26 @@ describe "StatusBar", ->
|
||||
editor.on 'grammar-selector:show', eventHandler
|
||||
statusBar.find('.grammar-name').click()
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the active item view does not implement getCursorBufferPosition()", ->
|
||||
it "hides the cursor position view", ->
|
||||
rootView.attachToDom()
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
editor.getPane().showItem(view)
|
||||
expect(statusBar.cursorPosition).toBeHidden()
|
||||
|
||||
describe "when the active item implements getTitle() but not getPath()", ->
|
||||
it "displays the title", ->
|
||||
rootView.attachToDom()
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
view.getTitle = => 'View Title'
|
||||
editor.getPane().showItem(view)
|
||||
expect(statusBar.currentPath.text()).toBe 'View Title'
|
||||
expect(statusBar.currentPath).toBeVisible()
|
||||
|
||||
describe "when the active item neither getTitle() nor getPath()", ->
|
||||
it "hides the path view", ->
|
||||
rootView.attachToDom()
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
editor.getPane().showItem(view)
|
||||
expect(statusBar.currentPath).toBeHidden()
|
||||
|
||||
@@ -77,11 +77,8 @@ class TabBarView extends View
|
||||
(@paneContainer.getPanes().length > 1) or (@pane.getItems().length > 1)
|
||||
|
||||
onDragStart: (event) =>
|
||||
unless @shouldAllowDrag(event)
|
||||
event.preventDefault()
|
||||
return
|
||||
|
||||
event.originalEvent.dataTransfer.setData 'atom-event', 'true'
|
||||
if @shouldAllowDrag()
|
||||
event.originalEvent.dataTransfer.setData 'atom-event', 'true'
|
||||
|
||||
el = $(event.target).closest('.sortable')
|
||||
el.addClass 'is-dragging'
|
||||
@@ -91,8 +88,15 @@ class TabBarView extends View
|
||||
paneIndex = @paneContainer.indexOfPane(pane)
|
||||
event.originalEvent.dataTransfer.setData 'from-pane-index', paneIndex
|
||||
|
||||
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()
|
||||
|
||||
onDragEnd: (event) =>
|
||||
@find(".is-dragging").removeClass 'is-dragging'
|
||||
@children('.is-drop-target').removeClass 'is-drop-target'
|
||||
@children('.drop-target-is-after').removeClass 'drop-target-is-after'
|
||||
|
||||
onDragOver: (event) =>
|
||||
unless event.originalEvent.dataTransfer.getData('atom-event') is 'true'
|
||||
@@ -120,8 +124,6 @@ class TabBarView extends View
|
||||
return
|
||||
|
||||
event.stopPropagation()
|
||||
@children('.is-drop-target').removeClass 'is-drop-target'
|
||||
@children('.drop-target-is-after').removeClass 'drop-target-is-after'
|
||||
|
||||
dataTransfer = event.originalEvent.dataTransfer
|
||||
fromIndex = parseInt(dataTransfer.getData('sortable-index'))
|
||||
|
||||
@@ -279,8 +279,8 @@ describe "TabBarView", ->
|
||||
expect(pane2.activeItem).toBe item1
|
||||
expect(pane2.focus).toHaveBeenCalled()
|
||||
|
||||
describe 'when a non-tab is dragged to pane', ->
|
||||
it 'has no effect', ->
|
||||
describe "when a non-tab is dragged to pane", ->
|
||||
it "has no effect", ->
|
||||
expect(tabBar.getTabs().map (tab) -> tab.text()).toEqual ["Item 1", "sample.js", "Item 2"]
|
||||
expect(pane.getItems()).toEqual [item1, editSession1, item2]
|
||||
expect(pane.activeItem).toBe item2
|
||||
@@ -294,3 +294,11 @@ describe "TabBarView", ->
|
||||
expect(pane.activeItem).toBe item2
|
||||
expect(pane.focus).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a tab is dragged out of application", ->
|
||||
it "should carry file's information", ->
|
||||
[dragStartEvent, dropEvent] = buildDragEvents(tabBar.tabAtIndex(1), tabBar.tabAtIndex(1))
|
||||
tabBar.onDragStart(dragStartEvent)
|
||||
|
||||
expect(dragStartEvent.originalEvent.dataTransfer.getData("text/plain")).toEqual editSession1.getPath()
|
||||
expect(dragStartEvent.originalEvent.dataTransfer.getData("text/uri-list")).toEqual 'file://' + editSession1.getPath()
|
||||
|
||||
|
||||
@@ -4,5 +4,10 @@ module.exports =
|
||||
@subscriptions ?= []
|
||||
@subscriptions.push(cancel: -> eventEmitter.off eventName, callback)
|
||||
|
||||
subscribeToCommand: (view, eventName, callback) ->
|
||||
view.command eventName, callback
|
||||
@subscriptions ?= []
|
||||
@subscriptions.push(cancel: -> view.off eventName, callback)
|
||||
|
||||
unsubscribe: ->
|
||||
subscription.cancel() for subscription in @subscriptions ? []
|
||||
|
||||
14
static/image-view.less
Normal file
14
static/image-view.less
Normal file
@@ -0,0 +1,14 @@
|
||||
.image-view {
|
||||
height:100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
|
||||
img {
|
||||
padding: 25px;
|
||||
border: 2px solid;
|
||||
background-image: url(images/transparent-background.gif);
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
BIN
static/images/transparent-background.gif
Normal file
BIN
static/images/transparent-background.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 B |
7
themes/atom-dark-ui/image-view.less
Normal file
7
themes/atom-dark-ui/image-view.less
Normal file
@@ -0,0 +1,7 @@
|
||||
.image-view {
|
||||
background-color: #1d1f21;
|
||||
|
||||
img {
|
||||
border-color: #c5c8c6;
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,5 @@
|
||||
'command-panel'
|
||||
'command-logger'
|
||||
'blurred'
|
||||
'image-view'
|
||||
]
|
||||
|
||||
7
themes/atom-light-ui/image-view.less
Normal file
7
themes/atom-light-ui/image-view.less
Normal file
@@ -0,0 +1,7 @@
|
||||
.image-view {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.image-view img {
|
||||
border-color: #ccc;
|
||||
}
|
||||
@@ -9,4 +9,5 @@
|
||||
'command-panel'
|
||||
'command-logger'
|
||||
'blurred'
|
||||
'image-view'
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user