/*******************************************************************************
* Copyright (c) Emil Crumhorn - Hexapixel.com - emil.crumhorn@gmail.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* emil.crumhorn@gmail.com - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.ganttchart;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.eclipse.nebula.widgets.ganttchart.undoredo.commands.EventMoveCommand;
import org.eclipse.nebula.widgets.ganttchart.undoredo.commands.EventResizeCommand;
import org.eclipse.nebula.widgets.ganttchart.undoredo.commands.IUndoRedoCommand;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Menu;
/**
* One GanttEvent represents one "active" object in the GANTT chart.
* <p>
* This object can take many shapes, here is a list of a few:<br>
* <ul>
* <li>Normal event
* <li>Checkpoint event
* <li>Scope event
* <li>Image event
* <li>And so on...
* </ul>
* The event may also take revised start and end dates, and can be modified individually to be locked, non-movable,
* non-resizable and much more.
* <p>
* Events <b>may be</b> modified on the fly to become a different object type from the above list. Please do ensure that
* the ALL parameters are set for it to become the new object before you do so.
* <p>
* Once an event has been created, add it onto the GanttChart widget via the addScopeEvent(...) methods available.
* <p>
* <b>Sample Code:</b><br>
* <br>
* <code>
* // make a 10 day long event<br>
* Calendar cStartDate = Calendar.getInstance(Locale.getDefault());<br>
* Calendar cEndDate = Calendar.getInstance(Locale.getDefault());<br>
* cEndDate.add(Calendar.DATE, 10);
* <br><br>
* // we're setting the percentage complete to 50%<br>
* GanttEvent ganttEvent = new GanttEvent(ganttChart, "Event Name", cStartDate, cEndDate, 50);
* <br><br>
* </code> <br>
* <br>
* This class should not be subclassed, do so at your own risk.
*
* @author Emil Crumhorn <a href="mailto:emil.crumhorn@gmail.com">emil.crumhorn@gmail.com</a>
*/
public class GanttEvent extends AbstractGanttEvent implements IGanttChartItem, Cloneable {
/*
* public static final int TYPE_EVENT = 0; public static final int TYPE_CHECKPOINT = 1; public static final int TYPE_IMAGE = 2; public static final int TYPE_SCOPE = 3;
*/
public static final int FIXED_ROW_HEIGHT_AUTOMATIC = -1;
private Object _data;
private String _name;
private Calendar _revisedStart;
private Calendar _revisedEnd;
private Calendar _startDate;
private Calendar _endDate;
private int _percentComplete;
private boolean _checkpoint;
private boolean _scope;
private boolean _locked;
private boolean _image;
private boolean _resizable = true;
private boolean _moveable = true;
private int _x, _y, _width, _height;
private int _earliestStartX, _latestEndX, _actualWidth;
private Color _statusColor;
private Color _gradientStatusColor;
private boolean _showBoldText;
private String _textDisplayFormat;
private List _scopeEvents;
private Image _picture;
private Menu _menu;
private GanttChart _parentChart;
private GanttComposite _parentComposite;
private GanttGroup _ganttGroup;
private GanttSection _ganttSection;
private boolean _hidden;
private int _widthWithtText;
// TODO: Implement. Less constructors, more user power.
// private int mEventType = TYPE_EVENT;
private AdvancedTooltip _advancedTooltip;
private int _visibility;
private boolean _boundsHaveBeenSet;
private int _fixedRowHeight = FIXED_ROW_HEIGHT_AUTOMATIC;
private int _verticalEventAlignment = SWT.TOP;
private int _horizontalLineTopY;
private int _horizontalLineBottomY;
private Calendar _noMoveBeforeDate;
private Calendar _noMoveAfterDate;
// private items
private boolean _nameChanged = true;
private Point _nameExtent;
private String _parsedString;
private int _horizontalTextLocation = SWT.RIGHT;
private int _verticalTextLocation = SWT.CENTER;
private boolean _showText = true;
private Font _textFont;
private int _daysBetweenStartAndEnd;
// cloned holders used for cancelling a move/resize via ESC
private Calendar _preMoveDateEstiStart;
private Calendar _preMoveDateEstiEnd;
private Calendar _preMoveDateRevisedStart;
private Calendar _preMoveDateRevisedEnd;
private Rectangle _preMoveBounds;
private boolean _moving;
private int _moveType;
private int _preMoveGanttSectionIndex;
private int _preMoveGanttSectionEventLocationIndex;
private GanttEvent _scopeParent;
private int _dDayStart;
private int _dDayEnd;
private int _savedVerticalDragY;
private Rectangle _preVerticalDragBounds;
/**
* Creates a new GanttEvent.
*
* @param parent Parent chart
* @param name Name of event
* @param startDate Start date
* @param endDate End date
* @param percentComplete Percent complete
*/
public GanttEvent(final GanttChart parent, final String name, final Calendar startDate, final Calendar endDate, final int percentComplete) {
this(parent, null, name, startDate, endDate, percentComplete);
}
/**
* Creates a new GanttEvent object.
*
* @param parent Parent chart
* @param data Data object
* @param name Name of event
* @param startDate Start date
* @param endDate End date
* @param percentComplete Percent complete
*/
public GanttEvent(final GanttChart parent, final Object data, final String name, final Calendar startDate, final Calendar endDate, final int percentComplete) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._data = data;
this._name = name;
this._startDate = startDate;
this._endDate = endDate;
this._percentComplete = percentComplete;
init(); // NOPMD
}
/**
* Creates a new GanttEvent.
*
* @param parent Parent chart
* @param name Name of event
* @param startDate Start date
* @param endDate End date
* @param revisedStart Revised start
* @param revisedEnd Revised end
* @param percentComplete Percent complete
*/
public GanttEvent(final GanttChart parent, final String name, final Calendar startDate, final Calendar endDate, final Calendar revisedStart, final Calendar revisedEnd, final int percentComplete) {
this(parent, null, name, startDate, endDate, revisedStart, revisedEnd, percentComplete);
}
/**
* Creates a new GanttEvent object with revised start and end dates.
*
* @param parent Parent GanttChart
* @param data Data object
* @param name Display name
* @param startDate Start date
* @param endDate End date
* @param revisedStart Revised start date
* @param revisedEnd Revised end date
* @param percentComplete Percentage complete
*/
public GanttEvent(final GanttChart parent, final Object data, final String name, final Calendar startDate, final Calendar endDate, final Calendar revisedStart, final Calendar revisedEnd, final int percentComplete) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._data = data;
this._name = name;
this._startDate = startDate;
this._endDate = endDate;
this._revisedStart = revisedStart;
this._revisedEnd = revisedEnd;
this._percentComplete = percentComplete;
init(); // NOPMD
}
/**
* D-day event creation.
*
* @param parent Parent chart
* @param dDayStart D day start value (zero based)
* @param dDayEnd D day end value (zero based)
*/
public GanttEvent(final GanttChart parent, final int dDayStart, final int dDayEnd) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._dDayStart = dDayStart;
this._dDayEnd = dDayEnd;
_startDate = _parentChart.getGanttComposite().getDDayCalendar();
_endDate = _parentChart.getGanttComposite().getDDayCalendar();
_startDate.add(Calendar.DATE, _dDayStart);
_endDate.add(Calendar.DATE, _dDayEnd);
init(); // NOPMD
}
/**
* Creates a GanttEvent intended to be a scope.
*
* @param parent Chart parent
* @param name Name of scope
*/
public GanttEvent(final GanttChart parent, final String name) {
this(parent, null, name);
}
/**
* Creates a GanttEvent intended to be a scope.
*
* @param parent Chart parent
* @param data Data object
* @param name Name of scope
*/
public GanttEvent(final GanttChart parent, final Object data, final String name) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._data = data;
this._name = name;
this._scope = true;
try {
init(); // NOPMD
} catch (Exception err) {
SWT.error(SWT.ERROR_UNSPECIFIED, err);
}
}
/**
* Creates a GanttEvent intended to be a checkpoint.
*
* @param parent Chart parent
* @param name Name of checkpoint
* @param date Checkpoint start (and end) date
*/
public GanttEvent(final GanttChart parent, final String name, final Calendar date) {
this(parent, null, name, date);
}
/**
* Creates a GanttEvent intended to be a checkpoint.
*
* @param parent Chart parent
* @param data Data object
* @param name Name of checkpoint
* @param date Start (and end) date
*/
public GanttEvent(final GanttChart parent, final Object data, final String name, final Calendar date) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._data = data;
this._name = name;
this._startDate = date;
this._endDate = date;
this._checkpoint = true;
try {
init(); // NOPMD
} catch (Exception err) {
SWT.error(SWT.ERROR_UNSPECIFIED, err);
}
}
/**
* Creates a GanttEvent intended to be an image.
*
* @param parent Chart parent
* @param name Name of image
* @param date Start (and end) date
* @param picture Image to show
*/
public GanttEvent(final GanttChart parent, final String name, final Calendar date, final Image picture) {
this(parent, null, name, date, picture);
}
/**
* Creates a GanttEvent intended to be an image.
*
* @param parent Chart parent
* @param data Data object
* @param name Name of image
* @param date Start (and end) date
* @param picture Image to show
*/
public GanttEvent(final GanttChart parent, final Object data, final String name, final Calendar date, final Image picture) {
this._parentChart = parent;
this._parentComposite = _parentChart.getGanttComposite();
this._data = data;
this._name = name;
this._startDate = date;
this._endDate = date;
this._picture = picture;
this._image = true;
try {
init(); // NOPMD
} catch (Exception err) {
SWT.error(SWT.ERROR_UNSPECIFIED, err);
}
}
private final void init() {
_scopeEvents = new ArrayList();
_parentComposite.addEvent(this, true);
updateDaysBetweenStartAndEnd();
}
/**
* Returns the currently set data object.
*
* @return Data object
*/
public Object getData() {
return _data;
}
/**
* Sets the current data object.
*
* @param data Data object
*/
public void setData(final Object data) {
this._data = data;
}
/**
* Returns the display name of this event.
*
* @return Display name
*/
public String getName() {
return this._name;
}
/**
* Sets the display name of this event.
*
* @param name Display name
*/
public void setName(final String name) {
this._name = name;
_nameChanged = true;
}
/**
* Returns the start date of this event.
*
* @return Start date
*/
public Calendar getStartDate() {
if (_startDate == null) { return null; }
return DateHelper.getNewCalendar(_startDate);
}
/**
* Returns the revised start date if set, or the start date if not.
*
* @return Start date or null
*/
public Calendar getActualStartDate() {
final Calendar ret = _revisedStart == null ? _startDate : _revisedStart;
return ret == null ? null : DateHelper.getNewCalendar(ret);
}
/**
* Returns the revised end date if set, or the end date if not.
*
* @return End date or null
*/
public Calendar getActualEndDate() {
final Calendar ret = _revisedEnd == null ? _endDate : _revisedEnd;
return ret == null ? null : DateHelper.getNewCalendar(ret);
}
/**
* Returns whatever is the earliest calendar of the start date and the actual start date. If any of them are null,
* whichever has a calendar is returned. If both are null, null is returned.
*
* @return Earliest start date
*/
public Calendar getEarliestStartDate() {
if (_revisedStart == null && _startDate == null) { return null; }
if (_revisedStart == null) { return _startDate; }
if (_startDate == null) { return _revisedStart; }
return _startDate.before(_revisedStart) ? _startDate : _revisedStart;
}
/**
* Returns whatever is the latest calendar of the end date and the actual end date. If any of them are null,
* whichever has a calendar is returned. If both are null, null is returned.
*
* @return Latest end date
*/
public Calendar getLatestEndDate() {
if (_revisedEnd == null && _endDate == null) { return null; }
if (_revisedEnd == null) {
return _endDate;
} else if (_endDate == null) { return _revisedEnd; }
return _endDate.after(_revisedEnd) ? _endDate : _revisedEnd;
}
/**
* Sets the end date of this event.
*
* @param startDate Start date
*/
public void setStartDate(final Calendar startDate) {
if (startDate == null) {
_startDate = startDate;
updateDaysBetweenStartAndEnd();
return;
}
Calendar sDate = DateHelper.getNewCalendar(startDate);
if (_noMoveBeforeDate != null && startDate.before(_noMoveBeforeDate)) { return; }
Calendar aEnd = getActualEndDate();
if (aEnd != null && startDate.after(aEnd)) {
sDate = aEnd;
}
this._startDate = sDate;
updateDaysBetweenStartAndEnd();
}
/**
* Forces the chart to recognize that something within this event has changed and that it needs an update. This
* method will cause a redraw if told to redraw.
*
* @param redraw if to redraw the chart after notifying of changes.
*/
public void update(final boolean redraw) {
_parentComposite.eventDatesChanged(this, redraw);
}
/**
* Returns the end date of this event.
*
* @return End date
*/
public Calendar getEndDate() {
if (_endDate == null) { return null; }
return DateHelper.getNewCalendar(_endDate);
}
/**
* Sets the end date of this event.
*
* @param endDate End date
*/
public void setEndDate(final Calendar endDate) {
if (endDate == null) {
_endDate = endDate;
updateDaysBetweenStartAndEnd();
return;
}
Calendar eDate = DateHelper.getNewCalendar(endDate);
if (_noMoveAfterDate != null && endDate.after(_noMoveAfterDate)) { return; }
Calendar aDate = getActualStartDate();
if (aDate != null && endDate.before(aDate)) {
eDate = aDate;
}
this._endDate = eDate;
updateDaysBetweenStartAndEnd();
}
/**
* Returns the percentage complete of this event.
*
* @return Percentage complete
*/
public int getPercentComplete() {
return _percentComplete;
}
/**
* Sets the percentage complete of this event.
*
* @param percentComplete Percentage complete
*/
public void setPercentComplete(final int percentComplete) {
this._percentComplete = percentComplete;
}
/**
* Returns the individual Menu for this event for which custom events can be created. Custom events will be mixed
* with built-in events (if they exist). The menu will be created on the first get call to this method, any
* subsequent method calls will return the same menu object. Do remember that a menu counts as a handle towards the
* maximum number of handles. If you have very many events, it is probably better to use a different way of creating
* menus, this is merely meant as a convenience.
*
* @return Menu
*/
public Menu getMenu() {
if (_menu == null) {
_menu = new Menu(_parentComposite);
}
return _menu;
}
/**
* Sets the bounds of the event. This is done internally.
*
* @param x x location
* @param y y location
* @param width width of event
* @param height height of event
*/
void setBounds(final int x, final int y, final int width, final int height) {
_boundsHaveBeenSet = true;
this._x = x;
this._y = y;
this._width = width;
this._height = height;
}
/**
* Sets the bounds of the event.
*
* @param bounds New bounds
*/
void setBounds(final Rectangle bounds) {
_boundsHaveBeenSet = true;
this._x = bounds.x;
this._y = bounds.y;
this._width = bounds.width;
this._height = bounds.height;
//if (_name.indexOf("2") > -1)
//System.err.println("Updatebounds " + mName + " " + getBounds());
if (getEarliestStartDate() != null) {
setEarliestStartX(_parentComposite.getStartingXFor(getEarliestStartDate()));
}
if (getLatestEndDate() != null) {
setLatestEndX(_parentComposite.getXForDate(getLatestEndDate()) + _parentComposite.getDayWidth());
}
}
void updateX(final int x) {
this._x = x;
updateOtherXs();
}
private void updateOtherXs() {
if (getEarliestStartDate() != null) {
setEarliestStartX(_parentComposite.getStartingXFor(getEarliestStartDate()));
}
if (getLatestEndDate() != null) {
setLatestEndX(_parentComposite.getXForDate(getLatestEndDate()) + _parentComposite.getDayWidth());
}
}
void updateY(final int y) {
this._y = y;
}
void updateHeight(final int height) {
this._height = height;
}
void updateWidth(final int width) {
this._width = width;
}
/**
* Whether this is a checkpoint or not.
*
* @return true if this is a checkpoint
*/
public boolean isCheckpoint() {
return _checkpoint;
}
/**
* Sets the event to be a checkpoint.
*
* @param checkpoint true if the event should be a checkpoint
*/
public void setCheckpoint(final boolean checkpoint) {
this._scope = false;
this._image = false;
this._checkpoint = checkpoint;
}
/**
* Returns the x location of this event.
*
* @return x location
*/
public int getX() {
return _x;
}
/**
* Returns the ending x location for this event.
*
* @return x end location
*/
public int getXEnd() {
return _x + _width;
}
/**
* Returns the y location of this event.
*
* @return y location
*/
public int getY() {
return _y;
}
/**
* Returns the bottom y of this event.
*
* @return y bottom
*/
public int getBottomY() {
return _y + _height;
}
/**
* Returns the width of this event.
*
* @return width
*/
public int getWidth() {
return _width;
}
/**
* Returns the height of this event.
*
* @return height
*/
public int getHeight() {
return _height;
}
/**
* Returns the revised start date of this event.
*
* @return Revised date
*/
public Calendar getRevisedStart() {
if (_revisedStart == null) { return null; }
return DateHelper.getNewCalendar(_revisedStart);
}
/**
* Sets the revised start date of this event.
*
* @param revisedStart
*/
public void setRevisedStart(final Calendar revisedStart) {
setRevisedDates(revisedStart, null);
}
/**
* Returns the revised end date of this event.
*
* @return revised end date
*/
public Calendar getRevisedEnd() {
if (_revisedEnd == null) { return null; }
return DateHelper.getNewCalendar(_revisedEnd);
}
/**
* Sets the revised end date of this event.
*
* @param revisedEnd Revised end date
*/
public void setRevisedEnd(final Calendar revisedEnd) {
setRevisedDates(null, revisedEnd);
}
/**
* Sets the revised D-day start.
*
* @param dDayStart d-day start.
*/
public void setRevisedStart(final int dDayStart) {
_revisedStart = _parentComposite.getDDayCalendar();
_revisedStart.add(Calendar.DATE, dDayStart);
}
/**
* Sets the revised D-day end.
*
* @param dDayEnd d-day end
*/
public void setRevisedEnd(final int dDayEnd) {
_revisedEnd = _parentComposite.getDDayCalendar();
_revisedEnd.add(Calendar.DATE, dDayEnd);
}
/**
* Sets new revised dates. This is useful when you need to update two dates that move at the same time (such as
* manually doing a move via setDates). Normally each setting of a date would check it against its start date or end
* date to make sure it doesn't overlap. This does too, but at the same time, thus, no oddity in movement will
* appear. This is rather difficult to explain, but if you experience event-length changes when using individual
* start and end date sets that appear at the same time, you probably want to use this method instead.
* <p>
* Either parameter may be null to set just one, but both may not be null
*
* @param revisedStart New revised Start date
* @param revisedEnd New revised End date
*/
private void setRevisedDates(final Calendar revisedStart, final Calendar revisedEnd) {
if (revisedStart == null && revisedEnd == null) { return; }
if (revisedStart != null && getActualEndDate() != null && revisedStart.after(getActualEndDate())) { return; }
if (revisedEnd != null && getActualStartDate() != null && revisedEnd.before(getActualStartDate())) { return; }
if (revisedStart != null) {
_revisedStart = DateHelper.getNewCalendar(revisedStart);
}
if (revisedEnd != null) {
_revisedEnd = DateHelper.getNewCalendar(revisedEnd);
}
// check movement constraints
if (_noMoveBeforeDate != null && revisedStart != null && revisedStart.before(_noMoveBeforeDate)) {
_revisedStart = DateHelper.getNewCalendar(_noMoveBeforeDate);
}
if (_noMoveAfterDate != null && revisedEnd != null && revisedEnd.after(_noMoveAfterDate)) {
_revisedEnd = DateHelper.getNewCalendar(_noMoveAfterDate);
}
updateDaysBetweenStartAndEnd();
// mParentChart.getGanttComposite().eventDatesChanged(this);
}
/**
* When you need to move events manually you may run into issues as one date always has to be set before the other.
* So when you set a new end and start date one is checked for overlap before the other and is thus ignored.
* Sometimes you just want to set the dates and not enforce validation. Do remember, you need to validate the dates
* yourself before setting them. If the start comes after the end or vice versa you will run into serious drawing
* issues and strange behavior.
*
* @param revisedStart New revised start date
* @param validate true if to validate the date as normal, false to just set the date as is.
*/
public void setRevisedStart(final Calendar revisedStart, final boolean validate) {
if (validate) {
setRevisedStart(revisedStart);
} else {
_revisedStart = DateHelper.getNewCalendar(revisedStart);
updateDaysBetweenStartAndEnd();
}
}
/**
* When you need to move events manually you may run into issues as one date always has to be set before the other.
* So when you set a new end and start date one is checked for overlap before the other and is thus ignored.
* Sometimes you just want to set the dates and not enforce validation. Do remember, you need to validate the dates
* yourself before setting them. If the start comes after the end or vice versa you will run into serious drawing
* issues and strange behavior.
*
* @param revisedStart New revised start date
* @param validate true if to validate the date as normal, false to just set the date as is.
*/
public void setRevisedEnd(final Calendar revisedEnd, final boolean validate) {
if (validate) {
setRevisedEnd(revisedEnd);
} else {
_revisedEnd = DateHelper.getNewCalendar(revisedEnd);
updateDaysBetweenStartAndEnd();
}
}
/**
* Another utility method for setting new dates but this method enforces the usual validation. The difference here
* is that you can tell the method in which order the new dates should be set. If you say left to right, the start
* is set first, the end last.
*
* @param revisedStart Revised start date
* @param revisedEnd Revised end date
* @param order <code>SWT.LEFT_TO_RIHT</code> or <code>SWT.RIGHT_TO_LEFT</code>
*/
public void setRevisedDates(final Calendar revisedStart, final Calendar revisedEnd, final int order) {
if (order == SWT.LEFT_TO_RIGHT) {
setRevisedStart(revisedStart);
setRevisedEnd(revisedEnd);
} else {
setRevisedEnd(revisedEnd);
setRevisedStart(revisedStart);
}
updateDaysBetweenStartAndEnd();
}
/**
* Whether this event is locked or not.
*
* @return true if event is locked.
*/
public boolean isLocked() {
return _locked;
}
/**
* Sets whether this event is locked or not.
*
* @param locked true if locked
*/
public void setLocked(final boolean locked) {
this._locked = locked;
}
/**
* Returns the status color used as part of the gradient colors used to draw the event.
*
* @return Gradient color
*/
public Color getGradientStatusColor() {
return _gradientStatusColor;
}
/**
* Sets the status color used as part of the gradient colors used to draw the event.
*
* @param gradientStatusColor Gradient color
*/
public void setGradientStatusColor(final Color gradientStatusColor) {
_gradientStatusColor = gradientStatusColor;
}
/**
* Returns the status color of this event. This is also used for drawing gradients.
*
* @return Status color
*/
public Color getStatusColor() {
return _statusColor;
}
/**
* Sets the status color of this event. This is also used for drawing gradients.
*
* @param statusColor Status color
*/
public void setStatusColor(final Color statusColor) {
_statusColor = statusColor;
}
/**
* Whether to show the display name in bold text or not.
*
* @return true if to show bold text
*/
public boolean showBoldText() {
return _showBoldText;
}
/**
* Sets whether to show the display name in bold text or not.
*
* @param showBoldText Set to true if to show bold text
*/
public void setShowBoldText(final boolean showBoldText) {
_showBoldText = showBoldText;
}
/**
* Returns the bounds of this event (do note that events may have no bounds if they are invisible or hidden and will
* not get actual bounds set until they are shown).
*
* @return Bounds
*/
public Rectangle getBounds() {
return new Rectangle(getX(), getY(), getWidth(), getHeight());
}
/**
* Returns the text display format of this event. Please see ISettings.getTextDisplayFormat() for an overview. If
* this method returns null, whatever is set in the settings will be used.
*
* @return Text format or null
* @see ISettings#getTextDisplayFormat()
*/
public String getTextDisplayFormat() {
return _textDisplayFormat;
}
/**
* Sets the text display format of this event. Please see ISettings.getTextDisplayFormat() for an overview.
*
* @see ISettings#getTextDisplayFormat()
*/
public void setTextDisplayFormat(final String format) {
_textDisplayFormat = format;
}
/**
* Sets this event to be a scope. Don't forget to add events that the scope is supposed to encompass with
* {@link #addScopeEvent(GanttEvent)}.
*
* @param scope
* @see #addScopeEvent(GanttEvent)
*/
public void setScope(final boolean scope) {
_checkpoint = false;
_image = false;
_scope = scope;
if (!scope) {
for (int i = 0; i < _scopeEvents.size(); i++) {
((GanttEvent) _scopeEvents.get(i)).setScopeParent(null);
}
_scopeEvents.clear();
}
}
/**
* Returns whether this is a scope or not.
*
* @return true if scope
*/
public boolean isScope() {
return _scope;
}
/**
* Adds an event that this event should cover if it has been set to be a scope.
*
* @param event GanttEvent to encompass
*/
public void addScopeEvent(final GanttEvent event) {
if (event == this) { return; }
if (_scopeEvents.contains(event)) { return; }
_scopeEvents.add(event);
event.setScopeParent(this);
}
/**
* Removes event that this event encompasses as a scope.
*
* @param event GanttEvent
*/
public void removeScopeEvent(final GanttEvent event) {
_scopeEvents.remove(event);
}
/**
* Returns the list of GanttEvents that the scope encompasses.
*
* @return List of events
*/
public List getScopeEvents() {
return _scopeEvents;
}
private GanttEvent getEarliestOrLatestScopeEvent(final boolean earliest) {
Calendar ret = null;
GanttEvent retEvent = null;
for (int i = 0; i < _scopeEvents.size(); i++) {
final GanttEvent ge = (GanttEvent) _scopeEvents.get(i);
if (earliest) {
if (ret == null) {
ret = ge.getActualStartDate();
retEvent = ge;
continue;
}
if (ge.getActualStartDate().before(ret)) {
ret = ge.getActualStartDate();
retEvent = ge;
}
} else {
if (ret == null) {
ret = ge.getActualEndDate();
retEvent = ge;
continue;
}
if (ge.getActualEndDate().after(ret)) {
ret = ge.getActualEndDate();
retEvent = ge;
}
}
}
return retEvent;
}
/**
* Returns the event that has the earliest date of all events in a scope.
*
* @return Earliest event or null if none
*/
public GanttEvent getEarliestScopeEvent() {
if (!isScope() || _scopeEvents.isEmpty()) { return null; }
return getEarliestOrLatestScopeEvent(true);
}
/**
* Returns the event that has the latest date of all events in a scope.
*
* @return Latest event or null if none
*/
public GanttEvent getLatestScopeEvent() {
if (!isScope() || _scopeEvents.isEmpty()) { return null; }
return getEarliestOrLatestScopeEvent(false);
}
/**
* Returns the picture image for this event.
*
* @return Picture
*/
public Image getPicture() {
return _picture;
}
/**
* Sets the picture image for this event.
*
* @param picture Image picture
*/
public void setPicture(final Image picture) {
this._picture = picture;
}
/**
* Sets this event to be represented by an image.
*
* @param image true if it's an image
*/
public void setImage(final boolean image) {
_checkpoint = false;
_scope = false;
this._image = image;
}
/**
* Returns whether this event is an image representation or not.
*
* @return true if this event is an image representation
*/
public boolean isImage() {
return _image;
}
/**
* Returns what GanttGroup this event belongs to. Grouped events are drawn on the same line. Set null for no group.
*
* @return GanttGroup
*/
public GanttGroup getGanttGroup() {
return _ganttGroup;
}
/**
* Sets what group this event belongs to. Grouped events are drawn on the same line.
*
* @param group GanttGroup or null if none
*/
public void setGanttGroup(final GanttGroup group) {
_ganttGroup = group;
}
/**
* Returns the {@link GanttSection} that this event belongs to, or null if none.
*
* @return Parent {@link GanttSection}
*/
public GanttSection getGanttSection() {
return _ganttSection;
}
/**
* Sets the GanttSection that this event belongs to
*
* @param ganttSection
*/
void setGanttSection(final GanttSection ganttSection) {
_ganttSection = ganttSection;
}
/**
* Sets if this event should be hidden or not. Hidden events are not shown on the chart and the space they normally
* would occupy is free.
*
* @param hidden true to hide event.
*/
public void setHidden(boolean hidden) {
_hidden = hidden;
}
/**
* Returns whether this event is hidden or not. Hidden events are not shown on the chart and the space they normally
* would occupy is free.
*
* @return true if hidden.
*/
public boolean isHidden() {
return _hidden;
}
private void internalSetAllChildrenHidden(final boolean hidden) {
if (_scopeEvents == null) { return; }
for (int i = 0; i < _scopeEvents.size(); i++) {
((GanttEvent) _scopeEvents.get(i)).setHidden(hidden);
}
}
/**
* Hides all children from view. Children only exist on Scoped events.
*
* @see #isHidden()
*/
public void hideAllChildren() {
internalSetAllChildrenHidden(true);
_parentComposite.updateHorizontalScrollbar();
_parentComposite.updateVerticalScrollBar(false);
_parentComposite.heavyRedraw();
}
/**
* Un-hides all children from view. Children only exist on Scoped events.
*
* @see #isHidden()
*/
public void showAllChildren() {
internalSetAllChildrenHidden(false);
_parentComposite.updateHorizontalScrollbar();
_parentComposite.updateVerticalScrollBar(false);
_parentComposite.heavyRedraw();
}
/**
* Returns whether all children are hidden or not. Children only exist on Scoped events.
*
* @return true if all children are hidden.
*/
public boolean isChildrenHidden() {
if (_scopeEvents == null) { return false; }
for (int i = 0; i < _scopeEvents.size(); i++) {
if (!((GanttEvent) _scopeEvents.get(i)).isHidden()) { return false; }
}
return true;
}
/**
* Returns the full right most x value if event has text or images drawn after it.
*
* @return x position
*/
public int getWidthWithText() {
return _widthWithtText;
}
/**
* Sets the full width of the event width and the text and images that come after it.
*
* @param width x width
*/
public void setWidthWithText(final int width) {
this._widthWithtText = width;
}
/**
* Returns the currently set Advanced tooltip, or null if none is set.
*
* @return Advanced tooltip
*/
public AdvancedTooltip getAdvancedTooltip() {
return _advancedTooltip;
}
/**
* Sets the advanced tooltip. If none is set, a default tooltip will be used.
*
* @param advancedTooltip
*/
public void setAdvancedTooltip(final AdvancedTooltip advancedTooltip) {
this._advancedTooltip = advancedTooltip;
}
/**
* Returns the fixed row height in pixels.
*
* @return Fixed row height
*/
public int getFixedRowHeight() {
return _fixedRowHeight;
}
/**
* Sets the fixed row height in pixels.
*
* @param fixedRowHeight Fixed row height
*/
public void setFixedRowHeight(final int fixedRowHeight) {
this._fixedRowHeight = fixedRowHeight;
}
/**
* Whether the row height is calculated automatically or if it's fixed
*
* @return true if automatic
*/
public boolean isAutomaticRowHeight() {
return (getFixedRowHeight() == FIXED_ROW_HEIGHT_AUTOMATIC);
}
/**
* Resets the row height to be calculated automatically should the row height have been set to a specific value.
*/
public void setAutomaticRowHeight() {
setFixedRowHeight(FIXED_ROW_HEIGHT_AUTOMATIC);
}
/**
* Returns the vertical alignment set. Alignments are only valid if the row height is a fixed value.
*
* @return Row alignment, one of <code>SWT.TOP</code>, <code>SWT.CENTER</code>, <code>SWT.BOTTOM</code>. Default is
* <code>SWT.TOP</code>.
*/
public int getVerticalEventAlignment() {
return _verticalEventAlignment;
}
/**
* Sets the vertical alignment for this event. Alignments are only valid if the row height is a fixed value.
*
* @param verticalEventAlignment one of <code>SWT.TOP</code>, <code>SWT.CENTER</code>, <code>SWT.BOTTOM</code>
*/
public void setVerticalEventAlignment(final int verticalEventAlignment) {
this._verticalEventAlignment = verticalEventAlignment;
}
/**
* Whether this event is resizable. If resizing is turned off in the settings this method does nothing.
*
* @return true if resizable. Default is true.
*/
public boolean isResizable() {
return _resizable;
}
/**
* Sets this event to be resizable or not. If resizing is turned off in the settings this method does nothing.
*
* @param resizable true to make event resizable.
*/
public void setResizable(final boolean resizable) {
_resizable = resizable;
}
/**
* Whether this event is moveable. If moving is turned off in the settings this method does nothing.
*
* @return true if moveable. Default is true.
*/
public boolean isMoveable() {
return _moveable;
}
/**
* Sets this event to be moveable or not. If moving is turned off in the settings this method does nothing.
*
* @param resizable true to make event moveable.
*/
public void setMoveable(final boolean moveable) {
_moveable = moveable;
}
/**
* Returns the date prior to which no moves or resizes are allowed. Any events moved towards or across the date mark
* will stop at this mark.
*
* @return Calendar or null.
*/
public Calendar getNoMoveBeforeDate() {
return _noMoveBeforeDate;
}
/**
* Sets the date prior to which no moves or resizes are allowed. Any events moved towards or across the date mark
* will stop at this mark.
*
* @param noMoveBeforeDate Calendar or null.
*/
public void setNoMoveBeforeDate(final Calendar noMoveBeforeDate) {
_noMoveBeforeDate = noMoveBeforeDate;
}
/**
* Returns the date after which no moves or resizes are allowed. Any events moved towards or across the date mark
* will stop at this mark.
*
* @return Calendar or null.
*/
public Calendar getNoMoveAfterDate() {
return _noMoveAfterDate;
}
/**
* Sets the date after which no moves or resizes are allowed. Any events moved towards or across the date mark will
* stop at this mark.
*
* @param noMoveAfterDate Calendar or null.
*/
public void setNoMoveAfterDate(final Calendar noMoveAfterDate) {
_noMoveAfterDate = noMoveAfterDate;
}
/**
* Returns the location where the event text will be displayed. Default is SWT.RIGHT.
*
* @return Event text location
*/
public int getHorizontalTextLocation() {
return _horizontalTextLocation;
}
/**
* Sets the location of where the event text will be displayed. Options are: <code>SWT.LEFT</code>,
* <code>SWT.CENTER</code>, <code>SWT.RIGHT</code>. Center means the text will be drawn inside the event. Default is
* <code>SWT.RIGHT</code>.
*
* @param textLocation Text location, one of <code>SWT.LEFT</code>, <code>SWT.CENTER</code>, <code>SWT.RIGHT</code>.
*/
public void setHorizontalTextLocation(final int textLocation) {
_horizontalTextLocation = textLocation;
}
/**
* Returns the lcoation where the event text will be displayed vertically. Default is <code>SWT.CENTER</code> which
* is right behind the event itself.
*
* @return Vertical text location.
*/
public int getVerticalTextLocation() {
return _verticalTextLocation;
}
/**
* Sets the vertical location where the event text will be displayed. Options are: <code>SWT.TOP</code>,
* <code>SWT.CENTER</code>, <code>SWT.BOTTOM</code>. Default is <code>SWT.CENTER</code>.
*
* @param verticalTextLocation Vertical text location
*/
public void setVerticalTextLocation(final int verticalTextLocation) {
_verticalTextLocation = verticalTextLocation;
}
/**
* Returns the text font to use when drawing the event text. Default is null.
*
* @return Event font
*/
public Font getTextFont() {
return _textFont;
}
/**
* Sets the text font to use when drawing the event text. Default is null. Setting a font will override any flags
* for font settings in the Settings implementation.
*
* @param textFont Font or null.
*/
public void setTextFont(final Font textFont) {
_textFont = textFont;
}
/**
* Removes this item from the chart.
*/
public void dispose() {
_parentComposite.removeEvent(this);
}
public int getActualDDayStart() {
return _revisedStart == null ? getDDayStart() : getDDayRevisedStart();
}
public int getActualDDayEnd() {
return _revisedEnd == null ? getDDayEnd() : getDDayRevisedEnd();
}
/**
* Returns the D-day start value.
*
* @return
*/
public int getDDayStart() {
return _dDayStart;
}
public int getDDayRevisedStart() {
if (_revisedStart == null) { return Integer.MAX_VALUE; }
return (int) DateHelper.daysBetween(_parentComposite.getDDayCalendar(), _revisedStart);
}
public int getDDayRevisedEnd() {
if (_revisedEnd == null) { return Integer.MAX_VALUE; }
return (int) DateHelper.daysBetween(_parentComposite.getDDayCalendar(), _revisedEnd);
}
/**
* Sets the D-day start value.
*
* @param day
*/
public void setDDayStart(final int day) {
_dDayStart = day;
this._startDate = _parentComposite.getDDayCalendar();
_startDate.add(Calendar.DATE, day);
updateDaysBetweenStartAndEnd();
}
public int getDDayEnd() {
return _dDayEnd;
}
public void setDDayEnd(final int day) {
_dDayEnd = day;
this._endDate = _parentComposite.getDDayCalendar();
_endDate.add(Calendar.DATE, day);
updateDaysBetweenStartAndEnd();
}
public int getDDateRange() {
return (int) DateHelper.daysBetween(getStartDate(), getEndDate());
}
public int getRevisedDDateRange() {
return (int) DateHelper.daysBetween(getActualStartDate(), getActualEndDate()) + 1;
}
// internal methods
/**
* This takes any text drawing widths into account and returns the bounds as such
*
* @return Rectangle of bounds
*/
public Rectangle getActualBounds() {
// for starters the bounds are the same as normal, then we add on text widths, planned date widths etc
Rectangle ret = getBounds();
int plannedExtraRight = 0;
int plannedExtraLeft = 0;
boolean usePlannedLeft = false;
boolean usePlannedRight = false;
// if we're showing planned dates, check to see what is further away, the text width or our planned date width
// we save the values and compare to the bonuses calculated for text widths below
if (_parentComposite.isShowingPlannedDates()) {
// note to self: we used to have date checks here, but I can't remember what for, as these checks aren't necessarily valid. Revised vs. Planned
// dates can come before one or another, doesn't matter, we still need offsets, so I took them out as it fixes a reported bug as well (no bugzilla)
if (getStartDate() != null && getRevisedStart() != null) { // && getStartDate().before(getRevisedStart())) {
// this is a negative value as it's to the left
plannedExtraLeft = getX() - _earliestStartX;
}
if (getEndDate() != null && getRevisedEnd() != null) { // && getEndDate().after(getRevisedEnd())) {
plannedExtraRight = _latestEndX - getXEnd() + _parentComposite.getDayWidth();
}
}
// now calculate text widths, later we'll check what takes up the most space, planned dates or text width. Whoever is bigger
// becomes the "bonus" width that we add to the actual bounds
int xExtra = 0, yExtra = 0, wExtra = 0, hExtra = 0;
// TODO: this should take connected/not connected into account
final int textSpacer = _parentChart.getSettings().getTextSpacerConnected();
if (getNameExtent() != null) {
switch (_horizontalTextLocation) {
case SWT.LEFT:
final int extra = getNameExtent().x + textSpacer;
if (plannedExtraLeft > extra) {
usePlannedLeft = true;
}
xExtra -= extra;
wExtra += extra;
usePlannedRight = plannedExtraRight > 0;
break;
case SWT.CENTER:
int start = _width / 2;
start += getNameExtent().x + textSpacer;
if (start > (_x + _width)) {
wExtra += (start - (_x + _width)); // add on the difference
}
if (plannedExtraRight > wExtra) {
usePlannedRight = true;
}
usePlannedLeft = plannedExtraLeft > 0;
break;
case SWT.RIGHT:
wExtra += getNameExtent().x + textSpacer;
if (plannedExtraRight > wExtra) {
usePlannedRight = true;
}
usePlannedLeft = plannedExtraLeft > 0;
break;
default:
break;
}
switch (_verticalTextLocation) {
case SWT.TOP:
yExtra -= getNameExtent().y;
hExtra += getNameExtent().y;
break;
case SWT.CENTER:
if (getNameExtent().y > _height) {
final int diff = _height - getNameExtent().y;
yExtra -= (diff / 2);
hExtra += (diff / 2);
}
break;
case SWT.BOTTOM:
hExtra += getNameExtent().y;
yExtra -= getNameExtent().y;
break;
default:
break;
}
}
if (_parentComposite.isShowingPlannedDates()) {
//System.err.println(plannedExtraLeft + " " + plannedExtraRight + " " + usePlannedLeft + " " + usePlannedRight);
if (usePlannedRight && usePlannedLeft) {
xExtra -= plannedExtraLeft;
wExtra = plannedExtraLeft;
wExtra += plannedExtraRight;
} else {
if (usePlannedRight) {
wExtra = plannedExtraRight + _parentComposite.getDayWidth();
} else if (usePlannedLeft) {
xExtra = -(plannedExtraLeft + _parentComposite.getDayWidth());
wExtra += Math.abs(plannedExtraLeft) + _parentComposite.getDayWidth();
}
}
}
// widths and horizontal
ret.x += xExtra;
ret.width += wExtra;
// heights and vertical
ret.y += yExtra;
ret.height += hExtra;
return ret;
}
// Internal method for calculating the earliest and latest dates of the scope.
void calculateScope() {
Calendar earliest = null;
Calendar latest = null;
float percentage = 0f;
for (int i = 0; i < _scopeEvents.size(); i++) {
final GanttEvent event = (GanttEvent) _scopeEvents.get(i);
if (earliest == null) {
earliest = event.getActualStartDate();
} else {
if (event.getActualStartDate().before(earliest)) {
earliest = event.getActualStartDate();
}
}
if (latest == null) {
latest = event.getActualEndDate();
} else {
if (event.getActualEndDate().after(latest)) {
latest = event.getActualEndDate();
}
}
percentage += (float) event.getPercentComplete();
}
percentage /= (_scopeEvents.isEmpty() ? 1 : _scopeEvents.size());
// allow start/end dates to override if we have zero events
if (earliest == null && _startDate != null) {
earliest = _startDate;
}
if (latest == null && _endDate != null) {
latest = _endDate;
}
setStartDate(earliest);
setEndDate(latest);
setPercentComplete((int) percentage);
updateDaysBetweenStartAndEnd();
}
boolean hasMovementConstraints() {
return (_noMoveAfterDate != null || _noMoveBeforeDate != null);
}
// internal
int getVisibility() {
return _visibility;
}
// internal
void setVisibility(final int visibility) {
this._visibility = visibility;
}
// internal
boolean isBoundsSet() {
return _boundsHaveBeenSet;
}
void setBoundsSet(final boolean set) {
_boundsHaveBeenSet = set;
}
void setHorizontalLineTopY(final int y) {
this._horizontalLineTopY = y;
}
int getHorizontalLineTopY() {
return _horizontalLineTopY;
}
int getHorizontalLineBottomY() {
return _horizontalLineBottomY;
}
void setHorizontalLineBottomY(final int y) {
this._horizontalLineBottomY = y;
}
void setNameChanged(final boolean changed) {
this._nameChanged = changed;
}
boolean isNameChanged() {
return _nameChanged;
}
Point getNameExtent() {
return _nameExtent;
}
void setNameExtent(final Point extent) {
this._nameExtent = extent;
}
String getParsedString() {
return _parsedString;
}
void setParsedString(final String parsed) {
this._parsedString = parsed;
}
int getDaysBetweenStartAndEnd() {
return this._daysBetweenStartAndEnd;
}
private final void updateDaysBetweenStartAndEnd() {
if (getActualStartDate() == null || getActualEndDate() == null) {
_daysBetweenStartAndEnd = -1;
return;
}
_daysBetweenStartAndEnd = (int) DateHelper.daysBetween(getActualStartDate(), getActualEndDate());
if (_parentComposite.getCurrentView() == ISettings.VIEW_D_DAY) {
_dDayStart = (int) DateHelper.daysBetween(_parentComposite.getDDayCalendar(), getStartDate());
_dDayEnd = (int) DateHelper.daysBetween(_parentComposite.getDDayCalendar(), getEndDate());
_dDayStart--;
}
}
void moveStarted(final int moveType) {
if (_moving) { return; }
_moveType = moveType;
if (_startDate != null) {
final Calendar cal = Calendar.getInstance();
cal.setTime(_startDate.getTime());
_preMoveDateEstiStart = cal;
} else {
_preMoveDateEstiStart = null;
}
if (_endDate != null) {
final Calendar cal = Calendar.getInstance();
cal.setTime(_endDate.getTime());
_preMoveDateEstiEnd = cal;
} else {
_preMoveDateEstiEnd = null;
}
if (_revisedStart != null) {
final Calendar cal = Calendar.getInstance();
cal.setTime(_revisedStart.getTime());
_preMoveDateRevisedStart = cal;
} else {
_preMoveDateRevisedStart = null;
}
if (_revisedEnd != null) {
final Calendar cal = Calendar.getInstance();
cal.setTime(_revisedEnd.getTime());
_preMoveDateRevisedEnd = cal;
} else {
_preMoveDateRevisedEnd = null;
}
_preMoveBounds = new Rectangle(_x, _y, _width, _height);
_preMoveGanttSectionIndex = _parentComposite.getGanttSections().indexOf(_ganttSection);
if (_ganttSection != null) {
_preMoveGanttSectionEventLocationIndex = _ganttSection.getEvents().indexOf(this);
}
else {
_preMoveGanttSectionEventLocationIndex = _parentComposite.getEvents().indexOf(this);
}
_moving = true;
}
/**
* Call after a move/resize is done to get the command to undo/redo the latest move/resize
*
* @return Command or null if none of the given move events matched
*/
IUndoRedoCommand getPostMoveOrResizeUndoCommand() {
switch (_moveType) {
case Constants.TYPE_MOVE:
int indexNow = 0;
if (_ganttSection != null) {
indexNow = _ganttSection.getEvents().indexOf(this);
}
else {
indexNow = _parentComposite.getEvents().indexOf(this);
}
GanttSection gs = null;
if (_preMoveGanttSectionIndex > -1
&& _preMoveGanttSectionIndex < _parentComposite.getGanttSections().size() ) {
gs = (GanttSection) _parentComposite.getGanttSections().get(_preMoveGanttSectionIndex);
}
return new EventMoveCommand(this, _preMoveDateEstiStart, _startDate, _preMoveDateEstiEnd, _endDate, _preMoveDateRevisedStart, _revisedStart, _preMoveDateRevisedEnd, _revisedEnd, gs, _ganttSection,
_preMoveGanttSectionEventLocationIndex, indexNow);
case Constants.TYPE_RESIZE_LEFT:
case Constants.TYPE_RESIZE_RIGHT:
return new EventResizeCommand(this, _preMoveDateEstiStart, _startDate, _preMoveDateEstiEnd, _endDate, _preMoveDateRevisedStart, _revisedStart, _preMoveDateRevisedEnd, _revisedEnd);
default:
break;
}
return null;
}
void moveCancelled() {
_moving = false;
_startDate = _preMoveDateEstiStart;
_endDate = _preMoveDateEstiEnd;
_revisedStart = _preMoveDateRevisedStart;
_revisedEnd = _preMoveDateRevisedEnd;
if (_preMoveBounds != null) {
_x = _preMoveBounds.x;
_y = _preMoveBounds.y;
_width = _preMoveBounds.width;
_height = _preMoveBounds.height;
}
}
void moveFinished() {
_moving = false;
}
/**
* Returns the scope parent of this event if it has one.
*
* @return Scope parent
*/
public GanttEvent getScopeParent() {
return _scopeParent;
}
// not external as it's the wrong way to set a scope parent
void setScopeParent(final GanttEvent parent) {
_scopeParent = parent;
}
void setEarliestStartX(final int x) {
_earliestStartX = x;
}
void setLatestEndX(final int x) {
_latestEndX = x;
}
int getEarliestStartX() {
return _earliestStartX;
}
int getLatestEndX() {
return _latestEndX;
}
int getActualWidth() {
return _actualWidth;
}
void updateActualWidth() {
_actualWidth = Math.abs(Math.abs(_latestEndX) - Math.abs(_earliestStartX));
}
void flagDragging() {
_savedVerticalDragY = _y;
_preVerticalDragBounds = new Rectangle(_x, _y, _width, _height);
}
Rectangle getPreVerticalDragBounds() {
return _preVerticalDragBounds;
}
void undoVerticalDragging() {
_y = _savedVerticalDragY;
_preVerticalDragBounds = null;
}
boolean wasVerticallyMovedUp() {
if (_preVerticalDragBounds == null) {
return false;
}
return (_y < _preVerticalDragBounds.y);
}
boolean hasMovedVertically() {
return _y != _savedVerticalDragY;
}
/**
* Reparents this event from the current {@link GanttSection} to a new {@link GanttSection}
*
* @param index index to put event at in new section
* @param newSection new section to put event in
*/
public void reparentToNewGanttSection(final int index, final GanttSection newSection) {
if (_ganttSection != null) {
_ganttSection.removeGanttEvent(this);
newSection.addGanttEvent(index, this);
}
}
public String toString() {
return _name;
}
/**
* Returns the parent {@link GanttChart}
*
* @return {@link GanttChart}
*/
public GanttChart getParentChart() {
return _parentChart;
}
/**
* Returns the parent {@link GanttComposite}
*
* @return {@link GanttComposite}
*/
public GanttComposite getParentComposite() {
return _parentComposite;
}
/**
* Will update planned dates without question or internal checks. This is
* used internally, it's not recommended to be used externally.
*
* @param start
* Date or null
* @param end
* Date or null
*/
public void setNoUpdatePlannedDates(Calendar start, Calendar end) {
_startDate = start == null ? null : (Calendar) start.clone();
_endDate = end == null ? null : (Calendar) end.clone();
updateDaysBetweenStartAndEnd();
}
/**
* Will update revised dates without question or internal checks. This is
* used internally, it's not recommended to be used externally.
*
* @param start
* Date or null
* @param end
* Date or null
*/
public void setNoUpdateRevisedDates(Calendar start, Calendar end) {
_revisedStart = start == null ? null : (Calendar) start.clone();
_revisedEnd = end == null ? null : (Calendar) end.clone();
updateDaysBetweenStartAndEnd();
}
/**
* Clones the GanttEvent and all objects of it (assuming they are cloneable). The clone should be exactly like the
* original except for a possible few internal flags. The clone does not need to be re-added to the chart, but if it
* needs to exist below a certain parent it will need to be re-added to that parent (such as a scope).
*/
public Object clone() throws CloneNotSupportedException { // NOPMD
final GanttEvent clone = new GanttEvent(_parentChart, getName());
if (_endDate != null) {
clone._endDate = (Calendar) _endDate.clone();
}
if (_noMoveAfterDate != null) {
clone._noMoveAfterDate = (Calendar) _noMoveAfterDate.clone();
}
if (_noMoveBeforeDate != null) {
clone._noMoveBeforeDate = (Calendar) _noMoveBeforeDate.clone();
}
if (_preMoveDateEstiStart != null) {
clone._preMoveDateEstiEnd = (Calendar) _preMoveDateEstiEnd.clone();
}
if (_preMoveDateEstiStart != null) {
clone._preMoveDateEstiStart = (Calendar) _preMoveDateEstiStart.clone();
}
if (_preMoveDateRevisedEnd != null) {
clone._preMoveDateRevisedEnd = (Calendar) _preMoveDateRevisedEnd.clone();
}
if (_preMoveDateRevisedStart != null) {
clone._preMoveDateRevisedStart = (Calendar) _preMoveDateRevisedStart.clone();
}
if (_revisedEnd != null) {
clone._revisedEnd = (Calendar) _revisedEnd.clone();
}
if (_revisedStart != null) {
clone._revisedStart = (Calendar) _revisedStart.clone();
}
clone._scopeParent = _scopeParent;
clone._scopeEvents = new ArrayList(_scopeEvents);
if (_startDate != null) {
clone._startDate = (Calendar) _startDate.clone();
}
clone._advancedTooltip = _advancedTooltip;
clone._boundsHaveBeenSet = _boundsHaveBeenSet;
clone._checkpoint = _checkpoint;
clone._data = _data;
clone._daysBetweenStartAndEnd = _daysBetweenStartAndEnd;
clone._dDayEnd = _dDayEnd;
clone._dDayStart = _dDayStart;
clone._fixedRowHeight = _fixedRowHeight;
clone._ganttGroup = _ganttGroup;
clone._gradientStatusColor = _gradientStatusColor;
clone._hidden = _hidden;
clone._horizontalLineBottomY = _horizontalLineBottomY;
clone._horizontalLineTopY = _horizontalLineTopY;
clone._horizontalTextLocation = _horizontalTextLocation;
clone._image = _image;
clone._locked = _locked;
clone._menu = _menu;
clone._moveable = _moveable;
// it's 100% sure a clone is not being moved, we'd rather not have some funky result of matching this variable
clone._moving = false;
clone._nameChanged = _nameChanged;
clone._nameExtent = _nameExtent;
clone._parsedString = _parsedString;
clone._percentComplete = _percentComplete;
clone._picture = _picture;
clone._preMoveBounds = _preMoveBounds;
clone._resizable = _resizable;
clone._scope = _scope;
clone._scopeEvents = new ArrayList(_scopeEvents);
clone._scopeParent = _scopeParent;
clone._showBoldText = _showBoldText;
clone._statusColor = _statusColor;
clone._textDisplayFormat = _textDisplayFormat;
clone._textFont = _textFont;
clone._verticalEventAlignment = _verticalEventAlignment;
clone._verticalTextLocation = _verticalTextLocation;
clone._visibility = _visibility;
clone._widthWithtText = _widthWithtText;
clone._latestEndX = _latestEndX;
clone._earliestStartX = _earliestStartX;
clone._actualWidth = _actualWidth;
clone._savedVerticalDragY = _savedVerticalDragY;
return clone;
}
/**
* @return the _showText
*/
public boolean isShowText() {
return _showText;
}
/**
* @param _showText the _showText to set
*/
public void setShowText(boolean _showText) {
this._showText = _showText;
}
}