/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.property;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import com.servoy.j2db.FlattenedSolution;
import com.servoy.j2db.FormController;
import com.servoy.j2db.FormManager;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.component.ComponentFormat;
import com.servoy.j2db.persistence.Column;
import com.servoy.j2db.persistence.ColumnInfo;
import com.servoy.j2db.persistence.ColumnWrapper;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.IColumn;
import com.servoy.j2db.persistence.IDataProvider;
import com.servoy.j2db.persistence.IPersist;
import com.servoy.j2db.persistence.ITable;
import com.servoy.j2db.persistence.Relation;
import com.servoy.j2db.persistence.ScriptCalculation;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.persistence.Table;
import com.servoy.j2db.persistence.IColumnTypes;
import com.servoy.j2db.plugins.ClientPluginAccessProvider;
import com.servoy.j2db.plugins.IClientPluginAccess;
import com.servoy.j2db.smart.J2DBClient;
import com.servoy.j2db.util.Debug;
/**
* Make it possible to set a dataprovider on element
*
* @author jblok
*/
public class DataProviderEditor extends JPanel implements IOptimizedPropertyEditor, ItemListener
{
private boolean showRelatedOptionsOnly = false;
private boolean showColumnsOnly = false;
private String value = null;
protected IApplication application;
protected JList list;
protected JComboBox relationsComboBox;
public DataProviderEditor()
{
this(false);
}
public DataProviderEditor(boolean showToolTips)
{
// main part of the dialog
list = new JList();
list.setCellRenderer(new PropertyListCellRenderer(showToolTips)
{
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof IPersist && component instanceof JLabel)
{
JLabel label = (JLabel)component;
Solution sol = (Solution)((IPersist)value).getRootObject();
if (application.getSolution() != sol)
{
label.setText(label.getText() + " (" + sol.getName() + ")"); //$NON-NLS-1$//$NON-NLS-2$
}
}
else if (value instanceof Column && component instanceof JLabel)
{
((JLabel)component).setText(((Column)value).getTitle());
}
return component;
}
});
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
fireActionEvent();
}
}
});
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(300, 300));
// //XXX: Must do the following, too, or else the scroller thinks
// //XXX: it's taller than it is:
// listScroller.setMinimumSize(new Dimension(250, 80));
// listScroller.setAlignmentX(LEFT_ALIGNMENT);
// Create a container so that we can add a title around
// the scroll pane. Can't add a title directly to the
// scroll pane because its background would be white.
// Lay out the label and scroll pane from top to button.
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.Y_AXIS));
relationsComboBox = new JComboBox();
// base = db.getBase();
// JLabel label = new JLabel("hello");
// listPane.add(comboBox);
listPane.add(Box.createRigidArea(new Dimension(0, J2DBClient.BUTTON_SPACING)));
listPane.add(listScroller);
list.setModel(new DefaultListModel());
// listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
// Lay out the buttons from left to right.
/*
* JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
* buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(setButton);
* buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(cancelButton);
*/
// Put everything together, using the content pane's BorderLayout.
// Container contentPane = getContentPane();
// JPanel borderPanel = new JPanel();
setLayout(new BorderLayout());
// borderPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(relationsComboBox, BorderLayout.NORTH);
add(listPane, BorderLayout.CENTER);
// borderPanel.add(buttonPane, BorderLayout.SOUTH);
// add(borderPanel, BorderLayout.CENTER);
// loadBounds("SelectFieldDialog");
// createItemsInBox();
relationsComboBox.addItemListener(this);
// setButton.requestFocus();
setName("DataProviderEditor");
}
public Relation getRelation()
{
Object item = relationsComboBox.getSelectedItem();
if (item instanceof Relation)
{
return (Relation)item;
}
return null;
}
protected Table definedTable;
protected void fillRelationsComboBox(Relation[] relations) throws Exception
{
boolean relationsAdded = false;
String item = null;
Table table = null;
if (definedTable == null)
{
FormManager fm = (FormManager)application.getFormManager();
FormController fc = fm.getCurrentMainShowingFormController();
if (fc != null)
{
Form form = fc.getForm();
table = form.getTable();
}
}
else
{
table = definedTable;
// definedTable = null;//clear!
}
if (relationsComboBox.getItemCount() > 0) relationsComboBox.removeAllItems();
Iterator it = application.getFlattenedSolution().getRelations(table, true, true);
while (it.hasNext())
{
Relation rel = (Relation)it.next();
if (!showSortableOnly || (showSortableOnly && rel.isUsableInSort()))
{
relationsComboBox.addItem(rel);
relationsAdded = true;
}
}
if (!showRelatedOptionsOnly)
{
String tname = ""; //$NON-NLS-1$
if (table != null) tname = table.getName();
item = "DataProviders for " + tname;
if (relationsComboBox.getModel().getSize() > 0)
{
relationsComboBox.insertItemAt(item, 0);
}
else
{
relationsComboBox.addItem(item);
}
}
if (relations == null)
{
if (item == null)
{
if (relationsComboBox.getModel().getSize() != 0) relationsComboBox.setSelectedIndex(0);
}
else
{
relationsComboBox.setSelectedItem(item);
}
}
else
{
relationsComboBox.setSelectedItem(relations[0]);
}
relationsComboBox.setEnabled(relationsAdded && !showRelatedOptionsOnly);
}
public void setValue(Object v)
{
value = (String)v;
FormManager fm = (FormManager)application.getFormManager();
FormController fc = fm.getCurrentMainShowingFormController();
if (fc != null)
{
Form form = fc.getForm();
if (form != null)
{
try
{
IDataProvider dp = application.getFlattenedSolution().getDataproviderLookup(null, form).getDataProvider(value);
showDataEx(dp);
}
catch (Exception ex)
{
Debug.error(ex);
}
}
}
}
public void showDataEx(IDataProvider dp) throws Exception
{
relationsComboBox.removeItemListener(this);
if (dp instanceof ColumnWrapper)
{
fillRelationsComboBox(((ColumnWrapper)dp).getRelations());
}
else
{
fillRelationsComboBox(relation == null ? null : new Relation[] { relation });
}
relationsComboBox.addItemListener(this);
list.setModel(new DefaultListModel());
fillDataProviderList();
if (dp instanceof ColumnWrapper)
{
dp = ((ColumnWrapper)dp).getColumn();
}
if (dp != null) list.setSelectedValue(dp, true);
}
private Relation relation;
public void setRelation(Relation r) throws Exception
{
relation = r;
}
public void itemStateChanged(ItemEvent e) // for relations Combobox
{
fillDataProviderList();
}
protected void fillDataProviderList()
{
try
{
Table table = null;
if (definedTable == null)
{
FormManager fm = (FormManager)application.getFormManager();
FormController fc = fm.getCurrentMainShowingFormController();
if (fc != null)
{
Form form = fc.getForm();
table = form.getTable();
}
}
else
{
if (!showRelatedOptionsOnly) table = definedTable;
}
DefaultListModel model = (DefaultListModel)list.getModel();
model.removeAllElements();
if (showNoneOption) model.addElement("-none-");
if (!showColumnsOnly) model.addElement("*columns");
Object o = relationsComboBox.getSelectedItem();
if (o != null)
{
if (o instanceof String)
{
// table = form.getTable();
}
else
{
table = ((Relation)o).getForeignTable();
}
if (table != null)
{
Iterator<Column> it = table.getColumnsSortedByName();
while (it.hasNext())
{
Column c = it.next();
ColumnInfo ci = c.getColumnInfo();
if (ci != null && ci.isExcluded())
{
continue;
}
if (hideMediaColumns)
{
// use dataprovider type as defined by column converter
ComponentFormat componentFormat = ComponentFormat.getComponentFormat(null, c, application);
if (componentFormat.dpType == IColumnTypes.MEDIA)
{
continue;
}
}
model.addElement(c);
}
}
}
FlattenedSolution s = application.getFlattenedSolution();
if (table != null && !showColumnsOnly)
{
Iterator it = s.getScriptCalculations(table, true);
if (it.hasNext())
{
model.addElement("*calculations");
}
while (it.hasNext())
{
ScriptCalculation sc = (ScriptCalculation)it.next();
for (int i = 0; i < model.size(); i++)
{
Object obj = model.elementAt(i);
if (obj instanceof IDataProvider)
{
IDataProvider dp = (IDataProvider)obj;
if (dp.getDataProviderID().equals(sc.getDataProviderID()))
{
model.remove(i);// remove the column from the list if use by
// stored calc
break;
}
}
}
model.addElement(sc);
}
Iterator it2 = s.getScriptVariables(true);
if (it2.hasNext())
{
model.addElement("*globals");
}
while (it2.hasNext())
{
model.addElement(it2.next());
}
Iterator it3 = s.getAggregateVariables(table, true);
if (it3.hasNext())
{
model.addElement("*aggregates");
}
while (it3.hasNext())
{
model.addElement(it3.next());
}
}
if (table != null && showColumnsOnly && showSortableOnly)
{
Iterator it3 = s.getAggregateVariables(table, true);
while (it3.hasNext())
{
model.addElement(it3.next());
}
}
if (showGlobalsOption && showColumnsOnly)
{
Iterator it2 = s.getScriptVariables(true);
if (it2.hasNext())
{
model.addElement("*globals");
}
while (it2.hasNext())
{
model.addElement(it2.next());
}
}
}
catch (Exception ex)
{
Debug.error(ex);
}
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener)
{
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener)
{
}
public String getJavaInitializationString()
{
return null;
}
public String[] getTags()
{
return null;
}
public boolean isPaintable()
{
return false;
}
public void paintValue(Graphics gfx, java.awt.Rectangle box)
{
}
public Object getValue()
{
Object retval = null;
Object[] selections = list.getSelectedValues();
IDataProvider[] array = new IDataProvider[selections.length];
for (int i = 0; i < selections.length; i++)
{
Object o = selections[i];
if (o instanceof IDataProvider)
{
Object item = relationsComboBox.getSelectedItem();
if (item instanceof Relation && o instanceof IColumn)
{
array[i] = new ColumnWrapper((IColumn)o, new Relation[] { ((Relation)item) });
}
else
{
array[i] = (IDataProvider)o;
}
}
}
if (selections.length == 1)
{
retval = array[0];
}
else
{
retval = array;
}
if (returnValueAsString)// if used to setDataProviderID
{
if (array != null && array.length != 0 && array[0] != null)
{
retval = array[0].getDataProviderID();
}
else
{
return null;
}
}
relation = null;
return retval;
}
public void setAsText(String text)
{
value = text;
}
public String getAsText()
{
if (value != null)
{
return value;
}
/*
* Form form = application.getFormManager().getCurrentMainShowingForm(); if (form != null && value != null) { try { IDataProvider dp =
* form.getDataProvider(value); if (dp != null) { return dp.getDisplayName(); } } catch(Exception ex) { Debug.error(ex); } }
*/
return "<unknown>";
}
public Component getCustomEditor()
{
return this;
}
public boolean supportsCustomEditor()
{
return true;
}
public void init(IApplication app)
{
application = app;
}
public void init(IClientPluginAccess access)
{
application = ((ClientPluginAccessProvider)access).getApplication();
}
private final ArrayList elist = new ArrayList();
public void addActionListener(ActionListener l)
{
elist.add(l);
}
public void removeActionListener(ActionListener l)
{
elist.remove(l);
}
private void fireActionEvent()
{
ActionEvent ae = null;
Iterator iter = elist.iterator();
while (iter.hasNext())
{
ActionListener listener = (ActionListener)iter.next();
// Lazily create the event:
if (ae == null) ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "OK");
listener.actionPerformed(ae);
}
}
public void setAllowMultipleSelections(boolean b)
{
if (b)
{
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
else
{
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
private boolean showSortableOnly = false;
public void setShowSortableOnly(boolean b)
{
showSortableOnly = b;
}
public void setShowRelatedOnly(boolean b)
{
showRelatedOptionsOnly = b;
}
public void setShowColumnsOnly(boolean b)
{
showColumnsOnly = b;
}
public void setRelatedEnabled(boolean b)
{
relationsComboBox.setEnabled(b);
}
private boolean showNoneOption = true;
public void dontShowNoneOption()
{
showNoneOption = false;
// fillDataProviderList();
}
/**
* Sets the definedTable.
*
* @param definedTable The definedTable to set
*/
public void setDefinedTable(ITable definedTable)
{
this.definedTable = (Table)definedTable;
}
private boolean returnValueAsString = true;
/**
* Sets the returnValueAsString.
*
* @param returnValueAsString The returnValueAsString to set
*/
public void setReturnValueAsString(boolean returnValueAsString)
{
this.returnValueAsString = returnValueAsString;
}
public void prepareForVisible(IApplication app, boolean b)
{
// ignore
}
/**
* @param b
*/
public void setShowGlobals(boolean b)
{
showGlobalsOption = b;
}
private boolean showGlobalsOption = false;
private boolean hideMediaColumns = false;
public void setHideMediaColumns(boolean b)
{
hideMediaColumns = b;
}
}