CanvasSectionContainer: Fixes.
Bugs related to ordering of sections are fixed. addSection and createSection functions are separated. contextMenu event is added. Sections' drawing orders are updated for future uses. Signed-off-by: Gökay Şatır <gokaysatir@collabora.com> Change-Id: I89127c97ad7b7dac4b293c4108c44cb6c4427134
This commit is contained in:
parent
95a8028f00
commit
15bf787771
2 changed files with 98 additions and 70 deletions
|
@ -102,6 +102,7 @@ class CanvasSectionObject {
|
|||
onMouseLeave: Function; // Parameters: Point [x, y], e (native event object)
|
||||
onClick: Function; // Parameters: Point [x, y], e (native event object)
|
||||
onDoubleClick: Function; // Parameters: Point [x, y], e (native event object)
|
||||
onContextMenu: Function;
|
||||
onMouseWheel: Function; // Parameters: Point [x, y], DeltaY, e (native event object)
|
||||
onLongPress: Function; // Parameters: Point [x, y], e (native event object)
|
||||
onMultiTouchStart: Function; // Parameters: e (native event object)
|
||||
|
@ -130,6 +131,7 @@ class CanvasSectionObject {
|
|||
this.onMouseLeave = options.onMouseLeave ? options.onMouseLeave: function() {};
|
||||
this.onClick = options.onClick ? options.onClick: function() {};
|
||||
this.onDoubleClick = options.onDoubleClick ? options.onDoubleClick: function() {};
|
||||
this.onContextMenu = options.onContextMenu ? options.onContextMenu: function() {};
|
||||
this.onMouseWheel = options.onMouseWheel ? options.onMouseWheel: function() {};
|
||||
this.onLongPress = options.onLongPress ? options.onLongPress: function() {};
|
||||
this.onMultiTouchStart = options.onMultiTouchStart ? options.onMultiTouchStart: function() {};
|
||||
|
@ -179,6 +181,7 @@ class CanvasSectionContainer {
|
|||
this.canvas.onmouseup = this.onMouseUp.bind(this);
|
||||
this.canvas.onclick = this.onClick.bind(this);
|
||||
this.canvas.ondblclick = this.onDoubleClick.bind(this);
|
||||
this.canvas.oncontextmenu = this.onContextMenu.bind(this);
|
||||
this.canvas.onwheel = this.onMouseWheel.bind(this);
|
||||
this.canvas.onmouseleave = this.onMouseLeave.bind(this);
|
||||
this.canvas.ontouchstart = this.onTouchStart.bind(this);
|
||||
|
@ -343,12 +346,11 @@ class CanvasSectionContainer {
|
|||
if (section) {
|
||||
section.onLongPress(this.convertPositionToSectionLocale(section, this.mousePosition), e);
|
||||
}
|
||||
this.potentialLongPress = false;
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseDown (e: MouseEvent) { // Ignore this event, just rely on this.draggingSomething variable.
|
||||
if (!this.touchEventInProgress) {
|
||||
if (e.button === 0 && !this.touchEventInProgress) { // So, we only handle left button.
|
||||
this.clearMousePositions();
|
||||
this.positionOnMouseDown = this.convertPositionToCanvasLocale(e);
|
||||
|
||||
|
@ -361,7 +363,7 @@ class CanvasSectionContainer {
|
|||
}
|
||||
|
||||
private onMouseUp (e: MouseEvent) { // Should be ignored unless this.draggingSomething = true.
|
||||
if (!this.touchEventInProgress) {
|
||||
if (e.button === 0 && !this.touchEventInProgress) {
|
||||
this.positionOnMouseUp = this.convertPositionToCanvasLocale(e);
|
||||
|
||||
if (!this.draggingSomething) {
|
||||
|
@ -379,6 +381,22 @@ class CanvasSectionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
private onContextMenu (e: MouseEvent) {
|
||||
var mousePosition = this.convertPositionToCanvasLocale(e);
|
||||
var section: CanvasSectionObject = this.findSectionContainingPoint(mousePosition);
|
||||
if (section) {
|
||||
section.onContextMenu();
|
||||
}
|
||||
if (this.potentialLongPress) {
|
||||
// LongPress triggers context menu.
|
||||
// We should stop propagating here because we are using different context menu handlers for touch and mouse events.
|
||||
// By stopping this event here, we can have real context menus (for mice) and other handlers (for longpress) at the same time (see Control.RowHeader.js).
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseWheel (e: WheelEvent) {
|
||||
var point = this.convertPositionToCanvasLocale(e);
|
||||
var delta = e.deltaY;
|
||||
|
@ -478,6 +496,14 @@ class CanvasSectionContainer {
|
|||
}
|
||||
|
||||
onResize (newWidth: number, newHeight: number) {
|
||||
var container: HTMLElement = <HTMLElement>this.canvas.parentNode;
|
||||
var cRect: ClientRect = container.getBoundingClientRect();
|
||||
if (!newWidth)
|
||||
newWidth = cRect.right - cRect.left;
|
||||
|
||||
if (!newHeight)
|
||||
newHeight = cRect.bottom - cRect.top;
|
||||
|
||||
this.dpiScale = window.devicePixelRatio;
|
||||
newWidth = Math.floor(newWidth * this.dpiScale);
|
||||
newHeight = Math.floor(newHeight * this.dpiScale);
|
||||
|
@ -504,7 +530,7 @@ class CanvasSectionContainer {
|
|||
|
||||
findSectionContainingPoint (point: Array<number>): any {
|
||||
for (var i: number = this.sections.length - 1; i > -1; i--) { // Search from top to bottom. Top section will be sent as target section.
|
||||
if (this.sections[i].interactable && this.doesSectionIncludePoint(this.sections[i], point))
|
||||
if (this.sections[i].isLocated && this.sections[i].interactable && this.doesSectionIncludePoint(this.sections[i], point))
|
||||
return this.sections[i];
|
||||
}
|
||||
|
||||
|
@ -545,10 +571,7 @@ class CanvasSectionContainer {
|
|||
private hitLeft (section: CanvasSectionObject): number {
|
||||
var maxX = -1;
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
if (!this.sections[i].isLocated)
|
||||
continue;
|
||||
|
||||
if (this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
if (this.sections[i].isLocated && this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
var currentLeft = this.sections[i].myTopLeft[0] + this.sections[i].size[0];
|
||||
if (currentLeft > maxX && currentLeft < section.myTopLeft[0]) {
|
||||
if (this.doSectionsIntersectOnYAxis(this.sections[i], section)) {
|
||||
|
@ -567,10 +590,7 @@ class CanvasSectionContainer {
|
|||
private hitRight (section: CanvasSectionObject): number {
|
||||
var minX = Infinity;
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
if (!this.sections[i].isLocated)
|
||||
continue;
|
||||
|
||||
if (this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
if (this.sections[i].isLocated && this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
var currentRight = this.sections[i].myTopLeft[0];
|
||||
if (currentRight < minX && currentRight > section.myTopLeft[0]) {
|
||||
if (this.doSectionsIntersectOnYAxis(this.sections[i], section)) {
|
||||
|
@ -590,10 +610,7 @@ class CanvasSectionContainer {
|
|||
private hitTop (section: CanvasSectionObject): number {
|
||||
var maxY = -1;
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
if (!this.sections[i].isLocated)
|
||||
continue;
|
||||
|
||||
if (this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
if (this.sections[i].isLocated && this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
var currentTop = this.sections[i].myTopLeft[1] + this.sections[i].size[1];
|
||||
if (currentTop > maxY && currentTop < section.myTopLeft[1]) {
|
||||
if (this.doSectionsIntersectOnXAxis(this.sections[i], section)) {
|
||||
|
@ -612,10 +629,7 @@ class CanvasSectionContainer {
|
|||
private hitBottom (section: CanvasSectionObject): number {
|
||||
var minY = Infinity;
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
if (!this.sections[i].isLocated)
|
||||
continue;
|
||||
|
||||
if (this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
if (this.sections[i].isLocated && this.sections[i].zIndex === section.zIndex && this.sections[i].name !== section.name) {
|
||||
var currentBottom = this.sections[i].myTopLeft[1];
|
||||
if (currentBottom < minY && currentBottom > section.myTopLeft[1]) {
|
||||
if (this.doSectionsIntersectOnXAxis(this.sections[i], section)) {
|
||||
|
@ -644,13 +658,11 @@ class CanvasSectionContainer {
|
|||
private locateSections () {
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
var section: CanvasSectionObject = this.sections[i];
|
||||
if (section.isLocated)
|
||||
continue;
|
||||
|
||||
section.isLocated = false;
|
||||
section.myTopLeft = null;
|
||||
var x = section.anchor[1] === 'left' ? section.position[0]: (this.right - (section.position[0] + section.size[0]));
|
||||
var y = section.anchor[0] === 'top' ? section.position[1]: (this.bottom - (section.position[1] + section.size[1]));
|
||||
if (!section.boundToSection)
|
||||
if (!section.boundToSection) {
|
||||
section.myTopLeft = [x, y];
|
||||
if (section.expand[0] !== '') {
|
||||
if (section.expand.includes('left') || section.expand.includes('right'))
|
||||
|
@ -658,6 +670,10 @@ class CanvasSectionContainer {
|
|||
if (section.expand.includes('top') || section.expand.includes('bottom'))
|
||||
section.size[1] = 0;
|
||||
}
|
||||
else {
|
||||
section.isLocated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
section.myTopLeft = [0, 0];
|
||||
section.size = [0, 0];
|
||||
|
@ -667,10 +683,7 @@ class CanvasSectionContainer {
|
|||
// We have initial positions, now we'll expand them.
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
var section: CanvasSectionObject = this.sections[i];
|
||||
if (section.isLocated)
|
||||
continue;
|
||||
|
||||
if (section.expand && !section.boundToSection) {
|
||||
if (section.expand[0] !== '' && !section.boundToSection) {
|
||||
if (section.expand.includes('left')) {
|
||||
var initialX = section.myTopLeft[0];
|
||||
section.myTopLeft[0] = this.hitLeft(section);
|
||||
|
@ -693,16 +706,11 @@ class CanvasSectionContainer {
|
|||
|
||||
section.isLocated = true;
|
||||
}
|
||||
else if (!section.boundToSection)
|
||||
section.isLocated = true; // expand is empty => its location/size is already defined.
|
||||
}
|
||||
|
||||
// Set location and size of bound sections.
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
var section: CanvasSectionObject = this.sections[i];
|
||||
if (section.isLocated)
|
||||
continue;
|
||||
|
||||
if (section.boundToSection) {
|
||||
var parentSection = this.getSectionWithName(section.boundToSection);
|
||||
if (parentSection) {
|
||||
|
@ -710,9 +718,8 @@ class CanvasSectionContainer {
|
|||
section.size[1] = parentSection.size[1];
|
||||
section.myTopLeft[0] = parentSection.myTopLeft[0];
|
||||
section.myTopLeft[1] = parentSection.myTopLeft[1];
|
||||
section.isLocated = true;
|
||||
}
|
||||
|
||||
section.isLocated = true; // FIXME: do only if parentSection is available ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -732,13 +739,12 @@ class CanvasSectionContainer {
|
|||
// According to processing order. Section with the highest processing order will be calculated last.
|
||||
for (var i: number = 0; i < this.sections.length - 1; i++) {
|
||||
var zIndex = this.sections[i].zIndex;
|
||||
while (i < this.sections.length - 1 && zIndex === this.sections[i + 1].zIndex) {
|
||||
if (this.sections[i].processingOrder > this.sections[i + 1].processingOrder) {
|
||||
var temp = this.sections[i + 1];
|
||||
this.sections[i + 1] = this.sections[i];
|
||||
for (var j: number = i + 1; j < this.sections.length && this.sections[j].zIndex === zIndex; j++) {
|
||||
if (this.sections[i].processingOrder > this.sections[j].processingOrder) {
|
||||
var temp = this.sections[j];
|
||||
this.sections[j] = this.sections[i];
|
||||
this.sections[i] = temp;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -747,13 +753,12 @@ class CanvasSectionContainer {
|
|||
// According to drawing order. Section with the highest drawing order will be drawn on top.
|
||||
for (var i: number = 0; i < this.sections.length - 1; i++) {
|
||||
var zIndex = this.sections[i].zIndex;
|
||||
while (i < this.sections.length - 1 && zIndex === this.sections[i + 1].zIndex) {
|
||||
if (this.sections[i].drawingOrder > this.sections[i + 1].drawingOrder) {
|
||||
var temp = this.sections[i + 1];
|
||||
this.sections[i + 1] = this.sections[i];
|
||||
for (var j: number = i + 1; j < this.sections.length && this.sections[j].zIndex === zIndex; j++) {
|
||||
if (this.sections[i].drawingOrder > this.sections[j].drawingOrder) {
|
||||
var temp = this.sections[j];
|
||||
this.sections[j] = this.sections[i];
|
||||
this.sections[i] = temp;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -789,16 +794,24 @@ class CanvasSectionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
setPenPosition (section: CanvasSectionObject) {
|
||||
this.context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
this.context.translate(section.myTopLeft[0], section.myTopLeft[1]);
|
||||
}
|
||||
|
||||
private drawSections () {
|
||||
this.context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
this.context.fillStyle = this.clearColor;
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
this.context.font = String(20 * this.dpiScale) + "px Verdana";
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
this.context.translate(this.sections[i].myTopLeft[0], this.sections[i].myTopLeft[1]);
|
||||
this.sections[i].onDraw();
|
||||
this.context.translate(-this.sections[i].myTopLeft[0], -this.sections[i].myTopLeft[1]);
|
||||
if (this.sections[i].isLocated) {
|
||||
this.context.translate(this.sections[i].myTopLeft[0], this.sections[i].myTopLeft[1]);
|
||||
this.sections[i].onDraw();
|
||||
this.context.translate(-this.sections[i].myTopLeft[0], -this.sections[i].myTopLeft[1]);
|
||||
}
|
||||
}
|
||||
//this.drawSectionBorders();
|
||||
}
|
||||
|
@ -846,23 +859,12 @@ class CanvasSectionContainer {
|
|||
return true;
|
||||
}
|
||||
|
||||
addSection (options: any, parentSectionName: string = null) {
|
||||
createSection (options: any, parentSectionName: string = null) {
|
||||
if (this.newSectionChecks(options)) {
|
||||
// Every section can draw from Point(0, 0), their drawings will be translated to myTopLeft position.
|
||||
var newSection: CanvasSectionObject = new CanvasSectionObject(options);
|
||||
|
||||
newSection.context = this.context;
|
||||
newSection.documentTopLeft = this.documentTopLeft;
|
||||
newSection.containerObject = this;
|
||||
newSection.dpiScale = this.dpiScale;
|
||||
newSection.sectionProperties.section = newSection;
|
||||
newSection.boundToSection = parentSectionName;
|
||||
|
||||
this.sections.push(newSection);
|
||||
newSection.onInitialize();
|
||||
this.reNewAllSections(false);
|
||||
this.drawSections();
|
||||
|
||||
this.pushSection(newSection);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -870,6 +872,29 @@ class CanvasSectionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
addSection (newSection: CanvasSectionObject) {
|
||||
if (this.newSectionChecks(newSection)) {
|
||||
this.pushSection(newSection);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private pushSection (newSection: CanvasSectionObject) {
|
||||
// Every section can draw from Point(0, 0), their drawings will be translated to myTopLeft position.
|
||||
newSection.context = this.context;
|
||||
newSection.documentTopLeft = this.documentTopLeft;
|
||||
newSection.containerObject = this;
|
||||
newSection.dpiScale = this.dpiScale;
|
||||
newSection.sectionProperties.section = newSection;
|
||||
this.sections.push(newSection);
|
||||
newSection.onInitialize();
|
||||
this.reNewAllSections(false);
|
||||
this.drawSections();
|
||||
}
|
||||
|
||||
removeSection (name: string) {
|
||||
var found: boolean = false;
|
||||
for (var i: number = 0; i < this.sections.length; i++) {
|
||||
|
|
|
@ -202,6 +202,8 @@ L.TileSectionManager = L.Class.extend({
|
|||
if (!ctx)
|
||||
ctx = this._paintContext();
|
||||
|
||||
this._sectionContainer.setPenPosition(this._tilesSection);
|
||||
|
||||
if (ctx.paneBoundsActive === true)
|
||||
this._paintWithPanes(tile, ctx);
|
||||
else
|
||||
|
@ -210,16 +212,16 @@ L.TileSectionManager = L.Class.extend({
|
|||
|
||||
_addTilesSection: function () {
|
||||
var that = this;
|
||||
this._sectionContainer.addSection({
|
||||
this._sectionContainer.createSection({
|
||||
name: 'tiles',
|
||||
anchor: 'top left',
|
||||
position: [250 * that._dpiScale, 250 * that._dpiScale], // Set its initial position to somewhere blank. Other sections shouldn't cover this point after initializing.
|
||||
size: [0, 0], // Going to be expanded, no initial width or height is necessary.
|
||||
expand: 'top left bottom right', // Expand to all directions.
|
||||
processingOrder: 1,
|
||||
processingOrder: 5,
|
||||
drawingOrder: 5,
|
||||
zIndex: 5,
|
||||
interactable: true,
|
||||
interactable: false,
|
||||
sectionProperties: {
|
||||
docLayer: that._layer,
|
||||
tsManager: that
|
||||
|
@ -233,13 +235,13 @@ L.TileSectionManager = L.Class.extend({
|
|||
|
||||
_addGridSection: function () {
|
||||
var that = this;
|
||||
this._sectionContainer.addSection({
|
||||
this._sectionContainer.createSection({
|
||||
name: 'calc grid',
|
||||
anchor: 'top left',
|
||||
position: [0, 0],
|
||||
size: [0, 0],
|
||||
expand: '',
|
||||
processingOrder: 2, // Size and position will be copied, this value is not important.
|
||||
processingOrder: 5, // Size and position will be copied, this value is not important.
|
||||
drawingOrder: 4,
|
||||
zIndex: 5,
|
||||
// Even if this one is drawn on top, won't be able to catch events.
|
||||
|
@ -302,13 +304,13 @@ L.TileSectionManager = L.Class.extend({
|
|||
// This section is added when debug is enabled. Splits are enabled for only Calc for now.
|
||||
_addSplitsSection: function () {
|
||||
var that = this;
|
||||
this._sectionContainer.addSection({
|
||||
this._sectionContainer.createSection({
|
||||
name: 'splits',
|
||||
anchor: 'top left',
|
||||
position: [0, 0],
|
||||
size: [0, 0],
|
||||
expand: '',
|
||||
processingOrder: 3, // Size and position will be copied, this value is not important.
|
||||
processingOrder: 5, // Size and position will be copied, this value is not important.
|
||||
drawingOrder: 8, // Above tiles section (same zIndex, higher drawing order).
|
||||
zIndex: 5,
|
||||
// Even if this one is drawn on top, won't be able to catch events.
|
||||
|
@ -324,13 +326,13 @@ L.TileSectionManager = L.Class.extend({
|
|||
// This section is added when debug is enabled.
|
||||
_addTilePixelGridSection: function () {
|
||||
var that = this;
|
||||
this._sectionContainer.addSection({
|
||||
this._sectionContainer.createSection({
|
||||
name: 'tile pixel grid',
|
||||
anchor: 'top left',
|
||||
position: [0, 0],
|
||||
size: [0, 0],
|
||||
expand: '',
|
||||
processingOrder: 4, // Size and position will be copied, this value is not important.
|
||||
processingOrder: 5, // Size and position will be copied, this value is not important.
|
||||
drawingOrder: 6,
|
||||
zIndex: 5,
|
||||
interactable: false,
|
||||
|
@ -572,6 +574,7 @@ L.CanvasTileLayer = L.TileLayer.extend({
|
|||
if (this._docType === 'spreadsheet') {
|
||||
this._painter._addGridSection();
|
||||
}
|
||||
this._syncTileContainerSize();
|
||||
},
|
||||
|
||||
_syncTilePanePos: function () {
|
||||
|
|
Loading…
Reference in a new issue