Version 11 (modified by mitex, 16 years ago) (diff) |
---|
Analysis
Overview
The goal of this task is to expose the Sophie book's model and Sophie's logic in a user-friendly way to the user.
Generally, there are two use-cases for scripting, which imply some differences in the requirements:
- Scripts used for automation
- The result of their execution should be undoable, as each other change to the model
- Scripts as link targets
- They have limited scope - for example, user cannot create a new book with them
- There's no need to be undoable
Task requirements
- The user should have access to the current book and should be able to do the following actions with it:
- get/set its title
- get/set the page size (width and height)
- get a list of all pages or a page with a given index
- add a new page in it
- remove a page
- reorder the pages
- get/set the current page
- For every page the user should be able to:
- get/set its name
- get its index (but not set it)
- get the bounding rectangle (a rectangle that contains all page elements)
- [Optional for this revision] get/set the background style
- [Optional for this revision] get/set the border style
- get a list of all frames
- add a new frame
- remove a frame
- For every frame the user should be able to:
- get/set its size
- get/set its z-order
- get/set its content location
- get/set its rotation angle
- get/set its background style
- get/set its border style
- get/set its paddings
- [Optional] The user should also be able to work with groups.
- Allow scripts to be defined as link actions.
- The action settings panel should contain a combo box with all available scripts for current book.
- Not all Java classes have to be exposed to Sophie scripts, because:
- Some scripts can crash the application.
- Some other scripts can allow crackers to execute malicious code.
- When closing a book, close any open document windows that display scripts from current book. Generally, when closing a document window, close all children resources' document windows.
Task result
- Source code
Implementation idea
- Decide whether to expose the model classes (org.sophie2.base.model.book.Book, org.sophie2.base.model.book.Page, org.sophie2.base.model.book.Frame, etc.) or to write adapter classes.
- The first approach will make scripts very powerful - the user will be able to do with them everything he/she can do with the application. In addition, it won't be necessary to update the facade every time we change something.
- The second approach however will be more convenient for the user. It will also solve most of the security issues.
- To filter the access to some Java classes:
context.setClassShutter(new ClassShutter() { @Override public boolean visibleToScripts(String fullClassName) { return fullClassName.startsWith("org.mozilla.javascript"); } });
- The following lines add a global variable out that is a JavaScript reflection of the System.out variable:
Object wrappedOut = Context.javaToJS(System.out, scope); ScriptableObject.putProperty(scope, "out", wrappedOut);
Related
(Add links to related tasks that could be useful or helpful.)
How to demo
(Provide instructions for demonstration of the task.)
Design
- For the links:
- Package org.sophie2.extra.func.scripting.links
- Class RunScriptLinkAction extends LinkAction
- script property
- Class RunScriptActionProvider implements LinkActionProvider
- Register it as an extension
- Class RunScriptConfigurationPanel implements ActionConfigurationPanel extends BaseSwingVisualElement
- Nested class AvailableScripts extends BoundComboBox<Script>
- displays all script resources in current book
- @Own auto property of type AvailableScripts which returns computeElementProp(AvailableScripts.class, RunScriptConfigurationPanel.class, null);
- The swing component should be a panel with the combo box.
- Register it as an extension
- Nested class AvailableScripts extends BoundComboBox<Script>
- Enum org.sophie2.extra.func.scripting.logic.RunScriptLogic implements OperationDef
- Move RUN_SCRIPT from ScriptLogic
- Wrap the script execution in a new AutoChange and register it to the script.
- ACTION_RUN_SCRIPT
- Use this when activating a RunScriptLinkAction.
- Move RUN_SCRIPT from ScriptLogic
- For the API:
- Package org.sophie2.extra.func.scripting.facade
- Class JSBook extends ScriptableObject
- Override getClassName to return "Book". That means that script writers will use "Book" instead of "JSBook".
- Create a method void setBook(ResourceRef book) which sets the "real" book that is adapted.
- Create getters, setters and other methods according to the analysis.
- For example, for the title write String jsGet_title() and void jsSet_title(String title). This will allow users to benefit from the easy JavaScript syntax: "book.title = 'Design Patterns'".
- Class JSPage extends ScriptableObject
- getClassName returns "Page".
- Class JSFrame extends ScriptableObject
- getClassName returns "Frame".
- Class JSApp extends ScriptableObject
- getClassName returns "App".
- Create method JSBook jsFunction_newBook() which creates a new default book and adds it to the list of open documents.
- In RunScriptLogic:
- Use ScriptableObject.defineClass(scope, JSBook.class); to expose a given ScriptableObject to JavaScript.
- When executing a script from a document window, expose all adapter and facade classes. When the script is used as a link action, do not expose JSApp.
- Use the following to expose a global variable book which represents the book where the script is created:
Scriptable scriptableJsBook = context.newObject(scope, "Book"); ScriptableObject.putProperty(scope, "book", scriptableJsBook); JSBook jsBook = (JSBook) Context.jsToJava(scriptableJsBook, JSBook.class); jsBook.setBook(bookRef);
- Expose the app too, if running a script from a document window.
- Limit the scope of visible Java classes to only Rhino classes using context.setClassShutter.
- Source code: branches/private/deni/scripting_actions/
- Tests:
- branches/private/deni/scripting_actions/modules/org.sophie2.extra.func.scripting/src/test/java/org/sophie2/extra/func/scripting/facade/JSBookTest.java
- branches/private/deni/scripting_actions/modules/org.sophie2.extra.func.scripting/src/test/java/org/sophie2/extra/func/scripting/links/RunScriptLinkActionTest.java
Implementation
- Source code: branches/private/deni/scripting_actions/
Testing
(Place the testing results here.)
Comments
(Write comments for this or later revisions here.)