Converging Textual  and Graphical Editors
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Converging Textual and Graphical Editors

on

  • 3,461 views

I delivered this presentation at the Eclipse Modeling Days in NYC and Toronto, Ca: http://wiki.eclipse.org/Eclipse_Modeling_Day in November 2009....

I delivered this presentation at the Eclipse Modeling Days in NYC and Toronto, Ca: http://wiki.eclipse.org/Eclipse_Modeling_Day in November 2009.

The slides are based on the ones Jan Koehnlein presented at the Eclipse Summit Europe 09.

Statistics

Views

Total Views
3,461
Views on SlideShare
3,448
Embed Views
13

Actions

Likes
7
Downloads
183
Comments
1

1 Embed 13

http://www.slideshare.net 13

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • How can I use these .kex files locally on my maching?
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Converging Textual and Graphical Editors Presentation Transcript

  • 1. Converging Textual and Graphical Editors Moritz Eysholdt
  • 2. Modeling?
  • 3. Modeling? Should we model or code?
  • 4. Modeling? Should we model or code? Real programmers write code!
  • 5. Modeling? Should we model or code? Real programmers write code! Modeling is something the architect does.
  • 6. Modeling? Should we model or code? Real programmers write code! Modeling is something the architect does. Models are graphical!
  • 7. Modeling? Should we model or code? Real programmers write code! Modeling is something the architect does. Models are graphical! I model on my whiteboard.
  • 8. Modeling? Should we model or code? Real programmers write code! Modeling is something the architect does. Models are graphical! I model on my whiteboard. This doesn’t lead us anywhere!
  • 9. Let’s take a step back
  • 10. Let’s take a step back It’s about having the right notation for the job.
  • 11. Let’s take a step back It’s about having the right notation for the job. It would be nice if we could just run it.
  • 12. Let’s take a step back sounds like a language It’s about having the right notation for the job. It would be nice if we could just run it.
  • 13. Let’s take a step back sounds like a sounds like it is specific to language the job’s domain It’s about having the right notation for the job. It would be nice if we could just run it.
  • 14. Let’s take a step back sounds like a sounds like it is specific to language the job’s domain It’s about having the right notation for the job. It would be nice if we could just run it. it needs to be formal!
  • 15. The Right Notation The Right Notation
  • 16. The Right Notation The Right Notation • Whether we call it a model or not doesn’t matter
  • 17. The Right Notation The Right Notation • Whether we call it a model or not doesn’t matter • However, tools from Eclipse Modeling help to build tooling for this notation
  • 18. The Right Notation The Right Notation • Whether we call it a model or not doesn’t matter • However, tools from Eclipse Modeling help to build tooling for this notation • Instances of this notation are a primary artifact of your software
  • 19. The Right Notation The Right Notation • Whether we call it a model or not doesn’t matter • However, tools from Eclipse Modeling help to build tooling for this notation • Instances of this notation are a primary artifact of your software • If it has syntax and semantics, it is a language
  • 20. The Right Notation The Right Notation • Whether we call it a model or not doesn’t matter • However, tools from Eclipse Modeling help to build tooling for this notation • Instances of this notation are a primary artifact of your software • If it has syntax and semantics, it is a language • The focus on a certain kind of tasks makes it domain specific. It becomes a DSL or DSML
  • 21. Qualities for an effective development process and a high-quality product Language Tooling • Support for a few, • Content Assist Writable orthogonal concepts • Quickfixes • Appropriate, concise syntax • Navigation Readable • Hide technical details • Syntax highlighting • Outline • Reuse established Communicable syntax/semantics • Instant feedback Error-preventing • Statically typed • Short roundtrips
  • 22. Qualities for an effective development process and a high-quality product Language Tooling • Support for a few, • Content Assist Writable orthogonal concepts • Quickfixes • Appropriate, concise syntax • Navigation Readable • Hide technical details • Syntax highlighting • Outline • Reuse established Communicable syntax/semantics • Instant feedback Error-preventing • Statically typed • Short roundtrips
  • 23. Qualities for an effective development process and a high-quality product Language Tooling • Support for a few, • Content Assist Writable orthogonal concepts • Quickfixes • Appropriate, concise syntax • Navigation Readable • Hide technical details • Syntax highlighting • Outline • Reuse established Communicable syntax/semantics • Instant feedback Error-preventing • Statically typed • Short roundtrips
  • 24. Qualities for an effective development process and a high-quality product Where? Language Tooling • Support for a few, • Content Assist Writable orthogonal concepts • Quickfixes • Appropriate, concise syntax • Navigation Readable • Hide technical details • Syntax highlighting • Outline • Reuse established Communicable syntax/semantics • Instant feedback Error-preventing • Statically typed • Short roundtrips
  • 25. Qualities for an effective development process and a high-quality product Language Tooling • Support for a few, • Content Assist Writable orthogonal concepts • Quickfixes • Appropriate, concise syntax • Navigation Readable • Hide technical details • Syntax highlighting • Outline • Reuse established Communicable syntax/semantics • Instant feedback Error-preventing • Statically typed • Short roundtrips
  • 26. Examples?
  • 27. textual Examples?
  • 28. textual Examples? graphical
  • 29. textual Examples? graphical forms/tables
  • 30. textual Examples? graphical forms/tables mathematical
  • 31. textual Examples? graphical forms/tables You name it! mathematical The limit to design notations is available tooling and creativity.
  • 32. textual Examples? graphical forms/tables You name it! mathematical The limit to design notations is available tooling and creativity. Multiple notations can be combined.
  • 33. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 34. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } Information that is not in the text, protected boolean isSameClass(EClass left, exists. doesn’t EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 35. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { return errorMessage.toString(); • High-level views } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; The diagram is the big picture, details are } Information that is not in the text, in property dialogs. protected boolean isSameClass(EClass left, exists. doesn’t EClass right) { Graphical notations are commonly used return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); at higher levels of abstractions. } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 36. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • return errorMessage.toString(); } Very formal syntax public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } Non-Formal Elements whitespace, line-breaks, comments protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 37. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; Non-Formal Elements } Non-Formal Elements Modify: position, size, shape, color, font, icon whitespace, line-breaks, comments protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) Add: note-box, custom shapes, comments && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 38. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } The editor can be language-aware, but is protected boolean isSameClass(EClass required to. not left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 39. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } The editor can be language-aware, but is Each language requires a special protected boolean isSameClass(EClass required to. not left, EClass right) { (or generic) editor. return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 40. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } SVN, CVS, GIT, GNU diff/patch, etc. protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 41. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); return false; } List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } Model repositories, diff/merge needs to SVN, CVS, GIT, GNU diff/patch, etc. protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) be language-aware && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 42. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support • errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); } Editing with keyboard return false; List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 43. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support • • errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); } Editing with keyboard return false; Editing with mouse List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 44. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support • • errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); } Editing with keyboard return false; Editing with mouse • Expressions, Lists List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } return true; Mathematical Expressions, } Imperative Command Lists, Hierarchical Data, protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) etc. && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 45. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support • • errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); } Editing with keyboard return false; Editing with mouse • Expressions, Lists • Flow, Structure List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } Visual Pattern-Matching Mathematical Expressions, return true; Flow: Workflow, State-Machine, } Imperative Command Lists, Process Chain Hierarchical Data, protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) Structure: Class Diagram, Entity etc. && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } Relationship Diagram protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 46. public void assertSameStructure(EObject left, EObject right) { if(!isSameStructure(left, right)) { Text log.error(getErrorMessage()); Graphics Assert.fail(getErrorMessage()); } //logger.debug("" + counter + " elements compared"); } • Detailed views protected String getErrorMessage() { • High-level views • • return errorMessage.toString(); } Very formal syntax Suggests non-formalism • Standard text editor • Custom editor public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } • Standard versioning / public boolean internalIsSameStructure(EObject left, EObject right) { • Custom versioning / multi-user support ++counter; if (!isSameClass(left.eClass(), right.eClass())) { multi-user support • • errorMessage.append("Classes are not equal: " + left + " != " + right).append('n'); } Editing with keyboard return false; Editing with mouse • Expressions, Lists • Flow, Structure List<EObject> leftChildren = getRelevantChildren(left); List<EObject> rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n') return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) { errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append return false; } } Why not have both? return true; } protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); } protected List<EObject> getRelevantChildren(EObject _this) { List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents()); for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove();
  • 47. Xtext vs GMF A textual concrete syntax and a graphical concrete syntax on top of the same abstract syntax.
  • 48. Xtext
  • 49. Xtext G ra m m ar
  • 50. Xtext G ra m m ar
  • 51. Xtext ar m m ra G Runtime Superclass Subclass Class Ecore model LL(*) Parser Text editor
  • 52. Xtext ar m m ra G Semantic Metamodel Runtime Superclass Subclass Class Ecore model LL(*) Parser Text editor
  • 53. Superclass GMF Subclass Ecore model Class
  • 54. Superclass GMF Subclass Ecore model Class Graph Model
  • 55. Superclass GMF Subclass Ecore model Class Graph Tool Model Model
  • 56. Superclass GMF Subclass Ecore model Class Graph Map Tool Model Model Model
  • 57. Superclass GMF Subclass Ecore model Class Graph Map Tool Model Model Model GMF Generator Model
  • 58. Superclass GMF Subclass Ecore model Class Graph Map Tool Model Model Model GMF Generator Model
  • 59. Runtime Models and Synchronization
  • 60. Xtext EObject element eAdapters NodeAdapter node children AbstractNode offset: int length: int CompositeNode LeafNode text: String parent
  • 61. Xtext GMF EObject element EObject element eAdapters NodeAdapter View node children AbstractNode Node Edge offset: int length: int layoutConstraints bendpoints CompositeNode LeafNode Bounds Bendpoints text: String x: int parent y: int width: int height: int
  • 62. GMF ResourceSet XMIResource DiagramResource Canonical EditPolicy
  • 63. GMF ResourceSet XMIResource DiagramResource Canonical Canonical EditPolicy EditPolicy
  • 64. GMF ResourceSet XMIResource DiagramResource Canonical Canonical EditPolicy EditPolicy
  • 65. Xtext
  • 66. Xtext Textual Model Serializer Parser Node Model Ecore Model Instance
  • 67. Xtext XtextResource Textual Model Serializer Parser Node Model Ecore Model Instance
  • 68. Xtext XtextResource Textual Model Serializer Parser Node Model Ecore Model Instance getContents()
  • 69. Xtext load(), save() XtextResource Textual Model Serializer Parser Node Model Ecore Model Instance getContents()
  • 70. Xtext load(), save() XtextResource Textual Model Serializer Parser Node Model Ecore Model Instance FragmentProvider getContents() getURIFragment() getEObject()
  • 71. ResourceSet XtextResource DiagramResource
  • 72. diagram change ResourceSet XtextResource DiagramResource
  • 73. ResourceSet XtextResource DiagramResource
  • 74. reparse() w/ errors ResourceSet XtextResource DiagramResource
  • 75. ResourceSet XtextResource DiagramResource
  • 76. ResourceSet XtextResource DiagramResource Canonical EditPolicy
  • 77. ResourceSet XtextResource DiagramResource Canonical EditPolicy
  • 78. ResourceSet XtextResource DiagramResource Canonical EditPolicy
  • 79. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource XtextResource DiagramResource
  • 80. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource XtextResource DiagramResource
  • 81. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource XtextResource DiagramResource
  • 82. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource save() XtextResource DiagramResource
  • 83. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource reload() XtextResource DiagramResource
  • 84. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource reload() XtextResource DiagramResource
  • 85. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource XtextResource DiagramResource
  • 86. Fi e l od a M xtu le l Te ResourceSet ResourceSet XtextResource XtextResource DiagramResource
  • 87. Alignment
  • 88. grammar org.xtext.cg2009.Entities with org.eclipse.xtext.common.Terminals generate entities "http://www.xtext.org/cg2009/Entities" Model : {Model} (entities += Entity)*; Entity returns Entity: 'entity' (name=ID)? ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: SimpleProperty | ReferenceProperty; SimpleProperty: 'property' (name=ID)? ':' type=('String'|'Number'|'Bool'); ReferenceProperty : (name=ID)? 'refs' ('one' | many?='many')? type=[Entity];
  • 89. grammar org.xtext.cg2009.Entities with org.eclipse.xtext.common.Terminals Avoid empty generate entities "http://www.xtext.org/cg2009/Entities" models Model : {Model} (entities += Entity)*; Entity returns Entity: 'entity' (name=ID)? ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: SimpleProperty | ReferenceProperty; SimpleProperty: 'property' (name=ID)? ':' type=('String'|'Number'|'Bool'); ReferenceProperty : (name=ID)? 'refs' ('one' | many?='many')? type=[Entity];
  • 90. grammar org.xtext.cg2009.Entities with org.eclipse.xtext.common.Terminals Avoid empty generate entities "http://www.xtext.org/cg2009/Entities" models Model : {Model} (entities += Entity)*; Entity returns Entity: 'entity' (name=ID)? ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: Cover mandatory SimpleProperty | ReferenceProperty; properties in SimpleProperty: validation 'property' (name=ID)? ':' type=('String'|'Number'|'Bool'); ReferenceProperty : (name=ID)? 'refs' ('one' | many?='many')? type=[Entity];
  • 91. grammar org.xtext.cg2009.Entities with org.eclipse.xtext.common.Terminals Avoid empty generate entities "http://www.xtext.org/cg2009/Entities" Carefully select models Model : containment or cross {Model} (entities += Entity)*; references Entity returns Entity: 'entity' (name=ID)? ('extends' superType=[Entity])? '{' (properties+=Property)* '}'; Property: Cover mandatory SimpleProperty | ReferenceProperty; properties in SimpleProperty: validation 'property' (name=ID)? ':' type=('String'|'Number'|'Bool'); ReferenceProperty : (name=ID)? 'refs' ('one' | many?='many')? type=[Entity];
  • 92. Xtext
  • 93. Xtext Implement a Formatter
  • 94. Xtext Implement a Formatter Implement a FragmentProvider
  • 95. Xtext Implement a Formatter Implement a FragmentProvider Implement a JavaValidator
  • 96. GMF
  • 97. GMF Initialize mandatory properties
  • 98. GMF Initialize mandatory properties No Phantom Nodes without container
  • 99. Add a transaction on GMF load Initialize mandatory properties No Phantom Nodes without container
  • 100. Representing (Non)-Containment References in Xtext and GMF
  • 101. Representing (Non)-Containment References in Xtext and GMF EMF containment non-containment Rule-Call to a Parser Rule Cross-Reference Xtext Rule: value=MyRule Rule: value=[MyRule|ID] Diagram’ Root-Object: • Node Node’s Object: GMF Node’s Object: • Edge (an edge can have • Compartment an object) • Side-Affixed nodes • Edges (Phantom Nodes)
  • 102. Representing (Non)-Containment References in Xtext and GMF EMF containment non-containment Rule-Call to a Parser Rule Cross-Reference Xtext Rule: value=MyRule Rule: value=[MyRule|ID] Diagram’ Root-Object: • Node Node’s Object: GMF Node’s Object: • Edge (an edge can have • Compartment an object) • Side-Affixed nodes • Edges (Phantom Nodes)
  • 103. Representing (Non)-Containment References in Xtext and GMF EMF containment non-containment Rule-Call to a Parser Rule Cross-Reference Xtext Rule: value=MyRule Rule: value=[MyRule|ID] Diagram’ Root-Object: • Node Node’s Object: GMF Node’s Object: • Edge (an edge can have • Compartment an object) • Side-Affixed nodes • Edges (Phantom Nodes)
  • 104. Integration Helpers
  • 105. Integration Helpers • Prevent conflicting modifications
  • 106. Integration Helpers • Prevent conflicting modifications • Navigate • Diagram ➜ Text
  • 107. Integration Helpers • Prevent conflicting modifications • Navigate • Diagram ➜ Text • Text ➜ Diagram (needs Index)
  • 108. Integration Helpers • Prevent conflicting modifications • Navigate • Diagram ➜ Text • Text ➜ Diagram (needs Index) • Parser wrapper
  • 109. Integration Helpers • Prevent conflicting modifications • Navigate • Diagram ➜ Text • Text ➜ Diagram (needs Index) • Parser wrapper • Popup editor
  • 110. Demo Time
  • 111. Summary • Think about the notation, the language, that would be ideal to get your work done. • Textual and graphical syntax can be combined. • To integrate Xtext into GMF, exchange the XMIResource with an XtextResource -> GMF operates on a model persisted in textual syntax. • Some integration code is helpful, too. • itemis provides professional assistance. Moritz Eysholdt