/**
SpagoBI, the Open Source Business Intelligence suite
Copyright (C) 2012 Engineering Ingegneria Informatica S.p.A. - SpagoBI Competency Center
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at http://mozilla.org/MPL/2.0/.
**/
package it.eng.spagobi.studio.documentcomposition.editors;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.Document;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.DocumentComposition;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.Style;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.bo.ModelBO;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.metadata.MetadataBO;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.metadata.MetadataDocument;
import it.eng.spagobi.studio.documentcomposition.editors.model.documentcomposition.metadata.MetadataStyle;
import it.eng.spagobi.studio.documentcomposition.util.DocCompUtilities;
import it.eng.spagobi.studio.documentcomposition.views.DocumentParametersView;
import it.eng.spagobi.studio.documentcomposition.views.DocumentPropertiesView;
import it.eng.spagobi.studio.documentcomposition.views.NavigationView;
import it.eng.spagobi.studio.utils.util.FileFinder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Designer {
private static long idCounter = 0;
DocumentCompositionEditor editor=null;
private static Logger logger = LoggerFactory.getLogger(Designer.class);
public static synchronized String createID()
{
return String.valueOf(idCounter++);
}
String state=NORMAL;
Integer currentSelection=-1;
int currentX=0;
int currentY=0;
Composite mainComposite;
HashMap<Integer, DocContainer> containers;
String projectName=null;
public static final String NORMAL="normal";
public static final String SELECTION="selection";
public static final String RESIZE="resize";
public static final String DRAG="drag";
public static final int MOUSE_LEFT_KEY=1;
public static final int MOUSE_RIGHT_KEY=3;
public static final int DESIGNER_WIDTH=800;
public static final int DESIGNER_HEIGHT=600;
/**
* Adds a new Document Container in the designer
*
* @param mainComposite
* @param x
* @param y
* @param _width
* @param _height
* @return
*/
public Integer addNewDocContainer(Composite mainComposite, int x, int y, int _width, int _height, boolean isNew){
logger.debug("IN");
// shell check if overlaids or exceeds
int tempWidth=_width;
// tempWidth=tempWidth/DocContainer.ALIGNMENT_MARGIN;
// tempWidth=tempWidth*DocContainer.ALIGNMENT_MARGIN;
int tempHeight=_height;
// tempHeight=tempHeight/DocContainer.ALIGNMENT_MARGIN;
// tempHeight=tempHeight*DocContainer.ALIGNMENT_MARGIN;
Rectangle rectangle=new Rectangle(x,y, tempWidth, tempHeight);
boolean doesExceed=DocContainer.doesExceed(Integer.valueOf(-1), this, x, y, tempWidth, tempHeight, false);
boolean doesIntersect=DocContainer.doesIntersect(Integer.valueOf(-1), this, x, y, tempWidth, tempHeight, false);
if(!isNew){
doesExceed=false;
doesIntersect=false;
}
if(doesExceed==true){
MessageDialog.openWarning(mainComposite.getShell(),
"Warning", "Container you want to insert exceeds shell!");
logger.warn(Designer.class.toString()+": add New Container function: Container exceed shell limits");
return null;
}
if(doesIntersect==true){
MessageDialog.openWarning(mainComposite.getShell(),
"Warning", "Container you want to insert intersects other composites!");
logger.warn(Designer.class.toString()+": add New Container function: Container you want to insert intersects other composites");
return null;
}
DocContainer group=new DocContainer(this, mainComposite, x, y, tempWidth, tempHeight);
containers.put(group.getIdContainer(), group);
Composite g=group.getDocumentContained().getGroup();
mainComposite.layout();
mainComposite.update();
mainComposite.redraw();
mainComposite.setFocus();
logger.debug("OUT");
return group.getIdContainer();
}
/** Add Container reading the template
*
* @param mainComposite
* @param x
* @param y
* @param _width
* @param _height
* @param metadataDocument
*
*
*/
public void addDocContainerFromTemplate(Composite mainComposite, int x, int y, int _width, int _height, MetadataDocument metadataDocument, Document document){
logger.debug("IN");
Integer id=addNewDocContainer(mainComposite, x, y, _width, _height, false);
if(id==null) return;
else{
DocContainer docContainer=containers.get(id);
docContainer.setTitle(metadataDocument!=null ? metadataDocument.getLabel() : "NoDocument");
if(metadataDocument!=null){
docContainer.getDocumentContained().setMetadataDocument(metadataDocument);
//metadataDocument.setIdMetadataDocument(id+"_"+metadataDocument.getLabel());
metadataDocument.setLabel(metadataDocument.getLabel());
//document.setId(id+"_"+metadataDocument.getLabel());
document.setId(metadataDocument.getLabel());
if(docContainer.getDocumentContained()!= null){
DocumentContained docContained = docContainer.getDocumentContained();
docContained.setDocumentLabel(metadataDocument!=null ? metadataDocument.getLabel() : null);
}
}
docContainer.getDocumentContained().viewDocumentMetadata(metadataDocument);
}
logger.debug("OUT");
}
public Designer(Composite composite, DocumentCompositionEditor _editor) {
super();
logger.debug("IN");
FormLayout layout=new FormLayout();
//composite.setLayout(layout);
mainComposite=composite;
setMouseControls(mainComposite);
addContextMenu(mainComposite);
containers=new HashMap<Integer, DocContainer>();
addShellMouseControls(mainComposite);
this.editor=_editor;
logger.debug("OUT");
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Integer getCurrentSelection() {
return currentSelection;
}
public void setCurrentSelection(Integer currentSelection) {
this.currentSelection = currentSelection;
}
/** Track the mous eposition when clicking
*
* @param shell
*/
public void setMouseControls(final Composite shell){
shell.addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent arg0) {
}
public void mouseDown(MouseEvent arg0) {
if(arg0.button==MOUSE_LEFT_KEY){
currentX=arg0.x;
currentY=arg0.y;
}
else if(arg0.button==MOUSE_RIGHT_KEY){
// memorize th eposition of the menu
currentX=arg0.x;
currentY=arg0.y;
}
}
public void mouseUp(MouseEvent arg0) {
}
});
}
/** Add control on mouse events won the shell
*
* @param shell
*/
public void addShellMouseControls(final Composite shell){
logger.debug("IN");
final Point[] offset = new Point[1];
Listener listener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseDown:
/** IF in resizing state mouse button on shell causes end resizing**/
DocContainer selectedDoc=currentSelection.intValue()!=-1 ? containers.get(currentSelection) : null ;
Composite selected=currentSelection.intValue()!=-1 ? containers.get(currentSelection).getDocumentContained().getGroup() : null ;
if(getState().equals(Designer.RESIZE)){
setState(Designer.NORMAL);
offset[0] = null;
Cursor cursor=new Cursor(getMainComposite().getDisplay(), SWT.CURSOR_ARROW);
getMainComposite().setCursor(cursor);
DesignerUtilities designerUtilities=new DesignerUtilities();
//int tempWidth=selected.getBounds().width;
//int tempHeight=selected.getBounds().height;
int setWidth=designerUtilities.calculateWidth(selected, mainComposite.getBounds().width);
int setHeight=designerUtilities.calculateHeight(selected, mainComposite.getBounds().height);
// int tempWidth=selected.getBounds().width;
// tempWidth=tempWidth/DocContainer.ALIGNMENT_MARGIN;
// tempWidth=tempWidth*DocContainer.ALIGNMENT_MARGIN;
// int tempHeight=selected.getBounds().height;
// tempHeight=tempHeight/DocContainer.ALIGNMENT_MARGIN;
// tempHeight=tempHeight*DocContainer.ALIGNMENT_MARGIN;
selected.setSize(setWidth, setHeight);
DocContainer docContainerSelected=containers.get(currentSelection);
docContainerSelected.reloadStyleDocumentProperties();
// Update only if document is present
if(selectedDoc.getDocumentContained().getMetadataDocument()!=null){
(new ModelBO()).updateModelModifyDocument(selectedDoc.getDocumentContained().getMetadataDocument(), selectedDoc.calculateTemplateStyle(false));
}
if(selectedDoc.getDocumentContained()!=null && selectedDoc.getDocumentContained().getMetadataDocument()!=null){
selectedDoc.getDocumentContained().drawImage();
}
setCurrentSelection(new Integer(-1));
if(selected!=null){
selected.setBackground(new Color(selected.getDisplay(), DocContainer.COLOR_CONTAINERS));
}
editor.setIsDirty(true);
}
/** IF in Selection state mouse button on shell causes end selection**/
else if(getState().equals(Designer.SELECTION)){
setState(Designer.NORMAL);
offset[0] = null;
setCurrentSelection(new Integer(-1));
if(selected!=null){
selected.setBackground(new Color(selected.getDisplay(), DocContainer.COLOR_CONTAINERS));
}
// set Views Invisible
IViewPart viewPart=DocCompUtilities.getViewReference(DocCompUtilities.DOCUMENT_PROPERTIES_VIEW_ID);
if(viewPart!=null)((DocumentPropertiesView)viewPart).setVisible(false);
IViewPart viewPart2=DocCompUtilities.getViewReference(DocCompUtilities.DOCUMENT_PARAMETERS_VIEW_ID);
if(viewPart2!=null)((DocumentParametersView)viewPart2).setTableVisible(false);
}
break;
case SWT.MouseMove:
/** IF in resizing state mouse moving on shell causes resizing**/
DocContainer selectedDoc1=currentSelection.intValue()!=-1 ? containers.get(currentSelection) : null ;
if(selectedDoc1 != null){
Composite selected1=selectedDoc1.getDocumentContained().getGroup();
if(getState().equals(Designer.RESIZE)){
if(selected1!=null){
Rectangle rect=selected1.getBounds();
int x=event.x;
int y=event.y;
int nuova_larghezza=rect.width;
int nuova_altezza=rect.height;
if(x>rect.x+rect.width){
nuova_larghezza=rect.width+(x-rect.x-rect.width);
//selected1.setSize(nuova_larghezza, rect.height);
}
if(y>rect.y+rect.height){
nuova_altezza=rect.height+(y-rect.y-rect.height);
}
// check if intersects other components
boolean doesIntersect=DocContainer.doesIntersect(selectedDoc1.getIdContainer(), selectedDoc1.getDesigner(),selectedDoc1.getDocumentContained().getGroup().getLocation().x, selectedDoc1.getDocumentContained().getGroup().getLocation().y, nuova_larghezza,nuova_altezza, true);
// check if exceeds bounds
boolean doesExceed=DocContainer.doesExceed(selectedDoc1.getIdContainer(), selectedDoc1.getDesigner(),selectedDoc1.getDocumentContained().getGroup().getLocation().x, selectedDoc1.getDocumentContained().getGroup().getLocation().y, nuova_larghezza,nuova_altezza, true);
if(doesIntersect==false && doesExceed==false){
selected1.setSize(nuova_larghezza, nuova_altezza);
// Update model if document is present
if(selectedDoc1.getDocumentContained().getMetadataDocument()!=null){
(new ModelBO()).updateModelModifyDocument(selectedDoc1.getDocumentContained().getMetadataDocument(), selectedDoc1.calculateTemplateStyle(false));
}
editor.setIsDirty(true);
}
//shell.redraw();
}
}
else if(getState().equals(Designer.DRAG)){
if(selectedDoc1.getIdContainer().equals(selectedDoc1.getDesigner().getCurrentSelection())){
if (offset[0] != null) {
Point pt = offset[0];
int newX=event.x - pt.x;
int newY=event.y - pt.y;
boolean doesIntersect=DocContainer.doesIntersect(selectedDoc1.getIdContainer(), selectedDoc1.getDesigner(),newX, newY, selectedDoc1.getDocumentContained().getGroup().getBounds().width,selectedDoc1.getDocumentContained().getGroup().getBounds().height,true);
boolean doesExceed=DocContainer.doesExceed(selectedDoc1.getIdContainer(), selectedDoc1.getDesigner(),newX, newY, selectedDoc1.getDocumentContained().getGroup().getBounds().width,selectedDoc1.getDocumentContained().getGroup().getBounds().height,true);
if(doesIntersect==false && doesExceed==false){
selectedDoc1.getDocumentContained().getGroup().setLocation(newX, newY);
// Update model if document is present
if(selectedDoc1.getDocumentContained().getMetadataDocument()!=null){
(new ModelBO()).updateModelModifyDocument(selectedDoc1.getDocumentContained().getMetadataDocument(), selectedDoc1.calculateTemplateStyle(false));
}
editor.setIsDirty(true);
}
}
}
}
}
break;
case SWT.MouseUp:
// Composite selectedDoc2=currentSelection.intValue()!=-1 ? containers.get(currentSelection).getContainer() : null ;
// if(getState().equals(Designer.DRAG)){
// int tempX=selectedDoc2.getLocation().x;
// tempX=tempX/DocContainer.ALIGNMENT_MARGIN;
// tempX=tempX*DocContainer.ALIGNMENT_MARGIN;
// int tempY=selectedDoc2.getLocation().y;
// tempY=tempY/DocContainer.ALIGNMENT_MARGIN;
// tempY=tempY*DocContainer.ALIGNMENT_MARGIN;
// selectedDoc2.setLocation(tempX, tempY);
//
// }
break;
}
}
};
mainComposite.addListener(SWT.MouseDown, listener);
mainComposite.addListener(SWT.MouseUp, listener);
mainComposite.addListener(SWT.MouseMove, listener);
logger.debug("OUT");
}
/** Add the context menu
*
* @param composite
*/
public void addContextMenu(final Composite composite){
logger.debug("IN");
composite.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
Menu menu = new Menu(composite.getShell(), SWT.POP_UP);
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText("Add Doc");
item.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
if(getState().equals(Designer.NORMAL)){
addNewDocContainer(composite, currentX, currentY, DocContainer.DEFAULT_WIDTH+50, DocContainer.DEFAULT_HEIGHT+50, true);
editor.setIsDirty(true);
}
}
});
menu.setLocation(event.x, event.y);
menu.setVisible(true);
while (!menu.isDisposed() && menu.isVisible()) {
if (!composite.getDisplay().readAndDispatch())
composite.getDisplay().sleep();
}
menu.dispose();
}
});
logger.debug("OUT");
}
public int getCurrentX() {
return currentX;
}
public void setCurrentX(int currentX) {
this.currentX = currentX;
}
public int getCurrentY() {
return currentY;
}
public void setCurrentY(int currentY) {
this.currentY = currentY;
}
public HashMap<Integer, DocContainer> getContainers() {
return containers;
}
public void setContainers(HashMap<Integer, DocContainer> containers) {
this.containers = containers;
}
public Composite getMainComposite() {
return mainComposite;
}
public void setMainComposite(Composite mainComposite) {
this.mainComposite = mainComposite;
}
public DocumentCompositionEditor getEditor() {
return editor;
}
public void setEditor(DocumentCompositionEditor editor) {
this.editor = editor;
}
/**
* Initizialize the designer by the template
* @param documentComposition
*/
public void initializeDesigner(DocumentComposition documentComposition){
logger.debug("IN");
if(documentComposition == null ||
documentComposition.getDocumentsConfiguration()==null
|| (documentComposition.getDocumentsConfiguration()!= null && documentComposition.getDocumentsConfiguration().getDocuments()==null)
|| (documentComposition.getDocumentsConfiguration()!= null && documentComposition.getDocumentsConfiguration().getDocuments()!=null && documentComposition.getDocumentsConfiguration().getDocuments().size()==0)){
return;
}
Vector<Document> documentsToIterate=new Vector<Document>(documentComposition.getDocumentsConfiguration().getDocuments());
// Run all the documents, for each one calculate the style and search for paramters..
for (Iterator iterator = documentsToIterate.iterator(); iterator.hasNext();) {
Document document = (Document) iterator.next();
String sbiObjectLabel = document.getSbiObjLabel();
MetadataStyle metadataStyle=null;
// Recover style informations!
try{
Style styleS=document.getStyle();
metadataStyle=new MetadataStyle(styleS);
}
catch (Exception e) {
MessageDialog.openError(mainComposite.getShell(),
"Error", "Error in retrieving positioning metadata for the document with label "+sbiObjectLabel);
logger.error("END "+Designer.class.toString()+": Initialize designer function: " +
"Error in retrieving positioning metadata for the file with name "+sbiObjectLabel);
new ModelBO().deleteDocumentFromModel(document);
continue;
}
String localFileName = "";
try{
// Recover documentInformations from File
localFileName=document.getLocalFileName();
MetadataDocument metadataDocument=null;
if(localFileName!=null){
// search for the right file
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IPath workspacePath=root.getLocation();
IProject project = root.getProject(getProjectName());
IPath projectLocation=project.getLocation();
IPath pathRetrieved=FileFinder.retrieveFile(localFileName, projectLocation.toString(), workspacePath);
if(pathRetrieved != null){
IFile fileToGet = ResourcesPlugin.getWorkspace().getRoot().getFile(pathRetrieved);
if(fileToGet.exists()){
// not put yet Id beacuase not linked yet to the group; create the metadata document from FIles METADATA
// add the metadata document to the metadata container
metadataDocument=new MetadataDocument(fileToGet);
(new MetadataBO()).getMetadataDocumentComposition().addMetadataDocument(metadataDocument);
// ************ PREPARE MEASURES FOR THE DESIGNER *****************
String videoWidth=(new ModelBO()).getModel().getDocumentsConfiguration().getVideoWidth();
String videoHeight=(new ModelBO()).getModel().getDocumentsConfiguration().getVideoHeight();
int vWidth=Integer.valueOf(videoWidth);
int vHeight=Integer.valueOf(videoHeight);
int widthToPut=MetadataStyle.fromVideoWidthToDesignerWidth(metadataStyle.getWidth(), vWidth, DESIGNER_WIDTH);
int heightToPut=MetadataStyle.fromVideoHeightToDesignerHeight(metadataStyle.getHeight(), vHeight, DESIGNER_HEIGHT);
// scale x and y to default designer sizes
int scaledX=(DESIGNER_WIDTH*metadataStyle.getX())/vWidth;
int scaledY=(DESIGNER_HEIGHT*metadataStyle.getY())/vHeight;
addDocContainerFromTemplate(mainComposite, scaledX, scaledY, widthToPut, heightToPut, metadataDocument, document);
}
else{
MessageDialog.openError(mainComposite.getShell(),
"Error", "Could not find file "+localFileName+", download idt again!");
logger.error("END "+Designer.class.toString()+": Initialize designer function: " +
"Could not find file "+localFileName+", download idt again!");
// delete from model!!!!
new ModelBO().deleteDocumentFromModel(document);
}
}
else{
MessageDialog.openError(mainComposite.getShell(),
"Error", "Could not find file "+localFileName+", download idt again!");
logger.error("END "+Designer.class.toString()+": Initialize designer function: " +
"Could not find file "+localFileName+", download idt again!");
// delete from model!!!!
new ModelBO().deleteDocumentFromModel(document);
}
}
}
catch (Exception e) {
// Error in retrieving the document, download idt again
MessageDialog.openError(mainComposite.getShell(),
"Error", "The file with name "+localFileName+" was not found, download the document with label "+sbiObjectLabel+" or check that in tempate you have the right file name defined");
logger.error("END Initialize designer function: Error in retrieving metadata the file with name "+localFileName+", download idt again!",e);
}
}
// reloading navigation view
reloadNavigationView();
logger.debug("OUT");
}
public boolean isDocumentContained(Integer idActual, String label){
boolean found=false;
for (Iterator iterator = containers.keySet().iterator(); iterator.hasNext() && found==false;) {
Integer id = (Integer) iterator.next();
DocContainer docContainer=containers.get(id);
if(!id.equals(idActual)){
DocumentContained documentContained=docContainer.getDocumentContained();
if(documentContained!=null){
MetadataDocument metadata=documentContained.getMetadataDocument();
if(metadata!=null){
if(label.equals(metadata.getLabel())){
found=true;
}
}
}
}
}
return found;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
/** Reload the view with navigations
*
* @param id
*/
public void reloadNavigationView(){
IWorkbenchWindow a=PlatformUI.getWorkbench().getWorkbenchWindows()[0];
try{
// Navigation
IViewPart object=DocCompUtilities.getViewReference(DocCompUtilities.NAVIGATION_VIEW_ID);
if(object!=null && object instanceof NavigationView){
NavigationView view=(NavigationView)object;
view.reloadNavigations();
}
else{
logger.warn("view Document navigation closed");
}
}catch (Exception e) {
logger.error("Error reloading navigation view", e);
e.printStackTrace();
}
}
}