diff --git a/Block/Adminhtml/CategoryWidget.php b/Block/Adminhtml/CategoryWidget.php
new file mode 100755
index 0000000000000000000000000000000000000000..d6c0ac06ffa96a43b4a101a159da717882d93fed
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget.php
@@ -0,0 +1,26 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml;
+
+use \Magento\Backend\Block\Widget\Grid\Container;
+
+/**
+ * Class Image Slider
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class CategoryWidget extends Container
+{
+    protected function _construct()
+    {
+        $this->_blockGroup     = 'NicolasBejean_CategoryWidget';
+        $this->_controller     = 'adminhtml_categoryWidget';
+        $this->_headerText     = __('Image Slider');
+        $this->_addButtonLabel = __('Create New Image Slider');
+
+        parent::_construct();
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/AssignCategories.php b/Block/Adminhtml/CategoryWidget/AssignCategories.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c8ea3c1670d87e80f85a9405abe60d747c82c66
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/AssignCategories.php
@@ -0,0 +1,154 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget;
+
+use \Magento\Backend\Block\Template;
+use \Magento\Backend\Block\Template\Context;
+use \Magento\Framework\Exception\LocalizedException;
+use \Magento\Framework\Exception\NoSuchEntityException;
+use \Magento\Framework\Serialize\Serializer\Json as JsonSerializer;
+
+use \NicolasBejean\MediaManager\Model\Image as ImageModel;
+use \NicolasBejean\MediaManager\Model\ResourceModel\Image\Collection;
+use \NicolasBejean\MediaManager\Model\ResourceModel\Image\CollectionFactory as ImageCollectionFactory;
+use \NicolasBejean\MediaManager\Model\ImageRepository;
+
+use \NicolasBejean\CategoryWidget\Model\CategoryWidget as CategoryWidgetModel;
+use \NicolasBejean\CategoryWidget\Model\CategoryWidgetRepository;
+
+use \Exception;
+
+/**
+ * Class AssignCategories
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class AssignCategories extends Template
+{
+    /**
+     * Block template
+     *
+     * @var string
+     */
+    protected $_template = 'NicolasBejean_CategoryWidget::categorywidget/edit/assign_categories.phtml';
+
+    /**
+     * @var JsonSerializer
+     */
+    private $jsonSerializer;
+
+    /**
+     * @var ImageCollectionFactory
+     */
+    private $imageCollectionFactory;
+
+    /**
+     * @var ImageRepository
+     */
+    private $imageRepository;
+
+    /**
+     * @var CategoryWidgetRepository
+     */
+    private $categoryWidgetRepository;
+
+    /**
+     * AssignImages constructor.
+     *
+     * @param Context $context
+     * @param JsonSerializer $jsonSerializer
+     * @param ImageCollectionFactory $imageCollectionFactory
+     * @param ImageRepository $imageRepository
+     * @param CategoryWidgetRepository $categoryWidgetRepository
+     * @param array $data
+     */
+    public function __construct
+    (
+        Context                             $context,
+        JsonSerializer                      $jsonSerializer,
+        ImageCollectionFactory              $imageCollectionFactory,
+        ImageRepository                     $imageRepository,
+        CategoryWidgetRepository               $categoryWidgetRepository,
+        array $data                         = []
+    )
+    {
+        $this->jsonSerializer               = $jsonSerializer;
+        $this->imageCollectionFactory       = $imageCollectionFactory;
+        $this->imageRepository              = $imageRepository;
+        $this->categoryWidgetRepository        = $categoryWidgetRepository;
+
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * @return array
+     */
+    public function getImagesCollection()
+    {
+        try {
+            /** @var Collection $collection */
+            $collection = $this->imageCollectionFactory->create()->toOptionArray();
+
+            if (!empty($collection)) {
+                $result = array();
+
+                foreach ($collection as $image) {
+                    array_push($result, $this->getImage($image['value']));
+                }
+
+                return $result;
+            }
+        } catch (Exception $e) {
+            return array($e->getMessage());
+        }
+
+        return array();
+    }
+
+    /**
+     * @param $id
+     * @return array
+     * @throws NoSuchEntityException
+     * @throws LocalizedException
+     */
+    private function getImage (int $id)
+    {
+        /** @var ImageModel $image */
+        $image = $this->imageRepository->getById($id);
+
+        $result = array();
+        $result['id'] = $image->getId();
+        $result['path'] = $image->getPath();
+        $result['alt'] = $image->getAlt();
+        $result['is_active'] = $image->isActive();
+
+        return $result;
+    }
+
+    /**
+     * @param int $sliderId
+     * @return array
+     * @throws LocalizedException
+     * @throws NoSuchEntityException
+     */
+    public function getSlider (int $sliderId)
+    {
+        /** @var CategoryWidgetModel $categoryWidget */
+        $categoryWidget = $this->categoryWidgetRepository->getById($sliderId);
+
+        $array = explode('|', $categoryWidget->getContent());
+        $array = array_map('intval', $array);
+
+        $result = array();
+
+        /** @var array $image */
+        foreach ($array as $image) {
+            array_push($result, $this->getImage($image));
+        }
+
+        return $result;
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Edit/BackButton.php b/Block/Adminhtml/CategoryWidget/Edit/BackButton.php
new file mode 100755
index 0000000000000000000000000000000000000000..29bd7555275daf28a0eb723f1b69dbee33cd3d65
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Edit/BackButton.php
@@ -0,0 +1,41 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit;
+
+use \Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
+
+/**
+ * Class BackButton
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class BackButton extends GenericButton implements ButtonProviderInterface
+{
+    /**
+     * Get Button Data
+     *
+     * @return array
+     */
+    public function getButtonData()
+    {
+        return [
+            'label' => __('Back'),
+            'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
+            'class' => 'back',
+            'sort_order' => 10
+        ];
+    }
+
+    /**
+     * Get URL for back (reset) button
+     *
+     * @return string
+     */
+    public function getBackUrl()
+    {
+        return $this->getUrl('*/*/');
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Edit/DeleteButton.php b/Block/Adminhtml/CategoryWidget/Edit/DeleteButton.php
new file mode 100755
index 0000000000000000000000000000000000000000..ef177df1239a999b67a4dc86675ea09dc094edb8
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Edit/DeleteButton.php
@@ -0,0 +1,50 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit;
+
+use \Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
+use \Exception;
+
+/**
+ * Class DeleteButton
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class DeleteButton extends GenericButton implements ButtonProviderInterface
+{
+    /**
+     * Get Button Data
+     *
+     * @return array
+     * @throws Exception
+     */
+    public function getButtonData()
+    {
+        $data = [];
+        if ($this->getCategoryWidgetId()) {
+            $data = [
+                'label' => __('Delete Image Slider'),
+                'class' => 'delete',
+                'on_click' => 'deleteConfirm(\'' . __(
+                    'Are you sure you want to do this?'
+                ) . '\', \'' . $this->getDeleteUrl() . '\', {"data": {}})',
+                'sort_order' => 20,
+            ];
+        }
+        return $data;
+    }
+
+    /**
+     * URL to send delete requests to.
+     *
+     * @return string
+     * @throws Exception
+     */
+    public function getDeleteUrl()
+    {
+        return $this->getUrl('*/*/delete', ['entity_id' => $this->getCategoryWidgetId()]);
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Edit/GenericButton.php b/Block/Adminhtml/CategoryWidget/Edit/GenericButton.php
new file mode 100755
index 0000000000000000000000000000000000000000..43b8ba95c7483fd34ab43a6afdef57b85df0063a
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Edit/GenericButton.php
@@ -0,0 +1,73 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit;
+
+use \Magento\Backend\Block\Widget\Context;
+use \Magento\Framework\Exception\LocalizedException;
+use \Magento\Framework\Exception\NoSuchEntityException;
+use \NicolasBejean\CategoryWidget\Api\CategoryWidgetRepositoryInterface;
+
+/**
+ * Class GenericButton
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class GenericButton
+{
+    /**
+     * @var Context
+     */
+    protected $context;
+
+    /**
+     * @var CategoryWidgetRepositoryInterface
+     */
+    protected $categoryWidgetRepository;
+
+    /**
+     * GenericButton constructor.
+     * @param Context                           $context
+     * @param CategoryWidgetRepositoryInterface    $categoryWidgetRepository
+     */
+    public function __construct(
+        Context                                 $context,
+        CategoryWidgetRepositoryInterface          $categoryWidgetRepository
+    ) {
+        $this->context                          = $context;
+        $this->categoryWidgetRepository            = $categoryWidgetRepository;
+    }
+
+    /**
+     * Get Image Slider ID
+     *
+     * @return int|null
+     * @throws LocalizedException
+     */
+    public function getCategoryWidgetId()
+    {
+        try {
+            return $this->categoryWidgetRepository->getById(
+                $this->context->getRequest()->getParam('entity_id')
+            )->getId();
+        } catch (NoSuchEntityException $e) {
+        } catch (LocalizedException $e) {
+            throw new LocalizedException(__('Image Slider with id "%1" does not exist.'));
+        }
+        return null;
+    }
+
+    /**
+     * Get URL by route and parameters
+     *
+     * @param string $route
+     * @param array  $params
+     * @return string
+     */
+    public function getUrl($route = '', $params = [])
+    {
+        return $this->context->getUrlBuilder()->getUrl($route, $params);
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Edit/SaveAndNewButton.php b/Block/Adminhtml/CategoryWidget/Edit/SaveAndNewButton.php
new file mode 100755
index 0000000000000000000000000000000000000000..7854d61319862919ab1e79888c2bff7f0afcd505
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Edit/SaveAndNewButton.php
@@ -0,0 +1,49 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit;
+
+use \Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
+use \Magento\Ui\Component\Control\Container;
+
+/**
+ * Class SaveAndNewButton
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class SaveAndNewButton extends GenericButton implements ButtonProviderInterface
+{
+    /**
+     * Get Button Data
+     *
+     * @return array
+     */
+    public function getButtonData()
+    {
+        return [
+            'label' => __('Save and new'),
+            'class' => 'save',
+            'data_attribute' => [
+                'mage-init' => [
+                    'buttonAdapter' => [
+                        'actions' => [
+                            [
+                                'targetName' => 'categorywidget_categorywidget_form.categorywidget_categorywidget_form',
+                                'actionName' => 'save',
+                                'params' => [
+                                    true,
+                                    [
+                                        'back' => 'new'
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ]
+                ]
+            ],
+            'class_name' => Container::DEFAULT_CONTROL,
+        ];
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Edit/SaveButton.php b/Block/Adminhtml/CategoryWidget/Edit/SaveButton.php
new file mode 100755
index 0000000000000000000000000000000000000000..e5a37cf845ce256f567f9b209fefd1e7581016ef
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Edit/SaveButton.php
@@ -0,0 +1,107 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit;
+
+use \Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
+use \Magento\Ui\Component\Control\Container;
+
+/**
+ * Class SaveButton
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Edit
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class SaveButton extends GenericButton implements ButtonProviderInterface
+{
+    /**
+     * Get Button Data
+     *
+     * @return array
+     */
+    public function getButtonData()
+    {
+        return [
+            'label' => __('Save'),
+            'class' => 'save primary',
+            'data_attribute' => [
+                'mage-init' => [
+                    'buttonAdapter' => [
+                        'actions' => [
+                            [
+                                'targetName' => 'categorywidget_categorywidget_form.categorywidget_categorywidget_form',
+                                'actionName' => 'save',
+                                'params' => [
+                                    true,
+                                    [
+                                        'back' => 'continue'
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ]
+                ]
+            ],
+            'class_name' => Container::SPLIT_BUTTON,
+            'options' => $this->getOptions(),
+        ];
+    }
+
+    /**
+     * Get Options
+     *
+     * @return array
+     */
+    private function getOptions()
+    {
+        $options = [
+            [
+                'label' => __('Save & Duplicate'),
+                'id_hard' => 'save_and_duplicate',
+                'data_attribute' => [
+                    'mage-init' => [
+                        'buttonAdapter' => [
+                            'actions' => [
+                                [
+                                    'targetName' => 'categorywidget_categorywidget_form.categorywidget_categorywidget_form',
+                                    'actionName' => 'save',
+                                    'params' => [
+                                        true,
+                                        [
+                                            'back' => 'duplicate'
+                                        ]
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ]
+                ]
+            ],
+            [
+                'id_hard' => 'save_and_close',
+                'label' => __('Save & Close'),
+                'data_attribute' => [
+                    'mage-init' => [
+                        'buttonAdapter' => [
+                            'actions' => [
+                                [
+                                    'targetName' => 'categorywidget_categorywidget_form.categorywidget_categorywidget_form',
+                                    'actionName' => 'save',
+                                    'params' => [
+                                        true,
+                                        [
+                                            'back' => 'close'
+                                        ]
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ];
+
+        return $options;
+    }
+}
diff --git a/Block/Adminhtml/CategoryWidget/Widget/Chooser.php b/Block/Adminhtml/CategoryWidget/Widget/Chooser.php
new file mode 100755
index 0000000000000000000000000000000000000000..b059e9e8218933f698e660eb9871a626b853a52e
--- /dev/null
+++ b/Block/Adminhtml/CategoryWidget/Widget/Chooser.php
@@ -0,0 +1,190 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Widget;
+
+use \Magento\Backend\Block\Template\Context;
+use \Magento\Backend\Block\Widget\Grid\Extended;
+use \Magento\Backend\Helper\Data;
+use \Magento\Framework\Data\Form\Element\AbstractElement;
+use \Magento\Framework\Exception\LocalizedException;
+use \NicolasBejean\CategoryWidget\Model\CategoryWidgetFactory;
+use \NicolasBejean\CategoryWidget\Model\ResourceModel\CategoryWidget\CollectionFactory;
+use \Exception;
+use \Magento\Widget\Block\Adminhtml\Widget\Chooser as WidgetChooser;
+
+/**
+ * Class Chooser for Image Slider
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Adminhtml\CategoryWidget\Widget
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class Chooser extends Extended
+{
+    /**
+     * @var CategoryWidgetFactory
+     */
+    protected $categoryWidgetFactory;
+
+    /**
+     * @var CollectionFactory
+     */
+    protected $collectionFactory;
+
+    /**
+     * @param Context               $context
+     * @param Data                  $backendHelper
+     * @param CategoryWidgetFactory    $categoryWidgetFactory
+     * @param CollectionFactory     $collectionFactory
+     * @param array                 $data
+     */
+    public function __construct(
+        Context                     $context,
+        Data                        $backendHelper,
+        CategoryWidgetFactory          $categoryWidgetFactory,
+        CollectionFactory           $collectionFactory,
+        array $data = []
+    ) {
+        $this->categoryWidgetFactory   = $categoryWidgetFactory;
+        $this->collectionFactory    = $collectionFactory;
+
+        parent::__construct($context, $backendHelper, $data);
+    }
+
+    /**
+     * Image Slider construction, prepare grid params
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        parent::_construct();
+        $this->setDefaultSort('identifier');
+        $this->setDefaultDir('ASC');
+        $this->setUseAjax(true);
+        $this->setDefaultFilter(['chooser_enabled' => '1']);
+    }
+
+    /**
+     * Prepare chooser element HTML
+     *
+     * @param AbstractElement $element Form Element
+     * @return AbstractElement
+     * @throws LocalizedException
+     */
+    public function prepareElementHtml(AbstractElement $element)
+    {
+        $uniqId = $this->mathRandom->getUniqueHash($element->getId());
+        $sourceUrl = $this->getUrl('nicolasbejeancategorywidget/categorywidget_widget/chooser', ['uniq_id' => $uniqId]);
+
+        /** @var WidgetChooser $chooser */
+        $chooser = $this->getLayout()->createBlock(
+            WidgetChooser::class
+        )->setElement(
+            $element
+        )->setConfig(
+            $this->getConfig()
+        )->setFieldsetId(
+            $this->getFieldsetId()
+        )->setSourceUrl(
+            $sourceUrl
+        )->setUniqId(
+            $uniqId
+        );
+
+        if ($element->getValue()) {
+            $categoryWidget = $this->categoryWidgetFactory->create()->load($element->getValue());
+            if ($categoryWidget->getId()) {
+                $chooser->setLabel($this->escapeHtml($categoryWidget->getName()));
+            }
+        }
+
+        $element->setData('after_element_html', $chooser->toHtml());
+        return $element;
+    }
+
+    /**
+     * Grid Row JS Callback
+     *
+     * @return string
+     */
+    public function getRowClickCallback()
+    {
+        $chooserJsObject = $this->getId();
+        $js = '
+            function (grid, event) {
+                var trElement = Event.findElement(event, "tr");
+                var categoryWidgetId = trElement.down("td").innerHTML.replace(/^\s+|\s+$/g,"");
+                var categoryWidgetName = trElement.down("td").next().innerHTML;
+                ' .
+            $chooserJsObject .
+            '.setElementValue(categoryWidgetId);
+                ' .
+            $chooserJsObject .
+            '.setElementLabel(categoryWidgetName);
+                ' .
+            $chooserJsObject .
+            '.close();
+            }
+        ';
+        return $js;
+    }
+
+    /**
+     * Prepare Image Slider collection
+     *
+     * @return Extended
+     */
+    protected function _prepareCollection()
+    {
+        $this->setCollection($this->collectionFactory->create());
+        return parent::_prepareCollection();
+    }
+
+    /**
+     * Prepare columns for image grid
+     *
+     * @return Extended
+     * @throws Exception
+     */
+    protected function _prepareColumns()
+    {
+        $this->addColumn(
+            'chooser_id',
+            ['header' => __('ID'), 'align' => 'right', 'index' => 'entity_id', 'width' => 50]
+        );
+
+        $this->addColumn(
+            'chooser_identifier',
+            ['header' => __('Identifier'), 'align' => 'left', 'index' => 'identifier']
+        );
+
+        $this->addColumn(
+            'chooser_name',
+            ['header' => __('Name'), 'align' => 'left', 'index' => 'name']
+        );
+
+        $this->addColumn(
+            'chooser_is_active',
+            [
+                'header' => __('Status'),
+                'index' => 'is_active',
+                'type' => 'options',
+                'options' => [0 => __('Disabled'), 1 => __('Enabled')]
+            ]
+        );
+
+        return parent::_prepareColumns();
+    }
+
+    /**
+     * Get grid url
+     *
+     * @return string
+     */
+    public function getGridUrl()
+    {
+        return $this->getUrl('nicolasbejeancategorywidget/categorywidget_widget/chooser', ['_current' => true]);
+    }
+}
diff --git a/Block/Widget/CategoryWidgetNew.php b/Block/Widget/CategoryWidgetNew.php
new file mode 100755
index 0000000000000000000000000000000000000000..8ebe1dfa1f9a0f629c099fc8ccfbc8fec63e5cd2
--- /dev/null
+++ b/Block/Widget/CategoryWidgetNew.php
@@ -0,0 +1,520 @@
+<?php
+namespace NicolasBejean\CategoryWidget\Block\Widget;
+
+use \Magento\Framework\Filesystem;
+use \Magento\Framework\UrlInterface;
+use \Magento\Framework\App\Filesystem\DirectoryList;
+use \Magento\Framework\Image\AdapterFactory as ImageAdapterFactory;
+use \Magento\Framework\View\Element\Template;
+use \Magento\Framework\View\Element\Template\Context;
+use \Magento\Store\Model\ScopeInterface;
+use \Magento\Store\Model\StoreManagerInterface;
+use \Magento\Widget\Block\BlockInterface;
+
+use \NicolasBejean\Base\Helper\ImageOptimizer;
+
+use \NicolasBejean\CategoryWidget\Model\CategoryWidget as CategoryWidgetModel;
+use \NicolasBejean\CategoryWidget\Model\CategoryWidgetRepository;
+use \NicolasBejean\CategoryWidget\Model\CategoryWidgetFactory;
+use \NicolasBejean\CategoryWidget\Model\Template\FilterProvider;
+
+use \NicolasBejean\MediaManager\Model\ImageRepository;
+use \NicolasBejean\MediaManager\Model\Image as ImageModel;
+
+use \Exception;
+use \Magento\Framework\Exception\LocalizedException;
+use \Magento\Framework\Exception\NoSuchEntityException;
+
+/**
+ * Class CategoryWidgetNEw for Widget
+ *
+ * @category PHP
+ * @package  NicolasBejean\CategoryWidget\Block\Widget
+ * @author   Nicolas Béjean <nicolas@bejean.eu>
+ * @license  https://github.com/nicolasbejean/category-widget/blob/master/licence.txt BSD Licence
+ * @link     https://www.bejean.eu
+ */
+class CategoryWidgetNew extends Template implements BlockInterface
+{
+    /**
+     * @var string
+     */
+    protected $_template = "widget/categorywidget/default.phtml";
+
+    /**
+     * @var FilterProvider
+     */
+    protected $filterProvider;
+
+    /**
+     * Image Slider factory
+     *
+     * @var CategoryWidgetFactory
+     */
+    protected $categoryWidgetFactory;
+
+    /**
+     * @var ImageAdapterFactory
+     */
+    protected $imageAdapterFactory;
+
+    /**
+     * Store manager
+     *
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * Filesystem instance
+     *
+     * @var Filesystem
+     */
+    protected $filesystem;
+
+    /**
+     * @var array
+     */
+    protected $resizeSettings = [];
+
+    /**
+     * @var array
+     *
+     * - constrainOnly[true]: Guarantee, that image picture will not be bigger, than it was. It is false by default.
+     * - keepAspectRatio[true]: Guarantee, that image picture width/height will not be distorted. It is true by default.
+     * - keepTransparency[true]: Guarantee, that image will not lose transparency if any. It is true by default.
+     * - keepFrame[false]: Guarantee, that image will have dimensions, set in $width/$height. Not applicable,
+     * if keepAspectRatio(false).
+     * - backgroundColor[null]: Default white
+     */
+    protected $defaultSettings = [];
+
+    /**
+     * @var ImageOptimizer
+     */
+    protected $imageOptimizer;
+
+    /**
+     * @var ImageRepository
+     */
+    private $imageRepository;
+
+    /**
+     * @var CategoryWidgetRepository
+     */
+    private $categoryWidgetRepository;
+
+    /**
+     * @param Context $context
+     * @param FilterProvider $filterProvider
+     * @param CategoryWidgetFactory $categoryWidgetFactory
+     * @param CategoryWidgetRepository $categoryWidgetRepository
+     * @param ImageRepository $imageRepository
+     * @param ImageOptimizer $imageOptimizer
+     * @param ImageAdapterFactory $imageAdapterFactory
+     * @param array $data
+     */
+    public function __construct(
+        Context                            $context,
+        FilterProvider                     $filterProvider,
+        CategoryWidgetFactory              $categoryWidgetFactory,
+        CategoryWidgetRepository           $categoryWidgetRepository,
+        ImageRepository                    $imageRepository,
+        ImageOptimizer                     $imageOptimizer,
+        ImageAdapterFactory                $imageAdapterFactory,
+        array $data                        = []
+    ) {
+        $this->storeManager                = $context->getStoreManager();
+        $this->filesystem                  = $context->getFilesystem();
+
+        $this->filterProvider              = $filterProvider;
+        $this->categoryWidgetFactory       = $categoryWidgetFactory;
+        $this->categoryWidgetRepository    = $categoryWidgetRepository;
+        $this->imageRepository             = $imageRepository;
+        $this->imageOptimizer              = $imageOptimizer;
+        $this->imageAdapterFactory         = $imageAdapterFactory;
+
+        parent::__construct($context, $data);
+
+        $this->defaultSettings = [
+            'constrainOnly' => $this->_scopeConfig->getValue('Categorywidget/resize/constrain_only', ScopeInterface::SCOPE_STORE),
+            'keepAspectRatio' => $this->_scopeConfig->getValue('Categorywidget/resize/keep_aspect_ratio', ScopeInterface::SCOPE_STORE),
+            'keepTransparency' => $this->_scopeConfig->getValue('Categorywidget/resize/keep_transparency', ScopeInterface::SCOPE_STORE),
+            'keepFrame' => $this->_scopeConfig->getValue('Categorywidget/resize/keep_frame', ScopeInterface::SCOPE_STORE),
+            'backgroundColor' => $this->_scopeConfig->getValue('Categorywidget/resize/background_color', ScopeInterface::SCOPE_STORE),
+            'identifier' => $this->_scopeConfig->getValue('Categorywidget/save/identifier', ScopeInterface::SCOPE_STORE),
+            'basename' => $this->_scopeConfig->getValue('Categorywidget/save/basename', ScopeInterface::SCOPE_STORE),
+            'width' => $this->_scopeConfig->getValue('Categorywidget/save/width', ScopeInterface::SCOPE_STORE),
+            'height' => $this->_scopeConfig->getValue('Categorywidget/save/height', ScopeInterface::SCOPE_STORE),
+            'compression' => $this->_scopeConfig->getValue('Categorywidget/save/compression', ScopeInterface::SCOPE_STORE)
+        ];
+    }
+
+    /**
+     * Get Slider
+     *
+     * @return CategoryWidgetModel
+     */
+    public function getSlider()
+    {
+        try {
+            /** @var CategoryWidgetModel $slider */
+            $slider = $this->categoryWidgetRepository->getById($this->getId());
+
+            return $slider;
+        } catch (LocalizedException $e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get Slider Content
+     *
+     * @param $content
+     * @return array
+     */
+    public function getSliderContent(string $content)
+    {
+        $array = explode('|', $content);
+        $array = array_map('intval', $array);
+
+        $result = array();
+
+        foreach ($array as $image) {
+            array_push($result, $this->getImage((int)$image));
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get Image
+     *
+     * @param int $id
+     * @return array
+     */
+    private function getImage (int $id)
+    {
+        try {
+            /** @var ImageModel $image */
+            $image = $this->imageRepository->getById($id);
+
+            $result = array();
+            $result['id'] = $image->getId();
+            $result['path'] = $image->getPath();
+            $result['alt'] = $image->getAlt();
+            $result['is_active'] = $image->isActive();
+
+            return $result;
+        } catch (LocalizedException $e) {
+            return null;
+        }
+    }
+
+    /**
+     * Récupère l'ID du slider
+     */
+    public function getId()
+    {
+        return $this->getData('id');
+    }
+
+    /**
+     * Récupère la valeur pour l'ajout d'un titre
+     */
+    public function getActiveTitle()
+    {
+        if ($this->getWidgetTitle() !== null) {
+            if ($this->getData('active_title') === 'true') {
+                return true;
+            }
+
+            return false;
+        }
+
+        return false;
+    }
+
+    /**
+     * Récupère le titre du widget
+     */
+    public function getWidgetTitle()
+    {
+        return $this->getData('title');
+    }
+
+    /**
+     * Récupère la balise du titre du widget
+     */
+    public function getWidgetTitleTag()
+    {
+        return $this->getData('title_tag');
+    }
+
+    /**
+     * Récupère la class CSS du titre du widget
+     */
+    public function getWidgetTitleCSS()
+    {
+        return $this->getData('title_css_classes');
+    }
+
+    /**
+     * Récupère la valeur pour l'ajout d'un contenu
+     */
+    public function getActiveContent()
+    {
+        if ($this->getWidgetContent() !== null) {
+            if ($this->getData('active_content') === 'true') {
+                return true;
+            }
+
+            return false;
+        }
+
+        return false;
+    }
+
+    /**
+     * Récupère le contenu du widget
+     */
+    public function getWidgetContent()
+    {
+        if (strlen($this->getData('content')) === 0) {
+            return false;
+        }
+
+        return $this->getData('content');
+    }
+
+    /**
+     * Récupère la class CSS du contenu du widget
+     */
+    public function getWidgetContentCSS()
+    {
+        if (strlen($this->getData('content_css_classes')) === 0) {
+            return false;
+        }
+
+        return $this->getData('content_css_classes');
+    }
+
+    /**
+     * Récupère la largeur de l'image du widget
+     */
+    public function getWidth()
+    {
+        if (is_null($this->getData('width'))) {
+            return $this->defaultSettings['width'];
+        }
+
+        return $this->getData('width');
+    }
+
+    /**
+     * Récupère la hauteur de l'image du widget
+     */
+    public function getHeight()
+    {
+        if (is_null($this->getData('height'))) {
+            return $this->defaultSettings['height'];
+        }
+
+        return $this->getData('height');
+    }
+
+    /**
+     * Récupère les classes CSS
+     */
+    public function getCssClasses()
+    {
+        if (strlen($this->getData('css_classes')) === 0) {
+            return false;
+        }
+
+        return $this->getData('css_classes');
+    }
+
+    /**
+     * Récupère le CSS pour l'attribut style
+     */
+    public function getExtraCss()
+    {
+        if (strlen($this->getData('extra_css')) === 0) {
+            return false;
+        }
+
+        return $this->getData('extra_css');
+    }
+
+    /**
+     * Récupère les attributs pour le data-bind
+     */
+    public function getDataBind()
+    {
+        if (strlen($this->getData('data')) === 0) {
+            return false;
+        }
+
+        return $this->getData('data');
+    }
+
+    /**
+     * Récupère la valeur pour l'activation du wrapper
+     */
+    public function getActiveWrapper()
+    {
+        if ($this->getData('active_wrapper') === 'true') {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Récupère les classes CSS complémentaires pour le wrapper
+     */
+    public function getWrapperCssClasses()
+    {
+        if (strlen($this->getData('wrapper_css_classes')) === 0) {
+            return false;
+        }
+
+        return $this->getData('wrapper_css_classes');
+    }
+
+    /**
+     * Récupère la création du lien
+     */
+    public function getActiveLink()
+    {
+        if ($this->getData('active_link') === 'true') {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Récupère le lien
+     */
+    public function getLinkHref()
+    {
+        return $this->getData('link');
+    }
+
+    /**
+     * Récupère la cible du lien
+     */
+    public function getLinkTarget()
+    {
+        return $this->getData('link_target');
+    }
+
+    /**
+     * Prepare and set resize settings for image
+     *
+     * @param array $resizeSettings
+     */
+    protected function initResizeSettings(array $resizeSettings)
+    {
+        // Init resize settings with default
+        $this->resizeSettings = $this->defaultSettings;
+        // Override resizeSettings only if key matches with existing settings
+        foreach ($resizeSettings as $key => $value) {
+            if (array_key_exists($key, $this->resizeSettings)) {
+                $this->resizeSettings[$key] = $value;
+            }
+        }
+    }
+
+    /**
+     * Permet d'optimiser les images
+     *
+     * @param $image
+     * @param null $width
+     * @param null $height
+     * @param array $settings
+     * @return string
+     * @throws NoSuchEntityException
+     */
+    public function getResizeImage($image, $width = null, $height = null, array $settings = [])
+    {
+        $baseURL = $this->storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA);
+
+        /* Si c'est pas un fichier JPG, on retourne l'original */
+        if (substr($image, -3) != 'jpg') {
+            return $baseURL . $image;
+        }
+
+        /* Si il n'y a pas de resize activé, on retourne l'original */
+        if ($this->getData('active_resize') === 'false') {
+            return $baseURL . $image;
+        }
+
+        $settings['basename'] = $image;
+
+        if ($image) {
+            if (is_string($image)) {
+                $isRelativeUrl = substr($image, 0, 1) === '/';
+                if ($isRelativeUrl) {
+                    $image = ltrim($image, '/media/');
+                } else {
+                    $image = 'mediamanager/image/' . $image;
+                }
+            }
+        }
+
+        $dirPath = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA);
+        $absolutePath = $dirPath->getAbsolutePath('') . $image;
+
+        if (!is_null($width)) {
+            $settings['width'] = (int)$width;
+        }
+
+        if (!is_null($height)) {
+            $settings['height'] = (int)$height;
+        }
+
+        if (!is_null($this->getData('quality'))) {
+            $settings['compression'] = (int)$this->getData('quality');
+        }
+
+        /* Initialise les options de redimensionnement */
+        $this->initResizeSettings($settings);
+
+        try {
+            return $this->imageOptimizer->getResizeImage($absolutePath, $dirPath->getAbsolutePath(''), $this->resizeSettings);
+        } catch (Exception $e) {
+            return $baseURL . $image;
+        }
+    }
+
+    /**
+     * Récupère la largeur de l'image du widget
+     *
+     * @param $imagePath
+     * @return int|mixed|null
+     */
+    public function getResizedImageWidth($imagePath)
+    {
+        $dirPath = $this->filesystem->getDirectoryRead(DirectoryList::PUB);
+        $absoluteImagePath = $dirPath->getAbsolutePath($imagePath);
+
+        return $this->imageOptimizer->getImageWidth($absoluteImagePath);
+    }
+
+    /**
+     * Récupère la hauteur de l'image du widget
+     *
+     * @param $imagePath
+     * @return int|mixed|null
+     */
+    public function getResizedImageHeight($imagePath)
+    {
+        $dirPath = $this->filesystem->getDirectoryRead(DirectoryList::PUB);
+        $absoluteImagePath = $dirPath->getAbsolutePath($imagePath);
+
+        return $this->imageOptimizer->getImageHeight($absoluteImagePath);
+    }
+}