| /******************************************************************************* |
| * Copyright (c) 2006 Sybase, Inc. 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: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.pagedesigner.jsf.ui.elementedit.jsfhtml; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.gef.DragTracker; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.EditPolicy; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.requests.DropRequest; |
| import org.eclipse.gef.requests.LocationRequest; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jst.jsf.common.dom.TagIdentifier; |
| import org.eclipse.jst.jsf.core.internal.tld.IJSFConstants; |
| import org.eclipse.jst.pagedesigner.actions.single.SelectEditPartAction; |
| import org.eclipse.jst.pagedesigner.editors.PageDesignerActionConstants; |
| import org.eclipse.jst.pagedesigner.editpolicies.DragMoveEditPolicy; |
| import org.eclipse.jst.pagedesigner.editpolicies.ElementResizableEditPolicy; |
| import org.eclipse.jst.pagedesigner.jsf.core.dom.JSFDOMUtil; |
| import org.eclipse.jst.pagedesigner.jsf.ui.JSFUIPlugin; |
| import org.eclipse.jst.pagedesigner.jsf.ui.actions.DeleteHColumnHeaderFooterAction; |
| import org.eclipse.jst.pagedesigner.jsf.ui.actions.DeleteHeaderFooterAction; |
| import org.eclipse.jst.pagedesigner.jsf.ui.actions.InsertHColumnHeaderFooterAction; |
| import org.eclipse.jst.pagedesigner.jsf.ui.actions.InsertHeaderFooterAction; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableDeleteColumnCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableDeleteColumnHeaderCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableDeleteHeaderCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableInsertColumnCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableInsertColumnHeaderCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.commands.jsfhtml.DataTableInsertHeaderCommand; |
| import org.eclipse.jst.pagedesigner.jsf.ui.elementedit.request.DeleteHColumnHeaderFooterRequest; |
| import org.eclipse.jst.pagedesigner.jsf.ui.elementedit.request.DeleteHeaderFooterRequest; |
| import org.eclipse.jst.pagedesigner.jsf.ui.elementedit.request.InsertHColumnHeaderFooterRequest; |
| import org.eclipse.jst.pagedesigner.jsf.ui.elementedit.request.InsertHeaderFooterRequest; |
| import org.eclipse.jst.pagedesigner.jsf.ui.elementedit.util.DataTableUtil; |
| import org.eclipse.jst.pagedesigner.parts.ElementEditPart; |
| import org.eclipse.jst.pagedesigner.parts.NodeEditPart; |
| import org.eclipse.jst.pagedesigner.tableedit.DeleteRowColumnAction; |
| import org.eclipse.jst.pagedesigner.tableedit.InsertRowColumnAction; |
| import org.eclipse.jst.pagedesigner.tableedit.TableInsertRequest; |
| import org.eclipse.jst.pagedesigner.tableedit.TableResizeRequest; |
| import org.eclipse.jst.pagedesigner.tableedit.TableRowColumnDeleteRequest; |
| import org.eclipse.jst.pagedesigner.tools.ObjectModeDragTracker; |
| import org.eclipse.jst.pagedesigner.validation.caret.ActionData; |
| import org.eclipse.jst.pagedesigner.validation.caret.DefaultPositionRule; |
| import org.eclipse.jst.pagedesigner.validation.caret.DnDPositionValidator; |
| import org.eclipse.jst.pagedesigner.validation.caret.DropActionData; |
| import org.eclipse.jst.pagedesigner.validation.caret.IPositionMediator; |
| import org.eclipse.jst.pagedesigner.validation.caret.Target; |
| import org.eclipse.jst.pagedesigner.validation.caret.DropActionData.DropData; |
| import org.eclipse.jst.pagedesigner.viewer.IHTMLGraphicalViewer; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| |
| /** |
| * @author mengbo |
| * @version 1.5 |
| */ |
| public class DataTableElementEdit extends DefaultJSFHTMLElementEdit |
| { |
| private final static Action EMPTY_ACTION = new Action() |
| { |
| // TODO: why? |
| }; |
| private final static int FAKE_INDEX = -10; |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jst.pagedesigner.elementedit.IElementEdit#fillContextMenu(org.eclipse.jface.action.IMenuManager, org.w3c.dom.Element) |
| */ |
| public void fillContextMenu(IMenuManager contextMenu, Element ele) |
| { |
| super.fillContextMenu(contextMenu, ele); |
| |
| final IMenuManager tableMenu = new MenuManager(JSFUIPlugin.getResourceString("ElementEdit.Submenu.DataTable"));//$NON-NLS-1$ |
| final ElementEditPart editPart = (ElementEditPart) ((IDOMElement) ele).getAdapterFor(EditPart.class); |
| // ok, we passed the checking, now let's create the actions. |
| tableMenu.add(EMPTY_ACTION); |
| tableMenu.addMenuListener(new IMenuListener() |
| { |
| public void menuAboutToShow(IMenuManager manager) |
| { |
| tableMenu.removeAll(); |
| fillTableMenu(editPart, FAKE_INDEX, tableMenu); |
| } |
| }); |
| |
| contextMenu.appendToGroup(PageDesignerActionConstants.GROUP_CONTAINER, tableMenu); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jst.pagedesigner.elementedit.IElementEdit#fillContainerContextMenu(org.eclipse.jface.action.IMenuManager, org.eclipse.jst.pagedesigner.parts.ElementEditPart, org.eclipse.jst.pagedesigner.parts.NodeEditPart, org.eclipse.jface.viewers.ISelection) |
| */ |
| public boolean fillContainerContextMenu(IMenuManager contextMenu, final ElementEditPart elePart, |
| NodeEditPart nodePart, ISelection innerSelection) |
| { |
| Element table = (Element) elePart.getModel(); |
| Node node = (Node) nodePart.getModel(); |
| |
| DataTableUtil util = new DataTableUtil(table); |
| Element columnParent = util.findHColumnParent(node); |
| |
| final int cellColumn = util.getColumnIndex(columnParent); |
| |
| final IMenuManager tableMenu = new MenuManager(JSFUIPlugin.getResourceString("ElementEdit.Submenu.DataTable"));//$NON-NLS-1$ |
| |
| // ok, we passed the checking, now let's create the actions. |
| tableMenu.add(EMPTY_ACTION); |
| tableMenu.addMenuListener(new IMenuListener() |
| { |
| public void menuAboutToShow(IMenuManager manager) |
| { |
| tableMenu.removeAll(); |
| fillTableMenu(elePart, cellColumn, tableMenu); |
| } |
| }); |
| |
| contextMenu.appendToGroup(PageDesignerActionConstants.GROUP_CONTAINER, tableMenu); |
| return true; |
| |
| } |
| |
| /** |
| * @param elePart |
| * @param cellColumn |
| * @param tableMenu |
| */ |
| private void fillTableMenu(ElementEditPart elePart, int cellColumn, IMenuManager tableMenu) |
| { |
| SelectEditPartAction action = SelectEditPartAction.create(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DataTable.SelectTable"), elePart);//$NON-NLS-1$ |
| tableMenu.add(action); |
| |
| tableMenu.add(new Separator()); |
| |
| { |
| InsertRowColumnAction insertColumnBeforeAction = new InsertRowColumnAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DataTable.InsertColumnBefore"), //$NON-NLS-1$ |
| elePart, cellColumn, false, true); |
| tableMenu.add(insertColumnBeforeAction); |
| |
| InsertRowColumnAction insertColumnAfterAction = new InsertRowColumnAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DataTable.InsertColumnAfter"),//$NON-NLS-1$ |
| elePart, cellColumn, false, false); |
| tableMenu.add(insertColumnAfterAction); |
| |
| tableMenu.add(new Separator()); |
| } |
| |
| { |
| DeleteRowColumnAction deleteColumnAction = new DeleteRowColumnAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DataTable.DeleteColumn"), //$NON-NLS-1$ |
| elePart, cellColumn, false); |
| tableMenu.add(deleteColumnAction); |
| tableMenu.add(new Separator()); |
| } |
| |
| { |
| InsertHeaderFooterAction headerAction = new InsertHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.InsertTableHeader"), elePart, true);//$NON-NLS-1$ |
| tableMenu.add(headerAction); |
| |
| InsertHeaderFooterAction footerAction = new InsertHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.InsertTableFooter"), elePart, false);//$NON-NLS-1$ |
| tableMenu.add(footerAction); |
| |
| DeleteHeaderFooterAction delHeaderAction = new DeleteHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DeleteTableHeader"), elePart, true);//$NON-NLS-1$ |
| tableMenu.add(delHeaderAction); |
| |
| DeleteHeaderFooterAction delFooterAction = new DeleteHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DeleteTableFooter"), elePart, false);//$NON-NLS-1$ |
| tableMenu.add(delFooterAction); |
| tableMenu.add(new Separator()); |
| } |
| |
| { |
| InsertHColumnHeaderFooterAction hColHeaderAction = new InsertHColumnHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.InsertColumnHeader"),//$NON-NLS-1$ |
| elePart, true); |
| tableMenu.add(hColHeaderAction); |
| |
| InsertHColumnHeaderFooterAction hColFooterAction = new InsertHColumnHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.InsertColumnFooter"),//$NON-NLS-1$ |
| elePart, false); |
| tableMenu.add(hColFooterAction); |
| |
| DeleteHColumnHeaderFooterAction delColHeader = new DeleteHColumnHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DeleteColumnHeader"),//$NON-NLS-1$ |
| elePart, true); |
| tableMenu.add(delColHeader); |
| |
| DeleteHColumnHeaderFooterAction delColFooter = new DeleteHColumnHeaderFooterAction(JSFUIPlugin |
| .getResourceString("ElementEdit.Submenu.DeleteColumnFooter"),//$NON-NLS-1$ |
| elePart, false); |
| tableMenu.add(delColFooter); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jst.pagedesigner.elementedit.IElementEdit#createEditPolicies(org.eclipse.jst.pagedesigner.parts.ElementEditPart) |
| */ |
| public void createEditPolicies(ElementEditPart part) |
| { |
| part.installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new DataTableResizePolicy(part)); |
| part.installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, |
| new MyDragMoveEditPolicy()); |
| } |
| |
| static class DataTableResizePolicy extends ElementResizableEditPolicy |
| { |
| ElementEditPart _part; |
| Cursor _columnSelectCursor; |
| |
| /** |
| * @param part |
| */ |
| public DataTableResizePolicy(ElementEditPart part) |
| { |
| _part = part; |
| } |
| |
| public void deactivate() { |
| super.deactivate(); |
| if (_columnSelectCursor != null && !_columnSelectCursor.isDisposed()) |
| { |
| _columnSelectCursor.dispose(); |
| _columnSelectCursor = null; |
| } |
| } |
| |
| private Cursor getColumnSelectCursor() |
| { |
| if (_columnSelectCursor == null) |
| { |
| final Image cursorImage = JSFUIPlugin.getDefault().getImage("column_select.gif"); |
| _columnSelectCursor = new Cursor(null, cursorImage.getImageData(), 2, 5); |
| } |
| |
| return _columnSelectCursor; |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.gef.editpolicies.ResizableEditPolicy#getCommand(org.eclipse.gef.Request) |
| */ |
| public Command getCommand(Request request) |
| { |
| IHTMLGraphicalViewer viewer = (IHTMLGraphicalViewer) _part.getViewer(); |
| Element dataTable = (Element) _part.getIDOMNode(); |
| if (request instanceof TableResizeRequest) |
| { |
| return super.getCommand(request); |
| } |
| else if (request instanceof TableInsertRequest) |
| { |
| TableInsertRequest tableInsertRequest = (TableInsertRequest) request; |
| if (tableInsertRequest.isRow()) |
| { |
| // don't support insert row. |
| return null; |
| } |
| int index = tableInsertRequest.getIndex() + (tableInsertRequest.isBefore() ? 0 : 1); |
| return new DataTableInsertColumnCommand(viewer, dataTable, index); |
| } |
| else if (request instanceof InsertHeaderFooterRequest) |
| { |
| InsertHeaderFooterRequest req = (InsertHeaderFooterRequest) request; |
| boolean isHeader = req.isHeader(); |
| return new DataTableInsertHeaderCommand(viewer, dataTable, isHeader); |
| } |
| else if (request instanceof DeleteHeaderFooterRequest) |
| { |
| DeleteHeaderFooterRequest req = (DeleteHeaderFooterRequest) request; |
| boolean isHeader = req.isHeader(); |
| return new DataTableDeleteHeaderCommand(viewer, dataTable, isHeader); |
| } |
| else if (request instanceof InsertHColumnHeaderFooterRequest) |
| { |
| InsertHColumnHeaderFooterRequest req = (InsertHColumnHeaderFooterRequest) request; |
| boolean isHeader = req.isHeader(); |
| return new DataTableInsertColumnHeaderCommand(viewer, dataTable, isHeader); |
| } |
| else if (request instanceof DeleteHColumnHeaderFooterRequest) |
| { |
| DeleteHColumnHeaderFooterRequest req = (DeleteHColumnHeaderFooterRequest) request; |
| boolean isHeader = req.isHeader(); |
| return new DataTableDeleteColumnHeaderCommand(viewer, dataTable, isHeader); |
| } |
| else if (request instanceof TableRowColumnDeleteRequest) |
| { |
| TableRowColumnDeleteRequest deleteReq = (TableRowColumnDeleteRequest) request; |
| if (deleteReq.isRow()) |
| { |
| return null; |
| } |
| return new DataTableDeleteColumnCommand(viewer, dataTable, deleteReq.getIndex()); |
| } |
| return super.getCommand(request); |
| } |
| |
| public Cursor getSelectionToolCursor(Point mouseLocation) |
| { |
| if (hitTestColumnSelection(mouseLocation)) |
| { |
| return getColumnSelectCursor(); |
| } |
| |
| return null; |
| } |
| |
| protected DragTracker getSelectionTracker(LocationRequest request) { |
| final Point mouseLocator = request.getLocation(); |
| if (hitTestColumnSelection(mouseLocator)) |
| { |
| ObjectModeDragTracker dragTracker = new ObjectModeDragTracker(getHost()) |
| { |
| protected boolean handleButtonDown(int button) |
| { |
| // only customize the case where we are in a column selection mode |
| if (button == 1) |
| { |
| EditPart retarget = |
| getRetargetSelectionEditPart(mouseLocator); |
| |
| if (retarget != null) |
| { |
| setSourceEditPart(retarget); |
| } |
| } |
| |
| // default |
| return super.handleButtonDown(button); |
| } |
| }; |
| |
| dragTracker.setDefaultCursor(getSelectionToolCursor(mouseLocator)); |
| return dragTracker; |
| } |
| return new ObjectModeDragTracker(getHost()); |
| } |
| |
| public DragTracker getSelectionDragTracker(LocationRequest request) { |
| return getSelectionTracker(request); |
| } |
| |
| /** |
| * @param mouseLocation |
| * @return the edit part fo the given mouse location |
| */ |
| public EditPart getRetargetSelectionEditPart(Point mouseLocation) { |
| if (hitTestColumnSelection(mouseLocation)) |
| { |
| GraphicalEditPart editPart = (GraphicalEditPart) getHost(); |
| List children = editPart.getChildren(); |
| |
| for (Iterator it = children.iterator(); it.hasNext();) |
| { |
| GraphicalEditPart child = (GraphicalEditPart) it.next(); |
| |
| if (child instanceof NodeEditPart) |
| { |
| Node childNode = ((NodeEditPart)child).getDOMNode(); |
| |
| if (JSFDOMUtil.isHColumn(childNode)) |
| { |
| Point relativeMousePointer = mouseLocation.getCopy(); |
| IFigure hostFigure = child.getFigure(); |
| hostFigure.translateToRelative(relativeMousePointer); |
| Rectangle hostBounds = hostFigure.getBounds(); |
| if (relativeMousePointer.x >= hostBounds.x |
| && relativeMousePointer.x < hostBounds.x+hostBounds.width) |
| { |
| return child; |
| } |
| } |
| } |
| } |
| } |
| |
| // otherwise, don't retarget |
| return null; |
| } |
| |
| private boolean hitTestColumnSelection(Point mouseLocation) |
| { |
| final GraphicalEditPart part = (GraphicalEditPart) getHost(); |
| final IFigure panelFigure = part.getFigure(); |
| |
| Point relativeLocation = mouseLocation.getCopy(); |
| panelFigure.translateToRelative(relativeLocation); |
| |
| final int yoffsetAbs = Math.abs(panelFigure.getBounds().y - relativeLocation.y); |
| |
| if (yoffsetAbs <= 4) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| } |
| |
| /** |
| * @author cbateman |
| * |
| */ |
| public static class MyDragMoveEditPolicy extends DragMoveEditPolicy |
| { |
| protected IPositionMediator createDropChildValidator( |
| DropRequest r) |
| { |
| DropData dropData = createDropData(r); |
| |
| if (dropData!=null) |
| { |
| DnDPositionValidator validator = |
| new DnDPositionValidator(new DropActionData( |
| ActionData.COMPONENT_MOVE, dropData)); |
| validator.addRule(new OnlyColumnsAndFacetsRule(validator.getActionData())); |
| return validator; |
| } |
| return null; |
| } |
| |
| private static class OnlyColumnsAndFacetsRule extends DefaultPositionRule |
| { |
| /** |
| * @param actionData |
| */ |
| public OnlyColumnsAndFacetsRule(ActionData actionData) { |
| super(actionData); |
| } |
| |
| public boolean isEditable(Target target) { |
| if (IJSFConstants.TAG_IDENTIFIER_DATA_TABLE.isSameTagType(target.getTagWrapper())) |
| { |
| return isDataDroppable(); |
| } |
| |
| return true; |
| } |
| |
| private boolean isDataDroppable() |
| { |
| ActionData actionData = getActionData(); |
| if (actionData instanceof DropActionData) |
| { |
| DropActionData dropActionData = (DropActionData) actionData; |
| TagIdentifier tagId = |
| (TagIdentifier) dropActionData.getDropData().getTagIdentifiers().get(0); |
| |
| if (IJSFConstants.TAG_IDENTIFIER_FACET.isSameTagType(tagId) |
| || IJSFConstants.TAG_IDENTIFIER_COLUMN.isSameTagType(tagId)) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| } |
| } |
| } |