webgme
Version:
Web-based Generic Modeling Environment
907 lines (745 loc) • 32.5 kB
JavaScript
/*globals define, WebGMEGlobal, _, $*/
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
* @author pmeijer / https://github.com/pmeijer
*/
define([
'common/util/assert',
'js/PanelBase/PanelBase',
'./SplitMaximizeButton',
'css!./styles/SplitPanel.css'
], function (ASSERT, PanelBase, SplitMaximizeButton) {
'use strict';
var SPLIT_PANEL_CLASS = 'split-panel',
PANEL_CONTAINER_CLASS = 'split-panel-panel-container',
PANEL_ID_DATA_KEY = 'SPLIT_PANEL_ID',
SPLITTER_ID_DATA_KEY = 'SPLIT_PANEL_SPLITTER_ID',
SPLITTER_CLASS = 'splitter',
SPLITTER_SIZE = 4,
SPLITTER_RESIZE_CLASS = 'resize',
MINIMUM_PANEL_SIZE = 50,
SPLITTER_SNAP_FROM_DISTANCE = 0,
SPLITTER_RESIZE_PADDING = 2,
MINIMUM_RESCALE_WIDTH = 400,
MINIMUM_RESCALE_HEIGHT = 400;
function SplitPanel(/*layoutManager, params*/) {
var options = {};
//set properties from options
options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'SplitPanel';
//call parent's constructor
PanelBase.apply(this, [options]);
this._panelIdCounter = 1;
this._activePanelId = null;
this._maximized = false;
/**
*
* @example
* {
* 1: {
* instance: ModelEditor instance,
* panelContainer: <div class=PANEL_CLASS_CONTAINER, data=.. 0>,
* splitters: {
* top: null,
* right: 1_2,
* bottom: null,
* left: null
* },
* currentSplitter: 1_2
* },
* 2: {
* instance: MetaEditor instance,
* panelContainer: <div class=PANEL_CLASS_CONTAINER, data=.. 1>,
* splitters: {
* top: null,
* right: null,
* bottom: null,
* left: 1_2
* },
* currentSplitter: 1_2
* }
* }
* @private
*/
this._panels = {};
this._readOnly = false;
this._splitterPos = 0.5;
/**
*
* @example
* {
* 1_2: {
* vertical: true,
* el: $splitter,
* relPos: 0.5, // Range between 0 and 1
* x1: 50,
* y1: 0,
* x2: 50,
* y2, 100
* }
* }
* @private
*/
this._splitters = {};
//initialize UI
this._initialize();
this.logger.debug('SplitPanel ctor finished');
}
//inherit from PanelBaseWithHeader
_.extend(SplitPanel.prototype, PanelBase.prototype);
SplitPanel.prototype._initialize = function () {
var self = this,
panelContainer = $('<div/>', {class: PANEL_CONTAINER_CLASS});
this.$el.addClass(SPLIT_PANEL_CLASS);
// Add this first panel container ..
this._activePanelId = '' + this._panelIdCounter;
panelContainer.data(PANEL_ID_DATA_KEY, this._activePanelId);
this.$el.append(panelContainer);
this._panels[this._activePanelId] = {
panelContainer: panelContainer,
instance: null,
eventHandler: self._attachActivateHandler(panelContainer),
toolbar: null,
splitters: {
top: null,
right: null,
bottom: null,
left: null
},
currentSplitter: null
};
// the panel instance is still null at this point.
WebGMEGlobal.PanelManager.setActivePanel(null);
this.$el.on('mousedown', '.' + SPLITTER_CLASS, function (event) {
var el = $(this),
splitterId = el.data(SPLITTER_ID_DATA_KEY);
self._startPanelResize(splitterId, event);
event.stopPropagation();
event.preventDefault();
});
this._updateUI();
};
SplitPanel.prototype.setActivePanel = function (panelId) {
var panel;
if (typeof panelId === 'string') {
panel = this._panels[panelId].instance;
this._activePanelId = panelId;
WebGMEGlobal.PanelManager.setActivePanel(panel);
} else {
this.logger.error('panel el did not have "', PANEL_ID_DATA_KEY, '" data.');
}
};
SplitPanel.prototype.updateActivePanel = function (panel) {
var self = this,
activePanel = this._panels[this._activePanelId],
toolbar;
// activePanel.panelContainer.empty();
activePanel.instance = panel;
activePanel.panelContainer.append(panel.$pEl);
if (activePanel.toolbar) {
activePanel.toolbar.remove();
delete activePanel.toolbar;
}
toolbar = panel.getSplitPanelToolbarEl();
if (toolbar) {
(new SplitMaximizeButton(this._activePanelId, self, activePanel.panelContainer, toolbar));
activePanel.toolbar = toolbar;
}
panel.afterAppend();
WebGMEGlobal.PanelManager.setActivePanel(panel);
//make sure that read-only info is passed down to the actual panels
this.onReadOnlyChanged(this._readOnly);
this._updateUI();
};
SplitPanel.prototype.addPanel = function (vertical) {
var panelContainer = $('<div/>', {class: PANEL_CONTAINER_CLASS}),
self = this,
activePanelPos,
newPanelId,
splitterId,
splitterEl;
this._panelIdCounter += 1;
newPanelId = '' + this._panelIdCounter;
panelContainer.data(PANEL_ID_DATA_KEY, newPanelId);
this.$el.append(panelContainer);
this._panels[newPanelId] = {
panelContainer: panelContainer,
instance: null,
eventHandler: self._attachActivateHandler(panelContainer),
toolbar: null,
splitters: {
// Initially set splitters to same as panel splitting from.
top: this._panels[this._activePanelId].splitters.top,
right: this._panels[this._activePanelId].splitters.right,
bottom: this._panels[this._activePanelId].splitters.bottom,
left: this._panels[this._activePanelId].splitters.left
},
currentSplitter: null
};
splitterId = this._activePanelId + '_' + newPanelId;
splitterEl = $('<div/>', {class: SPLITTER_CLASS});
splitterEl.data(SPLITTER_ID_DATA_KEY, splitterId);
this.$el.append(splitterEl);
this._splitters[splitterId] = {
vertical: !!vertical,
el: splitterEl,
relPos: 0.5,
x1: 0,
y1: 0,
x2: 0,
y2: 0
};
this._panels[newPanelId].currentSplitter = splitterId;
this._panels[this._activePanelId].currentSplitter = splitterId;
// top: 0
// left: 0
// width: 0
// height: 0
activePanelPos = this._panels[this._activePanelId].panelContainer.position();
activePanelPos.width = this._panels[this._activePanelId].panelContainer.width();
activePanelPos.heigth = this._panels[this._activePanelId].panelContainer.height();
// Based on the splitting direction - update the splitters for the new and the active panel.
if (vertical) {
splitterEl.addClass('vertical');
this._panels[newPanelId].splitters.left = splitterId;
this._panels[this._activePanelId].splitters.right = splitterId;
this._splitters[splitterId].x1 = this._splitters[splitterId].x2 = activePanelPos.left +
activePanelPos.width * 0.5;
this._splitters[splitterId].y1 = activePanelPos.top;
this._splitters[splitterId].y2 = activePanelPos.top + activePanelPos.heigth;
splitterEl.css({
width: SPLITTER_SIZE,
height: this._splitters[splitterId].y2 - this._splitters[splitterId].y1,
top: this._splitters[splitterId].y1,
left: this._splitters[splitterId].x1
});
} else {
splitterEl.addClass('horizontal');
this._panels[newPanelId].splitters.top = splitterId;
this._panels[this._activePanelId].splitters.bottom = splitterId;
this._splitters[splitterId].y1 = this._splitters[splitterId].y2 = activePanelPos.top +
activePanelPos.heigth * 0.5;
this._splitters[splitterId].x1 = activePanelPos.left;
this._splitters[splitterId].x2 = activePanelPos.left + activePanelPos.width;
splitterEl.css({
width: this._splitters[splitterId].x2 - this._splitters[splitterId].x1,
height: SPLITTER_SIZE,
top: this._splitters[splitterId].y1,
left: this._splitters[splitterId].x1
});
}
this._activePanelId = newPanelId;
WebGMEGlobal.PanelManager.setActivePanel(null);
// Awaiting a call to updateActivePanel
};
SplitPanel.prototype.deletePanel = function () {
var activePanel = this._panels[this._activePanelId],
removedSplitterId = activePanel.currentSplitter,
newActivePanelId,
shiftSplitterType,
panelIds,
splitter,
i;
ASSERT(removedSplitterId, 'Panel did not have a currentSplitter');
splitter = this._splitters[removedSplitterId];
this._removeActivateHandler(activePanel.panelContainer, activePanel.eventHandler);
activePanel.panelContainer.remove();
delete this._panels[this._activePanelId];
splitter.el.remove();
delete this._splitters[removedSplitterId];
if (splitter.vertical) {
if (activePanel.splitters.left === removedSplitterId) {
shiftSplitterType = 'right';
} else if (activePanel.splitters.right === removedSplitterId) {
shiftSplitterType = 'left';
} else {
throw new Error('Mismatch in vertical splitters during remove!');
}
} else {
if (activePanel.splitters.top === removedSplitterId) {
shiftSplitterType = 'bottom';
} else if (activePanel.splitters.bottom === removedSplitterId) {
shiftSplitterType = 'top';
} else {
throw new Error('Mismatch in horizontal splitters during remove!');
}
}
// The shift has been determined - go through all panels and shift their splitters.
panelIds = Object.keys(this._panels);
for (i = 0; i < panelIds.length; i += 1) {
if (this._panels[panelIds[i]].splitters[shiftSplitterType] === removedSplitterId) {
this._panels[panelIds[i]].splitters[shiftSplitterType] = activePanel.splitters[shiftSplitterType];
// If the panel lost its current splitter we need to assign a new one.
if (this._panels[panelIds[i]].currentSplitter === removedSplitterId) {
this._panels[panelIds[i]].currentSplitter = this._getNewCurrentSplitter(this._panels[panelIds[i]]);
newActivePanelId = panelIds[i];
}
}
}
// If no panel shared the current splitter - a random panel will become the active one.
this._activePanelId = newActivePanelId ? newActivePanelId : panelIds[0];
if (this._activePanelId) {
WebGMEGlobal.PanelManager.setActivePanel(this._panels[this._activePanelId].instance);
} else {
this.logger.error('Deleted last panel..');
}
this._updateUI();
};
SplitPanel.prototype.deleteAllPanels = function () {
var panelIds = Object.keys(this._panels),
splitterIds = Object.keys(this._splitters),
i;
if (this._maximized) {
this._maximized = false;
}
for (i = 0; i < splitterIds.length; i += 1) {
this._splitters[splitterIds[i]].el.remove();
delete this._splitters[splitterIds[i]];
}
for (i = 0; i < panelIds.length; i += 1) {
if (panelIds[i] === this._activePanelId) {
this._panels[panelIds[i]].splitters.top = null;
this._panels[panelIds[i]].splitters.left = null;
this._panels[panelIds[i]].splitters.bottom = null;
this._panels[panelIds[i]].splitters.right = null;
this._panels[panelIds[i]].currentSplitter = null;
} else {
this._removeActivateHandler(this._panels[panelIds[i]].panelContainer,
this._panels[panelIds[i]].eventHandler);
this._panels[panelIds[i]].instance.destroy();
this._panels[panelIds[i]].panelContainer.remove();
delete this._panels[panelIds[i]];
}
}
this._updateUI();
};
SplitPanel.prototype.getNumberOfPanels = function () {
return Object.keys(this._panels).length;
};
SplitPanel.prototype.canSplitActivePanel = function (vertical) {
var splitters,
min,
max;
if (typeof this._activePanelId !== 'string') {
return false;
}
splitters = this._panels[this._activePanelId].splitters;
if (vertical) {
min = splitters.left ? this._splitters[splitters.left].x1 : 0;
max = splitters.right ? this._splitters[splitters.right].x1 : this._width;
} else {
min = splitters.top ? this._splitters[splitters.top].y1 : 0;
max = splitters.bottom ? this._splitters[splitters.bottom].y1 : this._height;
}
return (max - min) > (MINIMUM_PANEL_SIZE * 2 + SPLITTER_SIZE);
};
SplitPanel.prototype._getNewCurrentSplitter = function (p) {
var MARGIN = 2,
top = p.splitters.top && {
x1: this._splitters[p.splitters.top].x1,
x2: this._splitters[p.splitters.top].x2,
y: this._splitters[p.splitters.top].y1,
id: p.splitters.top
},
bottom = p.splitters.bottom && {
x1: this._splitters[p.splitters.bottom].x1,
x2: this._splitters[p.splitters.bottom].x2,
y: this._splitters[p.splitters.bottom].y1,
id: p.splitters.bottom
},
left = p.splitters.left && {
y1: this._splitters[p.splitters.left].y1,
y2: this._splitters[p.splitters.left].y2,
x: this._splitters[p.splitters.left].x1,
id: p.splitters.left
},
right = p.splitters.right && {
y1: this._splitters[p.splitters.right].y1,
y2: this._splitters[p.splitters.right].y2,
x: this._splitters[p.splitters.right].x,
id: p.splitters.right
},
candidate;
function eq(a, b) {
return (a >= b - MARGIN) && (a <= b + MARGIN);
}
// Find the first splitter that isn't intersected by any of the other splitters.
function verticalCheck(vertical) {
if (!vertical) {
return null;
}
if (top) {
if (bottom) {
if (eq(top.y, vertical.y1) && eq(bottom.y, vertical.y2)) {
//
// ----------------- top y
// | |y1
// | |
// | |y2
//------------------ bottom y
return vertical.id;
}
} else if (eq(top.y, vertical.y1)) {
return vertical.id;
}
} else if (bottom) {
if (eq(bottom.y, vertical.y2)) {
return vertical.id;
}
} else {
return vertical.id;
}
return null;
}
function horizontalCheck(horizontal) {
if (!horizontal) {
return null;
}
if (left) {
if (right) {
if (eq(left.x, horizontal.x1) && eq(right.x, horizontal.x2)) {
// left x right x
// | |
// |----------|
// |x1 x2|
// | |
// |----------|
// | |
return horizontal.id;
}
} else if (eq(left.x, horizontal.x1)) {
return horizontal.id;
}
} else if (right) {
if (eq(right.x, horizontal.x2)) {
return horizontal.id;
}
} else {
return horizontal.id;
}
return null;
}
candidate = verticalCheck(left);
if (candidate) {
return candidate;
}
candidate = verticalCheck(right);
if (candidate) {
return candidate;
}
candidate = horizontalCheck(top);
if (candidate) {
return candidate;
}
candidate = horizontalCheck(bottom);
if (candidate) {
return candidate;
}
ASSERT(!(left || right || top || bottom), 'Should have found new currentSplitter');
return null;
};
SplitPanel.prototype._getSplitterBoundary = function (splitterId) {
var self = this,
maxVal = this._splitters[splitterId].vertical ? this._width : this._height,
minVal = 0;
Object.keys(this._panels).forEach(function (pId) {
var candidateVal;
if (self._splitters[splitterId].vertical) {
if (self._panels[pId].splitters.left === splitterId && self._panels[pId].splitters.right) {
candidateVal = self._splitters[self._panels[pId].splitters.right].x1;
maxVal = candidateVal < maxVal ? candidateVal : maxVal;
}
if (self._panels[pId].splitters.right === splitterId && self._panels[pId].splitters.left) {
candidateVal = self._splitters[self._panels[pId].splitters.left].x1;
minVal = candidateVal > minVal ? candidateVal : minVal;
}
} else {
// horizontal splitter
if (self._panels[pId].splitters.top === splitterId && self._panels[pId].splitters.bottom) {
candidateVal = self._splitters[self._panels[pId].splitters.bottom].y1;
maxVal = candidateVal < maxVal ? candidateVal : maxVal;
}
if (self._panels[pId].splitters.bottom === splitterId && self._panels[pId].splitters.top) {
candidateVal = self._splitters[self._panels[pId].splitters.top].y1;
minVal = candidateVal > minVal ? candidateVal : minVal;
}
}
});
return {
min: minVal,
max: maxVal
};
};
SplitPanel.prototype._harmonizeSplitters = function () {
// TODO: This should make sure that all splitters fill up the canvas exactly.
// TODO: When we support loading of stored configurations this needs to be implemented.
};
SplitPanel.prototype._updateUI = function () {
var self = this,
panelIds = Object.keys(this._panels),
splitterIds = Object.keys(this._splitters),
newVertPos = {},
newHorzPos = {},
panel,
panelPos,
splitter,
splitterBoundary,
x1,
y1,
x2,
y2,
i;
function updateVerticalPositions(splitterId, panelPos) {
newVertPos[splitterId] = newVertPos[splitterId] || {y1: self._height, y2: 0};
newVertPos[splitterId].y1 = panelPos.top < newVertPos[splitterId].y1 ?
panelPos.top : newVertPos[splitterId].y1;
newVertPos[splitterId].y2 = panelPos.top + panelPos.height > newVertPos[splitterId].y2 ?
panelPos.top + panelPos.height : newVertPos[splitterId].y2;
}
function updateHorizontalPositions(splitterId, panelPos) {
newHorzPos[splitterId] = newHorzPos[splitterId] || {x1: self._width, x2: 0};
newHorzPos[splitterId].x1 = panelPos.left < newHorzPos[splitterId].x1 ?
panelPos.left : newHorzPos[splitterId].x1;
newHorzPos[splitterId].x2 = panelPos.left + panelPos.width > newHorzPos[splitterId].x2 ?
panelPos.left + panelPos.width : newHorzPos[splitterId].x2;
}
// Update all panels sizes based on splitter positions.
for (i = 0; i < panelIds.length; i += 1) {
panel = this._panels[panelIds[i]];
x1 = panel.splitters.left ? this._splitters[panel.splitters.left].x1 : 0;
y1 = panel.splitters.top ? this._splitters[panel.splitters.top].y1 : 0;
x2 = panel.splitters.right ? this._splitters[panel.splitters.right].x1 : this._width;
y2 = panel.splitters.bottom ? this._splitters[panel.splitters.bottom].y1 : this._height;
panel.panelContainer.css({
width: x2 - x1,
height: y2 - y1,
top: y1,
left: x1
});
if (panel.instance) {
panel.instance.setSize(x2 - x1, y2 - y1);
}
}
// Determine lengths of splitters.
for (i = 0; i < panelIds.length; i += 1) {
panel = this._panels[panelIds[i]];
panelPos = panel.panelContainer.position();
panelPos.height = panel.panelContainer.height();
panelPos.width = panel.panelContainer.width();
if (panel.splitters.left) {
updateVerticalPositions(panel.splitters.left, panelPos);
}
if (panel.splitters.right) {
updateVerticalPositions(panel.splitters.right, panelPos);
}
if (panel.splitters.top) {
updateHorizontalPositions(panel.splitters.top, panelPos);
}
if (panel.splitters.bottom) {
updateHorizontalPositions(panel.splitters.bottom, panelPos);
}
}
// Update the length and relPos of the splitters.
for (i = 0; i < splitterIds.length; i += 1) {
splitter = this._splitters[splitterIds[i]];
splitterBoundary = this._getSplitterBoundary(splitterIds[i]);
if (splitter.vertical) {
splitter.relPos = (splitter.x1 - splitterBoundary.min) / (splitterBoundary.max - splitterBoundary.min);
splitter.y1 = newVertPos[splitterIds[i]].y1;
splitter.y2 = newVertPos[splitterIds[i]].y2;
splitter.el.css({
top: splitter.y1,
height: splitter.y2 - splitter.y1
});
} else {
splitter.relPos = (splitter.y1 - splitterBoundary.min) / (splitterBoundary.max - splitterBoundary.min);
splitter.x1 = newHorzPos[splitterIds[i]].x1;
splitter.x2 = newHorzPos[splitterIds[i]].x2;
splitter.el.css({
left: splitter.x1,
width: splitter.x2 - splitter.x1
});
}
}
if (self._maximized) {
self._panels[self._activePanelId].panelContainer.css({
width: self._width,
height: self._height,
top: 0,
left: 0
});
self._panels[self._activePanelId].instance.setSize(self._width, self._height);
}
};
/* OVERRIDE FROM WIDGET-WITH-HEADER */
/* METHOD CALLED WHEN THE WIDGET'S READ-ONLY PROPERTY CHANGES */
SplitPanel.prototype.onReadOnlyChanged = function (isReadOnly) {
var self = this;
//apply parent's onReadOnlyChanged
PanelBase.prototype.onReadOnlyChanged.call(this, isReadOnly);
this._readOnly = isReadOnly;
Object.keys(this._panels).forEach(function (panelId) {
if (self._panels[panelId].instance) {
self._panels[panelId].instance.onReadOnlyChanged(isReadOnly);
}
});
};
SplitPanel.prototype.onResize = function (width, height) {
var self = this,
widthMultiplier,
heightMultiplier;
this.logger.debug('onResize --> width: ' + width + ', height: ' + height);
width = width < MINIMUM_RESCALE_WIDTH ? MINIMUM_RESCALE_WIDTH : width;
height = height < MINIMUM_RESCALE_HEIGHT ? MINIMUM_RESCALE_HEIGHT : height;
widthMultiplier = width / this._width;
heightMultiplier = height / this._height;
this._width = width;
this._height = height;
this.$el.width(this._width);
this.$el.height(this._height);
// Update splitters sizes..
Object.keys(this._splitters).forEach(function (id) {
if (self._splitters[id].vertical) {
self._splitters[id].x1 = self._splitters[id].x2 = Math.floor(self._splitters[id].x1 * widthMultiplier);
self._splitters[id].el.css({
left: self._splitters[id].x1
});
} else {
self._splitters[id].y1 = self._splitters[id].y2 = Math.floor(self._splitters[id].y1 * heightMultiplier);
self._splitters[id].el.css({
top: self._splitters[id].y1
});
}
});
// We need to make sure that splitters sizes still apply after truncations...
this._harmonizeSplitters();
// .. which will update the panel size in _updateUI.
this._updateUI();
};
/*** SPLITTER POSITION UPDATES ***/
SplitPanel.prototype._startPanelResize = function (splitterId, event) {
var self = this;
this._splitterResize = this._splitters[splitterId].el.clone().addClass(SPLITTER_RESIZE_CLASS);
this.$el.append(this._splitterResize);
this._splitterResizePos = this._splitters[splitterId].relPos;
this._splitStartMousePos = this._splitters[splitterId].vertical ? event.pageX : event.pageY;
$(document).on('mousemove.SplitPanel', function (event) {
self._onMouseMove(splitterId, event);
});
$(document).on('mouseup.SplitPanel', function (event) {
self._onMouseUp(splitterId, event);
});
};
SplitPanel.prototype._onMouseMove = function (splitterId, event) {
var mousePos = this._splitters[splitterId].vertical ? event.pageX : event.pageY,
mouseDelta = mousePos - this._splitStartMousePos,
boundary = this._getSplitterBoundary(splitterId),
resizeDelta = mouseDelta / (boundary.max - boundary.min),
snapDistance = SPLITTER_SNAP_FROM_DISTANCE / (boundary.max - boundary.min),
minPanelSize = MINIMUM_PANEL_SIZE / (boundary.max - boundary.min);
this._splitterResizePos = this._splitters[splitterId].relPos + resizeDelta;
if (this._splitterResizePos >= this._splitters[splitterId].relPos - snapDistance &&
this._splitterResizePos <= this._splitters[splitterId].relPos + snapDistance) {
this._splitterResizePos = this._splitters[splitterId].relPos;
}
if (this._splitterResizePos < minPanelSize) {
this._splitterResizePos = minPanelSize;
}
if (this._splitterResizePos > 1 - minPanelSize) {
this._splitterResizePos = 1 - minPanelSize;
}
this._updateSplitterResize(splitterId, boundary.min, boundary.max);
};
SplitPanel.prototype._updateSplitterResize = function (splitterId, minVal, maxVal) {
var sw = SPLITTER_SIZE + 2 * SPLITTER_RESIZE_PADDING,
sh = SPLITTER_SIZE + 2 * SPLITTER_RESIZE_PADDING,
splitterLeft,
splitterTop;
if (this._splitters[splitterId].vertical) {
sh = this._splitters[splitterId].y2 - this._splitters[splitterId].y1;
splitterLeft = Math.floor(minVal + (maxVal - minVal - sw) * this._splitterResizePos);
} else {
sw = this._splitters[splitterId].x2 - this._splitters[splitterId].x1;
splitterTop = Math.floor(minVal + (maxVal - minVal - sh) * this._splitterResizePos);
}
this._splitterResize.css({
width: sw,
height: sh,
top: splitterTop,
left: splitterLeft
});
};
SplitPanel.prototype._onMouseUp = function (splitterId /*, event*/) {
$(document).off('mousemove.SplitPanel');
$(document).off('mouseup.SplitPanel');
var pos = this._splitterResize.position();
this._splitters[splitterId].relPos = this._splitterResizePos;
if (this._splitters[splitterId].vertical) {
this._splitters[splitterId].x1 = this._splitters[splitterId].x2 = pos.left;
this._splitters[splitterId].el.css({
left: pos.left
});
} else {
this._splitters[splitterId].y1 = this._splitters[splitterId].y2 = pos.top;
this._splitters[splitterId].el.css({
top: pos.top
});
}
this._splitterResize.remove();
this._splitterResize = undefined;
this._splitterResizePos = undefined;
this._updateUI();
};
// Attaching/Detaching events handler for setting the active panel.
// It is important to use event capturing (instead of bubbling) since the panel container is the top-most
// element and it is crucial that it gets the mousedown event before any of the panel's child-elements.
// If using bubbling - the panel's child-elements might prevent the event propagation which cannot be controlled
// from this scope (and could even be part of libraries used in the panel).
// N.B. JQuery does not support event capturing..
SplitPanel.prototype._attachActivateHandler = function (panelContainer) {
var self = this,
handler = function (/*event*/) {
var el = $(this),
panelId = el.data(PANEL_ID_DATA_KEY);
self.setActivePanel(panelId);
};
panelContainer.get(0).addEventListener('mousedown', handler, true);
return handler;
};
SplitPanel.prototype._removeActivateHandler = function (panelContainer, handler) {
panelContainer.get(0).removeEventListener('mousedown', handler, true);
return handler;
};
SplitPanel.prototype.isMaximized = function () {
return this._maximized;
};
SplitPanel.prototype.maximize = function (setToMax, panelId) {
var panelIds = Object.keys(this._panels),
splitterIds = Object.keys(this._splitters),
i;
if (this._maximized === false) {
this._maximized = true;
for (i = 0; i < splitterIds.length; i += 1) {
$(this._splitters[splitterIds[i]].el).hide();
}
for (i = 0; i < panelIds.length; i += 1) {
if (panelIds[i] !== panelId) {
this._panels[panelIds[i]].panelContainer.hide();
}
}
this.setActivePanel(panelId);
} else {
this._maximized = false;
for (i = 0; i < splitterIds.length; i += 1) {
$(this._splitters[splitterIds[i]].el).show();
}
for (i = 0; i < panelIds.length; i += 1) {
if (panelIds[i] !== this._activePanelId) {
this._panels[panelIds[i]].panelContainer.show();
}
}
}
this._updateUI();
};
return SplitPanel;
});