]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.ui/src/org/simantics/document/ui/function/All.java
effe30cd9b51c0ead4d1b7e97105d48c93fd0838
[simantics/platform.git] / bundles / org.simantics.document.ui / src / org / simantics / document / ui / function / All.java
1 /*******************************************************************************
2  * Copyright (c) 2012, 2017 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - (#7066) introducing logger & refactoring
12  *******************************************************************************/
13 package org.simantics.document.ui.function;
14
15 import java.util.TreeMap;
16
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Status;
19 import org.eclipse.jface.viewers.ISelectionProvider;
20 import org.eclipse.jface.viewers.StructuredSelection;
21 import org.eclipse.swt.browser.LocationEvent;
22 import org.eclipse.swt.graphics.FontData;
23 import org.eclipse.swt.graphics.Point;
24 import org.eclipse.swt.graphics.RGB;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.Event;
27 import org.eclipse.swt.widgets.FontDialog;
28 import org.eclipse.swt.widgets.TreeItem;
29 import org.eclipse.ui.PartInitException;
30 import org.eclipse.ui.PlatformUI;
31 import org.simantics.Simantics;
32 import org.simantics.browsing.ui.BuiltinKeys;
33 import org.simantics.browsing.ui.NodeContext;
34 import org.simantics.databoard.Bindings;
35 import org.simantics.db.ReadGraph;
36 import org.simantics.db.Resource;
37 import org.simantics.db.Session;
38 import org.simantics.db.WriteGraph;
39 import org.simantics.db.common.request.ReadRequest;
40 import org.simantics.db.common.request.UnaryRead;
41 import org.simantics.db.common.request.WriteRequest;
42 import org.simantics.db.common.utils.NameUtils;
43 import org.simantics.db.common.utils.RequestUtil;
44 import org.simantics.db.exception.DatabaseException;
45 import org.simantics.db.layer0.adapter.Instances;
46 import org.simantics.db.layer0.request.PossibleModel;
47 import org.simantics.db.layer0.request.PossibleResource;
48 import org.simantics.db.layer0.util.RemoverUtil;
49 import org.simantics.db.layer0.variable.RVI;
50 import org.simantics.db.layer0.variable.Variable;
51 import org.simantics.db.layer0.variable.Variables;
52 import org.simantics.document.DocumentDialect;
53 import org.simantics.document.DocumentResource;
54 import org.simantics.document.DocumentUtils;
55 import org.simantics.document.ui.Activator;
56 import org.simantics.document.ui.CSSEditor;
57 import org.simantics.layer0.Layer0;
58 import org.simantics.scenegraph.INode;
59 import org.simantics.scenegraph.loader.ScenegraphLoaderProcess;
60 import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;
61 import org.simantics.scenegraph.loader.ScenegraphLoaderUtils.ScenegraphPropertyReference;
62 import org.simantics.scl.reflection.annotations.SCLValue;
63 import org.simantics.scl.runtime.function.Function1;
64 import org.simantics.scl.runtime.function.FunctionImpl1;
65 import org.simantics.scl.runtime.function.FunctionImpl3;
66 import org.simantics.ui.SimanticsUI;
67 import org.simantics.ui.workbench.ResourceEditorInput2;
68 import org.simantics.ui.workbench.action.DefaultActions;
69 import org.simantics.utils.threads.SWTThread;
70 import org.simantics.utils.ui.workbench.WorkbenchUtils;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73
74
75 public class All {
76
77         private static final Logger LOGGER = LoggerFactory.getLogger(All.class);
78
79         private static boolean createDocument(WriteGraph graph, Resource resource, Resource model) throws DatabaseException {
80
81                 Layer0 L0 = Layer0.getInstance(graph);
82                 DocumentResource DOC = DocumentResource.getInstance(graph);
83
84                 if(graph.hasStatement(resource, DOC.HasDocumentation)) return true;
85                 
86                 Instances query = graph.adapt(DOC.DocumentTypeBinding, Instances.class);
87                 
88                 TreeMap<Double, Resource> bindings = new TreeMap<Double, Resource>();
89                 for(Resource binding : query.find(graph, model)) {
90                         double priority = graph.getRelatedValue2(binding, DOC.DocumentTypeBinding_priority, Bindings.DOUBLE);
91                         Resource type = graph.getSingleObject(binding, DOC.DocumentTypeBinding_HasType);
92                         if(graph.isInstanceOf(resource, type)) {
93                                 bindings.put(priority, binding);
94                         }
95                 }
96                 
97                 if(bindings.isEmpty()) return false;
98                 
99                 Resource binding = bindings.lastEntry().getValue();
100                                 
101                 Resource documentType = graph.getSingleObject(binding, DOC.DocumentTypeBinding_HasDocumentType);
102                 Resource document = graph.newResource();
103                 graph.claim(document, L0.InstanceOf, null, DOC.ScenegraphDocument);
104                 graph.claimLiteral(document, L0.HasName, "Documentation");
105                 graph.claim(resource, DOC.HasDocumentation, document);
106                 graph.claim(document, L0.PartOf, resource);
107
108                 Resource scenegraph = graph.newResource();
109                 graph.claim(scenegraph, L0.InstanceOf, null, documentType);
110                 graph.claimLiteral(scenegraph, L0.HasName, "Scenegraph");
111                 graph.claim(scenegraph, L0.PartOf, document);
112                 graph.claim(document, DOC.ScenegraphDocument_scenegraph, scenegraph);
113
114                 return true;
115                 
116         }
117
118     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
119     public static Object onCreateDocumentButton(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
120
121         return new FunctionImpl1<Object, Object>() {
122
123                         @Override
124                         public Object apply(Object _o) {
125                                 
126                                 Simantics.async(new ReadRequest() {
127
128                                         @Override
129                                         public void run(ReadGraph graph) throws DatabaseException {
130                                                 
131                                         Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
132                                         if(selection == null) return;
133                                         
134                                                 final Resource input = selection.getRepresents(graph);
135                                         if(input == null) return;
136                                                 
137                                         graph.async(new WriteRequest() {
138
139                                                         @Override
140                                                         public void perform(WriteGraph graph) throws DatabaseException {
141                                                                 
142                                                                 Resource model = graph.sync(new PossibleModel(input));
143                                                                 if(model == null) return;
144                                                                 createDocument(graph, input, model);
145                                                                 
146                                                         }
147                                                 
148                                         });
149                                         
150                                         }
151                                         
152                                 });
153                                 
154                                 return true;
155                                 
156                         }
157                         
158                 };
159         
160     }
161
162     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
163     public static Object onDeleteDocumentButton(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
164
165         return new FunctionImpl1<Object, Object>() {
166
167                         @Override
168                         public Object apply(Object _o) {
169                                 
170                                 Simantics.async(new ReadRequest() {
171
172                                         @Override
173                                         public void run(ReadGraph graph) throws DatabaseException {
174                                                 
175                                         Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
176                                         if(selection == null) return;
177                                         
178                                                 final Resource input = selection.getRepresents(graph);
179                                         if(input == null) return;
180                                         
181                                                 DocumentResource DOC = DocumentResource.getInstance(graph);
182                                                 if(!graph.hasStatement(input, DOC.HasDocumentation)) return;
183                                                 
184                                         graph.async(new WriteRequest() {
185
186                                                         @Override
187                                                         public void perform(WriteGraph graph) throws DatabaseException {
188                                                                 
189                                                                 DocumentResource DOC = DocumentResource.getInstance(graph);
190                                                                 Resource document = graph.getPossibleObject(input, DOC.HasDocumentation);
191                                                                 if(document == null) return;
192                                                                 
193                                                                 RemoverUtil.remove(graph, document);
194                                                                 graph.markUndoPoint();
195                                                                 
196                                                         }
197                                                 
198                                         });
199                                         
200                                         }
201                                         
202                                 });
203                                 
204                                 return true;
205                                 
206                         }
207                         
208                 };
209         
210     }
211     
212     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
213     public static Object editorLoaded(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
214         
215         return new FunctionImpl3<WriteGraph, Variable, Variable, Boolean>() {
216
217                         @Override
218                         public Boolean apply(WriteGraph graph, Variable editor, Variable input) {
219
220 //                              try {
221 //                                      return createDocument(graph, input);
222 //                              } catch (DatabaseException e) {
223 //                                      Logger.defaultLogError(e);
224 //                              }
225
226                                 return true;
227                                 
228                         }
229                 
230         };
231         
232     }
233
234     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
235     public static Boolean hasDocument(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
236         
237                 DocumentResource DOC = DocumentResource.getInstance(graph);
238                 
239         Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
240         if(selection == null) return false;
241         
242                 Resource input = selection.getRepresents(graph);
243         if(input == null) return null;
244         
245                 return graph.hasStatement(input, DOC.HasDocumentation);
246         
247     }
248
249     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
250     public static Object viewInputChanged(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
251         
252         return new FunctionImpl1<Variable, Boolean>() {
253
254                         @Override
255                         public Boolean apply(final Variable viewVariable) {
256                                 return true;
257                         }
258                 
259         };
260         
261     }
262     
263         
264     @SCLValue(type = "ReadGraph -> Variable -> Boolean")
265     public static Boolean isWikitext(ReadGraph graph, Variable context) throws DatabaseException {
266         Layer0 L0 = Layer0.getInstance(graph);
267         DocumentResource DOC = DocumentResource.getInstance(graph);
268         Resource p = context.getPossiblePredicateResource(graph);
269         if (p == null)
270             return Boolean.FALSE;
271         Resource range = graph.getPossibleObject(p, L0.HasRange);
272         return DOC.WikiDocument_WikiText.equals(range);
273     }
274     
275     private static Variable getDefaultSelection(ReadGraph graph, Variable context) throws DatabaseException {
276         
277                 DocumentResource DOC = DocumentResource.getInstance(graph);
278         Variable sel = ScenegraphLoaderUtils.getVariableSelection(graph, context);
279         
280         Resource represents = sel.getRepresents(graph);
281         Resource doc = graph.getSingleObject(represents, DOC.HasDocument);
282         Resource scenegraph = graph.getSingleObject(doc, DOC.ScenegraphDocument_scenegraph);
283         
284         Variable runtime = ScenegraphLoaderUtils.getRuntimeVariable(graph, context);
285                 INode root = runtime.adapt(graph, INode.class);
286
287         Variable result = ScenegraphLoaderProcess.getVariable(graph, null, scenegraph, ScenegraphLoaderUtils.getRuntime(graph, context), root);
288         if(result != null) {
289                 Variable userDoc = result.getPossibleProperty(graph, "UserDocumentation");
290                 if(userDoc != null) return userDoc;
291         }
292         
293         return null;
294         
295     }
296     
297     private static Variable resolveEditSelection(ReadGraph graph, Variable context, String path) throws DatabaseException {
298         
299                 final ScenegraphPropertyReference<Variable> selectionReference = 
300                                 ScenegraphLoaderUtils.getRelativePropertyReference(SWTThread.getThreadAccess(), graph, context, path);
301                 
302                 Variable editSelection = selectionReference.getExternalValue(graph);
303                 if(editSelection == null) editSelection = getDefaultSelection(graph, context);
304                 
305                 return editSelection;
306         
307     }
308
309     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
310     public static Object wikitextModifier(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
311         
312                 final ScenegraphPropertyReference<String> textReference = ScenegraphLoaderUtils.getRelativePropertyReference(SWTThread.getThreadAccess(), graph, context, ".../TextContainer/Text#text");
313         
314         return new FunctionImpl1<Object, Object>() {
315
316                         @Override
317                         public Object apply(final Object event) {
318             
319                                 final String value = textReference.getValue();
320
321                                 try {
322                                         Simantics.getSession().sync(new WriteRequest() {
323
324                                                 @Override
325                                                 public void perform(WriteGraph graph) throws DatabaseException {
326                                                         Variable selection = resolveEditSelection(graph, context, "..../Scroll/Browser#edited");
327                                                         if (selection != null) {
328                                                             selection.setValue(graph, (String)value, Bindings.STRING);
329                                                                 graph.markUndoPoint();
330                                                         } else {
331                                                                 LOGGER.error("No selection for resource : " + resource + ", Variable context : " + context + ", value : " + value);
332                                                         }
333                                                 }
334                                                 
335                                         });
336                                 } catch (DatabaseException e) {
337                                         e.printStackTrace();
338                                 }
339                                 return null;
340                         }
341                 
342         };
343     }
344     
345     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
346     public static String wikitext(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
347         Variable selection = ScenegraphLoaderUtils.getVariableSelection(graph, context);
348         return selection.getValue(graph);
349     }
350
351     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
352     public static String selectedDocumentPart(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
353
354                 Variable selection = resolveEditSelection(graph, context, ".../Scroll/Browser#edited");
355                 if(selection == null) return null;
356
357         return selection.getValue(graph);
358         
359     }
360     
361     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
362     public static Object documentStructureSelected(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
363         
364         return new FunctionImpl1<Object, Boolean>() {
365                 
366             @Override
367             public Boolean apply(Object _event) {
368                 
369                 Event event = (Event)_event;
370                 
371                 final TreeItem item = (TreeItem)event.item;
372                 NodeContext context = (NodeContext)item.getData();
373                 final Variable entry = (Variable)context.getConstant(BuiltinKeys.INPUT);
374                 
375                 ISelectionProvider provider = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart().getSite().getSelectionProvider();
376                 provider.setSelection(new StructuredSelection(entry));
377                 
378                 return null;
379                 
380             }
381                 
382         };
383         
384     }
385
386     abstract static class WikiButtonModifier extends FunctionImpl1<Object, Object> {
387
388                 final ScenegraphPropertyReference<String> textReference;
389                 final ScenegraphPropertyReference<Point> selectionReference;
390
391         public WikiButtonModifier(ReadGraph graph, Variable context) throws DatabaseException {
392                 textReference = ScenegraphLoaderUtils.getRelativePropertyReference(SWTThread.getThreadAccess(), graph, context, ".../TextContainer/Text#text");
393                 selectionReference = ScenegraphLoaderUtils.getRelativePropertyReference(SWTThread.getThreadAccess(), graph, context, ".../TextContainer/Text#selection");
394         }
395         
396         abstract void perform(String before, String selected, String after, Point selection);
397         
398             @Override
399             public Object apply(Object _event) {
400                 String text = textReference.getValue();
401                 Point selection = selectionReference.getValue(); 
402                 String before = text.substring(0, selection.x);
403                 String selected = text.substring(selection.x, selection.y);
404                 String after = text.substring(selection.y);
405                 perform(before, selected, after, selection);
406                 return null;
407             }
408
409     }
410     
411     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
412     public static Object boldModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
413
414         return new WikiButtonModifier(graph, context) {
415                         
416                         @Override
417                         void perform(String before, String selected, String after, Point selection) {
418
419                                 if(selected.isEmpty()) {
420                                         textReference.setValue(before + "'''bold text'''" + after);
421                                 } else {
422                                         textReference.setValue(before + "'''" + selected + "'''" + after);      
423                                 }
424                                 
425                         }
426                         
427                 };
428         
429     }
430
431     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
432     public static Object italicModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
433
434         return new WikiButtonModifier(graph, context) {
435                         
436                         @Override
437                         void perform(String before, String selected, String after, Point selection) {
438
439                                 if(selected.isEmpty()) {
440                                         textReference.setValue(before + "''italic text''" + after);
441                                 } else {
442                                         textReference.setValue(before + "''" + selected + "''" + after);        
443                                 }
444                                 
445                         }
446                         
447                 };
448         
449     }
450     
451     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
452     public static Object strikethroughModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
453
454         return new WikiButtonModifier(graph, context) {
455                         
456                         @Override
457                         void perform(String before, String selected, String after, Point selection) {
458
459                                 if(selected.isEmpty()) {
460                                         textReference.setValue(before + "<span style=\"text-decoration:line-through;\">strikethrough text</span>" + after);
461                                 } else {
462                                         textReference.setValue(before + "<span style=\"text-decoration:line-through;\">" + selected + "</span>" + after);       
463                                 }
464                                 
465                         }
466                         
467                 };
468         
469     }
470
471     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
472     public static Object underlineModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
473
474         return new WikiButtonModifier(graph, context) {
475                         
476                         @Override
477                         void perform(String before, String selected, String after, Point selection) {
478
479                                 if(selected.isEmpty()) {
480                                         textReference.setValue(before + "<span style=\"text-decoration:underline;\">strikethrough text</span>" + after);
481                                 } else {
482                                         textReference.setValue(before + "<span style=\"text-decoration:underline;\">" + selected + "</span>" + after);  
483                                 }
484                                 
485                         }
486                         
487                 };
488         
489     }
490
491     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
492     public static Object horizontalRulerModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
493
494         return new WikiButtonModifier(graph, context) {
495                         
496                         @Override
497                         void perform(String before, String selected, String after, Point selection) {
498
499                                 textReference.setValue(before + "\r\n<hr/>\r\n" + selected + after);
500                                 
501                         }
502                         
503                 };
504         
505     }
506     
507     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
508     public static Object indentModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
509
510         return new WikiButtonModifier(graph, context) {
511                         
512                         @Override
513                         void perform(String before, String selected, String after, Point selection) {
514
515                                 textReference.setValue(before + ":" + selected + after);
516                                 
517                         }
518                         
519                 };
520         
521     }
522
523     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
524     public static Object fontModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
525
526         return new WikiButtonModifier(graph, context) {
527                         
528                 private String hex2(int value) {
529                         String result = Integer.toHexString(value);
530                         if(result.length() == 1) result = "0" + result;
531                         return result;
532                 }
533                 
534                         @Override
535                         void perform(String before, String selected, String after, Point selection) {
536
537                                 FontDialog dialog = new FontDialog(Display.getCurrent().getActiveShell()); 
538                                 FontData data = dialog.open();
539                                 if(data == null) return;
540
541                                 String family = data.getName();
542                                 int size = data.getHeight();
543                                 
544                                 RGB rgb = dialog.getRGB();
545                                 String hex = hex2(rgb.red) + hex2(rgb.green) + hex2(rgb.blue);
546
547                                 if(selected.isEmpty()) {
548                                         textReference.setValue(before + "<font style=\"font-size:" + size + ";color: #" + hex + ";font-family:" + family + ";\" >formatted text</font>" + selected + after);
549                                 } else {
550                                         textReference.setValue(before + "<font style=\"font-size:" + size + ";color: #" + hex + ";font-family:" + family + ";\" >" + selected + "</font>" + after);
551                                 }
552                                 
553                         }
554                         
555                 };
556         
557     }
558
559     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
560     public static Object imageModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
561
562         return new WikiButtonModifier(graph, context) {
563                 
564                         @Override
565                         void perform(String before, String selected, String after, Point selection) {
566
567                                 textReference.setValue(before + "[[Image:root://Library/image.png|100px]]" + "\r\n" + selected + after);
568                                 
569                         }
570                         
571                 };
572         
573     }
574     
575     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
576     public static Object header1Modifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
577
578         return new WikiButtonModifier(graph, context) {
579                         
580                         @Override
581                         void perform(String before, String selected, String after, Point selection) {
582
583                                 textReference.setValue(before + "\r\n= Header 1 =\r\n" + selected + after);
584                                 
585                         }
586                         
587                 };
588         
589     }
590
591     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
592     public static Object header2Modifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
593
594         return new WikiButtonModifier(graph, context) {
595                         
596                         @Override
597                         void perform(String before, String selected, String after, Point selection) {
598
599                                 textReference.setValue(before + "\r\n== Header 2 ==\r\n" + selected + after);
600                                 
601                         }
602                         
603                 };
604         
605     }
606
607     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
608     public static Object header3Modifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
609
610         return new WikiButtonModifier(graph, context) {
611                         
612                         @Override
613                         void perform(String before, String selected, String after, Point selection) {
614
615                                 textReference.setValue(before + "\r\n=== Header 3 ===\r\n" + selected + after);
616                                 
617                         }
618                         
619                 };
620         
621     }
622     
623     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
624     public static Object header4Modifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
625
626         return new WikiButtonModifier(graph, context) {
627                         
628                         @Override
629                         void perform(String before, String selected, String after, Point selection) {
630
631                                 textReference.setValue(before + "\r\n==== Header 4 ====\r\n" + selected + after);
632                                 
633                         }
634                         
635                 };
636         
637     }
638     
639     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
640     public static Object numberedListModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
641
642         return new WikiButtonModifier(graph, context) {
643                         
644                         @Override
645                         void perform(String before, String selected, String after, Point selection) {
646
647                                 textReference.setValue(before + "\r\n" +
648                                                 "# Item1\r\n" + 
649                                                 "# Item2\r\n" + 
650                                                 "## Item2.1\r\n" + 
651                                                 "# Item3\r\n" + selected + after);
652                                 
653                         }
654                         
655                 };
656         
657     }
658
659     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
660     public static Object bulletListModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
661
662         return new WikiButtonModifier(graph, context) {
663                         
664                         @Override
665                         void perform(String before, String selected, String after, Point selection) {
666
667                                 textReference.setValue(before + "\r\n" +
668                                                 "* Item1\r\n" + 
669                                                 "* Item2\r\n" + 
670                                                 "** Item2.1\r\n" + 
671                                                 "* Item3\r\n" + selected + after);
672                                 
673                         }
674                         
675                 };
676         
677     }
678     
679     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
680     public static Object tableModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
681
682         return new WikiButtonModifier(graph, context) {
683                         
684                         @Override
685                         void perform(String before, String selected, String after, Point selection) {
686
687                                 textReference.setValue(before + "\r\n" +
688                                                 "{| border=\"1\"\r\n" + 
689                                                 "! header\r\n" +
690                                                 "! header2 \r\n" +
691                                                 "|-\r\n" +
692                                                 "| cell || cell2\r\n" + 
693                                                 "|-\r\n" +
694                                                 "| cell3\r\n" + 
695                                                 "| cell4\r\n" + 
696                                                 "|}\r\n"  + selected + after);
697                                 
698                         }
699                         
700                 };
701         
702     }
703
704     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
705     public static Object internalLinkModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
706         return new WikiButtonModifier(graph, context) {
707             @Override
708             void perform(String before, String selected, String after, Point selection) {
709                 textReference.setValue(before +
710                         "[[Media:root://Documents/Document.pdf|Link to a file within the model]]\r\n" + selected + after);
711                 
712             }
713         };
714     }
715     
716     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
717     public static Object linkModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
718
719         return new WikiButtonModifier(graph, context) {
720                         
721                         @Override
722                         void perform(String before, String selected, String after, Point selection) {
723
724                                 textReference.setValue(before +
725                                                 "[http://www.simantics.org External Website Link]\r\n" + selected + after);
726                                 
727                         }
728                         
729                 };
730         
731     }
732     
733     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
734     public static Object styleModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
735
736         return new WikiButtonModifier(graph, context) {
737                         
738                         @Override
739                         void perform(String before, String selected, String after, Point selection) {
740
741                                 Simantics.getSession().asyncRequest(new ReadRequest() {
742
743                                         @Override
744                                         public void run(ReadGraph graph) throws DatabaseException {
745
746                                         Variable sel = ScenegraphLoaderUtils.getVariableSelection(graph, context);
747                                         Resource root = sel.getIndexRoot(graph);
748                                         String editorId = CSSEditor.EDITOR_ID;
749                                 RVI rvi = null;
750
751                                 PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
752                                     try {
753                                         WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, root, root, rvi));
754                                     } catch (PartInitException e) {
755                                         LOGGER.error("Failed to open CSS editor for root " + root, e);
756                                     }
757                                 });
758
759                                         }
760                                         
761                                 });
762                                 
763                         }
764                         
765                 };
766         
767     }
768     
769     
770 //    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
771 //    public static Object navigate(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
772 //      
773 //      return new FunctionImpl1<String, Boolean>() {
774 //
775 //                      @Override
776 //                      public Boolean apply(final String path) {
777 //                              
778 //                              Simantics.getSession().asyncRequest(new ReadRequest() {
779 //
780 //                                      @Override
781 //                                      public void run(ReadGraph graph) throws DatabaseException {
782 //                                              
783 //                                              DocumentResource DOC = DocumentResource.getInstance(graph);
784 //                                      Variable sel = ScenegraphLoaderUtils.getVariableSelection(graph, context);
785 //                                      
786 //                                      Resource represents = sel.getRepresents(graph);
787 //                                      Resource doc = graph.getSingleObject(represents, DOC.HasDocument);
788 //                                      Resource scenegraph = graph.getSingleObject(doc, DOC.ScenegraphDocument_scenegraph);
789 //                                      
790 //                                      Variable runtime = ScenegraphLoaderUtils.getRuntimeVariable(graph, context);
791 //                                              INode root = runtime.adapt(graph, INode.class);
792 //                                      
793 //                                      Variable result = ScenegraphLoaderProcess.getVariable(graph, null, scenegraph, ScenegraphLoaderUtils.getRuntime(graph, context), root);
794 //                                      Variable location = result.browse(graph, path);
795 //                                              
796 //                                              ScenegraphPropertyReference<Variable> editReference = ScenegraphLoaderUtils.getRelativePropertyReference(SWTThread.getThreadAccess(), graph, context, ".#edited");
797 //                                              editReference.setValue(location);
798 //                                              
799 //                                      }
800 //                                      
801 //                              });
802 //                              
803 //                              return null;
804 //                              
805 //                      }
806 //              
807 //      };
808 //      
809 //    }
810
811     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
812     public static String noDocumentText(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
813                 
814         Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
815         if(selection == null) return "<no input>";
816         
817                 Resource input = selection.getRepresents(graph);
818         if(input == null) return "<no input>";
819         
820         String path = DocumentUtils.indexRootPath(graph, selection);
821         if(!path.isEmpty()) {
822                 return "for " + path + selection.getName(graph);
823         }
824         
825                 return "for " + NameUtils.getSafeLabel(graph, input);
826         
827     }
828
829     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
830     public static Boolean canCreateDocument(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
831                 
832         Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
833         if(selection == null) return false;
834         
835                 Resource input = selection.getRepresents(graph);
836         if(input == null) return false;
837         
838         return true;
839         
840     }
841
842     private static class ResolveURI extends UnaryRead<String, Object> {
843         public ResolveURI(String uri) {
844             super(uri);
845         }
846         @Override
847         public Object perform(ReadGraph graph) throws DatabaseException {
848             Object result = graph.syncRequest(new PossibleResource(parameter));
849             if (result == null)
850                 result = Variables.getPossibleVariable(graph, parameter);
851             return result;
852         }
853     }
854
855     private static final Function1<Object, Boolean> PERFORM_DEFAULT_ACTION_FOR_URI_RESOURCE = new Function1<Object, Boolean>() {
856         @Override
857         public Boolean apply(Object p0) {
858             LocationEvent le = (LocationEvent) p0;
859             if (le.location.startsWith(DocumentDialect.SIMANTICS_INTERNAL_URI_PREFIX)) {
860                 // This is not a valid URL anyway so deny relocation.
861                 le.doit = false;
862
863                 // Try to execute default action for the resource or variable
864                 // that the URI represents.
865                 String uri = le.location.substring(DocumentDialect.SIMANTICS_INTERNAL_URI_PREFIX.length());
866                 try {
867                     Session s = Simantics.getSession();
868                     Object input = RequestUtil.trySyncRequest(s,
869                             SimanticsUI.UI_THREAD_REQUEST_START_TIMEOUT,
870                             SimanticsUI.UI_THREAD_REQUEST_EXECUTION_TIMEOUT,
871                             new ResolveURI(uri));
872                     if (input != null) {
873                         DefaultActions.asyncPerformDefaultAction(s, input, false, false, false);
874                     }
875                 } catch (DatabaseException | InterruptedException e) {
876                     Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to resolve URI to a database resource or variable: " + uri, e));
877                 }
878             }
879             return true;
880         }
881     };
882
883     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
884     public static Function1<Object, Boolean> locationChanging(ReadGraph graph, Resource variable, Variable context) throws DatabaseException {
885         return PERFORM_DEFAULT_ACTION_FOR_URI_RESOURCE;
886     }
887
888 }