diff --git a/assets/css/browser-solidity.css b/assets/css/browser-solidity.css index 6b0c5db3ea..7c897d33e7 100644 --- a/assets/css/browser-solidity.css +++ b/assets/css/browser-solidity.css @@ -1,43 +1,3 @@ -.scroller { - position: absolute; - z-index: 999; - text-align: center; - cursor: pointer; - display: none; - padding: 0 0.9em; - vertical-align: middle; - background-color: rgba(255, 255, 255, 0.8); - height: 100%; - font-size: 1.3em; -} - -.scroller i { - line-height: 3em; -} - -.scroller-right { - right: 0; -} - -.scroller-left { - left: 0; -} - -#files { - list-style: none; - margin: 0; - font-size: 15px; - height: 2.5em; - box-sizing: border-box; - line-height: 2em; - padding: 0.5em 0 0; - position: relative; - left: 40px; - top:0; - min-width:3000px; - border-bottom: 0 none; -} - #files .file { padding: 0 0.6em; box-sizing: border-box; @@ -51,22 +11,6 @@ color: #999; } -.toggleRHP { - display: block; - float: left; - margin-top: 0.5em; - padding: 0.6em; - font-weight: bold; - cursor: pointer; - color: black; -} - -.toggleRHP { - float: right; - position: absolute; - right: 0; -} - #files .file.active { color: black; font-weight: bold; @@ -98,18 +42,6 @@ display: inline-block; } -#righthand-panel { - position: absolute; - top: 0; - width: 37em; - max-width: 80vw; - right: 0; - bottom: 0; - overflow: auto; - box-sizing: border-box; - overflow: hidden; -} - #header { font-size: 13px; height: 100%; @@ -378,17 +310,6 @@ border: .2em dotted #ffbd01; } -#ghostbar { - width: 1px; - background-color: red; - opacity: 0.5; - position: absolute; - cursor: col-resize; - z-index: 9999; - top: 0; - bottom: 0; -} - input[readonly] { display: block; width: 100%; diff --git a/src/app.js b/src/app.js index aa3338f887..53e587fbca 100644 --- a/src/app.js +++ b/src/app.js @@ -26,6 +26,7 @@ var ExecutionContext = require('./app/execution-context') var Debugger = require('./app/debugger') var StaticAnalysis = require('./app/staticanalysis/staticAnalysisView') var FilePanel = require('./app/file-panel') +var EditorPanel = require('./app/editor-panel') var RighthandPanel = require('./app/righthand-panel') var examples = require('./app/example-contracts') @@ -43,44 +44,88 @@ var css = csjs` position : relative; width : 100vw; height : 100vh; + overflow : hidden; } .centerpanel { display : flex; flex-direction : column; position : absolute; top : 0; - left : 200px; - right : 0; bottom : 0; - } - .tabsbar { overflow : hidden; } .leftpanel { display : flex; + flex-direction : column; position : absolute; top : 0; - left : 0; - right : 0; bottom : 0; - width : 200px; + left : 0; + overflow : hidden; } - .dragbar2 { - background-color : transparent; + .rightpanel { + display : flex; + flex-direction : column; position : absolute; - width : 0.5em; - top : 3em; + top : 0; + right : 0; bottom : 0; - cursor : col-resize; - z-index : 999; - border-right : 2px solid hsla(215, 81%, 79%, .3); + overflow : hidden; } ` class App { constructor (opts = {}) { var self = this + self._api = {} + var fileStorage = new Storage('sol:') + self._api.config = new Config(fileStorage) + self._api.filesProviders = {} + self._api.filesProviders['browser'] = new Browserfiles(fileStorage) + self._api.filesProviders['localhost'] = new SharedFolder(new Remixd()) self._view = {} + self._components = {} + self.data = { + _layout: { + right: { + offset: self._api.config.get('right-offset') || 400, + show: true + }, // @TODO: adapt sizes proportionally to browser window size + left: { + offset: self._api.config.get('left-offset') || 200, + show: true + } + } + } + // ----------------- editor ---------------------------- + self._components.editor = new Editor({}) // @TODO: put into editorpanel + // ----------------- editor panel ---------------------- + self._components.editorpanel = new EditorPanel({ + api: { editor: self._components.editor } + }) + self._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction)) + } + _adjustLayout (direction, delta) { + var self = this + var layout = self.data._layout[direction] + if (layout) { + if (delta === undefined) { + layout.show = !layout.show + if (layout.show) delta = layout.offset + else delta = 0 + } else { + self._api.config.set(`${direction}-offset`, delta) + layout.offset = delta + } + } + if (direction === 'left') { + self._view.leftpanel.style.width = delta + 'px' + self._view.centerpanel.style.left = delta + 'px' + } + if (direction === 'right') { + self._view.rightpanel.style.width = delta + 'px' + self._view.centerpanel.style.right = delta + 'px' + } } init () { var self = this @@ -89,31 +134,31 @@ class App { render () { var self = this if (self._view.el) return self._view.el - /***************************************************************************/ - self._view.leftpanel = yo`
` - self._view.rightpanel = yo`
` - self._view.tabsbar = yo` -
-
-
- + self._view.leftpanel = yo` +
+ ${''}
` self._view.centerpanel = yo`
- ${self._view.tabsbar} -
+ ${self._components.editorpanel.render()} +
+ ` + self._view.rightpanel = yo` +
+ ${''}
` self._view.el = yo`
${self._view.leftpanel} - ${self._view.centerpanel} -
${self._view.rightpanel}
` + // INIT + self._adjustLayout('left', self.data._layout.left.offset) + self._adjustLayout('right', self.data._layout.right.offset) return self._view.el } } @@ -126,6 +171,7 @@ function run () { var queryParams = new QueryParams() var gistHandler = new GistHandler() + var editor = self._components.editor // The event listener needs to be registered as early as possible, because the // parent will send the message upon the "load" event. var filesToLoad = null @@ -138,12 +184,9 @@ function run () { }, false) this.event = new EventManager() - var fileStorage = new Storage('sol:') - var config = new Config(fileStorage) - var remixd = new Remixd() - var filesProviders = {} - filesProviders['browser'] = new Browserfiles(fileStorage) - filesProviders['localhost'] = new SharedFolder(remixd) + + var config = self._api.config + var filesProviders = self._api.filesProviders var tabbedFiles = {} // list of files displayed in the tabs bar @@ -271,9 +314,6 @@ function run () { createName: createNonClashingName, switchToFile: switchToFile, event: this.event, - editorFontSize: function (incr) { - editor.editorFontSize(incr) - }, currentFile: function () { return config.get('currentFile') }, @@ -288,29 +328,9 @@ function run () { // TODO this should happen inside file-panel.js var filepanelContainer = document.querySelector('#filepanel') - filepanelContainer.appendChild(filePanel) - - filePanel.events.register('ui-hidden', function changeLayout (isHidden) { - var value - if (isHidden) { - value = -parseInt(self._view.leftpanel.style.width) - value = (isNaN(value) ? -self._view.leftpanel.getBoundingClientRect().width : value) - self._view.leftpanel.style.position = 'absolute' - self._view.leftpanel.style.left = (value - 5) + 'px' - self._view.leftpanel.style.width = -value + 'px' - self._view.centerpanel.style.left = '45px' - } else { - value = -parseInt(self._view.leftpanel.style.left) + 'px' - self._view.leftpanel.style.position = 'static' - self._view.leftpanel.style.width = value - self._view.leftpanel.style.left = '' - self._view.centerpanel.style.left = value - } - }) - filePanel.events.register('ui-resize', function changeLayout (width) { - self._view.leftpanel.style.width = width + 'px' - self._view.centerpanel.style.left = width + 'px' - }) + filepanelContainer.appendChild(filePanel.render()) + + filePanel.event.register('resize', delta => self._adjustLayout('left', delta)) function fileRenamedEvent (oldName, newName, isFolder) { // TODO please never use 'window' when it is possible to use a variable @@ -411,12 +431,8 @@ function run () { }) }) - // ----------------- editor ---------------------- - var editor = new Editor(document.getElementById('input')) - // --------------------Files tabs----------------------------- var $filesEl = $('#files') - var FILE_SCROLL_DELTA = 300 // Switch tab $filesEl.on('click', '.file:not(.active)', function (ev) { @@ -497,7 +513,6 @@ function run () { for (var file in tabbedFiles) { $filesEl.append($('
  • ' + file + '
  • ')) } - var currentFileOpen = !!config.get('currentFile') if (currentFileOpen) { @@ -506,57 +521,9 @@ function run () { } $('#input').toggle(currentFileOpen) $('#output').toggle(currentFileOpen) + self._components.editorpanel.refresh() } - var $scrollerRight = $('.scroller-right') - var $scrollerLeft = $('.scroller-left') - - function widthOfList () { - var itemsWidth = 0 - $('.file').each(function () { - var itemWidth = $(this).outerWidth() - itemsWidth += itemWidth - }) - return itemsWidth - } - - function widthOfVisible () { - return document.querySelector('#editor-container').offsetWidth - } - - function getLeftPosi () { - return $filesEl.position().left - } - - function reAdjust () { - if (widthOfList() + getLeftPosi() > widthOfVisible()) { - $scrollerRight.fadeIn('fast') - } else { - $scrollerRight.fadeOut('fast') - } - - if (getLeftPosi() < 0) { - $scrollerLeft.fadeIn('fast') - } else { - $scrollerLeft.fadeOut('fast') - $filesEl.animate({ left: getLeftPosi() + 'px' }, 'slow') - } - } - - $scrollerRight.click(function () { - var delta = (getLeftPosi() - FILE_SCROLL_DELTA) - $filesEl.animate({ left: delta + 'px' }, 'slow', function () { - reAdjust() - }) - }) - - $scrollerLeft.click(function () { - var delta = Math.min((getLeftPosi() + FILE_SCROLL_DELTA), 0) - $filesEl.animate({ left: delta + 'px' }, 'slow', function () { - reAdjust() - }) - }) - var compiler = new Compiler(handleImportCall) var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) @@ -703,18 +670,9 @@ function run () { // ---------------- Righthand-panel -------------------- var rhpAPI = { config: config, - setEditorSize (delta) { - $('#righthand-panel').css('width', delta) - self._view.centerpanel.style.right = delta + 'px' - document.querySelector(`.${css.dragbar2}`).style.right = delta + 'px' - onResize() - }, - reAdjust: reAdjust, warnCompilerLoading: (msg) => { renderer.clear() - if (msg) { - renderer.error(msg, $('#output'), {type: 'warning'}) - } + if (msg) renderer.error(msg, $('#output'), {type: 'warning'}) }, executionContextChange: (context) => { return executionContext.executionContextChange(context) @@ -728,17 +686,16 @@ function run () { app: self.event, udapp: udapp.event } - var righthandPanel = new RighthandPanel(rhpAPI, rhpEvents, {}) // eslint-disable-line - self._view.rightpanel.appendChild(righthandPanel.render()) - righthandPanel.init() + self._components.righthandpanel = new RighthandPanel(rhpAPI, rhpEvents, {}) + self._view.rightpanel.appendChild(self._components.righthandpanel.render()) + self._components.righthandpanel.init() + self._components.righthandpanel.event.register('resize', delta => self._adjustLayout('right', delta)) // ----------------- editor resize --------------- function onResize () { editor.resize(document.querySelector('#editorWrap').checked) - reAdjust() } - window.onresize = onResize onResize() self._view.el.addEventListener('change', onResize) diff --git a/src/app/editor-panel.js b/src/app/editor-panel.js new file mode 100644 index 0000000000..5749563223 --- /dev/null +++ b/src/app/editor-panel.js @@ -0,0 +1,240 @@ +var csjs = require('csjs-inject') +var yo = require('yo-yo') +var EventManager = require('ethereum-remix').lib.EventManager + +var css = csjs` + .tabsbar { + display : flex; + overflow : hidden; + } + .tabs { + position : relative; + display : flex; + margin : 0; + left : 10px; + margin-right : 10px; + width : 100%; + overflow : hidden; + } + .files { + position : relative; + list-style : none; + margin : 0; + font-size : 15px; + height : 2.5em; + box-sizing : border-box; + line-height : 2em; + padding : 0.5em 0 0; + top : 0; + border-bottom : 0 none; + } + .changeeditorfontsize { + margin : 0; + } + .changeeditorfontsize i { + cursor : pointer; + display : block; + color : #111111; + } + .changeeditorfontsize i { + cursor : pointer; + } + .changeeditorfontsize i:hover { + color : orange; + } + .buttons { + display : flex; + flex-direction : row; + justify-content : space-around; + align-items : center; + min-width : 45px; + } + .toggleLHP { + display : flex; + padding : 10px; + width : 100%; + font-weight : bold; + color : black; + } + .toggleLHP i { + cursor : pointer; + } + .toggleLHP i:hover { + color : orange; + } + .scroller { + position : absolute; + z-index : 999; + text-align : center; + cursor : pointer; + padding : 0 0.9em; + vertical-align : middle; + background-color : rgba(255, 255, 255, 0.8); + height : 100%; + font-size : 1.3em; + } + .scroller i { + line-height : 3em; + } + .scrollerright { + right : 0; + margin-right : 15px; + } + .scrollerleft { + left : 0; + } + .toggleRHP { + margin-top : 0.5em; + padding : 0.6em; + font-weight : bold; + color : black; + right : 0; + } + .toggleRHP i { + cursor : pointer; + } + .toggleRHP i:hover { + color : orange; + } + .show { + opacity : 1; + transition : .3s opacity ease-in; + } + .hide { + opacity : 0; + pointer-events : none; + transition : .3s opacity ease-in; + } +` + +class EditorPanel { + constructor (opts = {}) { + var self = this + self.data = { + _FILE_SCROLL_DELTA: 200 + } + self._view = {} + self._api = { editor: opts.api.editor } + self.event = new EventManager() + } + refresh () { + var self = this + self._view.tabs.onmouseenter() + } + render () { + var self = this + if (self._view.el) return self._view.el + self._view.el = [ + self._renderTabsbar(), + self._api.editor.render() + ] + return self._view.el + } + _renderTabsbar () { + var self = this + if (self._view.tabsbar) return self._view.tabsbar + self._view.filetabs = yo`` + self._view.tabs = yo` +
    +
    + +
    + ${self._view.filetabs} +
    + +
    +
    + ` + self._view.tabsbar = yo` +
    +
    + + + + + + + +
    + ${self._view.tabs} + + + +
    + ` + 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 toggleLHP (event) { + this.children[0].classList.toggle('fa-angle-double-right') + this.children[0].classList.toggle('fa-angle-double-left') + self.event.trigger('resize', ['left']) + } + function toggleRHP (event) { + this.children[0].classList.toggle('fa-angle-double-right') + this.children[0].classList.toggle('fa-angle-double-left') + self.event.trigger('resize', ['right']) + } + function increase () { self._api.editor.editorFontSize(1) } + function decrease () { self._api.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 diff --git a/src/app/editor.js b/src/app/editor.js index 799a9aa414..19ffda7088 100644 --- a/src/app/editor.js +++ b/src/app/editor.js @@ -24,12 +24,15 @@ document.head.appendChild(yo` `) -function Editor (editorElement) { - var editor = ace.edit(editorElement) - editorElement.editor = editor // required to access the editor during tests - editorElement.className += ' ' + css['ace-editor'] +function Editor (opts = {}) { + var self = this + var el = yo`
    ` + var editor = ace.edit(el) + el.className += ' ' + css['ace-editor'] + el.editor = editor // required to access the editor during tests + self.render = function () { return el } var event = new EventManager() - this.event = event + self.event = event var sessions = {} var sourceAnnotations = [] var readOnlySessions = {} @@ -37,7 +40,6 @@ function Editor (editorElement) { var emptySession = createSession('') - var self = this editor.on('guttermousedown', function (e) { var target = e.domEvent.target if (target.className.indexOf('ace_gutter-cell') === -1) { diff --git a/src/app/file-panel.js b/src/app/file-panel.js index 29ccd7bd00..316441d37e 100644 --- a/src/app/file-panel.js +++ b/src/app/file-panel.js @@ -13,6 +13,7 @@ var css = csjs` display : flex; flex-direction : row; width : 100%; + height : 100%; box-sizing : border-box; } .fileexplorer { @@ -28,37 +29,39 @@ var css = csjs` .newFile { padding : 10px; } + .newFile i { + cursor : pointer; + } + .newFile i:hover { + color : orange; + } .connectToLocalhost { padding : 10px; } - .uploadFile { - padding : 10px; + .connectToLocalhost i { + cursor : pointer; } - .toggleLHP { - display : flex; - justify-content : flex-end; + .connectToLocalhost i:hover { + color : orange; + } + .uploadFile { padding : 10px; - width : 100%; - font-weight : bold; - cursor : pointer; - color : black; } - .isVisible { - position : absolute; - left : 35px; + .uploadFile label:hover { + color : orange; } - .isHidden { - position : absolute; - height : 99%; - left : -101%; + .uploadFile label { + cursor : pointer; } .treeview { background-color : white; } .dragbar { - position : relative; - top : 36px; - left : 2px; + position : absolute; + top : 37px; + width : 0.5em; + right : 0; + bottom : 0; cursor : col-resize; z-index : 999; border-right : 2px solid hsla(215, 81%, 79%, .3); @@ -73,13 +76,6 @@ var css = csjs` top : 0; bottom : 0; } - .changeeditorfontsize { - padding: 10px; - } - .changeeditorfontsize i { - display: block; - color: #111111; - } ` var limit = 60 @@ -87,6 +83,7 @@ var canUpload = window.File || window.FileReader || window.FileList || window.Bl var ghostbar = yo`
    ` function filepanel (appAPI, filesProvider) { + var self = this var fileExplorer = new FileExplorer(appAPI, filesProvider['browser']) var fileSystemExplorer = new FileExplorer(appAPI, filesProvider['localhost']) var dragbar = yo`
    ` @@ -119,13 +116,6 @@ function filepanel (appAPI, filesProvider) { - - - - - - -
    ${fileExplorer.init()}
    @@ -135,10 +125,10 @@ function filepanel (appAPI, filesProvider) { ` } - var events = new EventManager() + var event = new EventManager() + self.event = event var element = template() - element.querySelector('.increditorsize').addEventListener('click', () => { appAPI.editorFontSize(1) }) - element.querySelector('.decreditorsize').addEventListener('click', () => { appAPI.editorFontSize(-1) }) + var containerFileSystem = element.querySelector('.filesystemexplorer') var websocketconn = element.querySelector('.websocketconn') filesProvider['localhost'].remixd.event.register('connecting', (event) => { @@ -166,9 +156,7 @@ function filepanel (appAPI, filesProvider) { containerFileSystem.removeChild(fileSystemExplorer.element) } }) - // TODO please do not add custom javascript objects, which have no - // relation to the DOM to DOM nodes - element.events = events + fileExplorer.events.register('focus', function (path) { appAPI.switchToFile(path) }) @@ -177,15 +165,7 @@ function filepanel (appAPI, filesProvider) { appAPI.switchToFile(path) }) - return element - - function toggle (event) { - var isHidden = element.classList.toggle(css.isHidden) - this.classList.toggle(css.isVisible) - this.children[0].classList.toggle('fa-angle-double-right') - this.children[0].classList.toggle('fa-angle-double-left') - events.trigger('ui-hidden', [isHidden]) - } + self.render = function render () { return element } function uploadFile (event) { // TODO The file explorer is merely a view on the current state of @@ -195,6 +175,7 @@ function filepanel (appAPI, filesProvider) { ;[...this.files].forEach(fileExplorer.api.addFile) } + // ----------------- resizeable ui --------------- function mousedown (event) { event.preventDefault() if (event.which === 1) { @@ -213,21 +194,21 @@ function filepanel (appAPI, filesProvider) { document.removeEventListener('keydown', cancelGhostbar) } } - function moveGhostbar (event) { - var rhp = window['righthand-panel'].offsetLeft + function getPosition (event) { + var rhp = document.body.offsetWidth - window['righthand-panel'].offsetWidth var newpos = (event.pageX < limit) ? limit : event.pageX newpos = (newpos < (rhp - limit)) ? newpos : (rhp - limit) - ghostbar.style.left = newpos + 'px' + return newpos + } + function moveGhostbar (event) { + 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) - var width = (event.pageX < limit) ? limit : event.pageX - element.style.width = width + 'px' - events.trigger('ui-resize', [width]) + self.event.trigger('resize', [getPosition(event)]) } function createNewFile () { diff --git a/src/app/righthand-panel.js b/src/app/righthand-panel.js index 9ebc705911..cce47f4fde 100644 --- a/src/app/righthand-panel.js +++ b/src/app/righthand-panel.js @@ -1,5 +1,6 @@ +var csjs = require('csjs-inject') var yo = require('yo-yo') -var $ = require('jquery') +var EventManager = require('ethereum-remix').lib.EventManager var tabbedMenu = require('./tabbed-menu') var contractTab = require('./contract-tab') @@ -8,8 +9,6 @@ var analysisTab = require('./analysis-tab') var debuggerTab = require('./debugger-tab') var filesTab = require('./files-tab') -var csjs = require('csjs-inject') - var css = csjs` .options { float: left; @@ -21,6 +20,28 @@ var css = csjs` margin-right: 0.5em; font-size: 1em; } + .dragbar { + position : absolute; + width : 0.5em; + top : 3em; + bottom : 0; + cursor : col-resize; + z-index : 999; + border-left : 2px solid hsla(215, 81%, 79%, .3); + } + .ghostbar { + width : 3px; + background-color : #C6CFF7; + opacity : 0.5; + position : absolute; + cursor : col-resize; + z-index : 9999; + top : 0; + bottom : 0; + } + .panel { + height : 100%; + } ` // ------------------------------------------------------------------ @@ -30,6 +51,9 @@ module.exports = RighthandPanel function RighthandPanel (appAPI, events, opts) { var self = this self._api = appAPI + self.event = new EventManager() + self._view = {} + var optionViews = yo`
    ` var options = yo` ` - var element = yo` -
    + self._view.dragbar = yo`
    ` + self._view.element = yo` +
    + ${self._view.dragbar}