/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS 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.
*
* CATS 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 CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.vision.panel.imagecompare;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import com.comcast.cats.image.ImageCompareRegionInfo;
import com.comcast.cats.image.OCRRegionInfo;
import com.comcast.cats.image.RegionInfo;
/**
* The RegionDetailsPanel helps to define regions selected in the
* FreezeVideoPanel. Contains three panels 1) Panel for defining region info 2)
* Panel for defining image compare settings 3)Panel to Add/update region.
*
* @author Sajay J K
*
*/
public class RegionDetailsPanel extends JPanel
{
private static final long serialVersionUID = -758016305574347046L;
/**
* Logger instance for RegionDetailsPanel.
*/
private static final Logger logger = Logger.getLogger( RegionDetailsPanel.class );
private JLabel lblPassFail;
private JLabel lbltimeTaken;
private JButton btnAddUpdate;
private RegionInfoPanel panelRegionInfo;
private ICSettingsPanel panelICSettings;
private OCRSettingsPanel panelOCRSettings;
private JPanel panelAddUpdate;
private List< RegionInfo > regionsList;
private RegionInfo currentRegion;
private String snapshotFilepath = null;
private boolean testMode = false;
private int mode = 1;
private static final Integer IC_PANEL_WIDTH = 30;
private static final Integer IC_PANEL_HEIGHT = 40;
private static final Dimension icPanelDim = new Dimension( IC_PANEL_WIDTH, IC_PANEL_HEIGHT );
private static final String ADD_TEXT = "Add";
private static final String UPDATE_TEXT = "Update";
private static final String FAILURE_STRING = "Fail";
private static final String PASS_STRING = "Pass";
public static final int IC_MODE = 1;
public static final int OCR_MODE = 2;
/**
* Constructor for creating the region details panel.
*/
public RegionDetailsPanel()
{
setName( "regionDetailsPanel" );
setLayout( new GridBagLayout() );
regionsList = new ArrayList< RegionInfo >();
panelRegionInfo = createRegionInfoPanel();
panelICSettings = createImageCompareSettingsPanel();
panelOCRSettings = createOCRSettingsPanel();
panelAddUpdate = createAddUpdatePanel();
this.add( panelRegionInfo, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.BOTH, new Insets( 0, 0, 0, 0 ), 0, 0 ) );
this.add( panelICSettings, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.BOTH, new Insets( 0, 0, 0, 0 ), 0, 0 ) );
this.add( panelOCRSettings, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.BOTH, new Insets( 0, 0, 0, 0 ), 0, 0 ) );
this.add( panelAddUpdate, new GridBagConstraints( 1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.BOTH, new Insets( 5, 0, 0, 0 ), 0, 0 ) );
panelOCRSettings.setVisible( false );
setMaximumSize( icPanelDim );
setVisible( false );
setupListeners();
logger.info( "Initialized RegionDetailsPanel" );
}
/**
* Creates panel for defining region info
*/
private RegionInfoPanel createRegionInfoPanel()
{
return new RegionInfoPanel();
}
/**
* Creates panel for defining OCR settings
*/
private OCRSettingsPanel createOCRSettingsPanel()
{
return new OCRSettingsPanel();
}
/**
* Creates panel for defining image compare settings
*/
private ICSettingsPanel createImageCompareSettingsPanel()
{
return new ICSettingsPanel();
}
/**
* Creates panel for Add/Update region
*/
private JPanel createAddUpdatePanel()
{
JPanel addUpdatePanel = new JPanel();
setName( "addUpdatePanel" );
addUpdatePanel.setLayout( new GridBagLayout() );
GridBagConstraints addUpdatePanelConstraints = new GridBagConstraints();
addUpdatePanelConstraints.insets = new Insets( 5, 200, 0, 5 );
btnAddUpdate = new JButton();
btnAddUpdate.setName( "btnAddUpdate" );
btnAddUpdate.setText( ADD_TEXT );
btnAddUpdate.setToolTipText( "Adds or updates the current region" );
btnAddUpdate.setPreferredSize( new java.awt.Dimension( 141, 22 ) );
addUpdatePanelConstraints.anchor = GridBagConstraints.LINE_END;
addUpdatePanelConstraints.gridx = 0;
addUpdatePanelConstraints.gridy = 1;
addUpdatePanel.add( btnAddUpdate, addUpdatePanelConstraints );
lblPassFail = new JLabel( FAILURE_STRING, JLabel.CENTER );
lblPassFail.setBackground( Color.RED );
lblPassFail.setBorder( BorderFactory.createLineBorder( Color.BLACK ) );
lblPassFail.setOpaque( true );
lblPassFail.setPreferredSize( new java.awt.Dimension( 141, 22 ) );
lblPassFail.setVisible( false );
lblPassFail.setName( "lblPassFail" );
addUpdatePanelConstraints.anchor = GridBagConstraints.LINE_END;
addUpdatePanelConstraints.gridx = 0;
addUpdatePanelConstraints.gridy = 3;
addUpdatePanel.add( lblPassFail, addUpdatePanelConstraints );
lbltimeTaken = new JLabel( "Time Passed : " );
lbltimeTaken.setToolTipText( "Time Passed" );
lbltimeTaken.setVisible( true );
addUpdatePanelConstraints.anchor = GridBagConstraints.LINE_START;
addUpdatePanelConstraints.gridx = 0;
addUpdatePanelConstraints.gridy = 4;
addUpdatePanel.add( lbltimeTaken, addUpdatePanelConstraints );
return addUpdatePanel;
}
public void setMode( int mode )
{
this.mode = mode;
}
public int getMode()
{
return mode;
}
@Override
public void repaint()
{
if ( OCR_MODE == mode )
{
panelICSettings.setVisible( false );
panelOCRSettings.setVisible( true );
}
else if ( IC_MODE == mode )
{
panelOCRSettings.setVisible( false );
panelICSettings.setVisible( true );
}
super.repaint();
}
/**
* Sets regions as the current region list.
*
* @param regionsList
*/
public void setRegionsList( List< RegionInfo > regionsList )
{
if ( null != regionsList )
{
this.regionsList = regionsList;
}
}
/**
* Returns a list of all the added regions.
*
* @return
*/
public List< RegionInfo > getRegionsList()
{
return regionsList;
}
/**
* Loads the region details.
*
* @param regionInfo
* contains all the region details.
*/
public void loadRegionDetails( RegionInfo regionInfo )
{
if ( null != regionInfo )
{
panelRegionInfo.setRegionName( regionInfo.getName() );
panelRegionInfo.setXValue( Integer.toString( regionInfo.getX() ) );
panelRegionInfo.setYValue( Integer.toString( regionInfo.getY() ) );
panelRegionInfo.setWidthValue( Integer.toString( regionInfo.getWidth() ) );
panelRegionInfo.setHeightValue( Integer.toString( regionInfo.getHeight() ) );
if ( regionInfo instanceof ImageCompareRegionInfo )
{
ImageCompareRegionInfo icRegionInfo = ( ImageCompareRegionInfo ) regionInfo;
panelICSettings.setMatchPct( icRegionInfo.getMatchPct().intValue() );
panelICSettings.setXTolerance( ( int ) icRegionInfo.getXTolerance() );
panelICSettings.setYTolerance( ( int ) icRegionInfo.getYTolerance() );
panelICSettings.setRedTolerance( ( int ) icRegionInfo.getRedTolerance() );
panelICSettings.setGreenTolerance( ( int ) icRegionInfo.getGreenTolerance() );
panelICSettings.setBlueTolerance( ( int ) icRegionInfo.getBlueTolerance() );
setMode( IC_MODE );
}
else if ( regionInfo instanceof OCRRegionInfo )
{
OCRRegionInfo ocrRegionInfo = ( OCRRegionInfo ) regionInfo;
panelOCRSettings.setMatchPct( ocrRegionInfo.getSuccessTolerance() );
panelOCRSettings.setTimeout( ocrRegionInfo.getTimeout() );
panelOCRSettings.setExpectedText( ocrRegionInfo.getExpectedResult() );
setMode( OCR_MODE );
}
lblPassFail.setText( FAILURE_STRING );
lblPassFail.setBackground( Color.red );
lbltimeTaken.setText( "Time Passed : " );
btnAddUpdate.setText( UPDATE_TEXT );
currentRegion = regionInfo;
repaint();
}
}
public void setCurrentRegion( RegionInfo currentRegion )
{
this.currentRegion = currentRegion;
}
/**
* Returns the Current region
*
* @return the current region (ImageCompareRegionInfo)
*/
public RegionInfo getCurrentRegion()
{
RegionInfo currentRegionInfo = null;
String regionName = panelRegionInfo.getRegionName();
int x = Integer.parseInt( panelRegionInfo.getXValue() );
int y = Integer.parseInt( panelRegionInfo.getYValue() );
int width = Integer.parseInt( panelRegionInfo.getWidthValue() );
int height = Integer.parseInt( panelRegionInfo.getHeightValue() );
if ( mode == IC_MODE )
{
currentRegionInfo = new ImageCompareRegionInfo();
float matchPct = panelICSettings.getMatchPct();
int xTolerance = panelICSettings.getXTolerance();
int yTolerance = panelICSettings.getYTolerance();
int redTolerance = panelICSettings.getRedTolerance();
int blueTolerance = panelICSettings.getBlueTolerance();
int greenTolerance = panelICSettings.getGreenTolerance();
currentRegionInfo.setName( regionName );
currentRegionInfo.setX( x );
currentRegionInfo.setY( y );
currentRegionInfo.setWidth( width );
currentRegionInfo.setHeight( height );
currentRegionInfo.setXTolerance( xTolerance );
currentRegionInfo.setYTolerance( yTolerance );
( ( ImageCompareRegionInfo ) currentRegionInfo ).setMatchPct( matchPct );
( ( ImageCompareRegionInfo ) currentRegionInfo ).setRedTolerance( redTolerance );
( ( ImageCompareRegionInfo ) currentRegionInfo ).setBlueTolerance( blueTolerance );
( ( ImageCompareRegionInfo ) currentRegionInfo ).setGreenTolerance( greenTolerance );
}
else if ( mode == OCR_MODE )
{
currentRegionInfo = new OCRRegionInfo();
int matchPct = panelOCRSettings.getMatchPct();
String expectedResult = panelOCRSettings.getExpectedText();
int timeout = panelOCRSettings.getTimeOut();
currentRegionInfo.setName( regionName );
currentRegionInfo.setX( x );
currentRegionInfo.setY( y );
currentRegionInfo.setWidth( width );
currentRegionInfo.setHeight( height );
( ( OCRRegionInfo ) currentRegionInfo ).setSuccessTolerance( matchPct );
( ( OCRRegionInfo ) currentRegionInfo ).setExpectedResult( expectedResult );
( ( OCRRegionInfo ) currentRegionInfo ).setTimeout( timeout );
}
return currentRegionInfo;
}
/**
* Clear current region details.
*/
public void clearCurrentRegionDetails()
{
panelRegionInfo.clearValues();
panelICSettings.clearValues();
panelOCRSettings.clearValues();
lblPassFail.setText( FAILURE_STRING );
lblPassFail.setBackground( Color.red );
lbltimeTaken.setText( "Time Passed : " );
btnAddUpdate.setText( ADD_TEXT );
repaint();
}
/**
* Clears information of all the regions defined.
*/
public void clearAllRegions(){
regionsList.clear();
}
/**
* Change the panel look for test mode.
*/
public void showTestMode()
{
testMode = true;
lblPassFail.setBackground( Color.yellow );
lblPassFail.setForeground( Color.black );
lblPassFail.setText( "Comparing..." );
lblPassFail.repaint();
lblPassFail.setVisible( testMode );
}
/**
* Display the text 'PASS' if the test is passed else 'FAIL' in the
* 'Add/Update' panel.
*
* @param testResult
* the test result(true if the test is passed, else false.).
* @param timeSpent
* the time spent on testing
*/
public void updateTestResults( boolean testResult, int timeSpentms )
{
lblPassFail.setBackground( testResult ? Color.green : Color.red );
lblPassFail.setText( testResult ? PASS_STRING : FAILURE_STRING );
lbltimeTaken.setText( "TimePassed : " + Math.round( timeSpentms / 1000 ) + " sec" );
lblPassFail.repaint();
}
/**
* Set the snapshot filepath. Used when the image is saved or loaded.
*
* @param filepath
*/
public void setSnapshotFilepath( String filepath )
{
if ( null != filepath && !filepath.isEmpty() )
{
snapshotFilepath = filepath;
}
}
/**
* Get the snapshot filepath. Null if snapshot was not loaded or saved
* before.
*
* @return
*/
public String getSnapshotFilepath()
{
return snapshotFilepath;
}
/**
* Checks if a given region is present in the list.
*
* @param currentRegionName
* region to be checked.
* @return true if region is present, else false.
*/
private boolean isRegionPresent( String currentRegionName )
{
boolean retVal = false;
for ( RegionInfo regionInfo : regionsList )
{
if ( regionInfo.getName().equals( currentRegionName ) )
{
retVal = true;
break;
}
}
return retVal;
}
/**
* Reset The panel to initial conditions.
*
* @param currentRegionName
* region to be checked.
* @return true if region is present, else false.
*/
public void resetRegionDetails()
{
clearCurrentRegionDetails();
regionsList.clear();
}
public void setRegionInfo( int x, int y, int width, int height )
{
panelRegionInfo.setXValue( String.valueOf( x ) );
panelRegionInfo.setYValue( String.valueOf( y ) );
panelRegionInfo.setWidthValue( String.valueOf( width ) );
panelRegionInfo.setHeightValue( String.valueOf( height ) );
}
/**
* Adding ChangeListener for Sliders, ActionListener for 'Add/Update'
* button.
*/
private void setupListeners()
{
// Add/Update button.
btnAddUpdate.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
RegionInfo currentRegionInfo = getCurrentRegion();
if ( currentRegionInfo == null || currentRegionInfo.getWidth() == 0 || currentRegionInfo.getHeight() == 0 )
{
JOptionPane.showMessageDialog( RegionDetailsPanel.this,
"Please select a region with a width and height > 0", "Cannot add",
JOptionPane.INFORMATION_MESSAGE );
return;
}
if ( currentRegionInfo.getName().trim().isEmpty() )
{ // if blank region name
JOptionPane.showMessageDialog( RegionDetailsPanel.this, "Please enter a region name",
"Cannot add", JOptionPane.INFORMATION_MESSAGE );
return;
}
if ( btnAddUpdate.getText().equals( ADD_TEXT ) )
{
if ( isRegionPresent( currentRegionInfo.getName() ) )
{ // if same region name exists
JOptionPane.showMessageDialog( RegionDetailsPanel.this,
"A region with this name already exists", "Cannot add",
JOptionPane.INFORMATION_MESSAGE );
return;
}
regionsList.add( currentRegionInfo );
setCurrentRegion(currentRegionInfo);
btnAddUpdate.setText( UPDATE_TEXT );
}
else
{
regionsList.remove( currentRegion );
// since ArrayList is ordered; 0th element will always
// be
// the last updated element
// i.e the current region
regionsList.add( currentRegionInfo );
currentRegion = currentRegionInfo;
}
}
} );
}
}