/* * This file is part of MazeSolver. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Copyright (c) 2014 MazeSolver * Sergio M. Afonso Fumero <theSkatrak@gmail.com> * Kevin I. Robayna Hernández <kevinirobaynahdez@gmail.com> */ /** * @file AgentConfigurationPanel.java * @date 22/11/2014 */ package es.ull.mazesolver.gui.configuration; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JPanel; import es.ull.mazesolver.agent.Agent; import es.ull.mazesolver.gui.MainWindow; import es.ull.mazesolver.translations.ButtonTranslations; import es.ull.mazesolver.translations.Translatable; /** * Se trata de un panel de configuración de agentes, que permite al usuario * configurar un agente dependiendo del tipo que sea. * * Los controles para aceptar o cancelar la configuración deben ser * implementados desde el exterior y utilizarse para llamar a los métodos * "accept()" o "cancel", respectivamente. */ public abstract class AgentConfigurationPanel extends JPanel implements Translatable { private static final long serialVersionUID = 1L; private JPanel m_root; private ArrayList <EventListener> m_listeners; private JButton m_accept, m_cancel; /** * Agente que se quiere configurar. */ protected Agent m_agent; /** * Lista de mensajes de error obtenidos al intentar guardar la configuración * de un agente. */ protected ArrayList <String> m_errors; /** * Lista de mensajes de éxito obtenidos tras guardar la configuración de un * agente. */ protected ArrayList <String> m_success; /** * Interfaz de escucha de eventos. */ public static interface EventListener { /** * LLamado cuando ocurre el evento de tipo "Exitoso". Estos eventos son * notificados cuando se guarda el agente y el cambio es aceptado. * * @param msgs * Lista de mensajes que se quieren mostrar al usuario. */ public void onSuccess (ArrayList <String> msgs); /** * LLamado cuando ocurre el evento de tipo "Cancelar". Estos eventos son * notificados cuando se cancela la edición de las propiedades. */ public void onCancel (); /** * LLamado cuando ocurre el evento de tipo "Error". Estos eventos son * notificados cuando se intenta guardar y no se aceptan las modificaciones. * * @param errors * Lista de mensajes de error a mostrar al usuario. */ public void onError (ArrayList <String> errors); } /** * Construye la interfaz del panel de configuración de agentes. * * @param agent * Agente que se quiere configurar. */ public AgentConfigurationPanel (Agent agent) { m_root = new JPanel(); m_listeners = new ArrayList <EventListener>(); m_agent = agent; m_errors = new ArrayList <String>(); m_success = new ArrayList <String>(); createGUI(m_root); createControls(); translate(); } /** * Añade un oyente de eventos. * * @param listener * Clase oyente que se quiere añadir. */ public final void addEventListener (EventListener listener) { if (!m_listeners.contains(listener)) m_listeners.add(listener); } /** * Elimina un oyente de eventos. Si no es un oyente, la lista de oyentes * permanece intacta. * * @param listener * Clase oyente que se quiere añadir. */ public final void removeEventListener (EventListener listener) { m_listeners.remove(listener); } /* (non-Javadoc) * @see es.ull.mazesolver.translations.Translatable#translate() */ @Override public void translate () { ButtonTranslations tr = MainWindow.getTranslations().button(); m_accept.setText(tr.ok()); m_cancel.setText(tr.cancel()); } /** * Provoca que la configuración actualmente almacenada en el panel de * configuración se guarde en el agente, modificando su comportamiento. * * Este método debe ser implementado por cada agente. * * @return <ul> * <li><b>true</b> si se pudo guardar el resultado.</li> * <li><b>false</b> si la configuración indicada no es válida.</li> * </ul> */ protected abstract boolean accept (); /** * Cancela la operación de configuración, dejando al agente en su estado de * partida. * * Este método debe ser implementado por cada agente. */ protected abstract void cancel (); /** * Crea la interfaz gráfica de usuario, que es la que se mostrará al mismo. * Estará personalizada para el agente específico, pero no incluirá los * botones de "Aceptar" y "Cancelar", que se proporcionan por defecto. * * @param root * Panel padre de todos los elementos que se creen. Si se intenta * utilizar el panel padre de la clase en lugar de éste, el panel de * configuración no se mostrará correctamente. */ protected abstract void createGUI (JPanel root); /** * Se crean los controles de "Aceptar" y "Cancelar" y los coloca en el panel * junto a los controles personalizados del agente, que ya deben haber sido * creados. */ private void createControls () { setLayout(new BorderLayout()); JPanel controls = new JPanel(new FlowLayout(FlowLayout.RIGHT)); m_accept = new JButton(); m_cancel = new JButton(); m_accept.addActionListener(new ActionListener() { @Override public void actionPerformed (ActionEvent e) { if (accept()) onSuccess(); else onError(); } }); m_cancel.addActionListener(new ActionListener() { @Override public void actionPerformed (ActionEvent e) { cancel(); onCancel(); } }); controls.add(m_accept); controls.add(m_cancel); add(m_root, BorderLayout.CENTER); add(controls, BorderLayout.SOUTH); } /** * Método llamado cuando el usuario aplica los cambios y éstos son guardados * correctamente. Notifica a los {@link EventListener#onSuccess}. */ private void onSuccess () { for (EventListener listener: m_listeners) listener.onSuccess(m_success); } /** * Método llamado cuando el usuario cancela la operación y el agente ha * quedado como al principio. Notifica a los {@link EventListener#onCancel}. */ private void onCancel () { for (EventListener listener: m_listeners) listener.onCancel(); } /** * Método llamado cuando el usuario intenta aplicar los cambios y no es * posible porque la configuración no es válida. Notifica a los {@link * EventListener#onError}. */ private void onError () { for (EventListener listener: m_listeners) listener.onError(m_errors); } }