/*
Copyright 2004-2012 GanttProject Team
This file is part of GanttProject, an opensource project management tool.
GanttProject is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GanttProject 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 Public License for more details.
You should have received a copy of the GNU General Public License
along with GanttProject. If not, see <http://www.gnu.org/licenses/>.
*/
package biz.ganttproject.core.chart.scene.gantt;
import java.util.ArrayList;
import java.util.List;
import biz.ganttproject.core.chart.canvas.Canvas;
import biz.ganttproject.core.chart.canvas.Canvas.HAlignment;
import biz.ganttproject.core.chart.canvas.Canvas.Polygon;
import biz.ganttproject.core.chart.canvas.Canvas.Text;
import biz.ganttproject.core.chart.canvas.Canvas.VAlignment;
import biz.ganttproject.core.chart.scene.BarChartActivity;
import biz.ganttproject.core.option.EnumerationOption;
/**
* This class is responsible for rendering text labels on the sides of task bars.
*
* @author dbarashev (Dmitry Barashev)
*/
public class TaskLabelSceneBuilder<T> {
public static final String ID_TASK_DATES = "taskDates";
public static final String ID_TASK_NAME = "name";
public static final String ID_TASK_LENGTH = "length";
public static final String ID_TASK_ADVANCEMENT = "advancement";
public static final String ID_TASK_COORDINATOR = "coordinator";
public static final String ID_TASK_RESOURCES = "resources";
public static final String ID_TASK_ID = "id";
public static final String ID_TASK_PREDECESSORS = "predecessors";
public static final int UP = 0;
public static final int DOWN = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
private EnumerationOption[] myLabelOptions;
private Canvas myCanvas;
private static List<String> ourInfoList;
private final TaskApi<T> myTaskApi;
private final InputApi myInputApi;
public interface TaskApi<T> {
Object getProperty(T task, String propertyID);
}
public interface InputApi {
EnumerationOption getTopLabelOption();
EnumerationOption getBottomLabelOption();
EnumerationOption getLeftLabelOption();
EnumerationOption getRightLabelOption();
int getFontSize();
}
static {
ourInfoList = new ArrayList<String>();
ourInfoList.add("");
ourInfoList.add(ID_TASK_ID);
ourInfoList.add(ID_TASK_DATES);
ourInfoList.add(ID_TASK_NAME);
ourInfoList.add(ID_TASK_LENGTH);
ourInfoList.add(ID_TASK_ADVANCEMENT);
ourInfoList.add(ID_TASK_COORDINATOR);
ourInfoList.add(ID_TASK_RESOURCES);
ourInfoList.add(ID_TASK_PREDECESSORS);
}
public TaskLabelSceneBuilder(TaskApi<T> taskApi, InputApi inputApi, Canvas canvas) {
myCanvas = canvas;
myTaskApi = taskApi;
myInputApi = inputApi;
myLabelOptions = new EnumerationOption[] { inputApi.getTopLabelOption(), inputApi.getBottomLabelOption(), inputApi.getLeftLabelOption(), inputApi.getRightLabelOption() };
}
public void renderLabels(List<Canvas.Polygon> activityRectangles) {
Polygon lastRectangle = activityRectangles.get(activityRectangles.size() - 1);
if (lastRectangle.isVisible()) {
createRightSideText(lastRectangle);
createDownSideText(lastRectangle);
createUpSideText(lastRectangle);
}
Polygon firstRectangle = activityRectangles.get(0);
if (firstRectangle.isVisible()) {
createLeftSideText(firstRectangle);
}
}
private void createRightSideText(Polygon rectangle) {
BarChartActivity<T> activity = (BarChartActivity<T>) rectangle.getModelObject();
String text = "";
int xText, yText;
text = getTaskLabel(activity.getOwner(), RIGHT);
if (text.length() != 0) {
xText = rectangle.getRightX() + 9;
yText = rectangle.getMiddleY();
Text textPrimitive = processText(xText, yText, text);
textPrimitive.setAlignment(HAlignment.LEFT, VAlignment.CENTER);
}
}
private void createDownSideText(Polygon rectangle) {
BarChartActivity<T> activity = (BarChartActivity<T>) rectangle.getModelObject();
String text = getTaskLabel(activity.getOwner(), DOWN);
if (text.length() > 0) {
int xOrigin = rectangle.getRightX();
int yOrigin = rectangle.getBottomY() + TINY_SPACE;
Text textPrimitive = processText(xOrigin, yOrigin, text);
textPrimitive.setAlignment(HAlignment.RIGHT, VAlignment.TOP);
}
}
private void createUpSideText(Polygon rectangle) {
BarChartActivity<T> activity = (BarChartActivity<T>) rectangle.getModelObject();
String text = getTaskLabel(activity.getOwner(), UP);
if (text.length() > 0) {
int xOrigin = rectangle.getRightX();
int yOrigin = rectangle.getTopY() - TINY_SPACE;
Text textPrimitive = processText(xOrigin, yOrigin, text);
textPrimitive.setAlignment(HAlignment.RIGHT, VAlignment.BOTTOM);
}
}
private void createLeftSideText(Polygon rectangle) {
BarChartActivity<T> activity = (BarChartActivity<T>) rectangle.getModelObject();
String text = getTaskLabel(activity.getOwner(), LEFT);
if (text.length() > 0) {
int xOrigin = rectangle.getLeftX() - 9;
int yOrigin = rectangle.getMiddleY();
Text textPrimitive = processText(xOrigin, yOrigin, text);
textPrimitive.setAlignment(HAlignment.RIGHT, VAlignment.CENTER);
}
}
private Text processText(int xorigin, int yorigin, String text) {
return processText(xorigin, yorigin, text, "text.ganttinfo");
}
private Text processText(int xorigin, int yorigin, String text, String style) {
Text res = getPrimitiveContainer().createText(xorigin, yorigin, text);
res.setStyle(style);
return res;
}
private String getTaskLabel(T task, int position) {
StringBuffer result = new StringBuffer();
Object property = myTaskApi.getProperty(task, myLabelOptions[position].getValue());
if (property != null) {
result.append(property);
}
return result.toString();
}
private Canvas getPrimitiveContainer() {
return myCanvas;
}
public boolean isTextUp() {
return myLabelOptions[UP].getValue() != null && myLabelOptions[UP].getValue().length() != 0;
}
public boolean isTextDown() {
return myLabelOptions[DOWN].getValue() != null && myLabelOptions[DOWN].getValue().length() != 0;
}
boolean isOnlyUp() {
return isTextUp() && !isTextDown();
}
boolean isOnlyDown() {
return isTextDown() && !isTextUp();
}
static final int TINY_SPACE = 2;
static final int MEDIUM_SPACE = 3;
static final int LARGE_SPACE = 4;
public int calculateRowHeight() {
boolean textUP = isTextUp();
boolean textDOWN = isTextDown();
int result;
if (textUP && textDOWN) {
result = getFontHeight() * 3 + 4 * TINY_SPACE;
} else if (textUP || textDOWN) {
result = getFontHeight() * 2 + 3 * MEDIUM_SPACE;
} else {
result = getFontHeight() + 2 * LARGE_SPACE;
}
return result;
}
public void stripVerticalLabelSpace(java.awt.Rectangle nextBounds) {
if (isTextUp()) {
nextBounds.y += getFontHeight();
}
int space;
if (isTextUp() && isTextDown()) {
space = TINY_SPACE * 2;
} else if (!isTextUp() && !isTextDown()) {
space = LARGE_SPACE;
} else if (isTextUp()) {
space = MEDIUM_SPACE * 2;
} else {
space = MEDIUM_SPACE;
}
nextBounds.y += space;
}
public int getFontHeight() {
return myInputApi.getFontSize();
}
}