Grids

Grids are elements allowing you to quickly display a table with pagination & search/sorting support.

To create a grid you will need either a Window or a Widget factory but also a DataCollection.

Data Collections are classes containing all the necessary methods for grids to get sorted & filtered data.

Data Collections,

There are 2 types of prebuilt data collections in eXpansion2, nothing prevents you from creating you own that will use a custom data source.

For exemple you may wish to create custom DataCollection to fetch data from an api.

Array Data Collection Factory

This allows you to create a data collection from a list of associative array.

The @expansion.framework.core.model.gui.grid.data_collection_factory.array factory will allow you to create one.

Example :

<?php
$collection = $this->dataCollectionFactory->create(
    [
        ['name' => 'TOTO-1', 'size' => 5],
        ['name' => 'TOTO-2', 'size' => 7],
    ]
);

Object Data Collection Factory,

Works very much like the Array Data Collection Factory; but instead of a list of associative arrays will have a list of objects.

The @expansion.framework.core.model.gui.grid.data_collection_factory.object factory will allow you to create one.

<?php
$collection = $this->dataCollectionFactory->create(
    [
        $myObject1,
        $myObject2,
    ]
);

Custom Data Collections

You can also create your own grid collections

TODO: Describe how to create a custom data collection.

Using the Grid Builder

  • Autowire: TRUE This service can be auto wired into your services.
  • Class: eXpansion\Framework\Core\Model\Gui\Grid\GridBuilderFactory

To create a grid you need the grid builder factory service. This service can be autowired into your window builder.

With this you can generate in instance of grid builder that you will be able to use to create you grid.

<?php
$gridBuilder = $this->gridBuilderFactory->create();

You need after that set a few more information:

<?php
function createContent(ManialinkInterface $manialink)
{
    $collection = $this->dataCollectionFactory->create($this->data);

    $gridBuilder = $this->gridBuilderFactory->create();
    $gridBuilder->setManialink($manialink)
        ->setDataCollection($collection)
        ->setManialinkFactory($this);
}

Basically the grid builder will need to access the manialink & the manialink factory (either the window factory or the widget factory). These are required so that pagination actions can be handled automatically by the grid builder. The grid can be added in any element of your manialink.

To add the grid to your manialink you need first to finish building it.

<?php
$grid = $gridBuilder->build($width, $height);
$manialink->addChild($grid);

Adding columns

Before building the grid you will need to configure the columns you wish to display. You will need to use the addTextColumn method of the grid builder for this.

<?php 
$gridBuilder->setManialink($manialink)
    ->addTextColumn(
        'command',
        "expansion_core.windows.chat_commands.column_command",
        25
    );

Parameters:

  1. the key in the associative array, or in case of a object collection the name of the getter method to call.
  2. the translation id of the title of the column.
  3. the width coefficient. Using this & total width the builder will arrange the width of each column.
<?php 
$gridBuilder->setManialink($manialink)
    ->addTextColumn(
        'command',
        "expansion_core.windows.chat_commands.column_command",
        25
    );
$gridBuilder->setManialink($manialink)
    ->addTextColumn(
        'command2',
        "expansion_core.windows.chat_commands.column_command_2",
        25
    );

In this case the both columns will be of equal width filling the full width of the grid.

If you wish to have a 2/1 width ration you can do :

<?php 
$gridBuilder->setManialink($manialink)
    ->addTextColumn(
        'command',
        "expansion_core.windows.chat_commands.column_command",
        2
    ); 
$gridBuilder->setManialink($manialink)
    ->addTextColumn(
        'command2',
        "expansion_core.windows.chat_commands.column_command_2",
        1
    );

Adding input field columns

You can easily add inputfields to gridview and datacollection.

Input fields will be autogenerated using datatype, booleans are converted to checkboxes, all other fields are inputboxes, you don’t need to worry about typecasting data back, it’ll be automatically done for you!

when using input fields, the data collection will be updated on page change to keep changed values on other pages

 <?php
 $gridBuilder->addInputColumn(
                 'value',
                 'expansion_admin.gui.window.scriptsettings.column.value',
                 3);
  1. Key from data collection to use as datavalue.
  2. Text for column name
  3. a width coefficiency

To recieve the data, you need to create action button, Then update of the data collection from entries and after that use the datacollection to get full changed dataset.

Example
<?php

protected function createGrid(ManialinkInterface $manialink)
    {
        // set datacollection data            
        $collection = $this->dataCollectionFactory->create(
            [
               ['name' => "booelan test", 'value' => true],
               ['name' => "numeric test", 'value' => 2],
               ['name' => "string test", 'value' => "test value"]            
            ]);
        $collection->setPageSize(20);
        
        $gridBuilder = $this->gridBuilderFactory->create();
        $gridBuilder->setManialink($manialink)
            ->setDataCollection($collection)
            ->setManialinkFactory($this)
            ->addTextColumn(
                'name',
                'expansion_admin.gui.window.scriptsettings.column.name',
                5,
                true,
                false
            )->addInputColumn(
                'value',
                'expansion_admin.gui.window.scriptsettings.column.value',
                3);

        // bind grid to manialink data
        $manialink->setData('grid', $gridBuilder);
        
        // set grid size windowsize, but leave some room for apply button. 
        $frame = $manialink->getContentFrame();
        $this->setGridSize($frame->getWidth(), $frame->getHeight() - 10);

        // create apply button  
        $apply = $this->uiFactory->createButton("Apply");
        $apply->setPosition(($frame->getWidth() - $apply->getWidth()), -($frame->getHeight() - $apply->getHeight()));

         
        $apply->setAction(
            // create action, notice we need to pass the grid as action parameter
            // it will be used to update and get data collection values. 
            $this->actionFactory->createManialinkAction(                
            $manialink, [$this, "callbackApply"], ["grid" => $manialink->getData('grid')]
            ));

        $manialink->addChild($apply);
    }
    
    /** Callback for apply button
     *
     * @param $login
     * @param $entries
     * @param $args
     */
    public function callbackApply($login, $entries, $args)
    {         
        /** @var GridBuilder $grid */
        $grid = $args['grid']; // retrieve grid object
        
        // we need to update the data collection from entry values, otherwise some data will be missing 
        $grid->updateDataCollection($entries); 

        // rebuild build settings from data collection
        $settings = [];
        foreach ($grid->getDataCollection()->getAll() as $key => $value) {
            $settings[$value['name']] = $value['value'];
        }

        try {
            $this->connection->setModeScriptSettings($settings);
        } catch (\Exception $ex) {
            $this->connection->chatSendServerMessage("error: ".$ex->getMessage());
            $this->console->writeln('$f00Error: $fff'.$ex->getMessage());
        }
    }

Adding action button

Adding actions buttons is very much like adding any other column. But in action buttons you will need to add something else then a string, but a button FML element directly.

<?php
$gridBuilder->addInputColumn('wish', 'expansion_maps.gui.window.column.wish', 1, [$this, 'callbackWish'], $queueButton);

1) Action columns need a unique key 2) Text for column name 3) a width coefficient 4) The action callback 5) The custom FML element to use (or null if wish to use a text)

Example
<?php

$tooltip = $this->uiFactory->createTooltip();
$manialink->addChild($tooltip);

$queueButton = $this->uiFactory->createButton('+', uiButton::TYPE_DECORATED);
$queueButton->setTextColor("fff")->setSize(5, 5);
$tooltip->addTooltip($queueButton, 'Adds map to jukebox');

$gridBuilder->addActionColumn('wish', 'expansion_maps.gui.window.column.wish', 1, 
[$this, 'callbackWish'], $queueButton);

Configuring searchable fields

TODO This has not been yet coded.

Full Example
<?php
class WindowHelpFactory extends WindowFactory
{
    protected function createContent(ManialinkInterface $manialink)
    {
        $collection = $this->dataCollectionFactory->create($this->getChatCommands($manialink));
        $collection->setPageSize(2);
        $helpButton = new Label();
        $helpButton->setText('')
            ->setSize(6, 6)
            ->setAreaColor("0000")
            ->setAreaFocusColor("0000");
        $desctiptionButton = new Label();
        $desctiptionButton->setText('')
            ->setSize(6, 6)
            ->setAreaColor("0000")
            ->setAreaFocusColor("0000");
        $gridBuilder = $this->gridBuilderFactory->create();
        $gridBuilder->setManialink($manialink)
            ->setDataCollection($collection)
            ->setManialinkFactory($this)
            ->addTextColumn(
                'command',
                "expansion_core.windows.chat_commands.column_command",
                25
            )
            ->addTextColumn(
                'description',
                'expansion_core.windows.chat_commands.column_description',
                70,
                false,
                true
            )
            ->addActionColumn('help', '', 5, array($this, 'callbackHelp'), $helpButton)
            ->addActionColumn(
                'description',
                '',
                5,
                array($this, 'callbackDescription'),
                $desctiptionButton
            );
        $manialink->setData('grid', $gridBuilder);
    }
    /**
     * @inheritdoc
     */
    protected function updateContent(ManialinkInterface $manialink)
    {
        /** @var Frame $contentFrame */
        $contentFrame = $manialink->getContentFrame();
        $contentFrame->removeAllChildren();
        $collection = $this->dataCollectionFactory->create($this->getChatCommands($manialink));
        $collection->setPageSize(20);
        /** @var GridBuilder $gridBuilder */
        $gridBuilder = $manialink->getData('grid');
        $contentFrame->addChild($gridBuilder->build($contentFrame->getWidth(), $contentFrame->getHeight()));
    }
}

Using the Grid Window

The grid window is prebuilt and allows an easy and fast usage of the grid.

It allows less flexibility as you can not display more then one grid in one window.

<?php

class MyWindoWFactory extends GridWindowFactory
{
    /**
     * @param ManialinkInterface $manialink
     * @return void
     */
    protected function createGrid(ManialinkInterface $manialink)
    {
        $collection = $this->dataCollectionFactory->create($this->getData());

        $gridBuilder = $this->gridBuilderFactory->create();
        $gridBuilder->setManialink($manialink)
            ->setDataCollection($collection)
            ->setManialinkFactory($this)
            ->addTextColumn(
                'index',
                'expansion_maps.gui.window.column.index',
                '1',
                true
            );
        $manialink->setData('grid', $gridBuilder);
    }
}