/******************************************************************************* * Copyright © 2008, 2013 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.rui.document.utils; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.edt.compiler.core.ast.ArrayLiteral; import org.eclipse.edt.compiler.core.ast.Assignment; import org.eclipse.edt.compiler.core.ast.ClassDataDeclaration; import org.eclipse.edt.compiler.core.ast.DefaultASTVisitor; import org.eclipse.edt.compiler.core.ast.Handler; import org.eclipse.edt.compiler.core.ast.NewExpression; import org.eclipse.edt.compiler.core.ast.Node; import org.eclipse.edt.compiler.core.ast.SettingsBlock; import org.eclipse.edt.compiler.core.ast.SimpleName; import org.eclipse.edt.ide.core.ast.rewrite.ASTRewrite; import org.eclipse.edt.ide.core.model.EGLCore; import org.eclipse.edt.ide.core.model.EGLModelException; import org.eclipse.edt.ide.core.model.IEGLFile; import org.eclipse.edt.ide.core.model.IField; import org.eclipse.edt.ide.core.model.IPart; import org.eclipse.edt.ide.core.model.document.IEGLDocument; import org.eclipse.edt.ide.rui.internal.Activator; import org.eclipse.edt.ide.ui.internal.EGLUI; import org.eclipse.edt.mof.utils.NameUtile; import org.eclipse.text.edits.TextEdit; public class GridLayoutOperation { public static final int ACTION_INSERT_ROW_AHEAD = 1; public static final int ACTION_INSERT_ROW_AFTER = 2; public static final int ACTION_INSERT_COLUMN_AHEAD = 3; public static final int ACTION_INSERT_COLUMN_AFTER = 4; public static final int ACTION_DELETE_ROW = 5; public static final int ACTION_DELETE_COLUMN = 6; private static final String GRID_LAYOUT_TYPE_NAME = NameUtile.getAsName("GridLayout"); private static final String CHILDREN_PROPERTY_NAME = NameUtile.getAsName("children"); private static final String LAYOUT_DATA_PROPERTY_NAME = NameUtile.getAsName("layoutData"); private static final String ROW_PROPERTY_NAME = NameUtile.getAsName("row"); private static final String ROWS_PROPERTY_NAME = NameUtile.getAsName("rows"); private static final String COLUMN_PROPERTY_NAME = NameUtile.getAsName("column"); private static final String COLUMNS_PROPERTY_NAME = NameUtile.getAsName("columns"); private static final String HORIZONTAL_SPAN_PROPERTY_NAME = NameUtile.getAsName("horizontalSpan"); private static final String VERTICAL_SPAN_PROPERTY_NAME = NameUtile.getAsName("verticalSpan"); private IEGLDocument currentDocument; private IPart modelPart; private IFile currentFile; private TextEdit textEdit; private List<String> newChildren = new ArrayList<String>(); private static final int ADD = 1; private static final int SUBSTRACT = 2; EGLWidgetDefinitionDeleteStragegy deleteStrategy; private boolean isLastChild; public GridLayoutOperation(IEGLDocument currentDocument, IFile currentFile){ this.currentDocument = currentDocument; this.currentFile = currentFile; } public void doOpeation(int iStatementOffset, int iStatementLength, final int row, final int column, final int operationType) { try{ IEGLFile modelFile = (IEGLFile)EGLCore.create(currentFile); IEGLFile sharedWorkingCopy = (IEGLFile)modelFile.getSharedWorkingCopy(null, EGLUI.getBufferFactory(), null); String partName = new Path(currentFile.getName()).removeFileExtension().toString(); modelPart = sharedWorkingCopy.getPart(partName); sharedWorkingCopy.open(null); sharedWorkingCopy.reconcile(false, null); try{ final org.eclipse.edt.compiler.core.ast.File fileAST = currentDocument.getNewModelEGLFile(); final ASTRewrite rewrite = ASTRewrite.create(fileAST); this.deleteStrategy = new EGLWidgetDefinitionDeleteStragegy( currentDocument, modelPart, rewrite ); Node gridLayoutWidgetName = DocumentUtil.getWidgetNode( currentDocument, iStatementOffset, iStatementLength ); if(gridLayoutWidgetName != null){ gridLayoutWidgetName.getParent().accept(new GridLayoutVisitor(row, column, operationType, rewrite)); } textEdit.apply(currentDocument); }catch(Exception e){ Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, "GridLayout Operation: Error doing GridLayout operation", e)); }finally{ sharedWorkingCopy.destroy(); } }catch(EGLModelException e){ Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, "GridLayout Operation: Error creating working copy", e)); } } private void modifyProperty( SettingsBlock fieldSettingsBlock, ASTRewrite rewrite, String property, int operationType, int number ) { AssignmentLocator assignmentLocator = new AssignmentLocator(property); fieldSettingsBlock.accept(assignmentLocator); Assignment assignment = assignmentLocator.getAssignment(); int value = convertToInt( assignment.getRightHandSide().getCanonicalString() ); if ( value < number ) { return; } switch ( operationType ) { case ADD: value ++; break; case SUBSTRACT: value --; break; } rewrite.setText(assignment, property + " = " + value); textEdit = rewrite.rewriteAST(currentDocument); } private void modifyHorizontalSpanProperty( SettingsBlock fieldSettingsBlock, ASTRewrite rewrite, int number ) { AssignmentLocator horizontalSpanAssignmentLocator = new AssignmentLocator(HORIZONTAL_SPAN_PROPERTY_NAME); fieldSettingsBlock.accept(horizontalSpanAssignmentLocator); Assignment horizontalSpanAssignment = horizontalSpanAssignmentLocator.getAssignment(); if(horizontalSpanAssignment == null){ return; } int horizontalSpan = convertToInt( horizontalSpanAssignment.getRightHandSide().getCanonicalString() ); if(horizontalSpan == 1){ return; } AssignmentLocator columnAssignmentLocator = new AssignmentLocator(COLUMN_PROPERTY_NAME); fieldSettingsBlock.accept(columnAssignmentLocator); Assignment columnAssignment = columnAssignmentLocator.getAssignment(); int column = convertToInt( columnAssignment.getRightHandSide().getCanonicalString() ); if( column < number && number < column + horizontalSpan){ horizontalSpan --; } rewrite.setText(horizontalSpanAssignment, HORIZONTAL_SPAN_PROPERTY_NAME + " = " + horizontalSpan); textEdit = rewrite.rewriteAST(currentDocument); } private void modifyVerticalSpanProperty( SettingsBlock fieldSettingsBlock, ASTRewrite rewrite, int number ) { AssignmentLocator verticalSpanAssignmentLocator = new AssignmentLocator(VERTICAL_SPAN_PROPERTY_NAME); fieldSettingsBlock.accept(verticalSpanAssignmentLocator); Assignment verticalSpanAssignment = verticalSpanAssignmentLocator.getAssignment(); if(verticalSpanAssignment == null){ return; } int verticalSpan = convertToInt( verticalSpanAssignment.getRightHandSide().getCanonicalString() ); if(verticalSpan == 1){ return; } AssignmentLocator rowAssignmentLocator = new AssignmentLocator(ROW_PROPERTY_NAME); fieldSettingsBlock.accept(rowAssignmentLocator); Assignment rowAssignment = rowAssignmentLocator.getAssignment(); int row = convertToInt( rowAssignment.getRightHandSide().getCanonicalString() ); if( row < number && number < row + verticalSpan){ verticalSpan --; } rewrite.setText(verticalSpanAssignment, VERTICAL_SPAN_PROPERTY_NAME + " = " + verticalSpan); textEdit = rewrite.rewriteAST(currentDocument); } private void deleteOperation( SettingsBlock fieldSettingsBlock, ASTRewrite rewrite, String property, String widgetName, int number) { AssignmentLocator assignmentLocator = new AssignmentLocator(property); fieldSettingsBlock.accept(assignmentLocator); Assignment assignment = assignmentLocator.getAssignment(); int value = convertToInt( assignment.getRightHandSide().getCanonicalString() ); if(value == number){ try { deleteStrategy.deleteWidgetDefinition(widgetName); } catch (Exception e) { Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, "GridLayoutOperation: error when delete", e)); } textEdit = deleteStrategy.getTextEdit(); newChildren.remove( widgetName ); }else if(value > number){ modifyProperty(fieldSettingsBlock, rewrite, property, SUBSTRACT, -1); } } private class GridLayoutVisitor extends DefaultASTVisitor{ private final int row, column, operationType; private final ASTRewrite rewrite; public GridLayoutVisitor(int row, int column, final int operationType, ASTRewrite rewrite){ this.row = row; this.column = column; this.operationType = operationType; this.rewrite = rewrite; } public boolean visit(Handler handler) { return true; } public boolean visit(ClassDataDeclaration classDataDeclaration){ if (classDataDeclaration.getType().getCanonicalName().equalsIgnoreCase(GRID_LAYOUT_TYPE_NAME) && classDataDeclaration.hasSettingsBlock()) { SettingsBlock fieldSettingsBlock = classDataDeclaration.getSettingsBlockOpt(); if(fieldSettingsBlock != null){ AssignmentLocator assignmentLocator = new AssignmentLocator(CHILDREN_PROPERTY_NAME); fieldSettingsBlock.accept(assignmentLocator); final Assignment childrenAssignment = assignmentLocator.getAssignment(); if(childrenAssignment != null){ childrenAssignment.accept( new ChildrenArrayVisitor( row+1, column+1, operationType, rewrite ) ); } switch ( operationType ) { case ACTION_INSERT_ROW_AHEAD: case ACTION_INSERT_ROW_AFTER: modifyProperty(fieldSettingsBlock, rewrite, ROWS_PROPERTY_NAME, ADD, -1 ); break; case ACTION_INSERT_COLUMN_AHEAD: case ACTION_INSERT_COLUMN_AFTER: modifyProperty(fieldSettingsBlock, rewrite, COLUMNS_PROPERTY_NAME, ADD, -1 ); break; case ACTION_DELETE_ROW: modifyProperty(fieldSettingsBlock, rewrite, ROWS_PROPERTY_NAME, SUBSTRACT, -1 ); break; case ACTION_DELETE_COLUMN: modifyProperty(fieldSettingsBlock, rewrite, COLUMNS_PROPERTY_NAME, SUBSTRACT, -1 ); break; } StringBuffer sbChildren = new StringBuffer("children = [ "); for(int i=0; i<newChildren.size(); i++){ sbChildren.append(newChildren.get(i)); if(i < newChildren.size() - 1){ sbChildren.append(", "); } } sbChildren.append("]"); rewrite.setText(childrenAssignment, sbChildren.toString()); textEdit = rewrite.rewriteAST(currentDocument); } } return false; } } private class ChildrenArrayVisitor extends DefaultASTVisitor{ private final int row, column, operationType; private final ASTRewrite rewrite; public ChildrenArrayVisitor(int row, int column, final int operationType, ASTRewrite rewrite){ this.row = row; this.column = column; this.operationType = operationType; this.rewrite = rewrite; } public boolean visit(final Assignment assignment){ assignment.getRightHandSide().accept(new DefaultASTVisitor(){ public boolean visit(ArrayLiteral arrayLiteral){ List expressions = arrayLiteral.getExpressions(); for ( int i = 0; i < expressions.size(); i ++ ) { if(i == expressions.size() - 1){ isLastChild = true; } if ( expressions.get(i) instanceof SimpleName ) { SimpleName simpleName = (SimpleName)expressions.get(i); newChildren.add(simpleName.getIdentifier()); try{ IField[] fields = modelPart.getFields(); for (int j = 0; j < fields.length; j++) { final IField field = fields[j]; if( field.getElementName().equalsIgnoreCase( simpleName.getIdentifier()) ) { Node childWidgetName = currentDocument.getNewModelNodeAtOffset(field.getNameRange().getOffset(), field.getNameRange().getLength()); if ( childWidgetName != null ) { childWidgetName.getParent().accept( new DefaultASTVisitor(){ public boolean visit(ClassDataDeclaration classDataDeclaration){ if(classDataDeclaration.getSettingsBlockOpt() != null){ SettingsBlock fieldSettingsBlock = classDataDeclaration.getSettingsBlockOpt(); if(fieldSettingsBlock != null){ AssignmentLocator assignmentLocator = new AssignmentLocator(LAYOUT_DATA_PROPERTY_NAME); fieldSettingsBlock.accept(assignmentLocator); Assignment layoutDataAssignment = assignmentLocator.getAssignment(); layoutDataAssignment.getRightHandSide().accept( new DefaultASTVisitor(){ public boolean visit(final NewExpression newExpression){ SettingsBlock fieldSettingsBlock = newExpression.getSettingsBlock(); switch ( operationType ) { case ACTION_INSERT_ROW_AHEAD: modifyProperty(fieldSettingsBlock, rewrite, ROW_PROPERTY_NAME, ADD, row ); break; case ACTION_INSERT_ROW_AFTER: modifyProperty(fieldSettingsBlock, rewrite, ROW_PROPERTY_NAME, ADD, row + 1 ); break; case ACTION_INSERT_COLUMN_AHEAD: modifyProperty(fieldSettingsBlock, rewrite, COLUMN_PROPERTY_NAME, ADD, column ); break; case ACTION_INSERT_COLUMN_AFTER: modifyProperty(fieldSettingsBlock, rewrite, COLUMN_PROPERTY_NAME, ADD, column + 1); break; case ACTION_DELETE_ROW: deleteOperation( fieldSettingsBlock, rewrite, ROW_PROPERTY_NAME, field.getElementName(), row ); modifyVerticalSpanProperty(fieldSettingsBlock, rewrite, row); if(isLastChild){ deleteStrategy.modifyFormManagerEntities(); isLastChild = false; } break; case ACTION_DELETE_COLUMN: deleteOperation( fieldSettingsBlock, rewrite, COLUMN_PROPERTY_NAME, field.getElementName(), column ); modifyHorizontalSpanProperty(fieldSettingsBlock, rewrite, column); if(isLastChild){ deleteStrategy.modifyFormManagerEntities(); isLastChild = false; } break; } return false; } }); } } return false; } }); } } } }catch(Exception e){ Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, "Get Event Handler: Error finding functions", e)); } } } return false; } }); return false; } } private int convertToInt( String str ) { try { return Integer.parseInt( str ); } catch ( Exception e ) { Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, "GridLayoutOperation: Error convert to int", e)); } return 0; } }