Package org.ribax.ui

Source Code of org.ribax.ui.TabContainer

/*
* RIBAX, Making Web Applications Easy
* Copyright (C) 2006 Damian Hamill and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.ribax.ui;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Component;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.awt.print.Printable;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.Box;
import javax.swing.JComponent;
import org.jdom.Element;

import org.ribax.parameters.ParameterSet;

import org.ribax.utils.log.LOG;
import org.ribax.utils.types.NameValuePair;
import org.ribax.utils.xml.XMLutils;
import org.ribax.*;

/**
* An abstract class that provides a common base for the Tab and TabbedDataSet classes.
*
* @version <tt>$Revision: $</tt>
* @author  <a href="mailto:damian@ribax.org">Damian Hamill</a>
*
* @see org.ribax.ui.Tab
* @see org.ribax.ui.TabbedDataSet
* @see org.ribax.ui.TabButtonListener
*/

public abstract class TabContainer extends DataItem implements TabButtonListener {
   
    /** The set of DataItems on this TabContainer */
    protected Vector<DataItem> dataItems = new Vector<DataItem>();

    /** A URL to a web service that returns the description of this TabContainer,
     * this is set if we have already read the description from the URL
     * */
    protected String url = null;
   
    /** A URL of a web service that provides the definition of this TabContainer */
    protected String source = null;
   
    /** Another DataItem that should handle button clicks */
    protected DataItem actionHandler = null;

    /** A global configuration set accessible by all parts of the application */
    protected RIBAXConfig config = RIBAXConfig.getInstance();
   
    /** A button panel that hosts buttons on this TabContainer */
    protected ButtonPanel buttonPanel = null;

    /** A set of parameters for this TabContainer */
    protected ParameterSet paramSet = null;
  
    /**
     * Constructor that takes a name, title and description
     */
    public TabContainer(String name, String title, String description) {

        super(name,title,description,null);
      
        layoutComponents();    
    }
   
    /**
     * Constructor that takes a DataItem parent (usually a Folder)
     */
    public TabContainer(DataItem parent) {
        setParent(parent);
    }
   
    /**
     * If there is a description and/or any parameters anchored North then make a panel
     * that contains these.
     *
     * @return a panel containing the description and/or parameters or null if there is no
     * description and no parameters anchored North.
     */
    protected JComponent getNorthPanel() {
        Box panel = null;
       
        if (description != null) {
            // there is a description so add it to the panel
            Description desc;
           
            if (prefWidth > 0)
                desc = new Description(description,getBackground(),prefWidth);
            else
                desc = new Description(description,getBackground());
           
            // if there are no parameters then we don't need to create a panel, we
            // can simply return the description component as the North panel
            if (paramSet == null)
                return desc;
           
            // create the panel and add the description
            panel = Box.createVerticalBox();
           
            panel.add(desc);
        }

        // if there are no parameters then return the panel whatever the value is now
        // this will in effect return null if the test is true
        if (paramSet == null)
            return panel;
       
        // there may be parameters but if they are not anchored North then we won't add them
        // here so return the panel as it is
        if (!BorderLayout.NORTH.equals(paramSet.getLayoutLocation()))
            return panel;
       
        LOG.debug(name+Messages.getString("Tab.0")+paramSet.getLayoutLocation()); //$NON-NLS-1$
       
        // if we didn't add a description then we can just return the parameter panel
        if (panel == null)
            return paramSet;
       
        // add the parameters to the panel
        panel.add(paramSet);
       
        return panel;
    }
   
    /**
     * If there is a set of button and/or parameters anchored South then make a panel
     * that contains these.
     *
     * @return a panel containing the buttons and/or parameters or null if there is no
     * buttons and no parameters anchored South.
     */
    protected JComponent getSouthPanel() {
        Box panel = null;
       
        if (paramSet != null && BorderLayout.SOUTH.equals(paramSet.getLayoutLocation())) {
            // there is a parameters set anchored South
            LOG.debug(name+Messages.getString("Tab.1")+paramSet.getLayoutLocation()); //$NON-NLS-1$
           
            // if there are no buttons we can just return the parameter panel
            if (buttonPanel == null)
                return paramSet;
               
            // create the panel and add the parameters
            panel = Box.createVerticalBox();
   
            panel.add(paramSet);
        }
       
        // if there are no buttons then return whatever the value of panel is now
        // this will in effect return null if the test is true
        if (buttonPanel == null)
            return panel;
       
        // if the panel has not already been created (no parameters anchored South) then
        // just return the button panel
        if (panel == null)
            return buttonPanel;
       
        // otherwise add the button panel
        panel.add(buttonPanel);

        return panel;
    }
   
    /**
     * If there is a set of parameters anchored East then return the parameter panel.
     *
     * @return a parameter panel that is anchored on the East border.
     */
    protected JComponent getEastPanel() {
        if (paramSet != null && BorderLayout.EAST.equals(paramSet.getLayoutLocation()))
                return paramSet;
       
        return null;
    }
    /**
     * If there is a set of parameters anchored West then return the parameter panel.
     *
     * @return a parameter panel that is anchored on the West border.
     */
    protected JComponent getWestPanel() {
        if (paramSet != null && BorderLayout.WEST.equals(paramSet.getLayoutLocation()))
            return paramSet;
           
        return null;
    }

    /**
     * Layout the GUI components.  DataItems occupy the majority of space with button and
     * parameters panels anchored around the border.
     */
    protected void layoutComponents() {

        // remove any previous contents
        removeAll();
       
        // use BorderLayout
        setLayout(new BorderLayout());
               
        // if there is more than 1 DataItem then embed the box (which contains
        // the DataItems) in a scroll pane
        if (dataItems.size() > 1) {
           
            /*
            JScrollPane scrpane = new JScrollPane(getComponent(),
                    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
           
            if (prefWidth > 0 || prefHeight > 0) {
                Dimension d = new Dimension (prefWidth == 0 ? 400 : prefWidth,
                        prefHeight == 0 ? 400 : prefHeight);
                scrpane.setPreferredSize(d);
            }
            */
           
            add(getComponent(),BorderLayout.CENTER);
        } else if (dataItems.size() == 1) {
            // there is only 1 DataItem so it occupies the whole of the center of the TabContainer
            DataItem item = (DataItem) dataItems.elementAt(0);
            add(item,BorderLayout.CENTER);
        }

        // add any panels that are anchored around the TabContainer border
       
        // get the North panel and add it to the North Border
        JComponent panel = getNorthPanel();
       
        if (panel != null)
            add(panel,BorderLayout.NORTH);
       
        // ditto south
        panel = getSouthPanel();
        if (panel != null)
            add(panel,BorderLayout.SOUTH);

        // ditto West
        panel = getWestPanel();
        if (panel != null)
            add(panel,BorderLayout.WEST);
   
        // ditto East
        panel = getEastPanel();
        if (panel != null)
            add(panel,BorderLayout.EAST);
        revalidate();
        repaint();

    }

    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#readDescription(org.jdom.Element)
     */
    public void readDescription(Element root) {
        Element e;
       
        super.readDescription(root);
             
        // clear out any previous DataItems and GUI components
        dataItems = new Vector<DataItem>();
        buttonPanel = null;
        paramSet = null;
               
        if (LOG.isDebugEnabled())
            LOG.debug(name+Messages.getString("Tab.2")); //$NON-NLS-1$
    
        source = XMLutils.getElementString("source",root); //$NON-NLS-1$
        // if a source has been specified then read the description from the source
        // test the value of url, if it has been set then this could be the 2nd
        // time we are in this method, a source tag in a sourced description would
        // otherwise cause an infinite loop
        if (source != null && url == null) {
            if (LOG.isDebugEnabled())
                LOG.debug(name+Messages.getString("Tab.4")); //$NON-NLS-1$
            
            url = source;
                       
            ArrayList params = null;

            if (paramSet != null) {
                params = paramSet.getNameValuePairs();
            }
    
            // read the description later (when it is needed, i.e. when the TabContainer is displayed)
            deferReadDescriptionFromURL(source,params,"LoadDescription"); //$NON-NLS-1$
            return;
        }
   
        // get the parameters
        if ((e = root.getChild("parameters")) != null) //$NON-NLS-1$
            paramSet = ParameterSet.readParameters(e);

        // get a set of buttons
        if ((e = root.getChild("buttons")) != null) { //$NON-NLS-1$
            if (LOG.isDebugEnabled())
                LOG.debug(name+Messages.getString("Tab.10")); //$NON-NLS-1$
            
            buttonPanel = new ButtonPanel(this);
            buttonPanel.readButtons(e);
        }
        if (LOG.isDebugEnabled())
            LOG.debug(name+Messages.getString("Tab.11")); //$NON-NLS-1$
    
   }
      
    /**
     * Setup an action handler which will handle button clicks from buttons on this TabContainer.
     *
     * @param parent the DataItem that will handle any button clicks.
     */
    protected void setActionHandler(DataItem parent) {
        this.actionHandler = parent;
    }
     
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#invalidateData()
     */
    public void invalidateData() {
        invalidateDataItems();
    }

    /**
     * Invalidate the data of all the DataItems on this TabContainer.
     */
    protected void invalidateDataItems() {
       
        if (LOG.isDebugEnabled())
            LOG.debug(name+Messages.getString("Tab.12")); //$NON-NLS-1$
       
        // tell each DataItem in our internal list to invalidate its data
        for(int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem) dataItems.elementAt(i);
           
            if (item == null) {
                LOG.error(name+Messages.getString("Tab.13")+getTitle()); //$NON-NLS-1$
                continue;
            }
            item.invalidateData();
        }
    }
   
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#close()
     */
    public void close() {      
        // tell each DataItem in our internal list to close
        for(int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem) dataItems.elementAt(i);
           
            if (item == null) {
                LOG.error(name+Messages.getString("Tab.14")+getTitle()); //$NON-NLS-1$
                continue;
            }
            item.close();
        }
    }

    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#refresh(java.util.ArrayList, java.lang.String)
     */
    public abstract void refresh(ArrayList params,String action);
   
    /**
     * Tell each DataItem in our internal list to load its data.
     *
     * @param params a set of parameters for DataItems to submit to web services.
     * @param action the action string associated with this event.
     */
    protected abstract void loadItemData(ArrayList params, String action);
    
    /**
     * Collect all the data elements from all the DataItems in this TabContainer and then
     * either replace the TabContainer contents from a web service or tell all the DataItems
     * in the TabContainer to replace their data using the collected data elements as
     * parameters for submission to web services.
     *
     * @param params a set of base parameters to submit to web services.
     * @param action the action string associated with this event.
     */
    protected abstract void updateItemData(ArrayList params, String action) ;

    /**
     * Collect SELECTED data elements from all the DataItems in this TabContainer and then
     * either replace the TabContainer contents from a web service or tell all the DataItems
     * in the TabContainer to replace their data using the collected data elements as
     * parameters for submission to web services.
     *
     * @param params a set of base parameters to submit to web services.
     * @param action the action string associated with this event.
     */
    protected abstract void selectItemData(ArrayList params,String action);

    /**
     * Collect all the data elements from all the DataItems in this TabContainer and then
     * either replace the TabContainer contents from a web service or tell all the DataItems
     * in the TabContainer to replace their data using the collected data elements as
     * parameters for submission to web services.
     *
     * @param params a set of base parameters to submit to web services.
     * @param action the action string associated with this event.
     */
    protected abstract void submitItemData( ArrayList params,String action) ;
   
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#validateContents()
     */
    public boolean validateContents() {
        // iterate through the DataItems on this tab and validate their data contents
        for(int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem) dataItems.elementAt(i);
            if (item.validateContents() == false)
                return false;
        }
        return true;
    }
   
    /* (non-Javadoc)
     * @see org.ribax.ui.TabButtonListener#doAction(int, java.lang.String)
     *
     * The user has clicked a button.  Take some action corresponding to the kind of button
     * that was clicked.
     */
    public void doAction(int buttonType, String action) {
               
        // validate the contents and do nothing if there is an error
        // unless we are going Back in which case we allow invalid content
        if (buttonType != TabButton.BACK &&
                buttonType != TabButton.CANCEL &&
                validateContents() == false)
            return;
       
        try {
            setCursor(new Cursor(Cursor.WAIT_CURSOR));

            // there are 4 kinds of buttons
            // submit all data items (default)
            // submit parameters & changed data items Update, Back, Finish,
            // submit selected data items  Select, Delete, Help, Action
            // submit nothing Refresh,  Reload, Cancel

            // if the actionHandler is non null and it can handle the action
            // then let the actionHandler handle the action
            if (actionHandler != null &&  
                    ( actionHandler instanceof TabbedDataSet ||
                            actionHandler instanceof SequenceDataItem)     
            ) {
                //LOG.info("sending button type "+buttonType+" action to parent action == "+action);

                // an action handler has been setup, pass the event to the action handler
                if (actionHandler instanceof TabbedDataSet)
                    ((TabbedDataSet)actionHandler).doAction(buttonType, action);
                else if (actionHandler instanceof SequenceDataItem)
                    ((SequenceDataItem)actionHandler).doAction(buttonType, action);

            } else {
                // no actionHandler setup so handle the event here
               
                //LOG.info("button type "+buttonType+" fired with action "+action);
                ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();

                // add the button type name
                params.add(new NameValuePair("ButtonType",TabButton.buttonTypeToName(buttonType))); //$NON-NLS-1$

                // add the button action
                if (action != null)
                    params.add(new NameValuePair("Action",action)); //$NON-NLS-1$

                // add any parameters from a parameter set
                if (paramSet != null) {
                    ArrayList<NameValuePair> tlist = paramSet.getNameValuePairs();

                    if (tlist != null
                        params.addAll(tlist);
                }

                // take an appropriate action based on the button type
                if (buttonType == TabButton.REFRESH ||
                        buttonType == TabButton.RELOAD ||
                        buttonType == TabButton.CANCEL) {
                    refresh(params,action);
                } else if (buttonType == TabButton.PRINT) {
                    printElements();
                } else if (buttonType == TabButton.UPDATE  ||
                        buttonType == TabButton.BACK ||
                        buttonType == TabButton.FINISH)
                    updateItemData(params,action);
                else if (buttonType == TabButton.SELECT  || 
                        buttonType == TabButton.DELETE ||
                        buttonType == TabButton.ACTION)
                    selectItemData(params,action);
                else
                    submitItemData(params,action);
            }
        } finally {
            // whatever happens we must set the cursor back to the default
            setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
       
    }
   
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#setData(org.jdom.Element)
     */
    public void setData(Element root) {
        Element tab;
       
        // see if the Element has a child Element that matches our internal name
        if ((tab = root.getChild(name)) != null) {
           
            // it does so iterate through our internal DataItem list and
            // set their data using a child Element of our Element matching the DataItem name
            for(int i = 0; i < dataItems.size(); i++) {
                DataItem item = (DataItem) dataItems.elementAt(i);
                Element e = tab.getChild(item.name);
                if (e != null)
                    item.setData(e);
            }
        }
    }
   
    protected ArrayList deferredParams = null;
    protected String deferredAction = null;
    protected String deferredSource = null;
   
    /**
     * Defer reading the TabContainer description until the TabContainer is loaded. 
     * This allows us to lazy load the TabContainer description when it is first displayed,
     * reducing network traffic during startup but causing a slight delay when the user
     * clicks on a Folder for the first time.
     *
     * @param source the URL to a web service that provides the TabContainer description.
     * @param params a set of parameters to submit to the web service.
     * @param action the action string associated with the event that caused the TabContainer
     * to be loaded from the web service.
     */
    protected void deferReadDescriptionFromURL(String source,ArrayList params, String action) {
        deferredSource = source;
        deferredParams = params;
        deferredAction = action;
    }
   
    /* (non-Javadoc)
     * @see dbaccessor.DataItem#loadData(java.util.ArrayList)
     *
     */
    public abstract void loadData(ArrayList params,String action);
   
    private final int PARAM = 0;
    private final int ALL = 1;
    private final int SELECTED = 2;
   
    /**
     * Get the data elements for all the DataItems on this TabContainer.  The data elements
     * that are returned depend on the kind of elements requested.
     *
     * @param mode indicates the kind of elements requested.
     * @return a list of data elements or null if the list is empty.
     */
    protected ArrayList getElements(int mode) {
        ArrayList tlist,list = new ArrayList();
       
        // iterate through the DataItems in our internal list
        Iterator<DataItem> it = dataItems.iterator();
        while (it.hasNext()) {
            DataItem item = it.next();
           
            // depending on the mode get the required data elements from the
            // DataItem
            if (mode == PARAM && (tlist = item.getParameters()) != null)
                list.addAll(tlist);
            else if (mode == ALL && (tlist = item.getAllElements()) != null)
                list.addAll(tlist);
            else if (mode == SELECTED && (tlist = item.getSelectedElements()) != null)
                list.addAll(tlist);
        }
       
        if (list.size() == 0)
            return null;
       
        return list;
    }
   
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getParameters()
     */
    public ArrayList getParameters() {
        return getElements(PARAM);
    }
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getAllElements()
     */
    public ArrayList getAllElements() {
        return getElements(ALL);
    }
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getSelectedElements()
     */
    public ArrayList getSelectedElements() {
        return getElements(SELECTED);
    }
    
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getComponent()
     */
    public abstract Component getComponent();

    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getNameValuePair()
     */
    public NameValuePair getNameValuePair() {
            return null;
    }

    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#updateData(java.util.ArrayList, java.lang.String)
     */
    public void updateData(ArrayList params,String action) {
        updateItemData(params,action);
    }
   
    /**
     * The user has clicked a print button.  Print all of the DataItems on this TabContainer.
     * This prints each DataItem as a separate print job and needs fixing to print all the
     * DataItems in a single print job so they appear on the same page(s) as the other
     * DataItems on the TabContainer.
     */
    public void printElements() {

        // iterate through the DataItems in our internal list and print them
        for(int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem) dataItems.elementAt(i);
           
            // we don't print hidden DataItems
            if (item instanceof HiddenDataItem)
                continue;
           
            printPrintable(item.getPrintable());
        }
       
        /*
         *
         * This is the code that we should use to print the DataItems on this list
         *
        if (dataItems.size() == 1) {
            DataItem item = (DataItem) dataItems.elementAt(0);
            printPrintable(item.getPrintable());
            return;
        }
       
        ComponentListPrinter list = new ComponentListPrinter();
       
        // copy the printable components
        for(int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem) dataItems.elementAt(i);
            Object o = item.getPrintableComponent();
           
            if (o != null) {
                if (o instanceof ArrayList)
                    list.addComponents((ArrayList)o);
                else
                    list.addComponent((Component)o);
            }
        }
        printPrintable(list);
        */
    }
   
    /**
     * Create a print job with the printable component and send it to the printer.
     *
     * @param printable the component Printable to print.
     *
     * @see {link java.awt.print.PrinterJob}
     */
    protected void printPrintable(Printable printable) {
       
        if (printable == null)
            return;
       
        // wrap in a try/finally so state can be restored even if something fails
        try {
           
            // fetch a PrinterJob
            PrinterJob job = PrinterJob.getPrinterJob();

            // set the Printable on the PrinterJob
            job.setPrintable(printable);

            // create an attribute set to store attributes from the print dialog
            PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();

            // set any attributes here
           
           
            // display a print dialog and record whether or not the user cancels it
            boolean printAccepted = job.printDialog(attr);

            // if the user didn't cancel the dialog do the print job
            if (printAccepted) {
                setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                // do the printing (may need to handle PrinterException)
                job.print(attr);
            }
        } catch (PrinterException ex) {
            // something bad happened so let the user know
            errorMessage(Messages.getString("Tab.24")); //$NON-NLS-1$
       
        } finally {
            // restore the original state here (for example, restore selection)
            setCursor( Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }
    /* (non-Javadoc)
     * @see org.ribax.ui.DataItem#getTypeName()
     */
    public abstract String getTypeName() ;
}
TOP

Related Classes of org.ribax.ui.TabContainer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.