Merge pull request #1691 from ethereum/swapit_mainView

Move tab logic outside of editor panel
pull/1/head
yann300 6 years ago committed by GitHub
commit 838135a75c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 59
      src/app/files/fileManager.js
  2. 120
      src/app/panels/editor-panel.js
  3. 182
      src/app/panels/left-icon-panel.js
  4. 176
      src/app/panels/tab-proxy.js

@ -1,7 +1,5 @@
'use strict' 'use strict'
var $ = require('jquery')
var yo = require('yo-yo')
var EventEmitter = require('events') var EventEmitter = require('events')
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
@ -14,7 +12,7 @@ var CompilerImport = require('../compiler/compiler-imports')
class FileManager { class FileManager {
constructor (localRegistry) { constructor (localRegistry) {
this.tabbedFiles = {} this.openedFiles = {} // list all opened files
this.event = new EventManager() this.event = new EventManager()
this.nodeEvent = new EventEmitter() this.nodeEvent = new EventEmitter()
this._components = {} this._components = {}
@ -64,18 +62,18 @@ class FileManager {
if (!isFolder) { if (!isFolder) {
self._deps.config.set('currentFile', '') self._deps.config.set('currentFile', '')
self._deps.editor.discard(oldName) self._deps.editor.discard(oldName)
if (this.tabbedFiles[oldName]) { if (this.openedFiles[oldName]) {
delete this.tabbedFiles[oldName] delete this.openedFiles[oldName]
this.tabbedFiles[newName] = newName this.openedFiles[newName] = newName
} }
this.switchFile(newName) this.switchFile(newName)
} else { } else {
var newFocus var newFocus
for (var k in this.tabbedFiles) { for (var k in this.openedFiles) {
if (k.indexOf(oldName + '/') === 0) { if (k.indexOf(oldName + '/') === 0) {
var newAbsolutePath = k.replace(oldName, newName) var newAbsolutePath = k.replace(oldName, newName)
this.tabbedFiles[newAbsolutePath] = newAbsolutePath this.openedFiles[newAbsolutePath] = newAbsolutePath
delete this.tabbedFiles[k] delete this.openedFiles[k]
if (self._deps.config.get('currentFile') === k) { if (self._deps.config.get('currentFile') === k) {
newFocus = newAbsolutePath newFocus = newAbsolutePath
} }
@ -85,7 +83,7 @@ class FileManager {
this.switchFile(newFocus) this.switchFile(newFocus)
} }
} }
this.refreshTabs() this.event.trigger('fileRenamed', [oldName, newName])
} }
currentFileProvider () { currentFileProvider () {
@ -101,6 +99,17 @@ class FileManager {
return self._deps.config.get('currentFile') return self._deps.config.get('currentFile')
} }
closeFile (name) {
delete this.openedFiles[name]
if (Object.keys(this.openedFiles).length) {
this.switchFile(Object.keys(this.openedFiles)[0])
} else {
this._deps.editor.displayEmptyReadOnlySession()
this._deps.config.set('currentFile', '')
}
this.event.trigger('fileClosed', [name])
}
currentPath () { currentPath () {
var self = this var self = this
var currentFile = self._deps.config.get('currentFile') var currentFile = self._deps.config.get('currentFile')
@ -145,7 +154,7 @@ class FileManager {
} }
removeTabsOf (provider) { removeTabsOf (provider) {
for (var tab in this.tabbedFiles) { for (var tab in this.openedFiles) {
if (this.fileProviderOf(tab).type === provider.type) { if (this.fileProviderOf(tab).type === provider.type) {
this.fileRemovedEvent(tab) this.fileRemovedEvent(tab)
} }
@ -154,36 +163,16 @@ class FileManager {
fileRemovedEvent (path) { fileRemovedEvent (path) {
var self = this var self = this
if (!this.tabbedFiles[path]) return if (!this.openedFiles[path]) return
if (path === self._deps.config.get('currentFile')) { if (path === self._deps.config.get('currentFile')) {
self._deps.config.set('currentFile', '') self._deps.config.set('currentFile', '')
} }
self._deps.editor.discard(path) self._deps.editor.discard(path)
delete this.tabbedFiles[path] delete this.openedFiles[path]
this.refreshTabs() this.event.trigger('fileRemoved', [path])
this.switchFile() this.switchFile()
} }
// Display files that have already been selected
refreshTabs (newfile) {
if (newfile) {
this.tabbedFiles[newfile] = newfile
}
var $filesEl = $('#files')
$filesEl.find('.file').remove()
for (var file in this.tabbedFiles) {
$filesEl.append(yo`<li class="file"><span class="name">${file}</span><span class="remove"><i class="fa fa-close"></i></span></li>`)
}
var active = $('#files .file').filter(function () {
return $(this).find('.name').text() === newfile
})
if (active.length) active.addClass('active')
$('#output').toggle(active)
}
switchFile (file) { switchFile (file) {
var self = this var self = this
if (file) return _switchFile(file) if (file) return _switchFile(file)
@ -203,7 +192,7 @@ class FileManager {
function _switchFile (file) { function _switchFile (file) {
self.saveCurrentFile() self.saveCurrentFile()
self._deps.config.set('currentFile', file) self._deps.config.set('currentFile', file)
self.refreshTabs(file) self.openedFiles[file] = file
self.fileProviderOf(file).get(file, (error, content) => { self.fileProviderOf(file).get(file, (error, content) => {
if (error) { if (error) {
console.log(error) console.log(error)

@ -1,10 +1,10 @@
var yo = require('yo-yo') var yo = require('yo-yo')
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
var $ = require('jquery')
var Terminal = require('./terminal') var Terminal = require('./terminal')
var Editor = require('../editor/editor') var Editor = require('../editor/editor')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
var { TabProxy } = require('./tab-proxy.js')
var ContextualListener = require('../editor/contextualListener') var ContextualListener = require('../editor/contextualListener')
var ContextView = require('../editor/contextView') var ContextView = require('../editor/contextView')
@ -41,6 +41,7 @@ class EditorPanel {
udapp: self._components.registry.get('udapp').api, udapp: self._components.registry.get('udapp').api,
pluginManager: self._components.registry.get('pluginmanager').api pluginManager: self._components.registry.get('pluginmanager').api
} }
self.tabProxy = new TabProxy(self._deps.fileManager, self._components.editor)
self.data = { self.data = {
_FILE_SCROLL_DELTA: 200, _FILE_SCROLL_DELTA: 200,
_layout: { _layout: {
@ -140,7 +141,7 @@ class EditorPanel {
self._view.terminal = self._components.terminal.render() self._view.terminal = self._components.terminal.render()
self._view.content = yo` self._view.content = yo`
<div class=${css.content}> <div class=${css.content}>
${self._renderTabsbar()} ${self.tabProxy.renderTabsbar()}
<div class=${css.contextviewcontainer}> <div class=${css.contextviewcontainer}>
${self._components.contextView.render()} ${self._components.contextView.render()}
</div> </div>
@ -164,121 +165,6 @@ class EditorPanel {
updateTerminalFilter (filter) { updateTerminalFilter (filter) {
this._components.terminal.updateJournal(filter) this._components.terminal.updateJournal(filter)
} }
_renderTabsbar () {
var self = this
if (self._view.tabsbar) return self._view.tabsbar
self._view.filetabs = yo`<ul id="files" class="${css.files} nav nav-tabs"></ul>`
self._view.tabs = yo`
<div class=${css.tabs} onmouseenter=${toggleScrollers} onmouseleave=${toggleScrollers}>
<div onclick=${scrollLeft} class="${css.scroller} ${css.hide} ${css.scrollerleft}">
<i class="fa fa-chevron-left "></i>
</div>
${self._view.filetabs}
<div onclick=${scrollRight} class="${css.scroller} ${css.hide} ${css.scrollerright}">
<i class="fa fa-chevron-right "></i>
</div>
</div>
`
self._view.tabsbar = yo`
<div class=${css.tabsbar}>
<div class=${css.buttons}>
<span class=${css.changeeditorfontsize} >
<i class="increditorsize fa fa-plus" onclick=${increase} aria-hidden="true" title="increase editor font size"></i>
<i class="decreditorsize fa fa-minus" onclick=${decrease} aria-hidden="true" title="decrease editor font size"></i>
</span>
</div>
${self._view.tabs}
</div>
`
// tabs
var $filesEl = $(self._view.filetabs)
// Switch tab
$filesEl.on('click', '.file:not(.active)', function (ev) {
ev.preventDefault()
self._deps.fileManager.switchFile($(this).find('.name').text())
return false
})
// Remove current tab
$filesEl.on('click', '.file .remove', function (ev) {
ev.preventDefault()
var name = $(this).parent().find('.name').text()
delete self._deps.fileManager.tabbedFiles[name]
self._deps.fileManager.refreshTabs()
if (Object.keys(self._deps.fileManager.tabbedFiles).length) {
self._deps.fileManager.switchFile(Object.keys(self._deps.fileManager.tabbedFiles)[0])
} else {
self._components.editor.displayEmptyReadOnlySession()
self._deps.config.set('currentFile', '')
}
return false
})
return self._view.tabsbar
function toggleScrollers (event = {}) {
if (event.type) self.data._focus = event.type
var isMouseEnter = self.data._focus === 'mouseenter'
var leftArrow = this.children[0]
var rightArrow = this.children[2]
if (isMouseEnter && this.children[1].offsetWidth > this.offsetWidth) {
var hiddenLength = self._view.filetabs.offsetWidth - self._view.tabs.offsetWidth
var currentLeft = self._view.filetabs.offsetLeft || 0
var hiddenRight = hiddenLength + currentLeft
if (currentLeft < 0) {
leftArrow.classList.add(css.show)
leftArrow.classList.remove(css.hide)
}
if (hiddenRight > 0) {
rightArrow.classList.add(css.show)
rightArrow.classList.remove(css.hide)
}
} else {
leftArrow.classList.remove(css.show)
leftArrow.classList.add(css.hide)
rightArrow.classList.remove(css.show)
rightArrow.classList.add(css.hide)
}
}
function increase () { self._components.editor.editorFontSize(1) }
function decrease () { self._components.editor.editorFontSize(-1) }
function scrollLeft (event) {
var leftArrow = this
var rightArrow = this.nextElementSibling.nextElementSibling
var currentLeft = self._view.filetabs.offsetLeft || 0
if (currentLeft < 0) {
rightArrow.classList.add(css.show)
rightArrow.classList.remove(css.hide)
if (currentLeft < -self.data._FILE_SCROLL_DELTA) {
self._view.filetabs.style.left = `${currentLeft + self.data._FILE_SCROLL_DELTA}px`
} else {
self._view.filetabs.style.left = `${currentLeft - currentLeft}px`
leftArrow.classList.remove(css.show)
leftArrow.classList.add(css.hide)
}
}
}
function scrollRight (event) {
var rightArrow = this
var leftArrow = this.previousElementSibling.previousElementSibling
var hiddenLength = self._view.filetabs.offsetWidth - self._view.tabs.offsetWidth
var currentLeft = self._view.filetabs.offsetLeft || 0
var hiddenRight = hiddenLength + currentLeft
if (hiddenRight > 0) {
leftArrow.classList.add(css.show)
leftArrow.classList.remove(css.hide)
if (hiddenRight > self.data._FILE_SCROLL_DELTA) {
self._view.filetabs.style.left = `${currentLeft - self.data._FILE_SCROLL_DELTA}px`
} else {
self._view.filetabs.style.left = `${currentLeft - hiddenRight}px`
rightArrow.classList.remove(css.show)
rightArrow.classList.add(css.hide)
}
}
}
}
} }
module.exports = EditorPanel module.exports = EditorPanel

@ -1,182 +0,0 @@
const yo = require('yo-yo')
const csjs = require('csjs-inject')
const remixLib = require('remix-lib')
var globalRegistry = require('../../global/registry')
const styleguide = require('../ui/styles-guide/theme-chooser')
const styles = styleguide.chooser()
// const PluginManager = require('../plugin/pluginManager')
// const TabbedMenu = require('../tabs/tabbed-menu')
// const CompileTab = require('../tabs/compile-tab')
// const SettingsTab = require('../tabs/settings-tab')
// const AnalysisTab = require('../tabs/analysis-tab')
// const DebuggerTab = require('../tabs/debugger-tab')
// const SupportTab = require('../tabs/support-tab')
// const PluginTab = require('../tabs/plugin-tab')
// const TestTab = require('../tabs/test-tab')
// const RunTab = require('../tabs/run-tab')
// const DraggableContent = require('../ui/draggableContent')
const EventManager = remixLib.EventManager
// var async = require('async')
// var tooltip = require('../ui/tooltip')
// var styleGuide = require('../ui/styles-guide/theme-chooser')
// var css = require('./styles/file-panel-styles')
// var canUpload = window.File || window.FileReader || window.FileList || window.Blob
// var ghostbar = yo`<div class=${css.ghostbar}></div>`
/*
Overview of APIs:
* fileManager: @args fileProviders (browser, shared-folder, swarm, github, etc ...) & config & editor
- listen on browser & localhost file provider (`fileRenamed` & `fileRemoved`)
- update the tabs, switchFile
- trigger `currentFileChanged`
- set the current file in the config
* fileProvider: currently browser, swarm, localhost, github, gist
- link to backend
- provide properties `type`, `readonly`
- provide API `resolveDirectory`, `remove`, `exists`, `rename`, `get`, `set`
- trigger `fileExternallyChanged`, `fileRemoved`, `fileRenamed`, `fileRenamedError`, `fileAdded`
* file-explorer: treeview @args fileProvider
- listen on events triggered by fileProvider
- call fileProvider API
*/
module.exports = class LeftIconPanel {
constructor (localRegistry) {
const self = this
self._components = {}
self._components.registry = localRegistry || globalRegistry
self._components.registry.put({api: this, name: 'lefticonpanel'})
self.event = new EventManager()
self._view = {
element: null,
tabbedMenu: null,
tabbedMenuViewport: null,
dragbar: null
}
self.plugins = [
{type: 'fileManager', displayName: 'File Manger', icon: 'fa fa-files-o fa-2x'},
{type: 'pluginManager', displayName: 'Plugin Manger', icon: 'fa fa-puzzle-piece fa-2x'},
{type: 'settings', displayName: 'setting', icon: 'fa fa-cog fa-2x'}
]
}
swapPlugin (name) {
console.log(name)
}
render () {
const self = this
// if (self._view.element) return self._view.element
// return self._view.element
return yo`
<div class=${css.container}>
<ul>
${self.plugins.map(function (pi) {
return yo`<li>
<i onclick=${() => { self.swapPlugin(pi.type) }} style="size: 24px;" class="${pi.icon} ${css.plugin}"></i>
</li>`
})
}
</ul>
</div>
`
}
init () {
// @TODO: init is for resizable drag bar only and should be refactored in the future
const self = this
const limit = 60
self._view.dragbar.addEventListener('mousedown', mousedown)
const ghostbar = yo`<div class=${css.ghostbar}></div>`
function mousedown (event) {
event.preventDefault()
if (event.which === 1) {
moveGhostbar(event)
document.body.appendChild(ghostbar)
document.addEventListener('mousemove', moveGhostbar)
document.addEventListener('mouseup', removeGhostbar)
document.addEventListener('keydown', cancelGhostbar)
}
}
function cancelGhostbar (event) {
if (event.keyCode === 27) {
document.body.removeChild(ghostbar)
document.removeEventListener('mousemove', moveGhostbar)
document.removeEventListener('mouseup', removeGhostbar)
document.removeEventListener('keydown', cancelGhostbar)
}
}
function getPosition (event) {
const lhp = window['filepanel'].offsetWidth
const max = document.body.offsetWidth - limit
var newpos = (event.pageX > max) ? max : event.pageX
newpos = (newpos > (lhp + limit)) ? newpos : lhp + limit
return newpos
}
function moveGhostbar (event) { // @NOTE VERTICAL ghostbar
ghostbar.style.left = getPosition(event) + 'px'
}
function removeGhostbar (event) {
document.body.removeChild(ghostbar)
document.removeEventListener('mousemove', moveGhostbar)
document.removeEventListener('mouseup', removeGhostbar)
document.removeEventListener('keydown', cancelGhostbar)
}
}
}
const css = csjs`
.lefticonpanel {
display : flex;
flex-direction : column;
top : 0;
right : 0;
bottom : 0;
box-sizing : border-box;
overflow : hidden;
height : 100%;
}
.header {
height : 100%;
}
.dragbar {
position : absolute;
width : ${styles.rightPanel.dragbarWidth};
top : 3em;
bottom : 0;
cursor : col-resize;
background-color : ${styles.rightPanel.dragbarBackgroundColor};
z-index : 999;
border-left : 2px solid ${styles.rightPanel.bar_Dragging};
}
.ghostbar {
width : 3px;
background-color : ${styles.rightPanel.bar_Ghost};
opacity : 0.5;
position : absolute;
cursor : col-resize;
z-index : 9999;
top : 0;
bottom : 0;
}
i.plugin {
cursor : pointer;
}
.container ul {
margin-top : 10px;
}
.container ul li {
text-align : center;
margin-top : 10px;
}
`

@ -0,0 +1,176 @@
var yo = require('yo-yo')
var $ = require('jquery')
var styles = require('./styles/editor-panel-styles')
var css = styles.css
export class TabProxy {
constructor (fileManager, editor) {
this.fileManager = fileManager
this.editor = editor
this.activeEntity
this.entities = {}
this.data = {}
this._view = {}
fileManager.event.register('fileRemoved', (name) => {
const filesEl = document.querySelector('#files')
var file = filesEl.querySelector(`li[path="${name}"]`)
if (file) {
filesEl.removeChild(file)
}
})
fileManager.event.register('fileClosed', (name) => {
const filesEl = document.querySelector('#files')
var file = filesEl.querySelector(`li[path="${name}"]`)
if (file) {
filesEl.removeChild(file)
}
})
fileManager.event.register('currentFileChanged', (file) => {
const filesEl = document.querySelector('#files')
if (!filesEl.querySelector(`li[path="${file}"]`)) {
filesEl.appendChild(yo`<li class="file" path="${file}" ><span class="name">${file}</span><span class="remove"><i class="fa fa-close"></i></span></li>`)
}
this.active(file)
})
fileManager.event.register('fileRenamed', (oldName, newName) => {
const filesEl = document.querySelector('#files')
var file = filesEl.querySelector(`li[path="${oldName}"]`)
if (file) {
filesEl.setAttribute('path', file)
file.querySelector(`.name`).innerHTML = newName
}
})
}
active (name) {
var filesEl = document.querySelector('#files')
let file = filesEl.querySelector(`li[path="${this.activeEntity}"]`)
if (file) $(file).removeClass('active')
if (name) {
let active = filesEl.querySelector(`li[path="${name}"]`)
if (active) {
$(active).addClass('active')
this.activeEntity = name
}
}
}
addHandler (type, fn) {
this.handlers[type] = fn
}
renderTabsbar () {
this._view.filetabs = yo`<ul id="files" class="${css.files} nav nav-tabs"></ul>`
this._view.tabs = yo`
<div class=${css.tabs} onmouseenter=${toggleScrollers} onmouseleave=${toggleScrollers}>
<div onclick=${scrollLeft} class="${css.scroller} ${css.hide} ${css.scrollerleft}">
<i class="fa fa-chevron-left "></i>
</div>
${this._view.filetabs}
<div onclick=${scrollRight} class="${css.scroller} ${css.hide} ${css.scrollerright}">
<i class="fa fa-chevron-right "></i>
</div>
</div>
`
let tabsbar = yo`
<div class=${css.tabsbar}>
<div class=${css.buttons}>
<span class=${css.changeeditorfontsize} >
<i class="increditorsize fa fa-plus" onclick=${increase} aria-hidden="true" title="increase editor font size"></i>
<i class="decreditorsize fa fa-minus" onclick=${decrease} aria-hidden="true" title="decrease editor font size"></i>
</span>
</div>
${this._view.tabs}
</div>
`
// tabs
var $filesEl = $(this._view.filetabs)
// Switch tab
var self = this
$filesEl.on('click', '.file:not(.active)', function (ev) {
ev.preventDefault()
self.fileManager.switchFile($(this).find('.name').text())
return false
})
// Remove current tab
$filesEl.on('click', '.file .remove', function (ev) {
ev.preventDefault()
var name = $(this).parent().find('.name').text()
self.fileManager.closeFile(name)
return false
})
function toggleScrollers (event = {}) {
if (event.type) self.data._focus = event.type
var isMouseEnter = self.data._focus === 'mouseenter'
var leftArrow = this.children[0]
var rightArrow = this.children[2]
if (isMouseEnter && this.children[1].offsetWidth > this.offsetWidth) {
var hiddenLength = self._view.filetabs.offsetWidth - self._view.tabs.offsetWidth
var currentLeft = self._view.filetabs.offsetLeft || 0
var hiddenRight = hiddenLength + currentLeft
if (currentLeft < 0) {
leftArrow.classList.add(css.show)
leftArrow.classList.remove(css.hide)
}
if (hiddenRight > 0) {
rightArrow.classList.add(css.show)
rightArrow.classList.remove(css.hide)
}
} else {
leftArrow.classList.remove(css.show)
leftArrow.classList.add(css.hide)
rightArrow.classList.remove(css.show)
rightArrow.classList.add(css.hide)
}
}
function increase () { self.editor.editorFontSize(1) }
function decrease () { self.editor.editorFontSize(-1) }
function scrollLeft (event) {
var leftArrow = this
var rightArrow = this.nextElementSibling.nextElementSibling
var currentLeft = self._view.filetabs.offsetLeft || 0
if (currentLeft < 0) {
rightArrow.classList.add(css.show)
rightArrow.classList.remove(css.hide)
if (currentLeft < -self.data._FILE_SCROLL_DELTA) {
self._view.filetabs.style.left = `${currentLeft + self.data._FILE_SCROLL_DELTA}px`
} else {
self._view.filetabs.style.left = `${currentLeft - currentLeft}px`
leftArrow.classList.remove(css.show)
leftArrow.classList.add(css.hide)
}
}
}
function scrollRight (event) {
var rightArrow = this
var leftArrow = this.previousElementSibling.previousElementSibling
var hiddenLength = self._view.filetabs.offsetWidth - self._view.tabs.offsetWidth
var currentLeft = self._view.filetabs.offsetLeft || 0
var hiddenRight = hiddenLength + currentLeft
if (hiddenRight > 0) {
leftArrow.classList.add(css.show)
leftArrow.classList.remove(css.hide)
if (hiddenRight > self.data._FILE_SCROLL_DELTA) {
self._view.filetabs.style.left = `${currentLeft - self.data._FILE_SCROLL_DELTA}px`
} else {
self._view.filetabs.style.left = `${currentLeft - hiddenRight}px`
rightArrow.classList.remove(css.show)
rightArrow.classList.add(css.hide)
}
}
}
return tabsbar
}
}
Loading…
Cancel
Save