Skip to content

Commit 079c5f3

Browse files
Moving a Group (shape container) now moves all contained shapes.
OffsetX/Y, ExtentX/Y, Width and Height are always calculated to prevent desync between Group and contained shapes.
1 parent 8b75773 commit 079c5f3

File tree

1 file changed

+69
-42
lines changed

1 file changed

+69
-42
lines changed

src/PhpPresentation/Shape/Group.php

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,13 @@
2020
namespace PhpOffice\PhpPresentation\Shape;
2121

2222
use PhpOffice\PhpPresentation\AbstractShape;
23-
use PhpOffice\PhpPresentation\GeometryCalculator;
2423
use PhpOffice\PhpPresentation\ShapeContainerInterface;
2524
use PhpOffice\PhpPresentation\Traits\ShapeCollection;
2625

2726
class Group extends AbstractShape implements ShapeContainerInterface
2827
{
2928
use ShapeCollection;
3029

31-
/**
32-
* Extent X.
33-
*
34-
* @var int
35-
*/
36-
protected $extentX;
37-
38-
/**
39-
* Extent Y.
40-
*
41-
* @var int
42-
*/
43-
protected $extentY;
44-
4530
public function __construct()
4631
{
4732
parent::__construct();
@@ -52,22 +37,33 @@ public function __construct()
5237
*/
5338
public function getOffsetX(): int
5439
{
55-
if (empty($this->offsetX)) {
56-
$offsets = GeometryCalculator::calculateOffsets($this);
57-
$this->offsetX = $offsets[GeometryCalculator::X];
58-
$this->offsetY = $offsets[GeometryCalculator::Y];
40+
$offsetX = null;
41+
42+
foreach ($this->getShapeCollection() as $shape) {
43+
if ($offsetX === null) {
44+
$offsetX = $shape->getOffsetX();
45+
} else {
46+
$offsetX = \min($offsetX, $shape->getOffsetX());
47+
}
5948
}
6049

61-
return $this->offsetX;
50+
return $offsetX ?? 0;
6251
}
6352

6453
/**
65-
* Ignores setting the X Offset, preserving the default behavior.
54+
* Change the X offset by moving all contained shapes
6655
*
6756
* @return $this
6857
*/
69-
public function setOffsetX(int $pValue = 0)
58+
public function setOffsetX(int $pValue = 0): self
7059
{
60+
$offsetX = $this->getOffsetX();
61+
$diff = $pValue - $offsetX;
62+
63+
foreach ($this->getShapeCollection() as $shape) {
64+
$shape->setOffsetX($shape->getOffsetX() + $diff);
65+
}
66+
7167
return $this;
7268
}
7369

@@ -76,22 +72,33 @@ public function setOffsetX(int $pValue = 0)
7672
*/
7773
public function getOffsetY(): int
7874
{
79-
if (empty($this->offsetY)) {
80-
$offsets = GeometryCalculator::calculateOffsets($this);
81-
$this->offsetX = $offsets[GeometryCalculator::X];
82-
$this->offsetY = $offsets[GeometryCalculator::Y];
75+
$offsetY = null;
76+
77+
foreach ($this->getShapeCollection() as $shape) {
78+
if ($offsetY === null) {
79+
$offsetY = $shape->getOffsetY();
80+
} else {
81+
$offsetY = \min($offsetY, $shape->getOffsetY());
82+
}
8383
}
8484

85-
return $this->offsetY;
85+
return $offsetY ?? 0;
8686
}
8787

8888
/**
89-
* Ignores setting the Y Offset, preserving the default behavior.
89+
* Change the Y offset by moving all contained shapes
9090
*
9191
* @return $this
9292
*/
93-
public function setOffsetY(int $pValue = 0)
93+
public function setOffsetY(int $pValue = 0): self
9494
{
95+
$offsetY = $this->getOffsetY();
96+
$diff = $pValue - $offsetY;
97+
98+
foreach ($this->getShapeCollection() as $shape) {
99+
$shape->setOffsetY($shape->getOffsetY() + $diff);
100+
}
101+
95102
return $this;
96103
}
97104

@@ -100,35 +107,55 @@ public function setOffsetY(int $pValue = 0)
100107
*/
101108
public function getExtentX(): int
102109
{
103-
if (null === $this->extentX) {
104-
$extents = GeometryCalculator::calculateExtents($this);
105-
$this->extentX = $extents[GeometryCalculator::X] - $this->getOffsetX();
106-
$this->extentY = $extents[GeometryCalculator::Y] - $this->getOffsetY();
110+
$extentX = 0;
111+
112+
foreach ($this->getShapeCollection() as $shape) {
113+
$extentX = \max($extentX, $shape->getOffsetX() + $shape->getWidth());
107114
}
108115

109-
return $this->extentX;
116+
return $extentX - $this->getOffsetX();
110117
}
111118

112119
/**
113120
* Get Y Extent.
114121
*/
115122
public function getExtentY(): int
116123
{
117-
if (null === $this->extentY) {
118-
$extents = GeometryCalculator::calculateExtents($this);
119-
$this->extentX = $extents[GeometryCalculator::X] - $this->getOffsetX();
120-
$this->extentY = $extents[GeometryCalculator::Y] - $this->getOffsetY();
124+
$extentY = 0;
125+
126+
foreach ($this->getShapeCollection() as $shape) {
127+
$extentY = \max($extentY, $shape->getOffsetY() + $shape->getHeight());
121128
}
122129

123-
return $this->extentY;
130+
return $extentY - $this->getOffsetY();
131+
}
132+
133+
/**
134+
* Calculate the width based on the size/position of the contained shapes
135+
*
136+
* @return int
137+
*/
138+
public function getWidth(): int
139+
{
140+
return $this->getExtentX();
141+
}
142+
143+
/**
144+
* Calculate the height based on the size/position of the contained shapes
145+
*
146+
* @return int
147+
*/
148+
public function getHeight(): int
149+
{
150+
return $this->getExtentY();
124151
}
125152

126153
/**
127154
* Ignores setting the width, preserving the default behavior.
128155
*
129-
* @return self
156+
* @return $this
130157
*/
131-
public function setWidth(int $pValue = 0)
158+
public function setWidth(int $pValue = 0): self
132159
{
133160
return $this;
134161
}
@@ -138,7 +165,7 @@ public function setWidth(int $pValue = 0)
138165
*
139166
* @return $this
140167
*/
141-
public function setHeight(int $pValue = 0)
168+
public function setHeight(int $pValue = 0): self
142169
{
143170
return $this;
144171
}

0 commit comments

Comments
 (0)