From b2983855ea01fd04a8ba53099d2d5ee7ebed31f9 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 29 Sep 2015 14:15:28 +0200 Subject: Add a statusbar to the editor widget --- css/codeq.css | 9 +++- index.html | 2 + js/codemirror/panel.js | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ js/codeq/editor.js | 30 +++++++++++++ js/codeq/prolog.js | 4 +- js/codeq/python.js | 14 +------ 6 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 js/codemirror/panel.js create mode 100644 js/codeq/editor.js diff --git a/css/codeq.css b/css/codeq.css index 138761b..0e4c689 100644 --- a/css/codeq.css +++ b/css/codeq.css @@ -174,6 +174,13 @@ body { border: 1px solid black; } +.editor-statusbar { + background-color: #F7F7F7; + border-top: 1px solid #DDD; + font-family: monospace; + padding: 1px 4px; + text-align: right; +} /***** helpers *****/ /* webkit-scrollbar */ @@ -208,4 +215,4 @@ ul.dropdown-menu a { /* problem index screen */ #screen_problem .language-problems a { cursor: pointer; -} \ No newline at end of file +} diff --git a/index.html b/index.html index 105fae4..7defa80 100644 --- a/index.html +++ b/index.html @@ -378,6 +378,7 @@ + @@ -388,6 +389,7 @@ + diff --git a/js/codemirror/panel.js b/js/codemirror/panel.js new file mode 100644 index 0000000..ba29484 --- /dev/null +++ b/js/codemirror/panel.js @@ -0,0 +1,112 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + CodeMirror.defineExtension("addPanel", function(node, options) { + options = options || {}; + + if (!this.state.panels) initPanels(this); + + var info = this.state.panels; + var wrapper = info.wrapper; + var cmWrapper = this.getWrapperElement(); + + if (options.after instanceof Panel && !options.after.cleared) { + wrapper.insertBefore(node, options.before.node.nextSibling); + } else if (options.before instanceof Panel && !options.before.cleared) { + wrapper.insertBefore(node, options.before.node); + } else if (options.replace instanceof Panel && !options.replace.cleared) { + wrapper.insertBefore(node, options.replace.node); + options.replace.clear(); + } else if (options.position == "bottom") { + wrapper.appendChild(node); + } else if (options.position == "before-bottom") { + wrapper.insertBefore(node, cmWrapper.nextSibling); + } else if (options.position == "after-top") { + wrapper.insertBefore(node, cmWrapper); + } else { + wrapper.insertBefore(node, wrapper.firstChild); + } + + var height = (options && options.height) || node.offsetHeight; + this._setSize(null, info.heightLeft -= height); + info.panels++; + return new Panel(this, node, options, height); + }); + + function Panel(cm, node, options, height) { + this.cm = cm; + this.node = node; + this.options = options; + this.height = height; + this.cleared = false; + } + + Panel.prototype.clear = function() { + if (this.cleared) return; + this.cleared = true; + var info = this.cm.state.panels; + this.cm._setSize(null, info.heightLeft += this.height); + info.wrapper.removeChild(this.node); + if (--info.panels == 0) removePanels(this.cm); + }; + + Panel.prototype.changed = function(height) { + var newHeight = height == null ? this.node.offsetHeight : height; + var info = this.cm.state.panels; + this.cm._setSize(null, info.height += (newHeight - this.height)); + this.height = newHeight; + }; + + function initPanels(cm) { + var wrap = cm.getWrapperElement(); + var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle; + var height = parseInt(style.height); + var info = cm.state.panels = { + setHeight: wrap.style.height, + heightLeft: height, + panels: 0, + wrapper: document.createElement("div") + }; + wrap.parentNode.insertBefore(info.wrapper, wrap); + var hasFocus = cm.hasFocus(); + info.wrapper.appendChild(wrap); + if (hasFocus) cm.focus(); + + cm._setSize = cm.setSize; + if (height != null) cm.setSize = function(width, newHeight) { + if (newHeight == null) return this._setSize(width, newHeight); + info.setHeight = newHeight; + if (typeof newHeight != "number") { + var px = /^(\d+\.?\d*)px$/.exec(newHeight); + if (px) { + newHeight = Number(px[1]); + } else { + info.wrapper.style.height = newHeight; + newHeight = info.wrapper.offsetHeight; + info.wrapper.style.height = ""; + } + } + cm._setSize(width, info.heightLeft += (newHeight - height)); + height = newHeight; + }; + } + + function removePanels(cm) { + var info = cm.state.panels; + cm.state.panels = null; + + var wrap = cm.getWrapperElement(); + info.wrapper.parentNode.replaceChild(wrap, info.wrapper); + wrap.style.height = info.setHeight; + cm.setSize = cm._setSize; + cm.setSize(); + } +}); diff --git a/js/codeq/editor.js b/js/codeq/editor.js new file mode 100644 index 0000000..e7d15f9 --- /dev/null +++ b/js/codeq/editor.js @@ -0,0 +1,30 @@ +codeq.makeEditor = function (elt, options) { + var statusBar = document.createElement("div"), + updateStatusBar = function (pos) { + statusBar.innerHTML = 'line ' + (pos.line+1) + ', column ' + (pos.ch+1); + }, + editor; + + options.cursorHeight = 0.85; + options.lineNumbers = true; + options.matchBrackets = true; + options.extraKeys = { + // replace tabs with spaces + Tab: function (cm) { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); + } + }; + editor = CodeMirror(elt, options), + + statusBar.className = 'editor-statusbar'; + updateStatusBar({line: 0, ch: 0}); + + editor.addPanel(statusBar, {position: 'bottom'}); + editor.on('cursorActivity', function (instance) { + var pos = instance.getDoc().getCursor(); + updateStatusBar(pos); + }); + + return editor; +}; diff --git a/js/codeq/prolog.js b/js/codeq/prolog.js index 640aa99..87ac353 100644 --- a/js/codeq/prolog.js +++ b/js/codeq/prolog.js @@ -259,7 +259,9 @@ jqEditor = jqCode.find('.code_editor'), jqTerminal = jqConsole.find('.console'), jqHints = jqInfo.find('.hints'), - editor = CodeMirror(jqEditor[0], { cursorHeight: 0.85, lineNumbers: true, matchBrackets: true }), + editor = codeq.makeEditor(jqEditor[0], { + mode: 'prolog' + }), activityHandler = makeActivityHandler(editor, problemDef.id), terminal = makePrologTerminalHandler(jqTerminal, editor, problemDef.id, activityHandler), hinter = codeq.makeHinter(jqHints, jqEditor, editor, 'prolog_hints', problemDef.hint, commonHints, problemDef.plan), diff --git a/js/codeq/python.js b/js/codeq/python.js index 4724982..e20fe06 100644 --- a/js/codeq/python.js +++ b/js/codeq/python.js @@ -217,19 +217,9 @@ jqEditor = jqCode.find('.code_editor'), jqTerminal = jqConsole.find('.console'), jqHints = jqInfo.find('.hints'), - editor = CodeMirror(jqEditor[0], { - cursorHeight: 0.85, - lineNumbers: true, - matchBrackets: true, + editor = codeq.makeEditor(jqEditor[0], { mode: 'python', - indentUnit: 4, - extraKeys: { - // replace tabs with spaces - Tab: function (cm) { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - } + indentUnit: 4 }), activityHandler = makeActivityHandler(editor, problemDef.id), terminal = makePythonTerminalHandler(jqTerminal, editor, problemDef.id, activityHandler), -- cgit v1.2.1