mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
390 lines
No EOL
11 KiB
JavaScript
390 lines
No EOL
11 KiB
JavaScript
|
|
/** @constructor */
|
|
function Window(el, winManager) {
|
|
this.root = el;
|
|
this.neverOpened = !this.root.is(':visible');
|
|
this.tileUpRelative = $('body');
|
|
this.onShowCallback = null;
|
|
var root = this.root;
|
|
var caption = this.root.find('.tool-caption');
|
|
caption.each(function() {
|
|
var closeBtn = '<span class="btn rm" style="float: right;"><i class="fa fa-remove"></i></span>';
|
|
$(this).append(closeBtn);
|
|
});
|
|
this.root.find('.tool-caption .rm').click(function() {
|
|
root.hide();
|
|
});
|
|
var DIRS = DIRECTIONS;
|
|
winManager.registerResize(this.root, DIRS.NORTH | DIRS.SOUTH | DIRS.WEST | DIRS.EAST);
|
|
winManager.registerDrag(this.root, caption);
|
|
}
|
|
|
|
|
|
Window.prototype.show = function() {
|
|
this.root.show();
|
|
}
|
|
|
|
Window.prototype.toggle = function() {
|
|
var aboutToShow = !this.root.is(':visible');
|
|
if (aboutToShow) {
|
|
this.tileUpPolicy(this.neverOpened, this.tileUpRelative);
|
|
}
|
|
this.neverOpened = false ;
|
|
this.root.toggle();
|
|
if (aboutToShow && this.onShowCallback != null) {
|
|
this.onShowCallback(this);
|
|
}
|
|
};
|
|
|
|
Window.prototype.tileUpPolicy = function(firstTime, relativeEl) {
|
|
var span = 20;
|
|
var relOff = relativeEl.offset();
|
|
var off = this.root.offset();
|
|
off = {
|
|
left: parseInt(this.root.css('left')),
|
|
top: parseInt(this.root.css('top'))
|
|
};
|
|
|
|
if (firstTime) {
|
|
off = {
|
|
left: relOff.left + relativeEl.width() - this.root.width() - span,
|
|
top: relOff.top + relativeEl.height() - this.root.height() - span
|
|
};
|
|
this.root.css({
|
|
left: off.left + 'px',
|
|
top: off.top + 'px'
|
|
});
|
|
}
|
|
var needToSet = false;
|
|
if (off.left < relOff.left || off.left >= relOff.left + relativeEl.width() - span) {
|
|
off.left = relOff.left + span;
|
|
needToSet = true;
|
|
}
|
|
if (off.top < relOff.top || off.top >= relOff.top + relativeEl.height() - span) {
|
|
off.top = relOff.top + span;
|
|
needToSet = true;
|
|
}
|
|
if (needToSet) {
|
|
this.root.css({
|
|
left: off.left + 'px',
|
|
top: off.top + 'px'
|
|
});
|
|
}
|
|
//var fixedWidth = null;
|
|
//var fixedHeight = null;
|
|
//
|
|
//if (off.left + this.root.width() > relOff.left + relativeEl.width()) {
|
|
// fixedWidth = this.root.width() - span * 2;
|
|
//}
|
|
//if (off.top + this.root.height() > relOff.top + relativeEl.height()) {
|
|
// fixedHeight = this.root.width() - span * 2;
|
|
//}
|
|
//if (fixedWidth != null) {
|
|
// console.log(fixedWidth)
|
|
// this.root.css({ width : fixedWidth + 'px'});
|
|
//}
|
|
//if (fixedHeight != null) {
|
|
// this.root.css({ height : fixedHeight + 'px'});
|
|
//}
|
|
};
|
|
|
|
function WinManager() {
|
|
this.moveHandler = null;
|
|
var wm = this;
|
|
$('body').mousemove(function(e) {
|
|
if (wm.moveHandler != null) {
|
|
wm.moveHandler(e);
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
$('body').mouseup(function(e) {
|
|
wm.moveHandler = null;
|
|
});
|
|
}
|
|
|
|
WinManager.prototype.captureDrag = function(el, e) {
|
|
var origin = {x : e.pageX, y : e.pageY};
|
|
var originLocation = el.offset();
|
|
this.moveHandler = function(e) {
|
|
var dx = e.pageX - origin.x;
|
|
var dy = e.pageY - origin.y;
|
|
el.offset({left : originLocation.left + dx, top : originLocation.top + dy});
|
|
};
|
|
};
|
|
|
|
WinManager.prototype.captureResize = function(el, dirMask, e, onResize) {
|
|
|
|
var origin = {x : e.pageX, y : e.pageY};
|
|
var originSize = {x : el.width(), y : el.height()};
|
|
var originLocation = el.offset();
|
|
var north = _maskTest(dirMask, DIRECTIONS.NORTH);
|
|
var south = _maskTest(dirMask, DIRECTIONS.SOUTH);
|
|
var west = _maskTest(dirMask, DIRECTIONS.WEST);
|
|
var east = _maskTest(dirMask, DIRECTIONS.EAST);
|
|
|
|
this.moveHandler = function(e) {
|
|
var dx = e.pageX - origin.x;
|
|
var dy = e.pageY - origin.y;
|
|
if (east) {
|
|
el.css('width', (originSize.x + dx) + 'px');
|
|
}
|
|
var top = originLocation.top;
|
|
var left = originLocation.left;
|
|
var setLoc = false;
|
|
if (west) {
|
|
el.css('width', (originSize.x - dx) + 'px');
|
|
left += dx;
|
|
setLoc = true;
|
|
}
|
|
if (south) {
|
|
el.css('height', (originSize.y + dy) + 'px');
|
|
}
|
|
if (north) {
|
|
el.css('height', (originSize.y - dy) + 'px');
|
|
top += dy;
|
|
setLoc = true;
|
|
}
|
|
if (setLoc) {
|
|
el.offset({left : left, top: top});
|
|
}
|
|
if (onResize !== undefined) {
|
|
onResize();
|
|
}
|
|
}
|
|
};
|
|
|
|
var DIRECTIONS = {
|
|
NORTH : 0x0001,
|
|
SOUTH : 0x0010,
|
|
WEST : 0x0100,
|
|
EAST : 0x1000,
|
|
};
|
|
|
|
WinManager.prototype.registerResize = function(el, dirMask, onResize) {
|
|
var wm = this;
|
|
var north = _maskTest(dirMask, DIRECTIONS.NORTH);
|
|
var south = _maskTest(dirMask, DIRECTIONS.SOUTH);
|
|
var west = _maskTest(dirMask, DIRECTIONS.WEST);
|
|
var east = _maskTest(dirMask, DIRECTIONS.EAST);
|
|
|
|
var borderTop = parseInt(el.css('borderTopWidth'), 10);
|
|
var borderLeft = parseInt(el.css('borderLeftWidth'), 10);
|
|
|
|
function onNorthEdge(e, el) {
|
|
var offset = el.offset();
|
|
return e.pageY < offset.top + borderTop;
|
|
}
|
|
|
|
function onSouthEdge(e, el) {
|
|
var offset = el.offset();
|
|
var height = el.height();
|
|
return e.pageY > offset.top + height + borderTop;
|
|
}
|
|
|
|
function onWestEdge(e, el) {
|
|
var offset = el.offset();
|
|
return e.pageX < offset.left + borderLeft;
|
|
}
|
|
|
|
function onEastEdge(e, el) {
|
|
var offset = el.offset();
|
|
var width = el.width();
|
|
return e.pageX > offset.left + width + borderLeft;
|
|
}
|
|
|
|
|
|
el.mousedown(function(e) {
|
|
var $this = $(this);
|
|
if (north && east && onNorthEdge(e, $this) && onEastEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.NORTH | DIRECTIONS.EAST, e, onResize);
|
|
} else if (north && west && onNorthEdge(e, $this) && onWestEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.NORTH | DIRECTIONS.WEST, e, onResize);
|
|
} else if (south && east && onSouthEdge(e, $this) && onEastEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.SOUTH | DIRECTIONS.EAST, e, onResize);
|
|
} else if (south && west && onSouthEdge(e, $this) && onWestEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.SOUTH | DIRECTIONS.WEST, e, onResize);
|
|
} else if (north && onNorthEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.NORTH, e, onResize);
|
|
} else if (south && onSouthEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.SOUTH, e, onResize);
|
|
} else if (west && onWestEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.WEST, e, onResize);
|
|
} else if (east && onEastEdge(e, $this)) {
|
|
wm.captureResize(el, DIRECTIONS.EAST, e, onResize);
|
|
}
|
|
});
|
|
el.mousemove(function(e) {
|
|
|
|
var $this = $(this);
|
|
if (north && east && onNorthEdge(e, $this) && onEastEdge(e, $this)) {
|
|
el.css('cursor', 'nesw-resize');
|
|
} else if (north && west && onNorthEdge(e, $this) && onWestEdge(e, $this)) {
|
|
el.css('cursor', 'nwse-resize');
|
|
} else if (south && east && onSouthEdge(e, $this) && onEastEdge(e, $this)) {
|
|
el.css('cursor', 'nwse-resize');
|
|
} else if (south && west && onSouthEdge(e, $this) && onWestEdge(e, $this)) {
|
|
el.css('cursor', 'nesw-resize');
|
|
} else if (south && onSouthEdge(e, $this)) {
|
|
el.css('cursor', 'ns-resize');
|
|
} else if (north && onNorthEdge(e, $this)) {
|
|
el.css('cursor', 'ns-resize');
|
|
} else if (east && onEastEdge(e, $this)) {
|
|
el.css('cursor', 'ew-resize');
|
|
} else if (west && onWestEdge(e, $this)) {
|
|
el.css('cursor', 'ew-resize');
|
|
} else {
|
|
el.css('cursor', 'inherited');
|
|
}
|
|
});
|
|
};
|
|
|
|
WinManager.prototype.registerDrag = function(el, dragger) {
|
|
var wm = this;
|
|
dragger.mousedown(function(e) {
|
|
wm.captureDrag(el, e);
|
|
});
|
|
};
|
|
|
|
function bindOpening(btn, win) {
|
|
btn.click(function(e) {
|
|
openWin(win, e);
|
|
});
|
|
}
|
|
|
|
function createActionsWinBuilder(win) {
|
|
var content = win.root.find('.content');
|
|
var template = content.html();
|
|
content.empty();
|
|
return function(name, action) {
|
|
content.append(template.replace("$value$", name));
|
|
content.find('div:last input').click(action);
|
|
};
|
|
}
|
|
|
|
function closeWin(win) {
|
|
win.root.hide();
|
|
}
|
|
|
|
function openWin(win, mouseEvent) {
|
|
|
|
var x = mouseEvent.pageX;
|
|
var y = mouseEvent.pageY;
|
|
var pageW = $(window).width();
|
|
var pageH = $(window).height();
|
|
var winW = win.root.width();
|
|
var winH = win.root.height();
|
|
|
|
var left = x < pageW / 2 ? x : x - winW;
|
|
var top = y < pageH / 2 ? y : y - winH;
|
|
|
|
win.root.show();
|
|
win.root.offset({top : top, left : left});
|
|
|
|
}
|
|
|
|
/** @constructor */
|
|
function List(id, model) {
|
|
this.ul = $('<ul>', { 'class' : 'tlist', id : id});
|
|
this.model = model;
|
|
this.template = '<li>$name$<span class="btn rm" style="float: right;"><i class="fa fa-remove"></i></span></li>';
|
|
}
|
|
|
|
List.prototype.refresh = function() {
|
|
this.ul.empty();
|
|
var items = this.model.items();
|
|
var model = this.model;
|
|
function makeCallbacks(li, item, index) {
|
|
li.find('.rm').click(function(e) {
|
|
model.remove(item, index);
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
});
|
|
li.hover(function() {model.hover(item, index)});
|
|
li.mouseleave(function() {model.mouseleave(item, index)});
|
|
li.click(function() {model.click(item, index)});
|
|
}
|
|
|
|
|
|
for (var i = 0; i < items.length; ++i) {
|
|
var item = items[i];
|
|
var li = $(this.template.replace('$name$', item.name));
|
|
this.ul.append(li);
|
|
makeCallbacks(li, item, i)
|
|
}
|
|
};
|
|
|
|
function dockBtn(name, icon) {
|
|
var btn = $('<span>', {'class': 'dock-btn'});
|
|
btn.append(faBtn(icon));
|
|
btn.append($('<span>', {'class': 'txt'}).text(name));
|
|
return btn;
|
|
}
|
|
|
|
function faBtn (iconName) {
|
|
return $('<i>', {'class' : 'fa fa-'+iconName});
|
|
}
|
|
|
|
function Dock(dockEl, switcherEl, viewDefinitions) {
|
|
this.views = {};
|
|
this.dockEl = dockEl;
|
|
function bindClick(dock, switchEl, viewName) {
|
|
switchEl.click(function(e) {
|
|
if (dock.isVisible(viewName)) {
|
|
dock.hide(viewName);
|
|
} else {
|
|
dock.show(viewName);
|
|
}
|
|
});
|
|
}
|
|
for (var i = 0; i < viewDefinitions.length; i++) {
|
|
var viewDef = viewDefinitions[i];
|
|
var view = {};
|
|
this.views[viewDef.name] = view;
|
|
view.node = $('<div>', {'class': 'dock-node'});
|
|
var caption = $('<div>', {'class': 'tool-caption'});
|
|
caption.append($('<span>', {'class': 'txt'}).text(viewDef.name.toUpperCase()));
|
|
caption.append(faBtn(viewDef.icon));
|
|
view.node.append(caption);
|
|
view.node.hide();
|
|
this.dockEl.append(view.node);
|
|
view.switchBtn = dockBtn(viewDef.name, viewDef.icon);
|
|
bindClick(this, view.switchBtn, viewDef.name);
|
|
switcherEl.append(view.switchBtn);
|
|
}
|
|
}
|
|
|
|
Dock.prototype.show = function(viewName) {
|
|
var view = this.views[viewName];
|
|
if (view.switchBtn.hasClass('selected')) {
|
|
return;
|
|
}
|
|
if (!this.dockEl.is(":visible")) {
|
|
this.dockEl.show();
|
|
$('body').trigger('layout');
|
|
}
|
|
view.node.show();
|
|
view.switchBtn.addClass('selected');
|
|
};
|
|
|
|
Dock.prototype.hide = function(viewName) {
|
|
var view = this.views[viewName];
|
|
if (!view.switchBtn.hasClass('selected')) {
|
|
return;
|
|
}
|
|
view.node.hide();
|
|
view.switchBtn.removeClass('selected');
|
|
if (this.dockEl.find('.dock-node:visible').length == 0) {
|
|
this.dockEl.hide();
|
|
$('body').trigger('layout');
|
|
}
|
|
};
|
|
|
|
Dock.prototype.isVisible = function(viewName) {
|
|
return this.views[viewName].switchBtn.hasClass('selected');
|
|
};
|
|
|
|
function _maskTest(mask, value) {
|
|
return (mask & value) === value;
|
|
}
|
|
|
|
export { WinManager, Window, List, Dock, dockBtn, faBtn, openWin, closeWin, bindOpening, createActionsWinBuilder, DIRECTIONS }; |