Skip to content

Commit

Permalink
Merge pull request #676 from mindline-analytics/feat-axis-options
Browse files Browse the repository at this point in the history
Support for axis options (Intersection Point & Reverse Axis) in PowerPoint2007 Writer
  • Loading branch information
Progi1984 authored Dec 7, 2021
2 parents 47046dd + 6163037 commit f5907e1
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 8 deletions.
6 changes: 5 additions & 1 deletion docs/changes/1.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Features

- Support for axis options - [@mindline](https://github.com/mindline-analytics) GH-676
- Axis intersection point (axis crossing) through `setCrossesAt`/ `getCrossesAt`
- Reverse axis order through `setIsReversedOrder`/ `isReversedOrder`
- PowerPoint2007 Writer
- Support for Hyperlink Text Color - [@MartynasJanu](https://github.com/MartynasJanu) & [@Progi1984](https://github.com/Progi1984) GH-682
- PowerPoint2007 Reader
- PowerPoint2007 Writer
- PowerPoint2007 Writer
56 changes: 56 additions & 0 deletions docs/usage/shapes/chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,62 @@ $shape->getPlotArea()->getAxisX()->setMinBounds(0);
$shape->getPlotArea()->getAxisX()->setMaxBounds(200);
```

#### Crossing

!!! warning
Available only on the PowerPoint2007 Writer

For Axis, `setCrossesAt` can be used to define where it should be crossed by the perpendicular/ horizontal axis.
The property can be defined by one of the three given constants or as an absolute value on the target axis.

``` php
use PhpOffice\PhpPresentation\Shape\Axis;
use PhpOffice\PhpPresentation\Shape\Chart\Type\Bar;

$bar = new Bar();

$shape = $slide->createChartShape();
$shape->getPlotArea()->setType($bar);

// Usage of constant: Horizontal axis will cross the Y-Axis at `0`
$shape->getPlotArea()->getAxisY()->setCrossesAt(Axis::CROSSES_AUTO);

// Usage of individual value: Horizontal axis will cross the Y-Axis at `3`
$shape->getPlotArea()->getAxisY()->setCrossesAt('3');
```

| Constant | Description |
| -------------------- | ------------------------ |
| `AXIS::CROSSES_AUTO` | Axis crosses at zero. |
| `AXIS::CROSSES_MIN` | Axis crosses at minimum. |
| `AXIS::CROSSES_MAX` | Axis crosses at maximum. |

#### Reversed Order

You can reverse the order of a categorial or value axis trought `setIsReversedOrder`.

Notice: If you reverse the order of a axis, this automatically changes the position of the other axis.
To reset this effect, the axis intersection point on the other axis must be set to `Axis::CROSSES_MAX` using `setCrossesAt`.

``` php
use PhpOffice\PhpPresentation\Shape\Axis;
use PhpOffice\PhpPresentation\Shape\Chart\Type\Bar;

$bar = new Bar();

$shape = $slide->createChartShape();
$shape->getPlotArea()->setType($bar);

// default value, will return false
$shape->getPlotArea()->getAxisY()->isReversedOrder()

// reverse order
$shape->getPlotArea()->getAxisY()->setIsReversedOrder(true);

// revert the automatic intersection switch on x axis
$shape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MAX);
```

#### Outline

You can define outline for each axis (X & Y).
Expand Down
54 changes: 54 additions & 0 deletions src/PhpPresentation/Shape/Chart/Axis.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class Axis implements ComparableInterface
public const TICK_LABEL_POSITION_HIGH = 'high';
public const TICK_LABEL_POSITION_LOW = 'low';

public const CROSSES_AUTO = 'autoZero';
public const CROSSES_MIN = 'min';
public const CROSSES_MAX = 'max';

/**
* Title.
*
Expand Down Expand Up @@ -84,6 +88,16 @@ class Axis implements ComparableInterface
*/
protected $maxBounds;

/**
* @var string
*/
protected $crossesAt = self::CROSSES_AUTO;

/**
* @var bool
*/
protected $isReversedOrder = false;

/**
* @var string
*/
Expand Down Expand Up @@ -243,6 +257,46 @@ public function setMaxBounds(int $maxBounds = null): self
return $this;
}

/**
* @return string
*/
public function getCrossesAt(): string
{
return $this->crossesAt;
}

/**
* @param string $value
*
* @return self
*/
public function setCrossesAt(string $value = self::CROSSES_AUTO): self
{
$this->crossesAt = $value;

return $this;
}

/**
* @return bool
*/
public function isReversedOrder(): bool
{
return $this->isReversedOrder;
}

/**
* @param bool $value
*
* @return self
*/
public function setIsReversedOrder(bool $value = false): self
{
$this->isReversedOrder = $value;

return $this;
}

public function getMajorGridlines(): ?Gridlines
{
return $this->majorGridlines;
Expand Down
23 changes: 16 additions & 7 deletions src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php
Original file line number Diff line number Diff line change
Expand Up @@ -2288,15 +2288,18 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
return;
}

$crossesAt = $oAxis->getCrossesAt();
$orientation = $oAxis->isReversedOrder() ? 'maxMin' : 'minMax';

if (Chart\Axis::AXIS_X == $typeAxis) {
$mainElement = 'c:catAx';
$axIdVal = '52743552';
$axPosVal = 'b';
$axPosVal = $crossesAt === 'max' ? 't' : 'b';
$crossAxVal = '52749440';
} else {
$mainElement = 'c:valAx';
$axIdVal = '52749440';
$axPosVal = 'l';
$axPosVal = $crossesAt === 'max' ? 'r' : 'l';
$crossAxVal = '52743552';
}

Expand All @@ -2313,7 +2316,7 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty

// $mainElement > c:scaling > c:orientation
$objWriter->startElement('c:orientation');
$objWriter->writeAttribute('val', 'minMax');
$objWriter->writeAttribute('val', $orientation);
$objWriter->endElement();

if (null != $oAxis->getMaxBounds()) {
Expand Down Expand Up @@ -2476,10 +2479,16 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
$objWriter->writeAttribute('val', $crossAxVal);
$objWriter->endElement();

// c:crosses
$objWriter->startElement('c:crosses');
$objWriter->writeAttribute('val', 'autoZero');
$objWriter->endElement();
// c:crosses "autoZero" | "min" | "max" | custom string value
if (in_array($crossesAt, ['autoZero', 'min', 'max'])) {
$objWriter->startElement('c:crosses');
$objWriter->writeAttribute('val', $crossesAt);
$objWriter->endElement();
} else {
$objWriter->startElement('c:crossesAt');
$objWriter->writeAttribute('val', $crossesAt);
$objWriter->endElement();
}

if (Chart\Axis::AXIS_X == $typeAxis) {
// c:lblAlgn
Expand Down
19 changes: 19 additions & 0 deletions tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ public function testBounds(): void
$this->assertNull($object->getMaxBounds());
}

public function testCrossesAt(): void
{
$object = new Axis();

$this->assertEquals(Axis::CROSSES_AUTO, $object->getCrossesAt());
$this->assertInstanceOf(Axis::class, $object->setCrossesAt(Axis::CROSSES_MAX));
$this->assertEquals(Axis::CROSSES_MAX, $object->getCrossesAt());
}

public function testIsReversedOrder(): void
{
$object = new Axis();
$this->assertFalse($object->isReversedOrder());
$this->assertInstanceOf(Axis::class, $object->setIsReversedOrder(true));
$this->assertTrue($object->isReversedOrder());
$this->assertInstanceOf(Axis::class, $object->setIsReversedOrder(false));
$this->assertFalse($object->isReversedOrder());
}

public function testFont(): void
{
$object = new Axis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,85 @@ public function testAxisBounds(): void
$this->assertIsSchemaECMA376Valid();
}

public function testAxisCrosses(): void
{
$oSeries = new Series('Downloads', $this->seriesData);
$oSeries->getFill()->setStartColor(new Color('FFAABBCC'));
$oLine = new Line();
$oLine->addSeries($oSeries);
$oShape = $this->oPresentation->getActiveSlide()->createChartShape();
$oShape->getPlotArea()->setType($oLine);

$elementCrosses = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses';
$elementCrossesAt = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crossesAt';
$elementAxPos = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:axPos';

// Default autoZero
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'autoZero');
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
$this->assertIsSchemaECMA376Valid();

// Crosses max
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MAX);
$this->resetPresentationFile();

$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'max');
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 't');
$this->assertIsSchemaECMA376Valid();

// Crosses min
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MIN);
$this->resetPresentationFile();

$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'min');
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
$this->assertIsSchemaECMA376Valid();

// Crosses custom value
$oShape->getPlotArea()->getAxisX()->setCrossesAt('10');
$this->resetPresentationFile();

$this->assertZipXmlElementNotExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt, 'val', '10');
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
$this->assertIsSchemaECMA376Valid();
}

public function testIsReversedOrder(): void
{
$element = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:scaling/c:orientation';

$oSlide = $this->oPresentation->getActiveSlide();
$oShape = $oSlide->createChartShape();
$oLine = new Line();
$oShape->getPlotArea()->setType($oLine);

// default
$this->assertFalse($oShape->getPlotArea()->getAxisX()->isReversedOrder());
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'minMax');
$this->assertIsSchemaECMA376Valid();

// reversed order
$this->assertInstanceOf(Axis::class, $oShape->getPlotArea()->getAxisX()->setIsReversedOrder(true));
$this->resetPresentationFile();

$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'maxMin');
$this->assertIsSchemaECMA376Valid();

// reset reversed order
$this->assertInstanceOf(Axis::class, $oShape->getPlotArea()->getAxisX()->setIsReversedOrder(false));
$this->resetPresentationFile();

$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element);
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'minMax');
$this->assertIsSchemaECMA376Valid();
}

public function testAxisFont(): void
{
$oSlide = $this->oPresentation->getActiveSlide();
Expand Down

0 comments on commit f5907e1

Please sign in to comment.