blob: d7f6eeffb22a3cb27a54169d4a9d832309cef73f [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.redocs.wikitext.r.ui.editors;
import static org.eclipse.ui.IWorkbenchCommandConstants.NAVIGATE_EXPAND_ALL;
import static org.eclipse.statet.ecommons.ui.actions.UIActions.ADDITIONS_GROUP_ID;
import static org.eclipse.statet.ecommons.ui.actions.UIActions.VIEW_EXPAND_GROUP_ID;
import static org.eclipse.statet.ecommons.ui.actions.UIActions.VIEW_FILTER_GROUP_ID;
import java.util.Collections;
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler2;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.ui.viewers.ViewerUtils;
import org.eclipse.statet.base.ui.IStatetUIMenuIds;
import org.eclipse.statet.docmlet.base.ui.DocmlBaseUIResources;
import org.eclipse.statet.docmlet.wikitext.core.model.IWikidocModelInfo;
import org.eclipse.statet.docmlet.wikitext.core.model.IWikitextSourceElement;
import org.eclipse.statet.docmlet.wikitext.core.model.WikitextModel;
import org.eclipse.statet.internal.redocs.wikitext.r.RedocsWikitextRPlugin;
import org.eclipse.statet.internal.redocs.wikitext.r.ui.sourceediting.DocROutlineContentProvider;
import org.eclipse.statet.ltk.model.core.elements.IEmbeddedForeignElement;
import org.eclipse.statet.ltk.model.core.elements.IModelElement;
import org.eclipse.statet.ltk.model.core.elements.IModelElement.Filter;
import org.eclipse.statet.ltk.model.core.elements.ISourceStructElement;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnitModelInfo;
import org.eclipse.statet.ltk.ui.sourceediting.OutlineContentProvider;
import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor1;
import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor2OutlinePage;
import org.eclipse.statet.ltk.ui.util.ViewerDragSupport;
import org.eclipse.statet.ltk.ui.util.ViewerDropSupport;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.r.launching.RCodeLaunching;
import org.eclipse.statet.redocs.r.ui.RedocsRUIResources;
import org.eclipse.statet.redocs.wikitext.r.ui.WikitextRweaveLabelProvider;
public class WikidocRweaveOutlinePage extends SourceEditor2OutlinePage {
private static final String EXPAND_ELEMENTS_COMMAND_ID= "org.eclipse.statet.workbench.commands.ExpandElements"; //$NON-NLS-1$
private static boolean isRChunk(final IModelElement element) {
if (element instanceof IEmbeddedForeignElement) {
final ISourceStructElement foreignElement= ((IEmbeddedForeignElement) element).getForeignElement();
if (foreignElement != null && foreignElement.getModelTypeId() == RModel.R_TYPE_ID) {
return true;
}
}
return false;
}
private static Map<String, String> H2_PARAMETERS= Collections.singletonMap("type", "h2"); //$NON-NLS-1$ //$NON-NLS-2$
private static Map<String, String> H3_PARAMETERS= Collections.singletonMap("type", "h3"); //$NON-NLS-1$ //$NON-NLS-2$
private static Map<String, String> H4_PARAMETERS= Collections.singletonMap("type", "h4"); //$NON-NLS-1$ //$NON-NLS-2$
private static Map<String, String> RCHUNK_PARAMETERS= Collections.singletonMap("type", "rchunks"); //$NON-NLS-1$ //$NON-NLS-2$
private class FilterRChunks extends AbstractToggleHandler {
public FilterRChunks() {
super("filter.r_chunks.enabled", false, null, 0); //$NON-NLS-1$
}
@Override
protected void apply(final boolean on) {
final TreeViewer viewer= getViewer();
WikidocRweaveOutlinePage.this.filter.hideRChunks= on;
if (UIAccess.isOkToUse(viewer)) {
viewer.refresh(false);
}
}
}
public class ExpandElementsContributionItem extends HandlerContributionItem {
private final IHandler2 expandElementsHandler;
public ExpandElementsContributionItem(
final IServiceLocator serviceLocator, final HandlerCollection handlers) {
super(new CommandContributionItemParameter(serviceLocator,
".ExpandElements", NAVIGATE_EXPAND_ALL, null, //$NON-NLS-1$
null, null, null,
"Expand All", "E", null,
HandlerContributionItem.STYLE_PULLDOWN, null, false ),
handlers.get(NAVIGATE_EXPAND_ALL) );
this.expandElementsHandler= handlers.get(EXPAND_ELEMENTS_COMMAND_ID);
}
@Override
protected void initDropDownMenu(final MenuManager menuManager) {
menuManager.addMenuListener(new IMenuListener2() {
@Override
public void menuAboutToShow(final IMenuManager manager) {
final TreeViewer viewer= getViewer();
if (viewer == null) {
return;
}
final IWikidocModelInfo modelInfo= getCurrentInputModel();
final DocmlBaseUIResources baseResources= DocmlBaseUIResources.INSTANCE;
final RedocsRUIResources redocsResources= RedocsRUIResources.INSTANCE;
if (modelInfo.getMinSectionLevel() > 0) {
if (modelInfo.getMinSectionLevel() < 2
&& modelInfo.getMaxSectionLevel() >= 2) {
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), null, EXPAND_ELEMENTS_COMMAND_ID, H2_PARAMETERS,
baseResources.getImageDescriptor(DocmlBaseUIResources.OBJ_HEADING2_IMAGE_ID), null, null,
"Show all H2 sections", "C", null,
HandlerContributionItem.STYLE_PUSH, null, false ),
ExpandElementsContributionItem.this.expandElementsHandler ));
}
if (modelInfo.getMinSectionLevel() < 3
&& modelInfo.getMaxSectionLevel() >= 3) {
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), null, EXPAND_ELEMENTS_COMMAND_ID, H3_PARAMETERS,
baseResources.getImageDescriptor(DocmlBaseUIResources.OBJ_HEADING3_IMAGE_ID), null, null,
"Show all H3 sections", "S", null,
HandlerContributionItem.STYLE_PUSH, null, false ),
ExpandElementsContributionItem.this.expandElementsHandler ));
}
if (modelInfo.getMinSectionLevel() < 4
&& modelInfo.getMaxSectionLevel() >= 4) {
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), null, EXPAND_ELEMENTS_COMMAND_ID, H4_PARAMETERS,
baseResources.getImageDescriptor(DocmlBaseUIResources.OBJ_HEADING4_IMAGE_ID), null, null,
"Show all H4 sections", "u", null,
HandlerContributionItem.STYLE_PUSH, null, false ),
ExpandElementsContributionItem.this.expandElementsHandler ));
manager.add(new Separator());
}
}
if (!WikidocRweaveOutlinePage.this.filter.hideRChunks) {
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), null, EXPAND_ELEMENTS_COMMAND_ID, RCHUNK_PARAMETERS,
redocsResources.getImageDescriptor(RedocsRUIResources.OBJ_RCHUNK_IMAGE_ID), null, null,
"Show all R Chunks", "R", null,
HandlerContributionItem.STYLE_PUSH, null, false ),
ExpandElementsContributionItem.this.expandElementsHandler ));
}
}
@Override
public void menuAboutToHide(final IMenuManager manager) {
ExpandElementsContributionItem.this.display.asyncExec(new Runnable() {
@Override
public void run() {
menuManager.dispose();
}
});
}
});
}
}
public class ExpandElementsHandler extends AbstractHandler {
public ExpandElementsHandler() {
}
@Override
public Object execute(final ExecutionEvent event) {
final TreeViewer viewer= getViewer();
final String type= event.getParameter("type");
if (UIAccess.isOkToUse(viewer) && type != null) {
final ISourceUnitModelInfo modelInfo= getModelInfo(viewer.getInput());
if (modelInfo == null) {
return null;
}
final Filter contentFilter= getContentFilter();
final Filter expandFilter;
if (type.equals("rchunks")) {
expandFilter= new Filter() {
@Override
public boolean include(final IModelElement element) {
if (contentFilter.include(element)) {
if ((element.getElementType() & IModelElement.MASK_C1) == IWikitextSourceElement.C1_EMBEDDED
&& isRChunk(element)) {
ViewerUtils.expandToLevel(viewer, element, 0);
return false;
}
((ISourceStructElement) element).hasSourceChildren(this);
return false;
}
return false;
}
};
}
else {
final int sectionLevel;
if (type.equals("h2")) { //$NON-NLS-1$
sectionLevel= 2;
}
else if (type.equals("h3")) { //$NON-NLS-1$
sectionLevel= 3;
}
else if (type.equals("h4")) { //$NON-NLS-1$
sectionLevel= 4;
}
else if (type.equals("h5")) { //$NON-NLS-1$
sectionLevel= 5;
}
else if (type.equals("h6")) { //$NON-NLS-1$
sectionLevel= 6;
}
else {
sectionLevel= 0;
}
if (sectionLevel < 1 || sectionLevel > 6) {
return null;
}
expandFilter= new Filter() {
private boolean childExpand;
@Override
public boolean include(final IModelElement element) {
if (contentFilter.include(element)
&& (element.getElementType() & IModelElement.MASK_C2) == IWikitextSourceElement.C2_SECTIONING) {
final int currentLevel= (element.getElementType() & 0xf);
if (currentLevel < 1 || currentLevel > sectionLevel) {
return false; // nothing to do
}
if (currentLevel < sectionLevel) {
this.childExpand= false;
((ISourceStructElement) element).hasSourceChildren(this);
if (this.childExpand) {
return false; // done
}
}
// expand
ViewerUtils.expandToLevel(viewer, element, 0);
this.childExpand= true;
return false;
}
return false;
}
};
}
modelInfo.getSourceElement().hasSourceChildren(expandFilter);
}
return null;
}
}
private class ContentFilter implements IModelElement.Filter {
private boolean hideRChunks;
@Override
public boolean include(final IModelElement element) {
switch ((element.getElementType() & IModelElement.MASK_C1)) {
case IWikitextSourceElement.C1_EMBEDDED:
if (isRChunk(element)) {
return !this.hideRChunks;
}
}
return true;
}
}
private final ContentFilter filter= new ContentFilter();
public WikidocRweaveOutlinePage(final SourceEditor1 editor) {
super(editor, WikitextModel.WIKIDOC_TYPE_ID, WikidocRweaveRefactoringFactory.getInstance(),
"org.eclipse.statet.docmlet.menus.WikidocOutlineViewContextMenu"); //$NON-NLS-1$
}
@Override
protected IDialogSettings getDialogSettings() {
return DialogUtils.getDialogSettings(RedocsWikitextRPlugin.getInstance(), "WikidocRweaveOutlineView"); //$NON-NLS-1$
}
@Override
protected OutlineContentProvider createContentProvider() {
return new DocROutlineContentProvider(new OutlineContent());
}
@Override
protected IModelElement.Filter getContentFilter() {
return this.filter;
}
@Override
protected void configureViewer(final TreeViewer viewer) {
super.configureViewer(viewer);
viewer.setLabelProvider(new WikitextRweaveLabelProvider(0));
final ViewerDropSupport drop= new ViewerDropSupport(viewer, this,
getRefactoringFactory() );
drop.init();
final ViewerDragSupport drag= new ViewerDragSupport(viewer);
drag.init();
}
@Override
protected void initActions(final IServiceLocator serviceLocator,
final HandlerCollection handlers) {
super.initActions(serviceLocator, handlers);
final IHandlerService handlerService= serviceLocator.getService(IHandlerService.class);
handlers.add(".FilterRChunks", new FilterRChunks()); //$NON-NLS-1$
{ final IHandler2 handler= new ExpandElementsHandler();
handlers.add(EXPAND_ELEMENTS_COMMAND_ID, handler);
// handlerService.activateHandler(EXPAND_ELEMENTS_COMMAND_ID, handler); //$NON-NLS-1$
}
}
@Override
protected void contributeToActionBars(final IServiceLocator serviceLocator,
final IActionBars actionBars, final HandlerCollection handlers) {
super.contributeToActionBars(serviceLocator, actionBars, handlers);
final IToolBarManager toolBarManager= actionBars.getToolBarManager();
final RedocsRUIResources redocsResources= RedocsRUIResources.INSTANCE;
toolBarManager.appendToGroup(VIEW_EXPAND_GROUP_ID,
new ExpandElementsContributionItem(serviceLocator, handlers));
// toolBarManager.appendToGroup(ECommonsUI.VIEW_SORT_MENU_ID,
// new AlphaSortAction());
toolBarManager.appendToGroup(VIEW_FILTER_GROUP_ID,
new HandlerContributionItem(new CommandContributionItemParameter(serviceLocator,
null, HandlerContributionItem.NO_COMMAND_ID, null,
redocsResources.getImageDescriptor(RedocsRUIResources.LOCTOOL_FILTERCHUNKS_IMAGE_ID), null, null,
"Hide R Chunks", "R", null,
HandlerContributionItem.STYLE_CHECK, null, false ),
handlers.get(".FilterRChunks") ) ); //$NON-NLS-1$
// toolBarManager.appendToGroup(ECommonsUI.VIEW_FILTER_MENU_ID,
// new FilterLocalDefinitions());
}
@Override
protected void contextMenuAboutToShow(final IMenuManager m) {
super.contextMenuAboutToShow(m);
final IPageSite site= getSite();
if (m.find(IStatetUIMenuIds.GROUP_SUBMIT_MENU_ID) == null) {
m.insertBefore(ADDITIONS_GROUP_ID,
new Separator(IStatetUIMenuIds.GROUP_SUBMIT_MENU_ID) );
}
m.appendToGroup(IStatetUIMenuIds.GROUP_SUBMIT_MENU_ID,
new CommandContributionItem(new CommandContributionItemParameter(
site, null, RCodeLaunching.SUBMIT_SELECTION_COMMAND_ID, null,
null, null, null,
null, "R", null, //$NON-NLS-1$
CommandContributionItem.STYLE_PUSH, null, false) ));
m.appendToGroup(IStatetUIMenuIds.GROUP_SUBMIT_MENU_ID,
new CommandContributionItem(new CommandContributionItemParameter(
site, null, RCodeLaunching.SUBMIT_UPTO_SELECTION_COMMAND_ID, null,
null, null, null,
null, "U", null, //$NON-NLS-1$
CommandContributionItem.STYLE_PUSH, null, false) ));
m.add(new Separator(IStatetUIMenuIds.GROUP_ADD_MORE_ID));
}
protected IWikidocModelInfo getCurrentInputModel() {
final TreeViewer viewer= getViewer();
if (viewer == null) {
return null;
}
return (IWikidocModelInfo) getModelInfo(viewer.getInput());
}
}