--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.graphfile.ui.ontology</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.simantics.graph.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.simantics.graph.nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: http://www.simantics.org/GraphFileUI
+Bundle-SymbolicName: org.simantics.graphfile.ui.ontology
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.simantics.graphfile.ui.ontology
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.modeling.ontology;bundle-version="1.2.0",
+ org.simantics.silk.ontology;bundle-version="1.1.0",
+ org.simantics.layer0;bundle-version="1.1.0",
+ org.simantics.viewpoint.ontology;bundle-version="1.2.0",
+ org.simantics.action.ontology;bundle-version="1.1.0",
+ org.simantics.graphfile.ontology;bundle-version="0.1.0"
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ graph.tg
--- /dev/null
+L0 = <http://www.simantics.org/Layer0-1.1>
+MOD = <http://www.simantics.org/Modeling-1.2>
+SILK = <http://www.simantics.org/Silk-1.1>
+VP = <http://www.simantics.org/Viewpoint-1.2>
+ACT = <http://www.simantics.org/Action-1.1>
+GF = <http://www.simantics.org/GraphFile-0.1>
+
+GFUI = <http://www.simantics.org/GraphFileUI-1.0> : L0.Ontology
+ @L0.new
+ L0.HasResourceClass "org.simantics.graphfile.ui.ontology.GraphFileUIResource" : L0.String
+
+GFUI.BrowseContext : VP.BrowseContext
+
+ACTIONS = GFUI.BrowseContext.Actions : L0.Library
+
+ACTIONS.ImportFileDocument : ACT.Action
+ACTIONS.ImportDocumentFolder : ACT.Action
+ACTIONS.NewFileDocument : ACT.Action
+ACTIONS.NewDocumentFolder : ACT.Action
+ACTIONS.ExportFileDocument : ACT.Action
+ACTIONS.ExportDocumentFolder : ACT.Action
+
+GFUI.ModelingBrowseContext : VP.BrowseContext
+ VP.BrowseContext.IsIncludedIn MOD.ModelingBrowseContext
+ @VP.relationChildRule L0.Library L0.ConsistsOf GF.Folder
+ @VP.relationChildRule L0.Library L0.ConsistsOf GF.File
+ @VP.relationChildRule GF.Folder L0.ConsistsOf GF.File
+ @VP.relationChildRule GF.Folder L0.ConsistsOf GF.Folder
+
+ @VP.constantImageRule GF.Folder SILK.folder_page
+ @VP.constantImageRule GF.File SILK.page_white
+ @VP.customLabelRule GF.File VP.ResourceNameLabelRule
+
+GFUI.ModelingActionContext : VP.BrowseContext
+ VP.BrowseContext.IsIncludedIn MOD.ModelingActionContext
+ @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder
+ @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder
+ @VP.actionContribution "File" L0.Library SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument
+ @VP.actionContribution "File" GF.Folder SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument
+
+ @VP.actionContribution "Files" L0.Library SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument
+ @VP.actionContribution "Files" GF.Folder SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument
+
+ @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder
+ @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder
+
+ @VP.actionContribution "File" GF.File SILK.page_white VP.ExportActionCategory ACTIONS.ExportFileDocument
+ @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ExportActionCategory ACTIONS.ExportDocumentFolder
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.graphfile.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GraphfileUI
+Bundle-SymbolicName: org.simantics.graphfile.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.simantics.graphfile.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.ui.editors,
+ org.simantics.ui,
+ org.eclipse.jface.text;bundle-version="3.12.0",
+ org.simantics.graphfile.ontology,
+ org.slf4j.api;bundle-version="1.7.25",
+ org.simantics.document.ui;bundle-version="1.0.0"
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2013, 2014 Association for Decentralized
+ Information Management in Industry THTH ry.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the THTH Simantics
+ Division Member Component License which accompanies this
+ distribution, and is available at
+ http://www.simantics.org/legal/sdmcl-v10.html
+
+ Contributors:
+ Semantum Oy - initial API and implementation
+ -->
+
+<adapters>
+ <target interface="org.simantics.db.layer0.adapter.ActionFactory">
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ImportFileDocument"
+ class="org.simantics.document.ui.actions.ImportDocument">
+ <graph/>
+ <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+ </resource>
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ImportDocumentFolder"
+ class="org.simantics.document.ui.actions.ImportDocumentFolder">
+ <graph/>
+ <string>http://www.simantics.org/GraphFile-0.0/Folder</string>
+ <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+ </resource>
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/NewFileDocument"
+ class="org.simantics.document.ui.actions.NewFileDocument">
+ <graph/>
+ <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+ <string>File</string>
+ </resource>
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/NewDocumentFolder"
+ class="org.simantics.document.ui.actions.NewDocumentFolder">
+ <graph/>
+ <string>http://www.simantics.org/GraphFile-0.0/Folder</string>
+ <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+ </resource>
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ExportFileDocument"
+ class="org.simantics.document.ui.actions.ExportDocumentFile" />
+ <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ExportDocumentFolder"
+ class="org.simantics.document.ui.actions.ExportDocumentFolder">
+ <graph/>
+ <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+ <string>false</string>
+ </resource>
+ </target>
+
+</adapters>
\ No newline at end of file
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ adapters.xml
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ default="false"
+ name="Text Editor"
+ icon="platform:/plugin/com.famfamfam.silk/icons/page_white.png"
+ class="org.simantics.graphfile.ui.editor.PlainTextEditor"
+ id="org.simantics.graphfile.ui.editor.plaintexteditor">
+ </editor>
+ </extension>
+
+ <extension
+ point="org.simantics.ui.resourceEditorAdapter">
+ <adapter
+ label="Text Editor"
+ priority="11"
+ editorId="org.simantics.graphfile.ui.editor.plaintexteditor"
+ type_uris="http://www.simantics.org/Document-0.0/FileDocument">
+ </adapter>
+ </extension>
+</plugin>
--- /dev/null
+package org.simantics.graphfile.ui.editor;
+
+import java.util.function.Supplier;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.simantics.Simantics;
+import org.simantics.db.Session;
+import org.simantics.db.common.request.ParametrizedRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.combinations.Combinators;
+import org.simantics.ui.workbench.IResourceEditorInput;
+import org.simantics.ui.workbench.ResourceEditorSupport;
+import org.simantics.ui.workbench.TitleRequest;
+import org.simantics.ui.workbench.TitleUpdater;
+import org.simantics.ui.workbench.ToolTipRequest;
+import org.simantics.ui.workbench.editor.input.InputValidationCombinators;
+
+/**
+ * @author Antti Villberg
+ */
+public class PlainTextEditor extends TextEditor {
+
+ boolean isDisposed = false;
+
+ ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =
+ Combinators.compose(
+ InputValidationCombinators.hasURI(),
+ InputValidationCombinators.extractInputResource()
+ );
+
+ ResourceEditorSupport support;
+
+ public PlainTextEditor() {
+ super();
+ setDocumentProvider(new PlainTextEditorDocumentProvider());
+ //setSourceViewerConfiguration(new QueueTextEditorViewerConfiguration(new QueueTextEditorColorManager()));
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ super.init(site, input);
+
+ support = new ResourceEditorSupport(this, INPUT_VALIDATOR);
+ support.activateValidation();
+ try {
+ getResourceEditorInput().init(null);
+ } catch (DatabaseException e) {
+ throw new PartInitException("Failed to initialize " + input, e);
+ }
+ }
+
+ protected IResourceEditorInput getResourceEditorInput() {
+ return (IResourceEditorInput) getEditorInput();
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+ updatePartName();
+ }
+
+ private void updatePartName() {
+ setPartName(getEditorInput().getName());
+
+ Session session = Simantics.peekSession();
+ if (session != null) {
+ Supplier<Boolean> disposedCallback = () -> isDisposed;
+ session.asyncRequest(
+ new TitleRequest(null, getResourceEditorInput()),
+ new TitleUpdater(getSite().getShell().getDisplay(), this::setPartName, disposedCallback));
+ session.asyncRequest(
+ new ToolTipRequest(getSite().getId(), getResourceEditorInput()),
+ new TitleUpdater(getSite().getShell().getDisplay(), this::setTitleToolTip, disposedCallback));
+ }
+
+ }
+
+ @Override
+ public void dispose() {
+ isDisposed = true;
+ if (support != null) {
+ support.dispose();
+ support = null;
+ }
+ super.dispose();
+ }
+
+}
--- /dev/null
+package org.simantics.graphfile.ui.editor;
+
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.AbstractDocumentProvider;
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.DocumentResource;
+import org.simantics.graphfile.ontology.GraphFileResource;
+import org.simantics.ui.workbench.ResourceEditorInput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PlainTextEditorDocumentProvider extends AbstractDocumentProvider {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PlainTextEditor.class);
+
+ protected String currentText;
+
+ @Override
+ protected IDocument createDocument(Object element) throws CoreException {
+ ResourceEditorInput input = (ResourceEditorInput)element;
+ final Resource resource = input.getResource();
+ try {
+ return Simantics.getSession().syncRequest(new UniqueRead<Document>() {
+ @Override
+ public Document perform(ReadGraph graph) throws DatabaseException {
+
+ GraphFileResource GF = GraphFileResource.getInstance(graph);
+ DocumentResource DOC = DocumentResource.getInstance(graph);
+ if (!graph.isInstanceOf(resource, DOC.FileDocument))
+ throw new DatabaseException("Invalid input resource for PlainTextEditor: " + NameUtils.getSafeName(graph, resource));
+
+ byte[] bytes = graph.getPossibleRelatedValue(resource, GF.HasFiledata, Bindings.BYTE_ARRAY);
+
+ currentText = bytes != null ? new String(bytes, StandardCharsets.UTF_8) : "";
+
+ return new Document(currentText);
+
+ }
+ });
+ } catch (DatabaseException e) {
+ StringWriter sw = new StringWriter();
+ LOGGER.error("Failed to create document", e);
+ return new Document(sw.toString());
+ }
+ }
+
+ @Override
+ protected IAnnotationModel createAnnotationModel(Object element)
+ throws CoreException {
+ return new AnnotationModel();
+ }
+
+ @Override
+ protected void doSaveDocument(IProgressMonitor monitor, Object element,
+ IDocument document, boolean overwrite) throws CoreException {
+ ResourceEditorInput input = (ResourceEditorInput)element;
+ final Resource resource = input.getResource();
+ final String text = document.get();
+ currentText = text;
+ Simantics.getSession().asyncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ GraphFileResource GF = GraphFileResource.getInstance(graph);
+ graph.claimLiteral(resource, GF.HasFiledata, text.getBytes(StandardCharsets.UTF_8));
+ graph.claimLiteral(resource, GF.LastModified, System.currentTimeMillis());
+ }
+ });
+ }
+
+ @Override
+ protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+ return null;
+ }
+
+ @Override
+ public boolean isModifiable(Object element) {
+ return true;
+ }
+
+ @Override
+ public boolean isReadOnly(Object element) {
+ return false;
+ }
+
+ @Override
+ public boolean canSaveDocument(Object element) {
+ return !getDocument(element).get().equals(currentText);
+ }
+
+}
<module>org.simantics.graph.db</module>
<module>org.simantics.graphfile</module>
<module>org.simantics.graphfile.ontology</module>
+ <module>org.simantics.graphfile.ui</module>
+ <module>org.simantics.graphfile.ui.ontology</module>
<module>org.simantics.graphviz</module>
<module>org.simantics.graphviz.ui</module>
<module>org.simantics.gnuplot</module>