
xdev.ui.ganttchart.template.XdevGanttTemplate Maven / Gradle / Ivy
package xdev.ui.ganttchart.template;
/*-
* #%L
* XDEV BI Suite
* %%
* Copyright (C) 2011 - 2021 XDEV Software
* %%
* This program 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 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.awt.BorderLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import xdev.db.DBException;
import xdev.ui.XdevMenu;
import xdev.ui.ganttchart.DateGanttVirtualTableSupport;
import xdev.ui.ganttchart.GanttChartVirtualTableRelationSupport;
import xdev.ui.ganttchart.GanttModelUIInformation;
import xdev.ui.ganttchart.UpdateableGanttEntry;
import xdev.ui.ganttchart.action.GanttDateScaleAreaUpdater;
import xdev.ui.ganttchart.action.GanttRelationManagementStrategy;
import xdev.ui.ganttchart.action.GanttTemplateRemoveKeyAdapter;
import xdev.ui.ganttchart.action.UpdateDateRelationManagementStrategy;
import xdev.ui.ganttchart.action.VirtualTableUpdateDateGanttChartPopupMenuCustomizer;
import xdev.ui.ganttchart.action.XdevGanttEntryRelationListener;
import xdev.ui.ganttchart.action.XdevRelationGanttChartPopupMenuCustomizer;
import xdev.ui.ganttchart.editor.XdevGanttChartPopupMenuInstaller;
import xdev.ui.ganttchart.editor.XdevGanttTemplateToolBar;
import xdev.ui.ganttchart.model.GanttPersistence;
import xdev.ui.ganttchart.model.VirtualTableGanttPersistence;
import xdev.ui.ganttchart.model.VirtualTableGanttRelationPersistence;
import xdev.ui.ganttchart.model.XdevGanttEntryVTMappings;
import xdev.ui.ganttchart.utils.DateGanttEntryColumnType;
import xdev.ui.ganttchart.utils.GanttRelationColumnType;
import xdev.ui.ganttchart.utils.VTDateGanttMappingConverter;
import xdev.ui.ganttchart.utils.VTGanttRelationMappingConverter;
import xdev.ui.ganttchart.utils.XdevGanttUtils;
import xdev.vt.VirtualTable;
import xdev.vt.VirtualTable.VirtualTableRow;
import xdev.vt.VirtualTableColumn;
import xdev.vt.VirtualTableException;
import com.jidesoft.gantt.DateGanttChartPane;
import com.jidesoft.gantt.DefaultGanttModel;
import com.jidesoft.gantt.GanttChart;
import com.jidesoft.gantt.GanttChartPane;
import com.jidesoft.gantt.GanttChartPopupMenuCustomizer;
import com.jidesoft.gantt.GanttEntryRelationModel;
import com.jidesoft.gantt.GanttModel;
import com.jidesoft.grid.AutoFilterTableHeader;
import com.jidesoft.grid.TableUtils;
import com.jidesoft.grid.TreeTable;
import com.jidesoft.scale.DatePeriod;
import com.jidesoft.scale.DateScaleModel;
import com.jidesoft.scale.ScaleModel;
/**
* The {@link XdevGanttTemplate} which is a concrete implementation of
* {@link RelationalGanttTemplate} provides a UI representation for project
* data.
*
*
* Use {@link AbstractGanttTemplate} for a fully customizable {@link GanttChart}
* .
*
*
*
* The data is displayed in a {@link GanttChart} on the right hand side, and a
* {@link TreeTable} for more detailed information, at the left hand side.
*
*
*
* Several interaction interfaces allow to update the data on the UI layer at
* runtime.
*
* It is also possible to disable the GanttChartTemplates
* components at runtime, a common use case would be to disable the
* TreeTable
for a better general view.
*
*
*
* @see GanttEntryEditor
* @see GanttChartTemplateTablePopup
* @see ComponentSplitHandler
*
* @author XDEV Software jwill
* @since 4.0
*/
public class XdevGanttTemplate extends AbstractGanttTemplate>
{
public static final String GANTT_PERSISTENCE_STATE = "GANTT_PERSISTENCE_STATE";
/**
* the serialization id.
*/
private static final long serialVersionUID = 1392342401154578284L;
/**
* the default divider location between {@link GanttChart} and
* {@link TreeTable} (GanttChartPane
)
*/
private static final int DEFAULT_DIVIDER_LOCATION = 0;
/**
* a default additional UI adjusting value.
*/
private static int SCROLLBAR_SPACER = 24;
private GanttChartPane> ganttChartPane;
private static final GanttChartVirtualTableRelationSupport> relationSupport = new GanttChartVirtualTableRelationSupport>();
private VirtualTable dataVT;
private Map> mapping;
private final DateGanttVirtualTableSupport support = new DateGanttVirtualTableSupport(
this);
private boolean persistenceState = false;
private boolean useDefaultGanttPopupMenuItems = true;
private PropertyChangeSupport gps = new PropertyChangeSupport(
this);
/**
* If a empty {@link GanttTemplate} is created, the invoke of
* {@link AbstractGanttTemplate}s
* {@link #reInitialize(DefaultGanttModel, VirtualTableGanttDataInformation)}
* method is required to wire the default functionalities.
*/
public XdevGanttTemplate()
{
super();
DefaultGanttModel> dateModel = new DefaultGanttModel>();
dateModel.setScaleModel(DateGanttVirtualTableSupport.DEFAULT_DATE_SCALE_MODEL);
this.ganttChartPane = new DateGanttChartPane>(dateModel);
this.add(this.getGanttChartPane(),BorderLayout.CENTER);
this.initTreeTable();
this.initToolbar();
}
/**
* Constructs a {@link GanttChart} from the given data structure to
* initialize this template.
*
* @param mapping
* the column mapping to identify the relevant data columns.
* @param periods
* the date periods to scale the chart entries.
* @param rootIdentifier
* to initialize the entry tree structure.
* @param autoQuery
* indicates whether the data should be auto queried or not.
* @param vt
* the data provider.
*/
public XdevGanttTemplate(final Map> mapping,
final List periods, final Object rootIdentifier, final boolean autoQuery,
final VirtualTable vt)
{
this.dataVT = vt;
this.mapping = mapping;
try
// code gen cant handle exceptions
{
support.setModel(mapping,vt,rootIdentifier,autoQuery);
}
catch(VirtualTableException e)
{
e.printStackTrace();
}
catch(DBException e)
{
e.printStackTrace();
}
this.init();
}
/**
* Constructs a {@link GanttModel} from the given data structure to
* initialize this template.
*
* @param mapping
* the column mapping to identify the relevant data columns.
* @param vt
* the data provider.
* @param uiInfo
* to scale the template/entries.
* @param rootIdentifier
* to initialize the entry tree structure.
* @param autoQuery
* indicates whether the data should be auto queried or not.
*/
public void setModel(final Map> mapping,
VirtualTable vt, GanttModelUIInformation uiInfo, final Object rootIdentifier,
final boolean autoQuery)
{
this.dataVT = vt;
this.mapping = mapping;
try
// code gen cant handle exceptions
{
this.support.setModel(mapping,vt,uiInfo,rootIdentifier,autoQuery);
}
catch(VirtualTableException e)
{
e.printStackTrace();
}
catch(DBException e)
{
e.printStackTrace();
}
// re init
this.init();
this.getGanttChartPane().getTreeTable()
.addKeyListener(new GanttTemplateRemoveKeyAdapter(this));
}
/**
* Constructs a {@link GanttModel} from the given data structure to
* initialize this template.
*
* @param mapping
* the column mapping to identify the relevant data columns.
* @param vt
* the data provider.
* @param rootIdentifier
* to initialize the entry tree structure.
* @param autoQuery
* indicates whether the data should be auto queried or not.
*/
public void setModel(final Map> mapping,
VirtualTable vt, final Object rootIdentifier, final boolean autoQuery)
{
this.dataVT = vt;
this.mapping = mapping;
try
// code gen cant handle exceptions
{
support.setModel(mapping,vt,rootIdentifier,autoQuery);
}
catch(VirtualTableException e)
{
e.printStackTrace();
}
catch(DBException e)
{
e.printStackTrace();
}
// re init
this.init();
this.getGanttChartPane().getTreeTable()
.addKeyListener(new GanttTemplateRemoveKeyAdapter(this));
}
/**
* Constructs a {@link GanttPersistence} from the given data structure to
* persist the templates data at runtime.
*
* @param mapping
* the column mapping to identify the relevant data columns.
* @param dataVT
* the data persistence container
* @param dbSync
* indicates whether the data should be synchronized at runtime.
* @param rootIdentifier
* to identify the entry tree structure.
*/
public void setGanttPersistence(Map> mapping,
VirtualTable dataVT, boolean dbSync, Object rootIdentifier)
{
XdevGanttEntryVTMappings dataContainer = VTDateGanttMappingConverter
.getEntryColumnMappings(mapping,dataVT);
GanttPersistence> persistence = new VirtualTableGanttPersistence>(
dataContainer,dbSync,rootIdentifier);
this.setGanttPersistence(persistence);
this.gps.firePropertyChange(GANTT_PERSISTENCE_STATE,this.persistenceState,dbSync);
this.persistenceState = dbSync;
}
/**
* Constructs a {@link GanttPersistence} from the given data structure to
* persist the templates data at runtime.
*
* @param mapping
* the column mapping to identify the relevant data columns.
* @param relationVT
* the relation data persistence container.
* @param dbSync
* indicates whether the relation data should be synchronized at
* runtime.
*/
public void setRelationPersistence(Map> mapping,
final VirtualTable relationVT, final boolean dbSync)
{
this.setGanttRelationPersistence(new VirtualTableGanttRelationPersistence>(
VTGanttRelationMappingConverter.getEntryRelationColumnMappings(mapping,relationVT),
dbSync));
}
/**
* {@inheritDoc}
*/
@Override
public void setModel(GanttModel> model)
{
support.setModel(model);
// re init
this.init();
this.getGanttChartPane().getTreeTable()
.addKeyListener(new GanttTemplateRemoveKeyAdapter(this));
}
/**
* Constructs a {@link GanttEntryRelationModel} from the given data
* structure to initialize the entry relations.
*
* @param relationMappings
* the column mapping to identify the relevant data columns.
* @param relationVT
* the data provider.
* @param autoQuery
* indicates whether the data should be auto queried or not.
*/
public void setRelationModel(
Map> relationMappings,
VirtualTable relationVT, boolean autoQuery)
{
if(autoQuery)
{
try
{
relationVT.queryAndFill();
}
catch(VirtualTableException e)
{
e.printStackTrace();
}
catch(DBException e)
{
e.printStackTrace();
}
}
relationSupport.addRelations(getGanttChart(),relationMappings,relationVT);
this.getGanttChart()
.getModel()
.getGanttEntryRelationModel()
.addGanttEntryRelationListener(
new XdevGanttEntryRelationListener>(this));
if(this.isRelationValidation())
{
relationSupport.validateRelationsInitially(this.getGanttChart().getModel(),
this.getGanttEntryRelationManagementStrategy(),this.getGanttPersistence());
}
firePropertyChange(RelationalGanttTemplate.PROPERTY_RELATION_ENABLED,false,true);
}
/**
* {@inheritDoc}
*/
@Override
public GanttRelationManagementStrategy> getGanttEntryRelationManagementStrategy()
{
if(this.getGanttChart() != null)
{
return new UpdateDateRelationManagementStrategy>(this
.getGanttChart().getModel());
}
return new UpdateDateRelationManagementStrategy>();
}
/**
* {@inheritDoc}
*/
@Override
public GanttChartPane> getGanttChartPane()
{
return this.ganttChartPane;
}
/**
* {@inheritDoc}
*/
@Override
public void setGanttChartPane(GanttChartPane> ganttChartPane)
{
this.ganttChartPane = ganttChartPane;
}
/**
* {@inheritDoc}
*/
@Override
public GanttChart> getGanttChart()
{
return this.ganttChartPane.getGanttChart();
}
/**
* Sets the scale periods which define the entry scale.
*
* @param periods
* the date scale periods to set.
*/
public void setScaleModel(List periods)
{
DatePeriod[] periodArray = periods.toArray(new DatePeriod[periods.size()]);
DefaultGanttModel> model = (DefaultGanttModel>)this
.getGanttChart().getModel();
List> entries = XdevGanttUtils.getEntries(model);
if(entries.size() > 0)
{
ScaleModel dateScale = new DateScaleModel(Locale.getDefault(),
XdevGanttUtils.getMinDate(entries),XdevGanttUtils.getMaxDate(entries),
periodArray);
// refresh models
model.setScaleModel(dateScale);
this.getGanttChart().getScaleArea().setScaleModel(dateScale);
this.getGanttChart().getScaleArea().setVisiblePeriods(periods);
}
else
{
ScaleModel dateScale = new DateScaleModel(periodArray);
// refresh models
model.setScaleModel(dateScale);
this.getGanttChart().getScaleArea().setScaleModel(dateScale);
this.getGanttChart().getScaleArea().setVisiblePeriods(periods);
}
// refresh model -> should be done automatically from jides API..
this.getGanttChart().setModel(model);
}
/**
* {@inheritDoc}
*/
@Override
public ScaleModel getScaleModel()
{
return this.getGanttChart().getModel().getScaleModel();
}
/**
* Returns the selected {@link VirtualTableRow} of this component, or
* null
if nothing is selected.
*
* @return the selected {@link VirtualTableRow} of this component
*/
public VirtualTableRow getSelectedVirtualTableRow()
{
return this.support.getSelectedVirtualTableRow(this.dataVT,this.mapping);
}
/**
* Returns the selected {@link VirtualTableRow}s of this component.
*
* @return the selected {@link VirtualTableRow} of this component
*/
public VirtualTableRow[] getSelectedVirtualTableRows()
{
return this.support.getSelectedVirtualTableRows(this.dataVT,this.mapping);
}
/**
* Selects the row if present.
*
* @param row
* the row to select
*/
public void setSelectedVirtualTableRow(VirtualTableRow row)
{
this.support.setSelectedVirtualTableRow(row,this.mapping);
}
/**
* Selects the row if present.
*
* @param rows
* the rows to select
*/
public void setSelectedVirtualTableRows(VirtualTableRow[] rows)
{
this.support.setSelectedVirtualTableRows(rows,this.mapping);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isPersistenceEnabled()
{
return this.persistenceState;
}
// ////// initialization utilities ///////////
/**
* Default initialization.
*/
protected void init()
{
this.add(this.getGanttChartPane(),BorderLayout.CENTER);
this.initUI();
}
/**
* {@link GanttChartPane} UI initialization.
*/
protected void initUI()
{
this.initTreeTable();
this.initToolbar();
this.initDefaultPopup();
if(this.getGanttChart().getEntryCount() > 0)
{
this.getGanttChart().getScaleArea()
.setStart(XdevGanttUtils.getFirstEntryStart(this.getGanttChart()));
this.getGanttChart()
.getScaleArea()
.setEnd(XdevGanttUtils.getMaxDate(XdevGanttUtils.getEntries(this
.getGanttChart().getModel())));
}
this.addGanttModelListener(new GanttDateScaleAreaUpdater(this.getGanttChart().getModel(),
this.getGanttChart().getScaleArea()));
}
/**
* initializes the GanttTemplate
toolbar (UI relation
* creation).
*/
private void initToolbar()
{
this.setToolbar(new XdevGanttTemplateToolBar>(this));
}
/**
* initializes the {@link TreeTable}.
*/
private void initTreeTable()
{
AutoFilterTableHeader header = new AutoFilterTableHeader(this.getGanttChartPane()
.getTreeTable());
header.setUseNativeHeaderRenderer(true);
header.setAutoFilterEnabled(true);
this.getGanttChartPane().getTreeTable().setTableHeader(header);
this.getGanttChartPane().getTreeTable().setDoubleClickEnabled(false);
this.getGanttChartPane().getTreeTable().setShowGrid(true);
this.getGanttChartPane().getTreeTable().setShowHorizontalLines(true);
this.getGanttChartPane().getTreeTable().setShowVerticalLines(true);
this.getGanttChartPane().getTreeTable().setSortable(false);
// initial resize
TableUtils.autoResizeAllColumns(this.getGanttChartPane().getTreeTable());
// listeners
this.getGanttChartPane().getTreeTable().getModel()
.addTableModelListener(new TableModelListener()
{
@Override
public void tableChanged(TableModelEvent e)
{
TableUtils.autoResizeAllColumns(getGanttChartPane().getTreeTable());
}
});
this.initSplitPaneWeight();
}
/**
* {@inheritDoc}
*/
@Override
public void setGanttPopupMenu(XdevMenu ganttPopupMenu)
{
super.setGanttPopupMenu(ganttPopupMenu);
this.initDefaultPopup();
}
/**
* initializes the {@link GanttChartTemplateTablePopup}.
*/
private void initDefaultPopup()
{
XdevGanttChartPopupMenuInstaller installer = new XdevGanttChartPopupMenuInstaller(
this.getGanttChart(),this.getGanttPopupMenu());
if(this.isUseDefaultGanttPopupMenuItems())
{
GanttChartPopupMenuCustomizer relationCustomizer = new XdevRelationGanttChartPopupMenuCustomizer();
VirtualTableUpdateDateGanttChartPopupMenuCustomizer updateCustomizer = new VirtualTableUpdateDateGanttChartPopupMenuCustomizer(
this.mapping,this.dataVT,this.isPersistenceEnabled());
this.addPropertyChangeListener(updateCustomizer);
installer.addGanttChartPopupMenuCustomizer(relationCustomizer);
installer.addGanttChartPopupMenuCustomizer(updateCustomizer);
}
}
/**
* initializes the TemplateSplitPane
.
*/
private void initSplitPaneWeight()
{
this.resizeDivider(0);
this.addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent e)
{
super.componentResized(e);
resizeDivider(DEFAULT_DIVIDER_LOCATION);
}
});
}
/**
* Resizes the divider at the given location to the maximum space that is
* left besides the {@link GanttChart}.
*
* @param divider
* the divider to resize.
*/
private void resizeDivider(final int divider)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
getGanttChartPane().setDividerLocation(
divider,
(int)getGanttChartPane().getTreeTable().getPreferredSize().getWidth()
+ SCROLLBAR_SPACER);
}
});
}
/**
* Displays the default GanttChart persistence actions additionally to a set
* {@link XdevMenu}.
*
* @param useDefaultItems
*/
public void setUseDefaultGanttPopupMenuItems(boolean useDefaultGanttPopupMenuItems)
{
this.useDefaultGanttPopupMenuItems = useDefaultGanttPopupMenuItems;
}
/**
* Displays the default GanttChart persistence actions additionally to a set
* {@link XdevMenu}.
*
* @return use default items state.
*/
public boolean isUseDefaultGanttPopupMenuItems()
{
return this.useDefaultGanttPopupMenuItems;
}
/**
* {@inheritDoc}
*/
@Override
public void setRelationValidation(boolean relationValidation)
{
super.setRelationValidation(relationValidation);
// validate & persist initially
if(this.getGanttChart().getModel().getGanttEntryRelationModel() != null
&& relationValidation)
{
relationSupport.validateRelationsInitially(this.getGanttChart().getModel(),
this.getGanttEntryRelationManagementStrategy(),this.getGanttPersistence());
}
}
/**
* {@inheritDoc}
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener listener)
{
this.gps.addPropertyChangeListener(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener listener)
{
super.removePropertyChangeListener(listener);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy