/*
 * Copyright (C) 2005 - 2007 JasperSoft Corporation.  All rights reserved. 
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased a commercial license agreement from JasperSoft,
 * the following license terms apply:
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed WITHOUT ANY WARRANTY; and without 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/gpl.txt
 * or write to:
 *
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA  USA  02111-1307
 *
 *
 *
 *
 * ReportElementSheetPanel.java
 * 
 * Created on 16 febbraio 2005, 6.57
 *
 */

package it.businesslogic.ireport.gui.sheet;

import it.businesslogic.ireport.*;
import it.businesslogic.ireport.BarcodeReportElement;
import it.businesslogic.ireport.FontListLoader;
import it.businesslogic.ireport.GraphicReportElement;
import it.businesslogic.ireport.IReportFont;
import it.businesslogic.ireport.LineReportElement;
import it.businesslogic.ireport.RectangleReportElement;
import it.businesslogic.ireport.TextFieldReportElement;
import it.businesslogic.ireport.TextReportElement;
import it.businesslogic.ireport.crosstab.CrosstabCell;
import it.businesslogic.ireport.gui.*;
import it.businesslogic.ireport.gui.JNumberComboBox;
import it.businesslogic.ireport.gui.JNumberField;
import it.businesslogic.ireport.gui.event.*;
import it.businesslogic.ireport.util.*;
import it.businesslogic.ireport.util.LanguageChangedEvent;
import it.businesslogic.ireport.util.LanguageChangedListener;
import java.awt.Color;
import java.awt.Point;
import java.util.*;
import javax.swing.FocusManager;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;

/**
 *
 * @author  Administrator
 */
public class ReportBandSheetPanel extends CategorySheetPanel implements ReportListener, LanguageChangedListener, ReportFrameActivatedListener {
    
    // Sheet properties
    private SheetProperty spHeight;
    private SheetProperty spSplitAllowed;
    private ExpressionSheetProperty spPrintWhenExpression;
    
    public  static java.awt.Color sharedDifferentValueLabelColor = java.awt.Color.red.darker().darker();
    public  static java.awt.Color mandatoryPropertiesLabelColor = java.awt.Color.blue;
    public  static java.awt.Color notMandatoryPropertiesLabelColor = java.awt.Color.black;
        
    private JReportFrame jrf = null;
    private boolean init = false;   
    
    private Vector bandSelection = new Vector();
    
    /** Creates a new instance of ReportElementSheetPanel */
    public ReportBandSheetPanel() {
        super();
        this.setBackground( Color.BLUE);
        initSheetProperties();
        // We have to register for element changes...
        MainFrame mf = MainFrame.getMainInstance();
        mf.addReportListener( this );
        mf.addReportFrameActivatedListener( this);       
        I18n.addOnLanguageChangedListener( this );
    }

    public void reportFrameActivated(ReportFrameActivatedEvent evt) {
    
        if (MainFrame.getMainInstance().getActiveReportFrame() == this.getJrf()) return;
        updateSelection(MainFrame.getMainInstance().getActiveReportFrame());
        
        
    }
    
    public void languageChanged(LanguageChangedEvent evt) {
        this.removeAllProperties();
        initSheetProperties();
        updateSelection();
    }

    
     public void updateSelection()
     {
         JReportFrame newJrf = MainFrame.getMainInstance().getActiveReportFrame();
         updateSelection(newJrf);
     }
     
     /**
      * Numbers do not change when the focus is lost due to a selection change.
      * This apply the value....
      */
     public void applyValueForNumbers()
     {
         Enumeration e = getProperties().elements();
         while (e.hasMoreElements())
         {
             SheetProperty sp = (SheetProperty)e.nextElement();

             //if (sp instanceof NumberComboBoxSheetProperty)
             //{
             //    JNumberComboBox c = (JNumberComboBox)sp.getEditor();
             //    System.out.println("NNNN");
             //    if (c.hasFocus())
             //    {
             //       FocusManager.getCurrentManager().clearGlobalFocusOwner();
             //       System.out.println(FocusManager.getCurrentManager().getFocusOwner());
             //       return; // Only a component can be focused at time...
             //    }
             //}
             if (sp.getType() == sp.INTEGER || sp.getType() == sp.NUMBER)
             {
                 JComponent c = sp.getEditor();
                 if (c.hasFocus() && c instanceof JNumberField)
                 {
                    ((JNumberField)c).focusLost(null);
                    return; // Only a component can be focused at time...
                 }
             }
             
         }
     }
     
    /**
     * Update all the element properties...
     * 
     */
     public void updateSelection(JReportFrame newJrf)
     {
        // Improving speed...
        // Do nothing if there are elements selected...
         if (newJrf != null && newJrf.getSelectedElements().size() > 0) return;

        // Fix for numbers focus losing...
        applyValueForNumbers();
        if (newJrf == null)
        {
            this.setBandSelection(new Vector());
        }
        else
        {
            this.setBandSelection( newJrf.getSelectedBands() );
        }
        
        setInit(true);
                
        this.removeAllProperties();
        
        this.jrf = newJrf;
        
        if (jrf == null || getBandSelection().size() == 0)
        {
            this.recreateSheet();
            return;
        }
      
        try {
        Vector selectedElements = getBandSelection();
        
        boolean sameHeight = true;
        boolean sameSplitAllowed = true;
        boolean samePrintWhenExpression = true;
   
        boolean isTheFirstElement = true;
        
        for (int i=0; i<selectedElements.size(); ++i)
        {
            Band band = (Band)selectedElements.elementAt(i);
           
            //if (sameName)  sameName = this.setGenericSheetProperty(isTheFirstElement, band.getName(), false);
            if (sameHeight)  sameHeight = this.setElementNumber(isTheFirstElement, band.getHeight(), (JNumberField)spHeight.getEditor());
            if (sameSplitAllowed)  sameSplitAllowed = this.setCheckBox(isTheFirstElement, band.isSplitAllowed(), false, spSplitAllowed );
            if (samePrintWhenExpression) samePrintWhenExpression = setTextArea(isTheFirstElement, band.getPrintWhenExpression(), spPrintWhenExpression);
            
            isTheFirstElement = false;
        }
        
        spHeight.setLabelColor( (sameHeight) ? notMandatoryPropertiesLabelColor : sharedDifferentValueLabelColor );
        //spSplitAllowed.setLabelColor( (sameSplitAllowed) ? mandatoryPropertiesLabelColor : sharedDifferentValueLabelColor );
        //spPrintWhenExpression.setLabelColor( (samePrintWhenExpression) ? mandatoryPropertiesLabelColor : sharedDifferentValueLabelColor );
        
        ExpressionContext ec = new ExpressionContext();
        ec.setSubDataset( jrf.getReport() );
        
        spPrintWhenExpression.setExpressionContext( ec );
        
        spPrintWhenExpression.setLabelError(null);
        spPrintWhenExpression.updateLabel();
        
        String commonStr = it.businesslogic.ireport.util.I18n.getString("bandProperties","Band Properties");
        this.addSheetProperty(commonStr, spHeight);
        this.addSheetProperty(commonStr, spSplitAllowed);
        this.addSheetProperty(commonStr, spPrintWhenExpression);
        
        spSplitAllowed.setDefaultValue( new Boolean(true));
        
        this.recreateSheet();

        } catch (Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            
        }
        
        setInit(false);
     }
     
     
     /**
      * This methos is called when a property changes...
      */
     public void sheetPropertyValueChanged(SheetPropertyValueChangedEvent evt)
     {
         if (isInit()) return;
         
         //System.out.println("Changed: " + evt.getPropertyName());
         //if (isNullItem((SheetProperty)evt.getSource())) return;
         
         //removeNullItem( (SheetProperty)evt.getSource() );
         
         Vector selectedElements = getBandSelection();
         
         for (int i=0; i<selectedElements.size(); ++i)
         {
             
             Band band = (Band)selectedElements.elementAt(i);
             applyNewProperty(band,evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
         }
         
         repaintEditor();
         
         /*
         ReportElementChangedEvent changedEvent = new ReportElementChangedEvent(jrf , selectedElements , ReportElementChangedEvent.CHANGED);
         changedEvent.setEventSource( this );
         if (evt.getPropertyName().equals("textfieldEvaluationTime"))
         {
            changedEvent.setPropertyChanged( evt.getPropertyName() );
            changedEvent.setNewValue( evt.getNewValue() );
         }
         jrf.fireReportListenerReportElementsChanged(changedEvent);
         MainFrame.getMainInstance().getElementPropertiesDialog().updateSelection();
         */
     }
     
     
     /*
      * This method apply the new value for the specified property
      * The oldValue can be wrong or null if a multiselection was performed
      */
     private void applyNewProperty(Band b, String propertyName, Object oldValue, Object newValue)
     {
         if (propertyName == null) return;
         if (isInit()) return;
         
         boolean fireEvent = true;
         if (propertyName.equals("height"))
         {
            if (newValue != null && !newValue.equals(""))
            {   
                int val = Integer.parseInt(""+newValue);

                BandsDialog.updateBandHeight(getJrf().getReport(), b, val);
            }
         }
         else if (propertyName.equals("splitAllowed"))
         {
            b.setSplitAllowed( ((Boolean)newValue).booleanValue() );
         }
         else if (propertyName.equals("printWhenExpression"))
         {
            if (newValue != null)
            {
                b.setPrintWhenExpression( ""+newValue );
            }
            ((SheetProperty)this.getSheetProperty(propertyName)).setLabelError(null);
            ((SheetProperty)this.getSheetProperty(propertyName)).updateLabel();
            
            fireEvent = false;
            MainFrame.getMainInstance().getBandsDialog().updateBands();
         }
         if (fireEvent)
         {
            getJrf().fireReportListenerReportBandChanged(new ReportBandChangedEvent(getJrf(),b, ReportBandChangedEvent.CHANGED));
         }
         
     }
      
     /*
      *     This method is called when a band is removed, changed or added.
      */ 
     public void reportBandChanged(ReportBandChangedEvent evt ) {
         updateSelection();
     }
     
     protected void initSheetProperties()
     {
        spHeight =  new SheetProperty("height",it.businesslogic.ireport.util.I18n.getString("gui.elementpropertiessheet.height","Height"), SheetProperty.INTEGER);
        spHeight.setShowResetButton(false);
        
        spSplitAllowed =  new SheetProperty("splitAllowed",it.businesslogic.ireport.util.I18n.getString("gui.bandpropertiessheet.splitAllowed","Is split allowed"), SheetProperty.BOOLEAN);
        spSplitAllowed.setShowResetButton(false);
        spPrintWhenExpression = new ExpressionSheetProperty("printWhenExpression",it.businesslogic.ireport.util.I18n.getString("gui.elementpropertiessheet.printWhenExpression","Print When Expression"));
        spPrintWhenExpression.setShowResetButton(false);

     }
     
   
    public boolean isInit() {
        return init;
    }

    public void setInit(boolean init) {
        this.init = init;
    }
   
    
    protected boolean setTextArea( boolean firstTime, String value, SheetProperty textProperty ) {
        
        if ((!firstTime) && (!(textProperty.getValue().equals(value) ))) {
            
            JComponent editor = textProperty.getEditor();
            if (editor instanceof ExpressionSheetPropertyComponent)
            {
                ((ExpressionSheetPropertyComponent)editor).setExpression("");
               ((ExpressionSheetPropertyComponent)editor).setText(it.businesslogic.ireport.util.I18n.getString("gui.elementpropertiessheet.differentValues","<different values>"));
            }
            return false;
        }
        else {
            try {
                textProperty.setValue(value);
            } catch (Exception ex){
                ex.printStackTrace();
            }
        }
        return true;
    }
    
   
    
    protected boolean setElementNumber( boolean firstTime, double value, JNumberField numberField ) {
        if (( ! firstTime ) && (!(numberField.getValue() == value))) {
            numberField.setText("");
            return false;
        }
        else {
            try {
                numberField.setValue( value );
            } catch (Exception ex){
                ex.printStackTrace();
            }
        }
        return true;
    }
    
    protected boolean setElementNumber( boolean firstTime, int defaultValue, Object value, NumberComboBoxSheetProperty sp) {
        if ( ( ! firstTime ) && (!((sp.getValue()+"").equals(""+value))) )  {
            
            boolean setting = sp.isSetting();
            sp.setSetting(true);
            sp.setValue(null);
            sp.setSetting(setting);
            //System.out.println("Setting value of editor to blank ");
            sp.setEditorValue( sp.getEditor(), "");
            return false;
        }
        else {
            try {
                 boolean setting = sp.isSetting();
                 sp.setSetting(true);
                 sp.setValue(value);
                 if (value == null)
                 {
                     if (!firstTime && !(((JNumberComboBox)sp.getEditor()).getSelectedItem()+"").equals(""+defaultValue))
                     {
                         sp.setEditorValue( sp.getEditor(), "");
                     }
                     else
                     {
                        sp.setEditorValue( sp.getEditor(), new Integer( defaultValue));
                    }
                 }
                 sp.setSetting(setting);
            } catch (Exception ex){
                ex.printStackTrace();
            }
        }
        return true;
    }
    
    protected boolean setGenericSheetProperty( boolean firstTime, Object value, SheetProperty sp) {
        if (firstTime )
        {    
            try {
                sp.setValue( value );
            } catch (Exception ex){
                ex.printStackTrace();
            }
            return true;
        } else
        {
            Object value2 = sp.getValue();
            if (value2 == value)
            {
                return true;
            }
            if (value2 != null && (""+value2).equals( value +""))
            {
                return true;
            }
            
            sp.setValue(null);
        }
       
        return false;
    }
    
    
    protected boolean setColorProperty( boolean firstTime, java.awt.Color color, SheetProperty sp) {
        
        
        if (firstTime )
        {    
            try {
                sp.setValue( color );
            } catch (Exception ex){
                ex.printStackTrace();
            }
            return true;
        } else
        {
            java.awt.Color c1 = (java.awt.Color)sp.getValue();
            if (c1 == color)
            {
                return true;
            }
            if (c1 != null && color != null && c1.getRGB() == color.getRGB())
            {
                return true;
            }
            
            sp.setValue(null);
        }
       
        return false;
    }
            
    protected boolean setCheckBox( boolean firstTime, boolean value, boolean isNull, SheetProperty sp ) {
        if (firstTime )
        {
            try {
                if (isNull)
                {
                    sp.setValue( null );
                    sp.setSetting(true);
                    ((JCheckBox)sp.getEditor()).setSelected(value);
                    sp.setSetting(false);
                }
                else
                {
                    sp.setValue(""+value);
                }
                
            } catch (Exception ex){
                ex.printStackTrace();
            }
            return true;
        }
        else
        {
             if (sp.getValue() == null && isNull) return true;
             if (sp.getValue() != null && sp.getValue().equals("" + value)  ) return true;
            
             sp.setValue( null );
             return false;
        }
        
    }

    public JReportFrame getJrf() {
        return jrf;
    }

    public void setJrf(JReportFrame jrf) {
        this.jrf = jrf;
    }
    
    
    /**
     * Redraw the correct editor panel (JReportPanel or the active CrosstabPanel)
     *
     */
    public void repaintEditor()
    {
        if (jrf == null) return;
        jrf.getJPanelReport().repaint( );
    }
    
    public Vector getBandSelection() {
        return bandSelection;
    }

    public void setBandSelection(Vector newBandSelection) {
        this.bandSelection.removeAllElements();
        if (newBandSelection == null) return;
        this.bandSelection.addAll(newBandSelection);
    }

    public void reportElementsSelectionChanged(ReportElementsSelectionEvent evt) {
    }

    public void reportElementsChanged(ReportElementChangedEvent evt) {
    }

    public void reportBandsSelectionChanged(ReportBandsSelectionEvent evt) {
        updateSelection();
    }
}
