Skip to content

Commit 089f8cf

Browse files
Armin Le Grand (collabora)Armin Le Grand (collabora)
authored andcommitted
1st changes for SmartArt UI in cool
Signed-off-by: Armin Le Grand (collabora) <[email protected]> Change-Id: I81da386de7e8ee3e66104c80122a025322a9d2db
1 parent 81881d5 commit 089f8cf

File tree

5 files changed

+301
-1
lines changed

5 files changed

+301
-1
lines changed

browser/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ COOL_JS_LST =\
331331
src/canvas/sections/ShapeHandleGluePointSubSection.ts \
332332
src/canvas/sections/ShapeHandleAnchorSubSection.ts \
333333
src/canvas/sections/ShapeHandleRotationSubSection.ts \
334+
src/canvas/sections/ShapeHandleDiagramSubSection.ts \
334335
src/canvas/sections/ShapeHandleScalingSubSection.ts \
335336
src/canvas/sections/ValidityInputHelpSection.ts \
336337
src/canvas/sections/CellCursorSection.ts \

browser/src/canvas/CanvasSectionContainer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,8 @@ class CanvasSectionContainer {
14271427
}
14281428

14291429
public doesSectionIncludePoint (section: any, point: number[]): boolean { // No ray casting here, it is a rectangle.
1430-
return ((point[0] >= section.myTopLeft[0] && point[0] <= section.myTopLeft[0] + section.size[0]) && (point[1] >= section.myTopLeft[1] && point[1] <= section.myTopLeft[1] + section.size[1]));
1430+
// use isHit from section, that does check against bounds of local range (position, size)
1431+
return section.isHit(point);
14311432
}
14321433

14331434
private doSectionsIntersectOnYAxis (section1: any, section2: any): boolean {

browser/src/canvas/CanvasSectionObject.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@ class CanvasSectionObject {
147147
return null;
148148
}
149149

150+
setSize(w: number, h: number): void {
151+
if (!this.containerObject)
152+
return;
153+
154+
w = Math.round(w);
155+
h = Math.round(h);
156+
157+
if (this.size[0] === w && this.size[1] === h)
158+
return;
159+
160+
this.size = [w, h];
161+
}
162+
150163
// Document objects only.
151164
setPosition(x: number, y: number): void {
152165
if (this.documentObject !== true || !this.containerObject)
@@ -187,6 +200,18 @@ class CanvasSectionObject {
187200
this.containerObject.createUpdateSingleDivElement(this);
188201
}
189202

203+
/*
204+
Allow locally to influence if this object is hit by the given point.
205+
This can be used e.g. to have CanvasSectionObjects with 'holes',
206+
e.g. a frame around something and you only want the frame to be hittable
207+
*/
208+
isHit(point: number[]): boolean {
209+
// return result of inside local range (position, size) check
210+
return (
211+
(point[0] >= this.myTopLeft[0] && point[0] <= this.myTopLeft[0] + this.size[0]) &&
212+
(point[1] >= this.myTopLeft[1] && point[1] <= this.myTopLeft[1] + this.size[1]))
213+
}
214+
190215
// All below functions should be included in their respective section definitions (or other classes), not here.
191216
isCalcRTL(): boolean { return; }
192217
setViewResolved(on: boolean): void { return; }
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/* global Proxy _ */
2+
/*
3+
* Copyright the Collabora Online contributors.
4+
*
5+
* SPDX-License-Identifier: MPL-2.0
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
12+
class ShapeHandleDiagramSubSection extends CanvasSectionObject {
13+
processingOrder: number =
14+
app.CSections.DefaultForDocumentObjects.processingOrder;
15+
drawingOrder: number =
16+
app.CSections.DefaultForDocumentObjects.drawingOrder + 1; // Handle events before the parent section.
17+
zIndex: number = app.CSections.DefaultForDocumentObjects.zIndex;
18+
documentObject: boolean = true;
19+
filledCombine: Path2D = new Path2D();
20+
filledCombineUsed: boolean = false;
21+
fillColor: string = '';
22+
fillColorDark: string = '';
23+
fillColorLight: string = '';
24+
25+
constructor(
26+
parentHandlerSection: ShapeHandlesSection,
27+
sectionName: string,
28+
size: number[],
29+
documentPosition: cool.SimplePoint,
30+
ownInfo: any,
31+
) {
32+
super(sectionName);
33+
34+
this.size = size;
35+
36+
this.sectionProperties.position = documentPosition.clone();
37+
this.sectionProperties.parentHandlerSection = parentHandlerSection;
38+
this.sectionProperties.ownInfo = ownInfo;
39+
this.sectionProperties.cursorStyle = 'pointer';
40+
41+
app.events.on(
42+
'TextCursorVisibility',
43+
this.onTextCursorVisibility.bind(this),
44+
);
45+
}
46+
47+
onTextCursorVisibility(event: any): void {
48+
if (event.detail.visible) {
49+
this.setShowSection(false);
50+
} else {
51+
this.setShowSection(true);
52+
}
53+
}
54+
55+
onInitialize(): void {
56+
this.setPosition(
57+
this.sectionProperties.position.pX,
58+
this.sectionProperties.position.pY,
59+
);
60+
}
61+
62+
onMouseEnter(point: cool.SimplePoint, e: MouseEvent): void {
63+
this.context.canvas.style.cursor = this.sectionProperties.cursorStyle;
64+
}
65+
66+
private createRoundRect(
67+
path: Path2D,
68+
x: number,
69+
y: number,
70+
w: number,
71+
h: number,
72+
r: number,
73+
): void {
74+
path.moveTo(x, y + r);
75+
path.arcTo(x, y, x + r, y, r);
76+
path.lineTo(x + w - r, y);
77+
path.arcTo(x + w, y, x + w, y + r, r);
78+
path.lineTo(x + w, y + h - r);
79+
path.arcTo(x + w, y + h, x + w - r, y + h, r);
80+
path.lineTo(x + r, y + h);
81+
path.arcTo(x, y + h, x, y + h - r, r);
82+
path.lineTo(x, y + r);
83+
}
84+
85+
onDraw(frameCount?: number, elapsedTime?: number): void {
86+
const origLineWidth: number = this.context.lineWidth;
87+
const halfWidthPx: number =
88+
this.sectionProperties.ownInfo.halfWidth * app.twipsToPixels;
89+
const halfWidthPy: number =
90+
this.sectionProperties.ownInfo.halfHeight * app.twipsToPixels;
91+
92+
// create outerBound
93+
var outerBound = new Path2D();
94+
this.createRoundRect(
95+
outerBound,
96+
0,
97+
0,
98+
this.size[0],
99+
this.size[1],
100+
halfWidthPx,
101+
);
102+
103+
// create innerBound
104+
var innerBound = new Path2D();
105+
const innerRelative: number = 0.5;
106+
this.createRoundRect(
107+
innerBound,
108+
halfWidthPx * innerRelative,
109+
halfWidthPy * (1.0 + innerRelative),
110+
this.size[0] - halfWidthPx * (2 * innerRelative),
111+
this.size[1] - halfWidthPy * (1.0 + 2.0 * innerRelative),
112+
halfWidthPx * (1.0 - innerRelative),
113+
);
114+
115+
// reset filledCombine & create combination for fill
116+
this.filledCombine = new Path2D();
117+
this.filledCombineUsed = true;
118+
this.filledCombine.addPath(outerBound);
119+
this.filledCombine.addPath(innerBound);
120+
121+
if (!this.fillColor) {
122+
const baseElem = document.getElementsByTagName('body')[0];
123+
const elem = window.L.DomUtil.create(
124+
'div',
125+
'spreadsheet-header-row',
126+
baseElem,
127+
);
128+
129+
// create colors
130+
this.fillColor = window.L.DomUtil.getStyle(elem, 'background-color');
131+
const blendFactor: number = 0.1;
132+
133+
let mix: any = colorParser(this.fillColor);
134+
mix.add(new RGBColor(blendFactor, blendFactor, blendFactor));
135+
this.fillColorLight = mix.toString();
136+
137+
mix = colorParser(this.fillColor);
138+
mix.add(new RGBColor(-blendFactor, -blendFactor, -blendFactor));
139+
this.fillColorDark = mix.toString();
140+
141+
window.L.DomUtil.remove(elem);
142+
}
143+
144+
// draw fill
145+
const selectionBackgroundGradient = this.context.createLinearGradient(
146+
0,
147+
0,
148+
this.size[0],
149+
this.size[1],
150+
);
151+
selectionBackgroundGradient.addColorStop(0, this.fillColorDark);
152+
selectionBackgroundGradient.addColorStop(0.5, this.fillColor);
153+
selectionBackgroundGradient.addColorStop(1, this.fillColorLight);
154+
this.context.fillStyle = selectionBackgroundGradient;
155+
this.filledCombine.closePath();
156+
this.context.fill(this.filledCombine, 'evenodd');
157+
158+
// draw outer
159+
this.context.strokeStyle = this.fillColorDark;
160+
this.context.lineWidth = 2;
161+
this.context.stroke(outerBound);
162+
163+
// draw inner
164+
this.context.stroke(innerBound);
165+
166+
this.context.lineWidth = origLineWidth;
167+
}
168+
169+
onClick(point: cool.SimplePoint, e: MouseEvent): void {
170+
app.map.sendUnoCommand('.uno:EditDiagram');
171+
}
172+
173+
isHit(point: number[]): boolean {
174+
if (!super.isHit(point)) {
175+
// use baseclass method to see if we are outside local range (position, size)
176+
return false;
177+
}
178+
179+
if (this.filledCombineUsed) {
180+
// if we have the geometry from paint, use it for HitTest
181+
return this.context.isPointInPath(
182+
this.filledCombine,
183+
point[0] - this.myTopLeft[0],
184+
point[1] - this.myTopLeft[1],
185+
'evenodd',
186+
);
187+
}
188+
189+
// if not, check for outer bounds defined by offsets from outside
190+
const halfWidthPx: number =
191+
this.sectionProperties.ownInfo.halfWidth * app.twipsToPixels;
192+
const halfWidthPy: number =
193+
this.sectionProperties.ownInfo.halfHeight * app.twipsToPixels;
194+
195+
if (
196+
point[0] <= this.myTopLeft[0] + halfWidthPx ||
197+
point[0] >= this.myTopLeft[0] + this.size[0] - halfWidthPx ||
198+
point[1] <= this.myTopLeft[1] + 2 * halfWidthPy ||
199+
point[1] >= this.myTopLeft[1] + this.size[1] - halfWidthPy
200+
) {
201+
return true;
202+
}
203+
204+
return false;
205+
}
206+
}
207+
208+
app.definitions.shapeHandleDiagramSubSection = ShapeHandleDiagramSubSection;

browser/src/canvas/sections/ShapeHandlesSection.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,42 @@ class ShapeHandlesSection extends CanvasSectionObject {
373373
}
374374
}
375375

376+
private getDiagram(halfWidth: number, halfHeight: number) {
377+
if (this.isDiagram() && this.sectionProperties.info?.handles?.kinds?.rectangle) {
378+
// get a scaled oversize measurement in X and Y
379+
const scaleFactor = 3;
380+
halfWidth *= scaleFactor;
381+
halfHeight *= scaleFactor;
382+
383+
// get object size as base for calculations
384+
const topLeft = this.sectionProperties.info.handles.kinds.rectangle['1'][0];
385+
386+
// create a shape with overhang of halfWidth/Height on all sides,
387+
// double at top to get space for graphics
388+
const width : number = this.getShapeWidth(true) + 2 * halfWidth;
389+
const height : number = this.getShapeHeight(true) + 3 * halfHeight;
390+
const info = {
391+
kind: 'DiagramHandle',
392+
size: new cool.SimplePoint(width, height),
393+
halfWidth: halfWidth,
394+
halfHeight: halfHeight
395+
};
396+
this.sectionProperties.handles.push({
397+
info: info,
398+
point: new cool.SimplePoint(
399+
topLeft.point.x - info.halfWidth,
400+
topLeft.point.y - 2 * info.halfHeight) });
401+
}
402+
}
403+
376404
// Get the handle positions and other information from the info that core side sent us.
377405
private getHandles() {
378406
this.sectionProperties.handles = [];
379407

380408
const halfWidth = app.pixelsToTwips * (this.sectionProperties.handleWidth * 0.5);
381409
const halfHeight = app.pixelsToTwips * (this.sectionProperties.handleHeight * 0.5);
382410

411+
this.getDiagram(halfWidth, halfHeight);
383412
this.getScalingHandles(halfWidth, halfHeight);
384413
this.getAnchorHandle(halfWidth, halfHeight);
385414
this.getRotationHandle();
@@ -403,6 +432,13 @@ class ShapeHandlesSection extends CanvasSectionObject {
403432
return false;
404433
}
405434

435+
isDiagram() {
436+
if (GraphicSelection?.extraInfo?.isDiagram === true)
437+
return true;
438+
else
439+
return false;
440+
}
441+
406442
removeSVG() {
407443
if (this.sectionProperties.svg)
408444
this.sectionProperties.svg.remove();
@@ -598,6 +634,33 @@ class ShapeHandlesSection extends CanvasSectionObject {
598634
}
599635
}
600636

637+
checkDiagramSubSection(handle: any) {
638+
let newSubSection = app.sectionContainer.getSectionWithName(this.sectionProperties.subSectionPrefix + 'diagram');
639+
640+
if (!newSubSection) {
641+
newSubSection = new app.definitions.shapeHandleDiagramSubSection(
642+
this,
643+
this.sectionProperties.subSectionPrefix + 'diagram',
644+
[handle.info.size.pX, handle.info.size.pY],
645+
new cool.SimplePoint(
646+
handle.point.x,
647+
handle.point.y),
648+
handle.info
649+
);
650+
return newSubSection;
651+
}
652+
else {
653+
newSubSection.sectionProperties.ownInfo = handle.info;
654+
newSubSection.setPosition(
655+
handle.point.pX,
656+
handle.point.pY);
657+
newSubSection.setSize(
658+
handle.info.size.pX,
659+
handle.info.size.pY);
660+
return null;
661+
}
662+
}
663+
601664
checkCustomSubSection(handle: any): any {
602665
let newSubSection = app.sectionContainer.getSectionWithName(this.sectionProperties.subSectionPrefix + handle.info.id);
603666

@@ -667,6 +730,8 @@ class ShapeHandlesSection extends CanvasSectionObject {
667730
newSubSection = this.checkScalingSubSection(this.sectionProperties.handles[i]);
668731
else if (this.sectionProperties.handles[i].info.kind === 'ShapeRotationHandle')
669732
newSubSection = this.checkRotationSubSection(this.sectionProperties.handles[i]);
733+
else if (this.sectionProperties.handles[i].info.kind === 'DiagramHandle')
734+
newSubSection = this.checkDiagramSubSection(this.sectionProperties.handles[i]);
670735
else if (this.sectionProperties.handles[i].info.kind === '22')
671736
newSubSection = this.checkCustomSubSection(this.sectionProperties.handles[i]);
672737
else if (this.sectionProperties.handles[i].info.kind === '9')

0 commit comments

Comments
 (0)