blob: c5567a1d006d7a6e4952b84fae4da0658d6dfcbc [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2019 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.docmlet.tex.ui.editors;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.text.core.util.TextUtils;
import org.eclipse.statet.ecommons.ui.actions.SubMenuContributionItem;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.docmlet.tex.core.TexCore;
import org.eclipse.statet.docmlet.tex.core.commands.LtxCommandCategories;
import org.eclipse.statet.docmlet.tex.core.commands.LtxCommandCategories.Category;
import org.eclipse.statet.docmlet.tex.core.commands.TexCommand;
import org.eclipse.statet.docmlet.tex.ui.TexUI;
import org.eclipse.statet.docmlet.tex.ui.TexUIResources;
import org.eclipse.statet.docmlet.tex.ui.editors.LtxEditor;
import org.eclipse.statet.internal.docmlet.tex.ui.editors.LtxCommandCompletionProposal.LtxCommandProposalParameters;
import org.eclipse.statet.internal.docmlet.tex.ui.sourceediting.LtxAssistInvocationContext;
@NonNullByDefault
public class LtxSymbolsMenuContributions extends CompoundContributionItem {
private static class CategoryContributions extends SubMenuContributionItem implements SelectionListener {
private final Category category;
public CategoryContributions(final Category category) {
this.category= category;
}
@Override
protected String getLabel() {
return this.category.getLabel();
}
@Override
protected @Nullable Image getImage() {
return null;
}
@Override
protected void fillMenu(final Menu menu) {
final TexUIResources texResources= TexUIResources.INSTANCE;
final List<TexCommand> commands= this.category.getCommands();
for (final TexCommand command : commands) {
final MenuItem item= new MenuItem(menu, SWT.PUSH);
final Image image= texResources.getCommandImage(command);
if (image != null) {
item.setImage(image);
}
item.setText(command.getControlWord());
item.setData(command);
item.addSelectionListener(this);
}
}
@Override
public void widgetDefaultSelected(final SelectionEvent event) {
}
@Override
public void widgetSelected(final SelectionEvent event) {
final TexCommand command= (TexCommand) nonNullAssert(event.widget.getData());
final IEditorPart editor= UIAccess.getActiveWorkbenchPage(true).getActiveEditor();
if (editor instanceof LtxEditor) {
final LtxEditor texEditor= (LtxEditor) editor;
if (!texEditor.isEditable(true)) {
return;
}
final SourceViewer viewer= ((LtxEditor) editor).getViewer();
Point selection= viewer.getSelectedRange();
if (selection == null || selection.x < 0) {
return;
}
try {
final String contentType= TextUtils.getContentType(viewer.getDocument(),
texEditor.getDocumentContentInfo(), selection.x,
selection.y == 0 );
final LtxAssistInvocationContext context= new LtxAssistInvocationContext(texEditor,
selection.x, contentType,
true, new NullProgressMonitor() );
final LtxCommandCompletionProposal proposal= new LtxCommandCompletionProposal(
new LtxCommandProposalParameters(context, command) );
proposal.apply(viewer, (char) 0, 1, context.getInvocationOffset());
selection= proposal.getSelection(viewer.getDocument());
if (selection != null) {
viewer.setSelectedRange(selection.x, selection.y);
viewer.revealRange(selection.x, selection.y);
}
else {
viewer.revealRange(context.getInvocationOffset(), 0);
}
}
catch (final Exception e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, TexUI.BUNDLE_ID,
"An error occurred when inserting LaTeX symbol.",
e ));
}
}
}
}
private LtxCommandCategories categories;
public LtxSymbolsMenuContributions() {
}
@Override
protected IContributionItem[] getContributionItems() {
this.categories= new LtxCommandCategories(TexCore.getWorkbenchAccess().getTexCommandSet().getAllLtxCommands()) {
@Override
protected boolean include(final TexCommand command) {
return ((command.getType() & TexCommand.MASK_MAIN) == TexCommand.MATHSYMBOL
&& (command.getType() & TexCommand.MASK_C3) != TexCommand.C3_MATHSYMBOL_OP_NAMED);
}
};
final List<Category> categories= this.categories.getCategories();
final List<IContributionItem> items= new ArrayList<>(categories.size()+10);
int sep= 0;
for (final Category category : categories) {
final int current= (category.getCommands().get(0).getType() & TexCommand.MASK_C2);
if (sep != current) {
sep= current;
if (items.size() > 0) {
items.add(new Separator());
}
}
items.add(new CategoryContributions(category));
}
return items.toArray(new @NonNull IContributionItem[items.size()]);
}
}