/****************************************************************************
* Copyright (C) 2012 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.gui.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.openecard.gui.ResultStatus;
import org.openecard.gui.StepResult;
import org.openecard.gui.definition.OutputInfoUnit;
import org.openecard.gui.definition.Step;
import org.openecard.gui.swing.common.NavigationEvent;
import org.openecard.gui.swing.components.StepComponent;
import org.openecard.gui.swing.steplayout.StepLayouter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The StepFrame class represents a single step.
* The actual layouting is however deferred to a layouting component.
*
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
* @author Tobias Wich <tobias.wich@ecsec.de>
* @author Florian Feldmann <florian.feldmann@rub.de>
*/
public class StepFrame {
private static final Logger logger = LoggerFactory.getLogger(StepFrame.class);
private static final long serialVersionUID = 1L;
private JPanel panel;
private Step step;
private SwingStepResult stepResult;
private List<StepComponent> components;
private String dialogType;
public StepFrame(Step step, String dialogType) {
this.panel = new JPanel();
this.step = step;
this.dialogType = dialogType;
this.stepResult = new SwingStepResult(step);
initLayout();
}
private void initLayout() {
panel.setLayout(new BorderLayout());
}
private void initComponents() {
StepLayouter stepLayouter = StepLayouter.create(step.getInputInfoUnits(), dialogType, step.getTitle());
Container contentPanel = stepLayouter.getPanel();
panel.add(contentPanel, BorderLayout.CENTER);
components = stepLayouter.getComponents();
}
public void resetResult() {
stepResult = new SwingStepResult(step);
}
public boolean isInstantReturn() {
return step.isInstantReturn();
}
public Container getPanel() {
revalidate(panel);
return panel;
}
public Step getStep() {
return step;
}
/**
* Check if all components on the frame are valid. This can be used to see
* if a jump to the next frame can be made.
*
* @return True if all components are valid, false otherwise.
*/
public boolean validateComponents() {
for (StepComponent next : components) {
Component component = next.getComponent();
if (next.isValueType() && ! next.validate()) {
component.setBackground(Color.RED);
return false;
}
component.setBackground(null);
}
return true;
}
/**
* Get result for all components on the frame that support result values.
*
* @return List containing all result values. As a matter of fact this list can be empty.
*/
public List<OutputInfoUnit> getResultContent() {
ArrayList<OutputInfoUnit> result = new ArrayList<OutputInfoUnit>(components.size());
for (StepComponent next : components) {
if (next.isValueType()) {
result.add(next.getValue());
}
}
return result;
}
public void updateFrame() {
panel.removeAll();
initComponents();
revalidate(panel);
}
public StepResult getStepResult() {
return stepResult;
}
private void revalidate(JComponent c) {
for (int i = 0; i < c.getComponentCount(); i++) {
this.revalidate((JComponent) c.getComponent(i));
}
c.revalidate();
c.repaint();
}
/**
* Locks elements on the frame, so they can not be modified anymore.
* This is needed when executing an action. That is the time between a button click and the update of the frame
* panel.
*/
public void lockControls() {
// TODO: lock all elements
}
/**
* Unlocks elements on this frame, so that they can be modified.
* This is needed to unlock the frame when it is displayed after it has been locked by an action.
*/
public void unlockControls() {
// TODO: unlock elements of this frame
}
/**
* Updates the StepResult when a button is clicked.
* Before a button is clicked by the user, the {@link org.openecard.gui.executor.ExecutionEngine} waits for the
* result content by calling {@link StepResult#getStatus()}. This method sets the portions of the result relevant
* for the respective button event and unlocks the getStatus method.
*
* @param event Event describing which button has been clicked.
*/
public void updateResult(NavigationEvent event) {
if (event == NavigationEvent.BACK) {
stepResult.setResult(getResultContent());
stepResult.setResultStatus(ResultStatus.BACK);
} else if (event == NavigationEvent.NEXT) {
stepResult.setResult(getResultContent());
stepResult.setResultStatus(ResultStatus.OK);
} else if (event == NavigationEvent.CANCEL) {
stepResult.setResultStatus(ResultStatus.CANCEL);
}
try {
logger.debug("Exchange result for step '{}", step.getTitle());
stepResult.syncPoint.exchange(null);
} catch (Exception ignore) {
}
}
}