diff --git a/src/language/JSLintUtils.js b/src/language/JSLintUtils.js
index 5e2c732628d..bd040d036ac 100644
--- a/src/language/JSLintUtils.js
+++ b/src/language/JSLintUtils.js
@@ -23,7 +23,7 @@
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, brackets, JSLINT, PathUtils */
+/*global define, $, JSLINT, PathUtils */
/**
* Allows JSLint to run on the current document and report results in a UI panel.
@@ -47,7 +47,15 @@ define(function (require, exports, module) {
Strings = require("strings"),
StringUtils = require("utils/StringUtils"),
AppInit = require("utils/AppInit"),
+ Resizer = require("utils/Resizer"),
StatusBar = require("widgets/StatusBar");
+
+ var PREFERENCES_CLIENT_ID = module.id,
+ defaultPrefs = { height: 200, enabled: true };
+
+ /** @type {Number} Height of the JSLint panel header in pixels. Hardcoded to avoid race
+ condition when measuring it on htmlReady*/
+ var HEADER_HEIGHT = 27;
/**
* @private
@@ -212,20 +220,33 @@ define(function (require, exports, module) {
setEnabled(!getEnabled());
}
-
// Register command handlers
CommandManager.register(Strings.CMD_JSLINT, Commands.TOGGLE_JSLINT, _handleToggleJSLint);
// Init PreferenceStorage
- _prefs = PreferencesManager.getPreferenceStorage(module.id, { enabled: !!brackets.config.enable_jslint });
+ _prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs);
_setEnabled(_prefs.getValue("enabled"));
- // Init StatusBar indicator
+ // Initialize items dependent on HTML DOM
AppInit.htmlReady(function () {
+ var height = Math.max(_prefs.getValue("height"), 100),
+ $jslintResults = $("#jslint-results"),
+ $jslintContent = $("#jslint-results .table-container");
+
+ $jslintResults.height(height);
+ $jslintContent.height(height - HEADER_HEIGHT);
+
+ if (_enabled) {
+ EditorManager.resizeEditor();
+ }
+
+ $jslintResults.on("panelResizeEnd", function (event, height) {
+ _prefs.setValue("height", height);
+ });
+
StatusBar.addIndicator(module.id, $("#gold-star"), false);
});
-
-
+
// Define public API
exports.run = run;
exports.getEnabled = getEnabled;
diff --git a/src/search/FindInFiles.js b/src/search/FindInFiles.js
index 12737095029..4c90306dce1 100644
--- a/src/search/FindInFiles.js
+++ b/src/search/FindInFiles.js
@@ -50,13 +50,23 @@ define(function (require, exports, module) {
DocumentManager = require("document/DocumentManager"),
EditorManager = require("editor/EditorManager"),
FileIndexManager = require("project/FileIndexManager"),
+ PreferencesManager = require("preferences/PreferencesManager"),
KeyEvent = require("utils/KeyEvent"),
+ AppInit = require("utils/AppInit"),
+ Resizer = require("utils/Resizer"),
StatusBar = require("widgets/StatusBar");
var searchResults = [];
var FIND_IN_FILES_MAX = 100;
-
+
+ var PREFERENCES_CLIENT_ID = module.id,
+ defaultPrefs = { height: 200 };
+
+ /** @type {Number} Height of the FIF panel header in pixels. Hardcoded to avoid race
+ condition when measuring it on htmlReady*/
+ var HEADER_HEIGHT = 27;
+
// This dialog class was mostly copied from QuickOpen. We should have a common dialog
// class that everyone can use.
@@ -340,6 +350,21 @@ define(function (require, exports, module) {
}
});
}
+
+ // Initialize items dependent on HTML DOM
+ AppInit.htmlReady(function () {
+ var $searchResults = $("#search-results"),
+ $searchContent = $("#search-results .table-container"),
+ prefs = PreferencesManager.getPreferenceStorage(module.id, defaultPrefs),
+ height = prefs.getValue("height");
+
+ $searchResults.height(height);
+ $searchContent.height(height - HEADER_HEIGHT);
+
+ $searchResults.on("panelResizeEnd", function (event, height) {
+ prefs.setValue("height", height);
+ });
+ });
function _fileNameChangeHandler(event, oldName, newName) {
if ($("#search-results").is(":visible")) {
@@ -353,4 +378,4 @@ define(function (require, exports, module) {
$(DocumentManager).on("fileNameChange", _fileNameChangeHandler);
CommandManager.register(Strings.CMD_FIND_IN_FILES, Commands.EDIT_FIND_IN_FILES, doFindInFiles);
-});
\ No newline at end of file
+});
diff --git a/src/styles/brackets.less b/src/styles/brackets.less
index 9caf9a17656..37aa9b222dd 100644
--- a/src/styles/brackets.less
+++ b/src/styles/brackets.less
@@ -62,11 +62,13 @@ html, body {
body {
.vbox;
- /* This appears to be necessary in Firefox when body is set to display: box. */
- width: 100%;
&.resizing a, &.resizing #projects a, &.resizing .main-view, &.resizing .CodeMirror-lines {
cursor: col-resize;
}
+
+ &.vert-resizing a, &.vert-resizing #projects a, &.vert-resizing .main-view, &.vert-resizing .CodeMirror-lines {
+ cursor: row-resize;
+ }
}
@@ -180,14 +182,32 @@ a, img {
background: @background-color-2 url('images/no_content_bg.svg') no-repeat center 45%;
}
}
-
+
+.vert-resizer {
+ position: absolute;
+ height: 6px;
+ width: 100%;
+ z-index: @z-index-brackets-panel-resizer;
+ opacity: 0;
+ cursor: row-resize;
+}
+
+.horz-resizer {
+ position: absolute;
+ height: 100%;
+ width: 6px;
+ z-index: @z-index-brackets-panel-resizer;
+ opacity: 0;
+ cursor: col-resize;
+}
+
.bottom-panel {
display: none;
height: 200px;
border-top-style: solid;
border-width: 1px;
border-color: lighten(@bc-grey, @bc-color-step-size*4);
-
+
.toolbar {
height: auto;
padding-top: @base-padding / 2;
diff --git a/src/styles/brackets_variables.less b/src/styles/brackets_variables.less
index 170bf59b3f4..79a1d61fd78 100644
--- a/src/styles/brackets_variables.less
+++ b/src/styles/brackets_variables.less
@@ -50,5 +50,6 @@
@z-index-brackets-sidebar-resizer: @z-index-brackets-ui + 2;
@z-index-brackets-resizer-div: @z-index-brackets-sidebar-resizer + 1;
+@z-index-brackets-panel-resizer: @z-index-brackets-ui + 2;
@z-index-brackets-context-menu-base: 1000;
diff --git a/src/utils/Resizer.js b/src/utils/Resizer.js
new file mode 100644
index 00000000000..c380034d48a
--- /dev/null
+++ b/src/utils/Resizer.js
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
+/*global define, $, window */
+
+/**
+ * Resizer is a Module utility to inject resizing capabilities to any element
+ * inside Brackets.
+ *
+ * On initialization, Resizer discovers all nodes tagged as "vert-resizable"
+ * and "horz-resizable" to add the resizer handler. Additionally, "top-resizer",
+ * "bottom-resizer", "left-resizer" and "right-resizer" classes control the
+ * position of the resizer on the element.
+ *
+ * An element can be made resizable at any time using the `makeResizable` API
+ *
+ * The resizable elements trigger a panelResizeStart, panelResizeUpdate and panelResizeEnd
+ * event that can be used to create performance optimizations (such as hiding/showing elements
+ * while resizing), custom or internal resizes and save the final resized value into local
+ * storage for example.
+ *
+ * TODO Trigger panelResizeStart and panelResizeUpdate as required. They aren't needed
+ * currently.
+ */
+define(function (require, exports, module) {
+ "use strict";
+
+ var DIRECTION_VERTICAL = "vert";
+ var DIRECTION_HORIZONTAL = "horz";
+
+ var POSITION_TOP = "top";
+ var POSITION_BOTTOM = "bottom";
+ var POSITION_LEFT = "left";
+ var POSITION_RIGHT = "right";
+
+ // Minimum size (height or width) for autodiscovered resizable panels
+ var DEFAULT_MIN_SIZE = 100;
+
+ // Load dependent modules
+ var AppInit = require("utils/AppInit"),
+ EditorManager = require("editor/EditorManager");
+
+ var $mainView;
+
+ /**
+ * Adds resizing capabilities to a given html element.
+ *
+ * Resizing can be configured in two directions:
+ * - Vertical ("vert"): Resizes the height of the element
+ * - Horizontal ("horz"): Resizes the width of the element
+ *
+ * Resizer handlers can be positioned on the element at:
+ * - Top ("top") or bottom ("bottom") for vertical resizing
+ * - Left ("left") or right ("right") for horizontal resizing
+ *
+ * A resizable element triggers the following events while resizing:
+ * - panelResizeEnds: When the resize ends
+ *
+ * @param {DOMNode} element Html element which should be made resizable.
+ * @param {string} direction The direction of the resize action. Must be "horz" or "vert".
+ * @param {string} position The position of the resizer on the element. Can be "top" or "bottom"
+ * for vertical resizing and "left" or "right" for horizontal resizing.
+ * @param {int} minSize Minimum size (width or height) of the element.
+ */
+ function makeResizable(element, direction, position, minSize) {
+
+ var $resizer = $('
'),
+ $element = $(element),
+ $resizableElement = $($element.find(".resizable-content:first")[0]),
+ $body = $(window.document.body),
+ animationRequest = null,
+ directionProperty = direction === DIRECTION_HORIZONTAL ? "clientX" : "clientY",
+ elementSizeFunction = direction === DIRECTION_HORIZONTAL ? $element.width : $element.height,
+ contentSizeFunction = null;
+
+ minSize = minSize || 0;
+
+ $element.prepend($resizer);
+
+ $resizer.on("mousedown", function (e) {
+ var startPosition = e[directionProperty],
+ startSize = elementSizeFunction.apply($element),
+ newSize = startSize,
+ baseSize = 0,
+ doResize = true,
+ isMouseDown = true;
+
+ if ($resizableElement !== undefined) {
+ $element.children().not(".horz-resizer, .vert-resizer, .resizable-content").each(function (index, child) {
+ if (direction === DIRECTION_HORIZONTAL) {
+ baseSize += $(child).outerWidth();
+ } else {
+ baseSize += $(child).outerHeight();
+ }
+ });
+
+ contentSizeFunction = direction === DIRECTION_HORIZONTAL ? $resizableElement.width : $resizableElement.height;
+ }
+
+ $body.toggleClass(direction + "-resizing");
+
+ animationRequest = window.webkitRequestAnimationFrame(function doRedraw() {
+ // only run this if the mouse is down so we don't constantly loop even
+ // after we're done resizing.
+ if (!isMouseDown) {
+ return;
+ }
+
+ if (doResize) {
+ // resize the main element to the new size
+ elementSizeFunction.apply($element, [newSize]);
+
+ // if there is a content element, its size is the new size
+ // minus the size of the non-resizable elements
+ if ($resizableElement !== undefined) {
+ contentSizeFunction.apply($resizableElement, [newSize - baseSize]);
+ }
+
+ EditorManager.resizeEditor();
+ }
+
+ animationRequest = window.webkitRequestAnimationFrame(doRedraw);
+ });
+
+ $mainView.on("mousemove", function (e) {
+ // calculate newSize adding to startSize the difference
+ // between starting and current position, capped at minSize
+ newSize = Math.max(startSize + (startPosition - e[directionProperty]), minSize);
+ e.preventDefault();
+ });
+
+ function endResize(e) {
+ if (isMouseDown) {
+ isMouseDown = false;
+ $mainView.off("mousemove");
+ $body.toggleClass(direction + "-resizing");
+ $element.trigger("panelResizeEnd", [elementSizeFunction.apply($element)]);
+ }
+ }
+
+ $mainView.one("mouseup", endResize);
+ $mainView.mouseleave(endResize);
+
+ e.preventDefault();
+ });
+ }
+
+ // Scan DOM for horz-resizable and vert-resizable classes and make them resizable
+ AppInit.htmlReady(function () {
+ $mainView = $(".main-view");
+
+ $(".vert-resizable").each(function (index, element) {
+
+ if ($(element).hasClass("top-resizer")) {
+ makeResizable(element, DIRECTION_VERTICAL, POSITION_TOP, DEFAULT_MIN_SIZE);
+ }
+
+ //if ($(element).hasClass("bottom-resizer")) {
+ // makeResizable(element, DIRECTION_VERTICAL, POSITION_BOTTOM, DEFAULT_MIN_SIZE);
+ //}
+ });
+
+ $(".horz-resizable").each(function (index, element) {
+
+ //if ($(element).hasClass("left-resizer")) {
+ // makeResizable(element, DIRECTION_HORIZONTAL, POSITION_LEFT, DEFAULT_MIN_SIZE);
+ //}
+
+ //if ($(element).hasClass("right-resizer")) {
+ // makeResizable(element, DIRECTION_HORIZONTAL, POSITION_RIGHT, DEFAULT_MIN_SIZE);
+ //}
+ });
+ });
+
+ exports.makeResizable = makeResizable;
+});
\ No newline at end of file