Visibilidade de opções de um menu


É possível esconder uma ou mais opções de um menu tendo em conta o estado de uma determinada entidade. Por exemplo, podemos querer que a opção de mostrar os números já inseridos (concretizado pelo comando ListNumbers) não seja apresentada se não houver nenhum número para apresentar.

Esta funcionalidade já é suportada pela framework de interacção da seguinte forma. É possível criar um comando com um parâmetro adicional do tipo Predicate<T> que representa um predicado que tem a responsabilidade de indicar se o comando deve ser visível ou não. Por omissão, caso não seja indicado nenhum predicado, então o comando fica associado a um predicado que devolve sempre true. Cada vez que um menu tem que apresentar as suas opções (ou seja os comandos presentes no menu), antes de apresentar cada opção, o menu verifica se o comando associado à opção é visível ou não avaliando o seu predicado. Se não for visível, então a opção não é apresentada.

A visibilidade do comando deve estar definida no método boolean isValid() de ValidityPredicate. O constructor da super-classe isValid(). recebe um parâmetro que deverá referenciar a entidade cujo estado afecta a visibilidade do comando.  Esta entidade depois pode ser acedida no método isValid através do atributo _receiver (o qual foi inicializado no construtor).

Para concretizar este novo requisito, precisamos de criar um Predicate<T> cuja concretização do método test() devolva true quando a entidade IntegerManager tenha pelo menos um número e devolva false quando está vaziaPodemos fazer isso criando uma classe anónima:

new Predicate<IntegerManager>(ent) {
      @Override
      public boolean test() {
        return ent.getNumbers().size() > 0;
      }
    }

ou então, utilizando uma expressão lambda:

x -> !ent.getNumbers().isEmpty() 

em que ent é uma referência para a entidade do domínio que gere a lista de números a apresentar.

Assim, devemos alterar a construção do comando ListNumbers para passar um parâmetro adicional do tipo Predicate na invocação do construtor da superclasse. Esta classe deverá passar a ter a seguinte concretização:
package ex.app.main;

import java.util.List;
import ex.core.IntegerManager;
import pt.tecnico.uilib.menus.Command;
import pt.tecnico.uilib.menus.ValidityPredicate;

public class ListNumbers extends Command<IntegerManager> {        
  //Constructor
  public ListNumbers(IntegerManager ent) {
    super("Listar Números", ent, x -> !ent.getNumbers().isEmpty() );
  }

  protected void execute() { // executed when this option is selected
    List<Integer> list = _receiver.getNumbers();
    
    for (Integer number : list)
      _display.addLine(number.toString());
    _display.display();
  }
}