General:
I user following libaries for this classes:
- jide-data.jar
- jide-grids.jar
- commons-lang-2.5.jar (Apache commonIO project for using Arrays)
- slqjdbc4.jar (driver for MS-SQL)
Also I used a MS-SQL Server 2008 (R2) for connection and I didnt use a table, I used views for the master/detail tables...
Okay, just start with this class (just copy/past and rename the package):
- Code: Select all
package versuche;
import versuche.QueryGeneral.*;
import org.apache.commons.lang.ArrayUtils;
public class QueryGeneral {
private String masterTableName = null;
private String[] masterTableFields = null;
private String childTableName = null;
private String[] childTableFields = null;
private QueryGeneral childQuery = null;
private boolean hasChild = false;
private boolean childIsQuery = false;
private String[] masterTableFieldsForChild=null;
private String[] childTableFieldsForMaster=null;
private int[] masterTableFieldsForChildIndex=null;
private int[] childTableFieldsForMasterIndex=null;
public QueryGeneral(String tableName) {
this.masterTableName=tableName;
this.masterTableFields=new String[]{"*"};
this.hasChild=false;
this.childIsQuery=false;
this.childTableName=null;
this.childTableFields=ArrayUtils.EMPTY_STRING_ARRAY;
this.childQuery=null;
this.masterTableFieldsForChild=ArrayUtils.EMPTY_STRING_ARRAY;
this.childTableFieldsForMaster=ArrayUtils.EMPTY_STRING_ARRAY;
this.masterTableFieldsForChildIndex=ArrayUtils.EMPTY_INT_ARRAY;
this.childTableFieldsForMasterIndex=ArrayUtils.EMPTY_INT_ARRAY;
}
/**
* @return the masterTableName
*/
public String getMasterTableName() {
return masterTableName;
}
/**
* @param masterTableName the masterTableName to set
*/
public void setMasterTableName(String masterTableName) {
this.masterTableName = masterTableName;
}
/**
* @return the masterTableFields
*/
public String[] getMasterTableFields() {
return masterTableFields;
}
/**
* @param masterTableFields the masterTableFields to set
*/
public void setMasterTableFields(String[] masterTableFields) {
this.masterTableFields = masterTableFields;
}
/**
* @return the childTableName
*/
public String getChildTableName() {
return childTableName;
}
/**
* @param childTableName the childTableName to set
*/
public void setChildTableName(String childTableName) {
this.childTableName = childTableName;
}
/**
* @return the childTableFields
*/
public String[] getChildTableFields() {
return childTableFields;
}
/**
* @param childTableFields the childTableFields to set
*/
public void setChildTableFields(String[] childTableFields) {
this.childTableFields = childTableFields;
}
/**
* @return the childQuery
*/
public QueryGeneral getChildQuery() {
return childQuery;
}
/**
* @param childQuery the childQuery to set
*/
public void setChildQuery(QueryGeneral childQuery) {
this.childQuery = childQuery;
if (childQuery==null) {
this.childIsQuery=false;
}
else {
this.childIsQuery=true;
this.hasChild=true;
}
}
/**
* @return the hasChild
*/
public boolean isHasChild() {
return hasChild;
}
/**
* @param hasChild the hasChild to set
*/
public void setHasChild(boolean hasChild) {
this.hasChild = hasChild;
if (this.hasChild==false) {
this.childQuery=null;
this.childTableName=null;
this.childTableFields=ArrayUtils.EMPTY_STRING_ARRAY;
}
}
/**
* @return the childIsQuery
*/
public boolean isChildIsQuery() {
return childIsQuery;
}
/**
* @param childIsQuery the childIsQuery to set
*/
public void setChildIsQuery(boolean childIsQuery) {
this.childIsQuery = childIsQuery;
if (childIsQuery==false)
this.childQuery=null;
}
/**
* @return the masterTableFieldsForChild
*/
public String[] getMasterTableFieldsForChild() {
return masterTableFieldsForChild;
}
/**
* @param masterTableFieldsForChild the masterTableFieldsForChild to set
*/
public void setMasterTableFieldsForChild(String[] masterTableFieldsForChild) {
this.masterTableFieldsForChild = masterTableFieldsForChild;
}
/**
* @return the childTableFieldsForMaster
*/
public String[] getChildTableFieldsForMaster() {
return childTableFieldsForMaster;
}
/**
* @param childTableFieldsForMaster the childTableFieldsForMaster to set
*/
public void setChildTableFieldsForMaster(String[] childTableFieldsForMaster) {
this.childTableFieldsForMaster = childTableFieldsForMaster;
}
/**
* @return the masterTableFieldsForChildIndex
*/
public int[] getMasterTableFieldsForChildIndex() {
return masterTableFieldsForChildIndex;
}
/**
* @param masterTableFieldsForChildIndex the masterTableFieldsForChildIndex to set
*/
public void setMasterTableFieldsForChildIndex(int[] masterTableFieldsForChildIndex) {
this.masterTableFieldsForChildIndex = masterTableFieldsForChildIndex;
}
/**
* @return the childTableFieldsForMasterIndex
*/
public int[] getChildTableFieldsForMasterIndex() {
return childTableFieldsForMasterIndex;
}
/**
* @param childTableFieldsForMasterIndex the childTableFieldsForMasterIndex to set
*/
public void setChildTableFieldsForMasterIndex(int[] childTableFieldsForMasterIndex) {
this.childTableFieldsForMasterIndex = childTableFieldsForMasterIndex;
}
}
Here comes the TableModel (also just copy/paste) and renaming of the packages:
- Code: Select all
package versuche;
import com.jidesoft.database.DatabaseTableModel;
import com.jidesoft.filter.Filter;
import com.jidesoft.grid.HierarchicalTableModel;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.lang.ArrayUtils;
import versuche.QueryGeneral.*;
public class DataTableJIDETableModel extends DatabaseTableModel implements HierarchicalTableModel {
private Connection connection = null;
private QueryGeneral query = null;
private Filter[] filterGeneral = null;
private int[] filterGeneralColumns = null;
public DataTableJIDETableModel(Connection conn,QueryGeneral query) throws SQLException {
super(conn,query.getMasterTableName());
this.connection=conn;
this.query=query;
this.filterGeneralColumns=ArrayUtils.EMPTY_INT_ARRAY;
this.fillMasterChildData();
}
public boolean hasChild(int arg0) {
return (this.query.getMasterTableFieldsForChildIndex().length>=0)?true:false;
}
public boolean isHierarchical(int arg0) {
return false;
}
public Object getChildValueAt(int arg0) {
return this.query.getMasterTableFieldsForChildIndex();
}
public boolean isExpandable(int arg0) {
return this.hasChild(arg0);
}
private void fillMasterChildData() {
if (query.isHasChild()==false) return;
int[] queryIndexMaster=ArrayUtils.EMPTY_INT_ARRAY;
String[] masterFields=query.getMasterTableFieldsForChild();
for(int i=0;i<this.getColumnCount();i++) {
for(int i1=0;i1<masterFields.length;i1++) {
if (masterFields[i1].equalsIgnoreCase(this.getColumnName(i))==true) {
queryIndexMaster=ArrayUtils.add(queryIndexMaster,i);
}//if(Name==masterFields)
}//for(i1)
}//for(i)
this.query.setMasterTableFieldsForChildIndex(queryIndexMaster);
}//fillMasterChildData
public int[] fillColumnDataIndex(String[] columnNames) {
int[] queryIndex=new int[columnNames.length];
for(int i=0;i<this.getColumnCount();i++) {
for(int i1=0;i1<columnNames.length;i1++) {
if (columnNames[i1].equalsIgnoreCase(this.getColumnName(i))==true) {
queryIndex[i1]=i;
}//if(Name==columnNames)
}//for(i1)
}//for(i)
return queryIndex;
}//fillColumnDataIndex
public void createChildFilter() {
this.setFiltersApplied(false);
for(int i=0;i<this.filterGeneralColumns.length;i++) {
this.setFiltersApplied(true);
this.addFilter(this.filterGeneralColumns[i],this.filterGeneral[i]);
}//for(i)
this.refresh();
}//createChildFilter
public void setFilterGeneral(int[] filterIndex, Filter[] filterGeneral) {
this.filterGeneralColumns=filterIndex;
this.filterGeneral=filterGeneral;
}//setFilterGeneral
}
Here is my implementation of the HierarchicalTableComponentFactory. Also just copy and paste.
- Code: Select all
package versuche;
import com.jidesoft.filter.EqualFilter;
import com.jidesoft.filter.Filter;
import com.jidesoft.grid.HierarchicalTable;
import com.jidesoft.grid.HierarchicalTableComponentFactory;
import com.jidesoft.grid.ListSelectionModelGroup;
import com.jidesoft.grid.TreeLikeHierarchicalPanel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseWheelListener;
import java.sql.Connection;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.apache.commons.lang.ArrayUtils;
import versuche.QueryGeneral.*;
public class JIDEHierarchicalTableComponentFactory implements HierarchicalTableComponentFactory {
private QueryGeneral query = null;
private Connection connection = null;
public JIDEHierarchicalTableComponentFactory(Connection conn, QueryGeneral query) {
this.connection=conn;
this.query=query;
}//JIDEHierarchicalTableComponentFactory
public Component createChildComponent(HierarchicalTable table, Object value, int row) {
System.out.println("Opening child mit value:"+value);
if (value == null)
return new JPanel();
int[] valueNew=(int[])value;
if (valueNew.length<=0)
return new JPanel();
try {
String filterName = "GENERALCHILDFILTER";
Filter[] filter = null;
int[] index = ArrayUtils.EMPTY_INT_ARRAY;
HirarchicalTable childTable = new HirarchicalTable(this.connection, this.query.getChildQuery());
DataTableJIDETableModel model=(DataTableJIDETableModel)childTable.getTable().getModel();
int[] fieldsMaster=this.query.getMasterTableFieldsForChildIndex();
int[] fieldsChild=model.fillColumnDataIndex(this.query.getChildTableFieldsForMaster());
for(int i=0;i<fieldsMaster.length;i++) {
Object valueMaster=table.getValueAt(row, fieldsMaster[i]);
filter=(Filter[])ArrayUtils.add(filter,new EqualFilter(filterName,valueMaster));
index=ArrayUtils.add(index, fieldsChild[i]);
}//for(i)
model.setFilterGeneral(index, filter);
model.createChildFilter();
FitScrollPane pane=new FitScrollPane(childTable.getTable());
TreeLikeHierarchicalPanel treeLikeHierarchicalPanel = new TreeLikeHierarchicalPanel(pane);
return treeLikeHierarchicalPanel;
} catch (Exception ex) {
return new JPanel();
}
}//createChildComponent
public void destroyChildComponent(HierarchicalTable table, Component component, int row) {
//System.out.println("Destroy:"+component);
}//destroyChildComponent
}
class FitScrollPane extends JScrollPane implements ComponentListener {
public FitScrollPane() {
initScrollPane();
}
public FitScrollPane(Component view) {
super(view);
initScrollPane();
}
public FitScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
super(view, vsbPolicy, hsbPolicy);
initScrollPane();
}
public FitScrollPane(int vsbPolicy, int hsbPolicy) {
super(vsbPolicy, hsbPolicy);
initScrollPane();
}
private void initScrollPane() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
getViewport().getView().addComponentListener(this);
removeMouseWheelListeners();
}
// remove MouseWheelListener as there is no need for it in FitScrollPane.
private void removeMouseWheelListeners() {
MouseWheelListener[] listeners = getMouseWheelListeners();
for (MouseWheelListener listener : listeners) {
removeMouseWheelListener(listener);
}
}
@Override
public void updateUI() {
super.updateUI();
removeMouseWheelListeners();
}
public void componentResized(ComponentEvent e) {
setSize(getSize().width, getPreferredSize().height);
}
public void componentMoved(ComponentEvent e) {
}
public void componentShown(ComponentEvent e) {
}
public void componentHidden(ComponentEvent e) {
}
@Override
public Dimension getPreferredSize() {
getViewport().setPreferredSize(getViewport().getView().getPreferredSize());
return super.getPreferredSize();
}
}
Then the table itself. Should be no problem, just renaming the real packages:
- Code: Select all
package versuche;
import com.jidesoft.filter.EqualFilter;
import com.jidesoft.filter.Filter;
import com.jidesoft.grid.AutoFilterTableHeader;
import com.jidesoft.grid.AutoResizePopupMenuCustomizer;
import com.jidesoft.grid.HierarchicalTable;
import com.jidesoft.grid.RowStripeTableStyleProvider;
import com.jidesoft.grid.TableColumnChooserPopupMenuCustomizer;
import com.jidesoft.grid.TableHeaderPopupMenuInstaller;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.SQLException;
import javax.swing.JTable;
import versuche.QueryGeneral.*;
public class DataTableJIDE extends HierarchicalTable {
private AutoFilterTableHeader header = null;
private Connection connection = null;
private QueryGeneral queryGeneral= null;
public DataTableJIDE(Connection conn, QueryGeneral query) throws SQLException {
super(new DataTableJIDETableModel(conn,query));
this.connection=conn;
this.queryGeneral=query;
this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); //notwendig für horizontalen Scrollbalken
this.setClickCountToStart(100);
this.setColumnSelectionAllowed(false);
//this.setAutoFilter(true);
this.setMasterChildDetail();
}
public void setMasterChildDetail() {
this.setComponentFactory(new JIDEHierarchicalTableComponentFactory(this.connection,this.queryGeneral));
}
public void setAutoFilter(boolean enabled) {
if (enabled==true) {
AutoFilterTableHeader header1=new AutoFilterTableHeader(this);
header1.setAutoFilterEnabled(true);
header1.setShowFilterIcon(true);
header1.setAllowMultipleValues(true);
header1.setShowFilterName(true);
this.setTableHeader(header1);
TableHeaderPopupMenuInstaller installer = new TableHeaderPopupMenuInstaller(this);
installer.addTableHeaderPopupMenuCustomizer(new AutoResizePopupMenuCustomizer());
installer.addTableHeaderPopupMenuCustomizer(new TableColumnChooserPopupMenuCustomizer());
}
else {
this.setAutoFilter(false);
}
}//setAutoFilter
}
Here ist a superclass for Hirarchical Tables. I used this to switch between some table classes...
- Code: Select all
package versuche;
import java.sql.Connection;
import java.sql.SQLException;
import javax.swing.JTable;
import versuche.QueryGeneral.*;
public class HirarchicalTable {
private JTable table = null;
public HirarchicalTable(Connection conn, QueryGeneral query) throws SQLException {
this.table=new DataTableJIDE(conn,query);
}
public JTable getTable() {
return this.table;
}
}
And finally the main class.
Here you have to insert the name of the master/detail table and the connectionfields between these two.
- Code: Select all
package versuche;
import java.awt.Frame;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Connection connection = null;
try {
String masterTable="<NAME OF THE MASTER TABLE/VIEW>";
String detailTable="<NAME OF THE DETAIL TABLE/VIEW>";
String[] masterFieldsJoinWithChild={"<FIELD(S) IN MASTERTABLE WITH CONNECTION TO CHILD TABLE>"};
String[] childFieldsJoinWithMaster={"<FIELD(S) IN CHILDTABLE WITH CONNECTION TO MASTER TABLE>"};
System.out.println("Registering driver");
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
System.out.println("Trying to open the Database...");
connection = DriverManager.getConnection("<HERE THE CONNECTION STRING>");
System.out.println("Database opened...");
System.out.println("Set Master-Detail Query...");
QueryGeneral master=new QueryGeneral(masterTable);
master.setChildTableName(detailTable);
master.setChildTableFieldsForMaster(childFieldsJoinWithMaster);
master.setMasterTableFieldsForChild(masterFieldsJoinWithChild);
QueryGeneral detail=new QueryGeneral(detailTable);
master.setChildQuery(detail);
System.out.println("Opening Hirarchical Table..");
JTable table=new HirarchicalTable(connection,master).getTable();
JFrame frame=new JFrame("TEST");
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
JScrollPane pane=new JScrollPane(table);
frame.add(pane);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}catch(Exception ex) {
try{connection.close();} catch(Exception ex1) {System.out.println("Failure when closing:"+ex1);}
System.out.println("Failure:"+ex);
}
}
}