Commit 0777205a authored by Frank Nägler's avatar Frank Nägler Committed by Andreas Fernandez
Browse files

[TASK] Introduce icon state for IconFactory

Resolves: #69095
Releases: master
Change-Id: I4a1077a9267ed293f049f6457aef5d8012aa28d4
Reviewed-on: http://review.typo3.org/42482

Reviewed-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Reviewed-by: default avatarDaniel Goerz <ervaude@gmail.com>
Tested-by: default avatarDaniel Goerz <ervaude@gmail.com>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
parent 1aac4a14
......@@ -25,6 +25,7 @@
@icon-size-default: 32px;
@icon-size-large: 48px;
@icon-unify-modifier: 0.86;
@icon-opacity-disabled: 0.5;
//
// Component
......@@ -93,6 +94,15 @@
}
}
//
// States
//
.icon-state-disabled {
.icon-markup {
opacity: @icon-opacity-disabled;
}
}
//
// Variants
//
......
......@@ -13,6 +13,8 @@ namespace TYPO3\CMS\Core\Imaging;
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
......@@ -44,28 +46,39 @@ class Icon {
/**
* The identifier which the PHP code that calls the IconFactory hands over
*
* @var string
*/
protected $identifier;
/**
* The identifier for a possible overlay icon
*
* @var Icon
*/
protected $overlayIcon = NULL;
/**
* Contains the size string ("large", "small" or "default")
*
* @var string
*/
protected $size = '';
/**
* Flag to indicate if the icon has a spinning animation
*
* @var bool
*/
protected $spinning = FALSE;
/**
* Contains the state information
*
* @var IconState
*/
protected $state;
/**
* @var Dimension
*/
......@@ -128,6 +141,7 @@ class Icon {
/**
* Sets the size and creates the new dimension
*
* @param string $size
*/
public function setSize($size) {
......@@ -136,19 +150,35 @@ class Icon {
}
/**
* @return boolean
* @return bool
*/
public function isSpinning() {
return $this->spinning;
}
/**
* @param boolean $spinning
* @param bool $spinning
*/
public function setSpinning($spinning) {
$this->spinning = $spinning;
}
/**
* @return IconState
*/
public function getState() {
return $this->state;
}
/**
* Sets the state of the icon
*
* @param IconState $state
*/
public function setState(IconState $state) {
$this->state = $state;
}
/**
* @return Dimension
*/
......@@ -187,6 +217,7 @@ class Icon {
$classes = array();
$classes[] = 'icon';
$classes[] = 'icon-size-' . $this->size;
$classes[] = 'icon-state-' . htmlspecialchars((string)$this->state);
$classes[] = 'icon-' . $this->getIdentifier();
if ($this->isSpinning()) {
$classes[] = 'icon-spin';
......
......@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Imaging;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
......@@ -36,17 +37,19 @@ class IconFactory {
/**
* @param string $identifier
* @param string $size
* @param string $size "large", "small" or "default", see the constants of the Icon class
* @param string $overlayIdentifier
* @param IconState $state
*
* @return Icon
*/
public function getIcon($identifier, $size = Icon::SIZE_DEFAULT, $overlayIdentifier = NULL) {
public function getIcon($identifier, $size = Icon::SIZE_DEFAULT, $overlayIdentifier = NULL, IconState $state = NULL) {
if (!$this->iconRegistry->isRegistered($identifier)) {
$identifier = $this->iconRegistry->getDefaultIconIdentifier();
}
$iconConfiguration = $this->iconRegistry->getIconConfigurationByIdentifier($identifier);
$iconConfiguration['state'] = $state;
$icon = $this->createIcon($identifier, $size, $overlayIdentifier, $iconConfiguration);
/** @var IconProviderInterface $iconProvider */
$iconProvider = GeneralUtility::makeInstance($iconConfiguration['provider']);
......@@ -58,7 +61,7 @@ class IconFactory {
* Creates an icon object
*
* @param string $identifier
* @param string $size "large" "small" or "default", see the constants of the Icon class
* @param string $size "large", "small" or "default", see the constants of the Icon class
* @param string $overlayIdentifier
* @param array $iconConfiguration the icon configuration array
* @return Icon
......@@ -67,6 +70,7 @@ class IconFactory {
$icon = GeneralUtility::makeInstance(Icon::class);
$icon->setIdentifier($identifier);
$icon->setSize($size);
$icon->setState($iconConfiguration['state'] ?: new IconState());
if ($overlayIdentifier !== NULL) {
$icon->setOverlayIcon($this->getIcon($overlayIdentifier, Icon::SIZE_OVERLAY));
}
......
<?php
namespace TYPO3\CMS\Core\Type\Icon;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* A class providing constants for icon states
*/
class IconState extends \TYPO3\CMS\Core\Type\Enumeration {
const __default = self::STATE_DEFAULT;
/**
* @var string the default state identifier
*/
const STATE_DEFAULT = 'default';
/**
* @var string the disabled state identifier
*/
const STATE_DISABLED = 'disabled';
}
......@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\ViewHelpers;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
......@@ -32,14 +33,16 @@ class IconViewHelper extends AbstractViewHelper implements CompilableInterface {
* @param string $identifier
* @param string $size
* @param string $overlay
* @param string $state
* @return string
*/
public function render($identifier, $size = Icon::SIZE_SMALL, $overlay = NULL) {
public function render($identifier, $size = Icon::SIZE_SMALL, $overlay = NULL, $state = IconState::STATE_DEFAULT) {
return static::renderStatic(
array(
'identifier' => $identifier,
'size' => $size,
'overlay' => $overlay
'overlay' => $overlay,
'state' => $state
),
$this->buildRenderChildrenClosure(),
$this->renderingContext
......@@ -58,9 +61,10 @@ class IconViewHelper extends AbstractViewHelper implements CompilableInterface {
$identifier = $arguments['identifier'];
$size = $arguments['size'];
$overlay = $arguments['overlay'];
$state = IconState::cast($arguments['state']);
/** @var IconFactory $iconFactory */
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
return $iconFactory->getIcon($identifier, $size, $overlay)->render();
return $iconFactory->getIcon($identifier, $size, $overlay, $state)->render();
}
}
======================================================
Feature: #69095 - Introduce icon state for IconFactory
======================================================
Description
===========
A state (default or disabled) for icons has been added. The state "disabled" marks an icon as disabled and shows the icon with 50% opacity.
Use an icon
-----------
The method ``IconFactory::getIcon()`` has now a fourth parameter for the state.
The ``\TYPO3\CMS\Core\Type\Icon\IconState`` class provides only the following constants for icon states:
* ``State::STATE_DEFAULT`` which currently means 100% opacity
* ``State::STATE_DISABLED`` which currently means 50% opacity
The states may change in future, so please make use of the constants for an unified layout.
.. code-block:: php
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$iconFactory->getIcon($identifier, Icon::SIZE_SMALL, $overlay, IconState::cast(IconState::STATE_DEFAULT))->render();
ViewHelper
----------
The core provides a Fluid ViewHelper which makes it really easy to use icons within a Fluid view.
This ViewHelper has an argument for the new state parameter.
.. code-block:: html
{namespace core = TYPO3\CMS\Core\ViewHelpers}
<core:icon identifier="my-icon-identifier" size="small" state="disabled" />
......@@ -15,8 +15,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Imaging;
*/
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Testcase for \TYPO3\CMS\Core\Imaging\Dimension
......
......@@ -15,7 +15,6 @@ namespace TYPO3\CMS\Core\Tests\Unit\Imaging;
*/
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconProvider\FontawesomeIconProvider;
......@@ -94,7 +93,7 @@ class IconFactoryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
* @test
*/
public function getIconByIdentifierReturnsIconWithCorrectMarkupIfRegisteredIconIdentifierIsUsed() {
$this->assertContains('<span class="icon icon-size-default icon-actions-document-close">',
$this->assertContains('<span class="icon icon-size-default icon-state-default icon-actions-document-close">',
$this->subject->getIcon($this->registeredIconIdentifier)->render());
}
......@@ -103,7 +102,7 @@ class IconFactoryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
* @dataProvider differentSizesDataProvider
*/
public function getIconByIdentifierAndSizeReturnsIconWithCorrectMarkupIfRegisteredIconIdentifierIsUsed($size) {
$this->assertContains('<span class="icon icon-size-' . $size['expected'] . ' icon-actions-document-close">',
$this->assertContains('<span class="icon icon-size-' . $size['expected'] . ' icon-state-default icon-actions-document-close">',
$this->subject->getIcon($this->registeredIconIdentifier, $size['input'])->render());
}
......@@ -129,7 +128,7 @@ class IconFactoryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
'additionalClasses' => 'fa-fw'
)
]);
$this->assertContains('<span class="icon icon-size-default icon-default-not-found">',
$this->assertContains('<span class="icon icon-size-default icon-state-default icon-default-not-found">',
$this->subject->getIcon($this->notRegisteredIconIdentifier)->render());
}
......@@ -147,7 +146,7 @@ class IconFactoryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
'additionalClasses' => 'fa-fw'
)
]);
$this->assertContains('<span class="icon icon-size-' . $size['expected'] . ' icon-default-not-found">',
$this->assertContains('<span class="icon icon-size-' . $size['expected'] . ' icon-state-default icon-default-not-found">',
$this->subject->getIcon($this->notRegisteredIconIdentifier, $size['input'])->render());
}
......@@ -163,7 +162,7 @@ class IconFactoryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
'spinning' => TRUE
)
]);
$this->assertContains('<span class="icon icon-size-default icon-' . $this->registeredSpinningIconIdentifier . ' icon-spin">',
$this->assertContains('<span class="icon icon-size-default icon-state-default icon-' . $this->registeredSpinningIconIdentifier . ' icon-spin">',
$this->subject->getIcon($this->registeredSpinningIconIdentifier)->render());
}
......
......@@ -52,14 +52,6 @@ class FontawesomeIconProviderTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
$this->assertEquals('<span class="icon-unify"><i class="fa fa-times"></i></span>', $this->icon->getMarkup());
}
/**
* @test
*/
public function prepareIconMarkupWithNameAndAdditionalClassesReturnsInstanceOfIconWithCorrectMarkup() {
$this->subject->prepareIconMarkup($this->icon, array('name' => 'times', 'additionalClasses' => 'foo'));
$this->assertEquals('<span class="icon-unify"><i class="fa fa-times foo"></i></span>', $this->icon->getMarkup());
}
/**
* DataProvider for icon names
*
......
......@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Imaging;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Type\Icon\IconState;
/**
* Testcase for \TYPO3\CMS\Core\Imaging\Icon
......@@ -44,7 +45,7 @@ class IconTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
*/
protected function setUp() {
$iconFactory = new IconFactory();
$this->subject = $iconFactory->getIcon($this->iconIdentifier, Icon::SIZE_SMALL, $this->overlayIdentifier);
$this->subject = $iconFactory->getIcon($this->iconIdentifier, Icon::SIZE_SMALL, $this->overlayIdentifier, IconState::cast(IconState::STATE_DISABLED));
}
/**
......@@ -74,4 +75,12 @@ class IconTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
public function getSizedentifierReturnsCorrectIdentifier() {
$this->assertEquals(Icon::SIZE_SMALL, $this->subject->getSize());
}
/**
* @test
*/
public function getStateReturnsCorrectIdentifier() {
$this->assertTrue($this->subject->getState()->equals(IconState::STATE_DISABLED));
}
}
......@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\ViewHelpers;
use Prophecy\Argument;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Type\Icon\IconState;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\ViewHelpers\IconViewHelper;
use TYPO3\CMS\Fluid\Tests\Unit\ViewHelpers\ViewHelperBaseTestcase;
......@@ -41,12 +42,12 @@ class IconViewHelperTest extends ViewHelperBaseTestcase {
/**
* @test
*/
public function renderCallsIconFactoryWithDefaultSizeAndReturnsResult() {
public function renderCallsIconFactoryWithDefaultSizeAndDefaultStateAndReturnsResult() {
$iconFactoryProphecy = $this->prophesize(IconFactory::class);
GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
$iconProphecy = $this->prophesize(Icon::class);
$iconFactoryProphecy->getIcon('myIdentifier', Icon::SIZE_SMALL, NULL)->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconFactoryProphecy->getIcon('myIdentifier', Icon::SIZE_SMALL, NULL, IconState::cast(IconState::STATE_DEFAULT))->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconProphecy->render()->shouldBeCalled()->willReturn('htmlFoo');
$this->assertSame('htmlFoo', $this->viewHelper->render('myIdentifier'));
......@@ -60,12 +61,26 @@ class IconViewHelperTest extends ViewHelperBaseTestcase {
GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
$iconProphecy = $this->prophesize(Icon::class);
$iconFactoryProphecy->getIcon('myIdentifier', Icon::SIZE_LARGE, NULL)->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconFactoryProphecy->getIcon('myIdentifier', Icon::SIZE_LARGE, NULL, IconState::cast(IconState::STATE_DEFAULT))->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconProphecy->render()->shouldBeCalled()->willReturn('htmlFoo');
$this->assertSame('htmlFoo', $this->viewHelper->render('myIdentifier', Icon::SIZE_LARGE));
}
/**
* @test
*/
public function renderCallsIconFactoryWithGivenStateAndReturnsResult() {
$iconFactoryProphecy = $this->prophesize(IconFactory::class);
GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
$iconProphecy = $this->prophesize(Icon::class);
$iconFactoryProphecy->getIcon('myIdentifier', Icon::SIZE_SMALL, NULL, IconState::cast(IconState::STATE_DISABLED))->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconProphecy->render()->shouldBeCalled()->willReturn('htmlFoo');
$this->assertSame('htmlFoo', $this->viewHelper->render('myIdentifier', Icon::SIZE_SMALL, NULL, IconState::cast(IconState::STATE_DISABLED)));
}
/**
* @test
*/
......@@ -74,10 +89,10 @@ class IconViewHelperTest extends ViewHelperBaseTestcase {
GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
$iconProphecy = $this->prophesize(Icon::class);
$iconFactoryProphecy->getIcon('myIdentifier', Argument::any(), 'overlayString')->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconFactoryProphecy->getIcon('myIdentifier', Argument::any(), 'overlayString', IconState::cast(IconState::STATE_DEFAULT))->shouldBeCalled()->willReturn($iconProphecy->reveal());
$iconProphecy->render()->shouldBeCalled()->willReturn('htmlFoo');
$this->assertSame('htmlFoo', $this->viewHelper->render('myIdentifier', Icon::SIZE_LARGE, 'overlayString'));
}
}
\ No newline at end of file
}
/*!
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
/*!
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
html {
......@@ -7810,6 +7810,9 @@ button.close {
transform: rotate(359deg);
}
}
.icon-state-disabled .icon-markup {
opacity: 0.5;
}
.icon-size-small {
height: 16px;
width: 16px;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment