package org.xmind.ui.internal.views;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.IContributedContentsView;
import org.eclipse.ui.part.ViewPart;
import org.xmind.core.Core;
import org.xmind.core.IComment;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.CoreEventRegister;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventRegister;
import org.xmind.core.event.ICoreEventSupport;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.ui.internal.comments.CommentTextViewer;
import org.xmind.ui.internal.comments.CommentsPartActionBarContributor;
import org.xmind.ui.internal.comments.CommentsSelectionProvider;
import org.xmind.ui.internal.comments.ICommentTextViewerContainer;
import org.xmind.ui.internal.comments.ICommentsActionBarContributor;
import org.xmind.ui.internal.comments.SheetCommentsViewer;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.resources.ColorUtils;
public class CommentsView extends ViewPart implements IContributedContentsView,
IPartListener, ISelectionChangedListener, ICoreEventListener,
ICommentTextViewerContainer {
public static final Color BG_COLOR = ColorUtils.getColor("#ffffff"); //$NON-NLS-1$
private static final String COMMENTS_EDIT_CONTEXT_ID = "org.xmind.ui.context.comments.edit"; //$NON-NLS-1$
private static final Color INVALID_COLER = ColorUtils.getColor("#f0f0f0"); //$NON-NLS-1$
private class ContextActivator implements IPartListener {
IContextActivation context;
IContextService service;
public ContextActivator() {
getSite().getPage().addPartListener(this);
}
private void activateContext() {
if (service == null)
service = (IContextService) getSite()
.getService(IContextService.class);
if (service != null) {
context = service.activateContext(COMMENTS_EDIT_CONTEXT_ID);
}
}
private void deactivateContext() {
if (service != null && context != null)
service.deactivateContext(context);
context = null;
}
public void partActivated(IWorkbenchPart part) {
if (part instanceof CommentsView) {
activateContext();
}
}
public void partBroughtToTop(IWorkbenchPart part) {
}
public void partClosed(IWorkbenchPart part) {
getSite().getPage().removePartListener(this);
}
public void partDeactivated(IWorkbenchPart part) {
if (part instanceof CommentsView) {
deactivateContext();
}
}
public void partOpened(IWorkbenchPart part) {
}
}
private class TextAction extends Action {
private TextViewer textViewer;
private int op;
public TextAction(int op) {
this.op = op;
}
public void run() {
if (textViewer != null && textViewer.canDoOperation(op)) {
textViewer.doOperation(op);
contentComposite.pack();
}
}
public void update(TextViewer textViewer) {
this.textViewer = textViewer;
setEnabled(textViewer != null && textViewer.canDoOperation(op));
}
}
private class CommitCommentHandler extends AbstractHandler {
public Object execute(ExecutionEvent event) throws ExecutionException {
saveComment();
return null;
}
}
private CommentsPartActionBarContributor contributor;
private ISelectionProvider selectionProvider = new CommentsSelectionProvider();
private Map<String, IWorkbenchAction> workbenchActions = new HashMap<String, IWorkbenchAction>(
7);
private List<TextAction> textActions = new ArrayList<TextAction>(7);
private IGraphicalEditor contributingEditor;
private ITopicPart currentTopicPart;
private ICoreEventRegister commentEventRegister;
private ICoreEventRegister globalEventRegister;
private ScrolledComposite sc;
private Composite contentComposite;
private SheetCommentsViewer contentViewer;
private ISheet sheet;
private Control control;
private ControlListener controlListener;
private IHandlerActivation commitHandlerActivation;
private IComment latestCreatedComment;
private IComment selectedComment;
public void createPartControl(Composite parent) {
contributor = new CommentsPartActionBarContributor(null,
contributingEditor);
control = createControl(parent);
setInitialInput();
activateHandlers();
IActionBars actionBars = getViewSite().getActionBars();
createActions(actionBars);
new ContextActivator();
getSite().getPage().addPartListener(this);
}
private void activateHandlers() {
IHandlerService handlerService = (IHandlerService) getSite()
.getService(IHandlerService.class);
if (handlerService != null) {
commitHandlerActivation = handlerService.activateHandler(
"org.xmind.ui.command.commitComments", //$NON-NLS-1$
new CommitCommentHandler());
}
}
private void deactivateHandlers() {
if (commitHandlerActivation != null) {
commitHandlerActivation.getHandlerService()
.deactivateHandler(commitHandlerActivation);
commitHandlerActivation = null;
}
}
private void saveComment() {
if (contentViewer != null) {
contentViewer.save();
}
}
private void setInitialInput() {
IEditorPart activeEditor = getSite().getPage().getActiveEditor();
if (activeEditor instanceof IGraphicalEditor) {
setContributingEditor((IGraphicalEditor) activeEditor);
} else {
setInput(null);
}
}
private Composite createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(BG_COLOR);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
composite.setLayout(gridLayout);
contentComposite = createContentComposite(composite);
return composite;
}
private Composite createContentComposite(Composite parent) {
sc = new ScrolledComposite(parent, SWT.V_SCROLL);
sc.setBackground(parent.getBackground());
sc.setLayoutData(new GridData(GridData.FILL_BOTH));
sc.setExpandHorizontal(true);
final Composite composite = new Composite(sc, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
gridLayout.marginBottom = 29;
composite.setLayout(gridLayout);
sc.setContent(composite);
sc.getVerticalBar().setIncrement(17);
sc.addControlListener(getControlListener());
return composite;
}
private ControlListener getControlListener() {
if (controlListener == null) {
controlListener = new ControlListener() {
public void controlMoved(ControlEvent e) {
}
public void controlResized(ControlEvent e) {
e.widget.getDisplay().asyncExec(new Runnable() {
public void run() {
if (contentComposite != null
&& !contentComposite.isDisposed()) {
contentComposite.pack();
}
}
});
}
};
}
return controlListener;
}
private void setInput(ISheet sheet) {
if (this.sheet == sheet) {
return;
}
this.sheet = sheet;
unhookSheet();
update();
hookSheet();
}
private void hookSheet() {
if (sheet != null) {
if (commentEventRegister == null)
commentEventRegister = new CoreEventRegister(
sheet.getAdapter(ICoreEventSupport.class), this);
commentEventRegister.register(Core.CommentAdd);
commentEventRegister.register(Core.CommentRemove);
registerGlobalEvent();
}
}
private void unhookSheet() {
if (commentEventRegister != null) {
commentEventRegister.unregisterAll();
commentEventRegister = null;
}
unRegisterGlobalEvent();
}
private void registerGlobalEvent() {
globalEventRegister = new CoreEventRegister(
sheet.getOwnedWorkbook().getAdapter(ICoreEventSupport.class),
this);
globalEventRegister.register(Core.CommentContent);
}
private void unRegisterGlobalEvent() {
if (globalEventRegister != null) {
globalEventRegister.unregisterAll();
globalEventRegister = null;
}
}
private void update() {
resetSelectedComment();
updateCompositeEnabled();
updateComments();
}
private void resetSelectedComment() {
contributor.selectedCommentChanged(null);
}
private void updateCompositeEnabled() {
sc.setEnabled(sheet != null);
if (sheet == null) {
contentComposite.getParent().setBackground(INVALID_COLER);
contentComposite.setBackground(INVALID_COLER);
} else {
contentComposite.getParent().setBackground(control.getBackground());
contentComposite.setBackground(control.getBackground());
}
}
private void updateComments() {
contentComposite.setRedraw(false);
clearContent();
selectionProvider.setSelection(null);
if (sheet != null) {
contentViewer = new SheetCommentsViewer(sheet, contributor,
selectionProvider, this, contributingEditor);
contentViewer.create(contentComposite);
}
contentComposite.pack();
contentComposite.setRedraw(true);
}
private void clearContent() {
Control[] controls = contentComposite.getChildren();
if (controls != null) {
for (Control control : controls) {
if (control != null && !control.isDisposed()) {
control.dispose();
control = null;
}
}
}
}
private void createActions(IActionBars actionBars) {
IWorkbenchWindow window = getSite().getWorkbenchWindow();
addGlobalTextAction(actionBars, window, ActionFactory.UNDO,
ITextOperationTarget.UNDO);
addGlobalTextAction(actionBars, window, ActionFactory.REDO,
ITextOperationTarget.REDO);
addGlobalTextAction(actionBars, window, ActionFactory.CUT,
ITextOperationTarget.CUT);
addGlobalTextAction(actionBars, window, ActionFactory.COPY,
ITextOperationTarget.COPY);
addGlobalTextAction(actionBars, window, ActionFactory.PASTE,
ITextOperationTarget.PASTE);
addGlobalTextAction(actionBars, window, ActionFactory.SELECT_ALL,
ITextOperationTarget.SELECT_ALL);
}
private void addGlobalTextAction(IActionBars actionBars,
IWorkbenchWindow window, ActionFactory actionFactory, int textOp) {
IWorkbenchAction action = actionFactory.create(window);
workbenchActions.put(action.getId(), action);
TextAction textAction = new TextAction(textOp);
textActions.add(textAction);
actionBars.setGlobalActionHandler(action.getId(), textAction);
}
public IWorkbenchAction getGlobalAction(String actionId) {
return workbenchActions == null ? null : workbenchActions.get(actionId);
}
public void updateTextActions(TextViewer textViewer) {
if (textViewer != null) {
for (TextAction action : textActions) {
action.update(textViewer);
}
}
}
public void dispose() {
unhookSheet();
deactivateHandlers();
if (contributor != null) {
contributor.dispose();
}
if (sc != null && !sc.isDisposed()) {
sc.removeControlListener(getControlListener());
}
getSite().getPage().removePartListener(this);
setContributingEditor(null);
super.dispose();
if (workbenchActions != null) {
for (IWorkbenchAction action : workbenchActions.values()) {
action.dispose();
}
workbenchActions = null;
}
textActions = null;
}
public void setFocus() {
if (control != null && !control.isDisposed()) {
control.setFocus();
}
}
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (adapter == IContributedContentsView.class) {
return this;
} else if (adapter == ITextViewer.class) {
return getImplementation() == null ? null
: getImplementation().getTextViewer();
} else if (adapter == ITopicPart.class) {
return currentTopicPart;
} else if (adapter == ITopic.class) {
return currentTopicPart == null ? null
: currentTopicPart.getTopic();
}
return super.getAdapter(adapter);
}
//It can be only used in getAdapter() for findReplaceAction.
private CommentTextViewer getImplementation() {
if (selectionProvider instanceof CommentsSelectionProvider) {
ISelection selection = selectionProvider.getSelection();
if (selection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) selection)
.getFirstElement();
if (obj instanceof CommentTextViewer) {
return (CommentTextViewer) obj;
}
}
ISelection oldSelection = ((CommentsSelectionProvider) selectionProvider)
.getOldSelection();
if (oldSelection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) oldSelection)
.getFirstElement();
if (obj instanceof CommentTextViewer) {
return (CommentTextViewer) obj;
}
}
}
return null;
}
public void partActivated(IWorkbenchPart part) {
if (part instanceof IGraphicalEditor) {
setContributingEditor((IGraphicalEditor) part);
}
}
public void partBroughtToTop(IWorkbenchPart part) {
}
public void partClosed(IWorkbenchPart part) {
if (part == this.contributingEditor) {
setContributingEditor(null);
}
}
public void partDeactivated(IWorkbenchPart part) {
}
public void partOpened(IWorkbenchPart part) {
}
private void setContributingEditor(IGraphicalEditor editor) {
if (editor == contributingEditor) {
return;
}
if (contributingEditor != null) {
ISelectionProvider selectionProvider = contributingEditor.getSite()
.getSelectionProvider();
if (selectionProvider != null)
selectionProvider.removeSelectionChangedListener(this);
}
contributingEditor = editor;
if (contributingEditor != null) {
ISelectionProvider selectionProvider = contributingEditor.getSite()
.getSelectionProvider();
if (selectionProvider != null) {
selectionProvider.addSelectionChangedListener(this);
}
}
if (getControl().isDisposed()) {
return;
}
if (contentViewer != null) {
contentViewer.setTargetEditor(contributingEditor);
}
if (contributor != null) {
contributor.setTargetEditor(contributingEditor);
}
ISheet sheet = getSheet(contributingEditor);
setInput(sheet);
}
public IWorkbenchPart getContributingPart() {
return contributingEditor;
}
public void selectionChanged(SelectionChangedEvent event) {
ISheet sheet = getSheet(contributingEditor);
setInput(sheet);
}
private ISheet getSheet(IGraphicalEditor editor) {
if (editor != null && editor.getActivePageInstance() != null) {
return (ISheet) editor.getActivePageInstance()
.getAdapter(ISheet.class);
} else {
return null;
}
}
public void handleCoreEvent(final CoreEvent event) {
final String type = event.getType();
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
public void run() {
if (!contentComposite.isDisposed()) {
if (Core.CommentAdd.equals(type)
|| Core.CommentRemove.equals(type)) {
update();
} else if (Core.CommentContent.equals(type)) {
IComment comment = (IComment) event.getSource();
Object source = comment.getOwnedWorkbook()
.getElementById(comment.getObjectId());
if ((source instanceof ITopic
&& ((ITopic) source).getOwnedSheet() == sheet)
|| source instanceof ISheet
&& source == sheet) {
update();
}
}
}
}
});
}
public void moveToPreviousTextViewer(CommentTextViewer implementation) {
List<CommentTextViewer> implementations = contentViewer
.getImplementations();
int index = implementations.indexOf(implementation);
if (index <= 0 || index > implementations.size() - 1) {
return;
}
setSelection(new StructuredSelection(implementations.get(index - 1)));
}
public void moveToNextTextViewer(CommentTextViewer implementation) {
List<CommentTextViewer> implementations = contentViewer
.getImplementations();
int index = implementations.indexOf(implementation);
if (index < 0 || index >= implementations.size() - 1) {
return;
}
setSelection(new StructuredSelection(implementations.get(index + 1)));
}
private void setSelection(ISelection selection) {
selectionProvider.setSelection(selection);
}
public Composite getContentComposite() {
return contentComposite;
}
public ScrolledComposite getScrolledComposite() {
return sc;
}
public ICommentsActionBarContributor getContributor() {
return contributor;
}
public void setLatestCreatedComment(IComment latestCreatedComment) {
this.latestCreatedComment = latestCreatedComment;
}
public IComment getLatestCreatedComment() {
return latestCreatedComment;
}
public void setSelectedComment(IComment selectedComment) {
this.selectedComment = selectedComment;
}
public IComment getSelectedComment() {
return selectedComment;
}
public Control getControl() {
return control;
}
@Override
public void createComment(String objectId) {
contentViewer.createNewComment(objectId);
}
@Override
public void cancelCreateComment() {
contentViewer.cancelCreateNewComment();
}
@Override
public void setEditingComment(IComment comment) {
}
@Override
public IComment getEditingComment() {
return null;
}
@Override
public void setModified(boolean modified) {
}
@Override
public boolean isModified() {
return false;
}
}