From 0888041d71e2550795a6c271f612953902b79f22 Mon Sep 17 00:00:00 2001 From: Amine Lajmi Date: Sun, 12 Feb 2017 02:08:37 +0100 Subject: [PATCH] added support for form editors --- .../texteditor/form/BasicTextFormEditor.java | 69 ++++ .../form/BasicTextFormEditorPage.java | 367 ++++++++++++++++++ .../form/TextFormEditorWithCanvasPage.java | 95 +++++ .../internal/TextEditorImageProvider.java | 21 + .../ui/actions/OpenResourceInFormAction.java | 75 ++++ .../ui/commands/OpenResourceCommand.java | 61 +++ .../workspace/IWorkspaceConstants.java | 2 +- .../common/forms/BasicXextFormEditor.java | 27 ++ .../common/forms/BasicXextFormEditorPage.java | 214 ++++++++++ 9 files changed, 930 insertions(+), 1 deletion(-) create mode 100644 plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditor.java create mode 100644 plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditorPage.java create mode 100644 plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/TextFormEditorWithCanvasPage.java create mode 100644 plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/internal/TextEditorImageProvider.java create mode 100644 plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/actions/OpenResourceInFormAction.java create mode 100644 plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/commands/OpenResourceCommand.java create mode 100644 plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditor.java create mode 100644 plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditorPage.java diff --git a/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditor.java b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditor.java new file mode 100644 index 0000000..8d9fa12 --- /dev/null +++ b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditor.java @@ -0,0 +1,69 @@ +/** + * + * + * Copyright (c) 2017 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.texteditor.form; + +import org.apache.log4j.Logger; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.editor.FormEditor; + +public class BasicTextFormEditor extends FormEditor{ + + private static final long serialVersionUID = 4934273569844174609L; + + static final Logger logger = Logger.getLogger(BasicTextFormEditor.class); + + public BasicTextFormEditor() { + super(); + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + super.init(site, input); + } + + @Override + protected void setPageText(int pageIndex, String text) { + super.setPageText(pageIndex, text); + } + + @Override + protected void addPages() { + try { + setActiveEditor(this); + addPage(new TextFormEditorWithCanvasPage(this)); + } catch (PartInitException e) { + logger.error(e.getStackTrace(), e); + } + } + + @Override + public void doSave(IProgressMonitor monitor) { + getActiveEditor().doSave(monitor); + } + + @Override + public void doSaveAs() { + getActiveEditor().doSaveAs(); + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditorPage.java b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditorPage.java new file mode 100644 index 0000000..ce830f6 --- /dev/null +++ b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/BasicTextFormEditorPage.java @@ -0,0 +1,367 @@ +/** + * + * + * Copyright (c) 2017 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.texteditor.form; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Scanner; + +import org.apache.log4j.Logger; +import org.dslforge.styledtext.BasicText; +import org.dslforge.styledtext.IContentAssistListener; +import org.dslforge.styledtext.ITextChangeListener; +import org.dslforge.styledtext.ITextModifyListener; +import org.dslforge.styledtext.TextChangedEvent; +import org.dslforge.styledtext.jface.IDocument; +import org.dslforge.styledtext.jface.ITextViewer; +import org.dslforge.styledtext.jface.TextDocument; +import org.dslforge.styledtext.jface.TextViewer; +import org.dslforge.texteditor.internal.Activator; +import org.dslforge.texteditor.internal.TextEditorImageProvider; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.emf.common.ui.URIEditorInput; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.rap.json.JsonObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IPathEditorInput; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; + +public class BasicTextFormEditorPage extends FormPage { + + private static final String FORM_EDITOR_SECTION_DESCRIPTION = "Write the code below then press the Run button."; + + static final Logger logger = Logger.getLogger(BasicTextFormEditorPage.class); + + public static final String FORM_EDITOR_PAGE_ID = "org.dslforge.texteditor.form.page"; + public static final String FORM_EDITOR_PAGE_TITLE = "Content"; + public static final String FORM_EDITOR_SECTION_TITLE = "Section"; + public static final String FORM_EDITOR_FORM_TITLE = "Form"; + protected static final int SECTION_HEADER_VERTICAL_SPACING = 6; + + protected ITextViewer viewer; + protected IPath filePath; + + public BasicTextFormEditorPage(FormEditor editor, String id, String title) { + super(editor, id, title); + } + + public BasicTextFormEditorPage(BasicTextFormEditor editor) { + super(editor, FORM_EDITOR_PAGE_ID, FORM_EDITOR_PAGE_TITLE); + } + + @Override + public void init(IEditorSite site, IEditorInput input) { + super.init(site, input); + setPartName(input.getName()); + } + + @Override + protected void setInput(IEditorInput input) { + super.setInput(input); + if (input instanceof IPathEditorInput) + filePath = ((IPathEditorInput) input).getPath(); + else if (input instanceof URIEditorInput) + filePath = new Path(((URIEditorInput) input).getURI().toFileString()); + else + throw new UnsupportedOperationException("Unsupported editor input type."); + } + + protected void loadContentFromFile() { + Display display = Display.getCurrent(); + if (display != null) { + display.syncExec(new Runnable() { + @Override + public void run() { + String content = ""; + try { + content = readFromFile(); + } catch (IOException ex) { + logger.error(ex.getMessage(), ex); + } finally { + setTextViewer(content); + viewer.getTextWidget().setURL(filePath.lastSegment().toString()); + } + } + }); + } + } + + protected void setTextViewer(String content) { + viewer.setText(content); + viewer.getTextWidget().setText(content); + } + + protected String readFromFile() throws IOException { + logger.debug("Reading from file " + filePath); + StringBuilder text = new StringBuilder(); + String NL = System.getProperty("line.separator"); + long start = System.currentTimeMillis(); + Scanner scanner = new Scanner(new FileInputStream(filePath.toFile()), "UTF-8"); + try { + while (scanner.hasNextLine()) { + text.append(scanner.nextLine() + NL); + } + } finally { + scanner.close(); + } + long end = System.currentTimeMillis(); + logger.debug("Reading took: " + ((end - start) / 1000)); + return text.toString(); + } + + @Override + protected void createFormContent(IManagedForm managedForm) { + super.createFormContent(managedForm); + ScrolledForm form = managedForm.getForm(); + FormToolkit toolkit = managedForm.getToolkit(); + form.setText(FORM_EDITOR_FORM_TITLE); + form.setImage(Activator.getImageDescriptor(TextEditorImageProvider.FILE).createImage()); + toolkit.decorateFormHeading(form.getForm()); + fillBody(managedForm, toolkit); + form.updateToolBar(); + } + + protected void fillBody(IManagedForm managedForm, FormToolkit toolkit) { + Composite body = managedForm.getForm().getBody(); + GridData layoutData = new GridData(); + layoutData.horizontalAlignment = SWT.FILL; + layoutData.verticalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = false; + layoutData.grabExcessVerticalSpace = true; + body.setLayoutData(layoutData); + createEditorSection(body, toolkit); + } + + protected void createEditorSection(Composite parent, FormToolkit toolkit) { + Section section = toolkit.createSection(parent, Section.TITLE_BAR | Section.DESCRIPTION); + final GridData layoutData = new GridData(SWT.BORDER | GridData.FILL_BOTH); + layoutData.grabExcessHorizontalSpace = false; + layoutData.widthHint = 400; + section.setLayoutData(layoutData); + section.setText(FORM_EDITOR_SECTION_TITLE); + section.setDescription(FORM_EDITOR_SECTION_DESCRIPTION); + + viewer = createTextViewer(section, toolkit); + viewer.setDocument(createEmptyDocument()); + getSite().setSelectionProvider(new ISelectionProvider() { + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + } + @Override + public ISelection getSelection() { + return new StructuredSelection(getEditorInput()); + } + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + } + @Override + public void setSelection(ISelection selection) { + } + }); + + loadContentFromFile(); + firePropertyChange(PROP_INPUT); + installListeners(); + } + + protected Section createSection(Composite parent, FormToolkit toolkit, String title) { + return createSection(parent, toolkit, title, null); + } + + protected Section createSection(Composite parent, FormToolkit toolkit, String title, String description) { + Section section = toolkit.createSection(parent, Section.TITLE_BAR | Section.DESCRIPTION); + final GridData layoutData = new GridData(SWT.BORDER | GridData.FILL_BOTH); + section.setLayoutData(layoutData); + section.setText(title); + if (description==null || description.length()==0) + return section; + section.setDescription(description); + return section; + } + + /** + * Creates this editor's styled text viewer + */ + protected ITextViewer createTextViewer(Section section, FormToolkit toolkit) { + Composite container = toolkit.createComposite(section); + section.setClient(container); + container.setLayout(new GridLayout()); + container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + BasicText textWidget = createTextWidget(container, container.getStyle()); + return new TextViewer(textWidget, section, container.getStyle()); + } + + /** + * Creates an empty document + */ + protected IDocument createEmptyDocument() { + return new TextDocument(); + } + + /** + * Creates and configures this editor's styled text widget + */ + protected BasicText createTextWidget(Composite parent, int styles) { + BasicText textWidget = new BasicText(parent, SWT.FILL); + GridData textLayoutData = new GridData(); + textLayoutData.horizontalAlignment = SWT.FILL; + textLayoutData.verticalAlignment = SWT.FILL; + textLayoutData.grabExcessHorizontalSpace = true; + textLayoutData.grabExcessVerticalSpace = true; + textWidget.setLayoutData(textLayoutData); + textWidget.setEditable(true); + return textWidget; + } + + ITextChangeListener iTextChangeListener = new ITextChangeListener() { + private static final long serialVersionUID = 1L; + + @Override + public void handleTextChanged(TextChangedEvent e) { + JsonObject object = (JsonObject) e.data; + BasicTextFormEditorPage.this.handleTextChanged(object); + } + }; + + protected void handleTextChanged(JsonObject object) { + //override in subclasses. + } + + IContentAssistListener iContentAssistListener = new IContentAssistListener() { + private static final long serialVersionUID = 1L; + + @Override + public boolean verifyKey(VerifyEvent event) { + JsonObject data = (JsonObject) event.data; + if (data != null && data instanceof JsonObject) { + JsonObject position = (JsonObject) data.get("pos"); + int row = position.get("row").asInt(); + int column = position.get("column").asInt(); + int offset = viewer.getTextWidget().getOffsetAtPosition(row, column); + createCompletionProposals(offset); + return true; + } + return false; + } + }; + + protected void createCompletionProposals(int offsetAtPosition) { + //override in subclasses. + } + + @SuppressWarnings("serial") + protected void installListeners() { + BasicText textWidget = viewer.getTextWidget(); + if (textWidget!= null && !textWidget.isDisposed()) { + textWidget.addTextChangeListener(iTextChangeListener); + + KeyListener iKeyListener = new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + //customize in subclasses + } + + @Override + public void keyPressed(KeyEvent e) { + if ((e.stateMask & SWT.CTRL) == SWT.CTRL) { + //createCompletionProposals(); + } + } + }; + textWidget.addKeyListener(iKeyListener); + + textWidget.addTextModifyListener(new ITextModifyListener() { + + @Override + public void handleTextModified(ModifyEvent event) { + JsonObject object = (JsonObject) event.data; + String text = object.get("value") != null ? object.get("value").asString() : null; + if (text!=null) { + viewer.setText(text); + } + } + }); + + textWidget.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent event) { + //customize in subclasses + } + + @Override + public void focusGained(FocusEvent event) { + //customize in subclasses + } + }); + textWidget.addContentAssistListener(iContentAssistListener); + textWidget.addMouseListener(new MouseListener() { + + @Override + public void mouseUp(MouseEvent e) { + //customize in subclasses + } + + @Override + public void mouseDown(MouseEvent e) { + //customize in subclasses + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + //customize in subclasses + } + }); + } + } + + public ITextViewer getViewer() { + return viewer; + } + + public IPath getFilePath() { + return filePath; + } + + public void setFilePath(IPath path) { + this.filePath = path; + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/TextFormEditorWithCanvasPage.java b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/TextFormEditorWithCanvasPage.java new file mode 100644 index 0000000..88e1ac2 --- /dev/null +++ b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/form/TextFormEditorWithCanvasPage.java @@ -0,0 +1,95 @@ +/** + * + * + * Copyright (c) 2017 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.texteditor.form; + +import org.apache.log4j.Logger; +import org.eclipse.rap.json.JsonObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; + +public class TextFormEditorWithCanvasPage extends BasicTextFormEditorPage { + + static final Logger logger = Logger.getLogger(TextFormEditorWithCanvasPage.class); + + protected static final String FORM_EDITOR_PAGE_ID = "org.dslforge.texteditor.form.page.canvas"; + protected static final String FORM_EDITOR_PAGE_TITLE = "Content"; + protected static final String FORM_EDITOR_SECTION_TITLE = "Section"; + protected static final String FORM_EDITOR_FORM_TITLE = "Form"; + protected static final int SECTION_HEADER_VERTICAL_SPACING = 6; + protected static final String FORM_EDITOR_CANVAS_TITLE = "Canvas"; + + public TextFormEditorWithCanvasPage(FormEditor editor, String id, String title) { + super(editor, id, title); + } + + public TextFormEditorWithCanvasPage(BasicTextFormEditor editor) { + super(editor, FORM_EDITOR_PAGE_ID, FORM_EDITOR_PAGE_TITLE); + } + + @Override + protected void fillBody(IManagedForm managedForm, FormToolkit toolkit) { + Composite body = managedForm.getForm().getBody(); + body.setLayout(new GridLayout(3, false)); + body.setLayoutData(new GridData(SWT.BORDER | GridData.FILL_BOTH)); + createEditorSection(body, toolkit); + createPanelSection(body, toolkit); + createCanvasSection(body, toolkit); + } + + protected void createPanelSection(Composite body, FormToolkit toolkit) { + final String runButtonLabel = "Run"; + Button runButton = toolkit.createButton(body, runButtonLabel, SWT.PUSH); + runButton.addSelectionListener(new SelectionListener() { + private static final long serialVersionUID = 1L; + + @Override + public void widgetSelected(SelectionEvent e) { + handleRunButtonPressed(e); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + //do nothing. + } + }); + } + + protected void handleRunButtonPressed(SelectionEvent e) { + //implement in subclasses + } + + protected void createCanvasSection(Composite body, FormToolkit toolkit) { + Section section = createSection(body, toolkit, FORM_EDITOR_CANVAS_TITLE); + Canvas canvas = new Canvas(section, SWT.NONE); + GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + canvas.setLayoutData(layoutData); + } + + @Override + protected void handleTextChanged(JsonObject object) { + //disabled + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/internal/TextEditorImageProvider.java b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/internal/TextEditorImageProvider.java new file mode 100644 index 0000000..3e03a38 --- /dev/null +++ b/plugins/org.dslforge.texteditor/src/org/dslforge/texteditor/internal/TextEditorImageProvider.java @@ -0,0 +1,21 @@ +/** + * + * + * Copyright (c) 2015 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.texteditor.internal; + +public class TextEditorImageProvider { + + public static final String FILE = "icons/file_obj.png"; +} \ No newline at end of file diff --git a/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/actions/OpenResourceInFormAction.java b/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/actions/OpenResourceInFormAction.java new file mode 100644 index 0000000..0bb48e1 --- /dev/null +++ b/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/actions/OpenResourceInFormAction.java @@ -0,0 +1,75 @@ +/** + * + * + * Copyright (c) 2015 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.workspace.ui.actions; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.dslforge.workspace.ui.util.EditorUtil; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +public class OpenResourceInFormAction extends AbstractWorkspaceAction { + + static final Logger logger = Logger.getLogger(OpenResourceInFormAction.class); + + @Override + public void run(IAction action) { + Iterator iterator = ((StructuredSelection) getSelection()).iterator(); + Object object = iterator.next(); + if (object instanceof File) { + final File file = (File) object; + openWithEditor(file); + } + } + + public boolean openWithEditor(final File file) { + IRunnableWithProgress operation = new IRunnableWithProgress() { + public void run(IProgressMonitor progressMonitor) { + try { + if (file.exists() && !file.isDirectory()) { + String absolutePath = file.getAbsolutePath(); + IWorkbench workbench = PlatformUI.getWorkbench(); + if (EditorUtil.openFormEditor(workbench, new Path(absolutePath)) != null) { + logger.info("Opened form editor on file " + absolutePath); + } + } + } catch (Exception ex) { + logger.error(ex.getMessage(), ex); + } finally { + progressMonitor.done(); + } + } + }; + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, operation); + } catch (InvocationTargetException ex) { + logger.error(ex.getMessage(), ex); + return false; + } catch (InterruptedException ex) { + logger.error(ex.getMessage(), ex); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/commands/OpenResourceCommand.java b/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/commands/OpenResourceCommand.java new file mode 100644 index 0000000..fa85534 --- /dev/null +++ b/plugins/org.dslforge.workspace.ui/src/org/dslforge/workspace/ui/commands/OpenResourceCommand.java @@ -0,0 +1,61 @@ +package org.dslforge.workspace.ui.commands; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; + +import org.apache.log4j.Logger; +import org.dslforge.workspace.ui.util.EditorUtil; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +public class OpenResourceCommand extends AbstractWorkspaceCommand { + + static final Logger logger = Logger.getLogger(OpenResourceCommand.class); + + public OpenResourceCommand() { + super(); + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + File file = unwrap(event, File.class); + if (!file.isDirectory()) + return openWithEditor(file); + return false; + } + + public boolean openWithEditor(final File file) { + IRunnableWithProgress operation = new IRunnableWithProgress() { + public void run(IProgressMonitor progressMonitor) { + try { + if (file.exists() && !file.isDirectory()) { + String absolutePath = file.getAbsolutePath(); + IWorkbench workbench = PlatformUI.getWorkbench(); + if (EditorUtil.openEditor(workbench, new Path(absolutePath)) != null) { + logger.info("Opened editor on file " + absolutePath); + } + } + } catch (Exception ex) { + logger.error(ex.getMessage(), ex); + } finally { + progressMonitor.done(); + } + } + }; + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, operation); + } catch (InvocationTargetException ex) { + logger.error(ex.getMessage(), ex); + return false; + } catch (InterruptedException ex) { + logger.error(ex.getMessage(), ex); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.workspace/src/org/dslforge/workspace/IWorkspaceConstants.java b/plugins/org.dslforge.workspace/src/org/dslforge/workspace/IWorkspaceConstants.java index 4f0e9f3..6ad4857 100644 --- a/plugins/org.dslforge.workspace/src/org/dslforge/workspace/IWorkspaceConstants.java +++ b/plugins/org.dslforge.workspace/src/org/dslforge/workspace/IWorkspaceConstants.java @@ -25,5 +25,5 @@ public interface IWorkspaceConstants { public static final String VISIBILITY_PUBLIC = "public"; public static final String LOCKED = "locked"; public static final String UNLOCKED = "unlocked"; - public static final String WORKSPACE_DEFAULT_PATH = "D:/www/dslforge/workspace"; + public static final String WORKSPACE_DEFAULT_PATH = "D:/www/dslforge/workbench"; } diff --git a/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditor.java b/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditor.java new file mode 100644 index 0000000..fe663c2 --- /dev/null +++ b/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditor.java @@ -0,0 +1,27 @@ +/** + * + * + * Copyright (c) 2017 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.xtext.common.forms; + +import org.dslforge.texteditor.form.BasicTextFormEditor; + +public class BasicXextFormEditor extends BasicTextFormEditor { + + private static final long serialVersionUID = 1127501393874924857L; + + public BasicXextFormEditor() { + super(); + } +} \ No newline at end of file diff --git a/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditorPage.java b/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditorPage.java new file mode 100644 index 0000000..d82b3a0 --- /dev/null +++ b/plugins/org.dslforge.xtext.common/src/org/dslforge/xtext/common/forms/BasicXextFormEditorPage.java @@ -0,0 +1,214 @@ +/** + * + * + * Copyright (c) 2017 PlugBee. 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: + * Amine Lajmi - Initial API and implementation + * + * + */ +package org.dslforge.xtext.common.forms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.apache.log4j.Logger; +import org.dslforge.styledtext.Annotation; +import org.dslforge.styledtext.Annotation.AceSeverity; +import org.dslforge.styledtext.BasicText; +import org.dslforge.texteditor.form.BasicTextFormEditorPage; +import org.dslforge.xtext.common.IBasicXtextEditor; +import org.dslforge.xtext.common.IXtextResourceFactory; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.rap.json.JsonObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.diagnostics.Severity; +import org.eclipse.xtext.resource.IEObjectDescription; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.IResourceDescription.Manager; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.util.ReplaceRegion; +import org.eclipse.xtext.validation.CheckMode; +import org.eclipse.xtext.validation.IConcreteSyntaxValidator; +import org.eclipse.xtext.validation.IResourceValidator; +import org.eclipse.xtext.validation.Issue; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import com.google.inject.Injector; + +public class BasicXextFormEditorPage extends BasicTextFormEditorPage implements IBasicXtextEditor{ + + static final Logger logger = Logger.getLogger(BasicXextFormEditorPage.class); + @Inject + protected Injector injector; + @Inject + protected IXtextResourceFactory xtextResourceFactory; + protected XtextResource xtextResource; + protected Iterable iObjectDescriptions; + protected String languageName; + @Inject + protected IResourceDescription.Manager descriptionManager; + + public BasicXextFormEditorPage(FormEditor editor, String id, String title) { + super(editor, id, title); + } + + public BasicXextFormEditorPage(BasicXextFormEditor editor) { + super(editor, FORM_EDITOR_PAGE_ID, FORM_EDITOR_PAGE_TITLE); + } + + @Override + public void init(IEditorSite site, IEditorInput input) { + super.init(site, input); + xtextResource = (XtextResource) xtextResourceFactory.createResource(getEditorInput()); + } + + @Override + protected BasicText createTextWidget(Composite parent, int styles) { + BasicText textWidget = new BasicText(parent, SWT.FILL); + GridData textLayoutData = new GridData(); + textLayoutData.horizontalAlignment = SWT.FILL; + textLayoutData.verticalAlignment = SWT.FILL; + textLayoutData.grabExcessHorizontalSpace = true; + textLayoutData.grabExcessVerticalSpace = true; + textWidget.setLayoutData(textLayoutData); + textWidget.setEditable(true); + return textWidget; + } + + @Override + protected void handleTextChanged(JsonObject object) { + int offset = object.get("offset") != null ? object.get("offset").asInt() : 0; + String value = object.get("value") != null ? object.get("value").asString() : null; + if (value != null) { + ReplaceRegion replaceRegionToBeProcessed = new ReplaceRegion(offset, value.length(), value); + xtextResource.update(replaceRegionToBeProcessed.getOffset(), replaceRegionToBeProcessed.getLength(), + replaceRegionToBeProcessed.getText()); + } + updateIndex(); + } + + @Override + public void validateResource() { + SafeRunnable.run(new SafeRunnable() { + private static final long serialVersionUID = 1L; + public void run() { + IResourceValidator resourceValidator = xtextResource.getResourceServiceProvider() + .getResourceValidator(); + try { + List issues = resourceValidator.validate(xtextResource, CheckMode.NORMAL_AND_FAST, + CancelIndicator.NullImpl); + createAnnotations(issues); + } catch (Exception ex) { + if (ex instanceof RuntimeException) { + logger.error(ex.getMessage(), ex); + } + } + } + }); + } + + @Override + public void updateIndex() { + SafeRunnable.run(new SafeRunnable() { + private static final long serialVersionUID = 1L; + public void run() { + iObjectDescriptions = Collections.emptyList(); + EcoreUtil2.resolveAll(xtextResource); + IResourceDescription resourceDescription = descriptionManager.getResourceDescription(xtextResource); + Manager manager = xtextResource.getResourceServiceProvider().getResourceDescriptionManager(); + resourceDescription = manager.getResourceDescription(xtextResource); + iObjectDescriptions = Iterables.concat(iObjectDescriptions, resourceDescription.getExportedObjects()); + Iterable referrables = Iterables.transform(iObjectDescriptions, + new Function() { + @Override + public String apply(IEObjectDescription input) { + return input.getName().toString() + ":" + input.getEClass().getName(); + } + }); + viewer.getTextWidget().setScope(Lists.newArrayList(referrables)); + } + }); + } + + protected void createAnnotations(List issues) { + List annotations = new ArrayList(); + for (Issue issue : issues) { + Integer offset = issue.getOffset(); + Integer line = issue.getLineNumber(); + int lineNumber = line.intValue(); + String message = issue.getMessage(); + Severity severity = issue.getSeverity(); + annotations.add(new Annotation(convertSeverity(severity), lineNumber, offset, message)); + } + getViewer().getTextWidget().setAnnotations(annotations); + } + + protected void updateResource(String text) { + ReplaceRegion replaceRegionToBeProcessed = new ReplaceRegion(0, text.length(), text); + xtextResource.update(replaceRegionToBeProcessed.getOffset(), replaceRegionToBeProcessed.getLength(), + replaceRegionToBeProcessed.getText()); + } + + protected boolean validateSyntax(EObject object, XtextResource hostingResource) { + List diagnostics = new ArrayList(); + IConcreteSyntaxValidator concreteSyntaxValidator = hostingResource.getConcreteSyntaxValidator(); + concreteSyntaxValidator.validateRecursive(object, + new IConcreteSyntaxValidator.DiagnosticListAcceptor(diagnostics), new HashMap()); + if (!diagnostics.isEmpty()) { + return false; + } + return true; + } + + private AceSeverity convertSeverity(Severity severity) { + switch (severity) { + case ERROR: + return AceSeverity.ERROR; + case WARNING: + return AceSeverity.WARNING; + case INFO: + return AceSeverity.INFO; + default: + break; + } + return null; + } + + public void setLanguageName(String name) { + this.languageName = name; + } + + public String getLanguageName() { + return languageName; + } + + protected Injector getInjector() { + return injector; + } + + protected void setInjector(Injector injector) { + injector.injectMembers(this); + this.injector = injector; + } +} \ No newline at end of file