When using Graphiti, changes to the model must be performed within a transaction. Noncompliance will result in an exception.
java.lang.IllegalStateException: Cannot modify resource set without a write transaction
You should not get this problem when only using features.
EMF Transactions are not only used by graphiti and all the information that follows is not Graphiti dependent.
How to use
To perform changes on the model you can use the org.eclipse.emf.transaction.RecordingCommand. This class stores all the changes performed in an editing domain during its execution (doExecute method). The command will have to be run in the command stack of the transaction domain. This is easier than it sounds:
TransactionalEditingDomain domain = TransactionUtils.getEditingDomain(model_object);
domain.getCommandStack().execute(new RecordingCommand(domain) {
public void doExecute() {
// do the changes here
}
});
The TransactionalEditingDomain related classes can be found in the org.eclipse.emf.transaction package.
Rollback
Transactions can be interrupted with exceptions. If done so, all changes done in the doExecute method, up to the exception, are discarded.
try {
TransactionalEditingDomain domain = TransactionUtils.getEditingDomain(model_object);
domain.getCommandStack().execute(new RecordingCommand(domain) {
public void doExecute() {
// do the changes here
// OperationCanceledException can be replaced with other runtime exception
throw new OperationCanceledException("Please rollback");
}
});
// if here model changed
} catch (OperationCanceledException exception) {
// if here, model did not change because it was interrupted
}
Nesting
Transactions can be nested. Executing a recording command withing a recording command is possible. And so is interrupting the inner command without affecting the outer one.
final TransactionalEditingDomain domain = TransactionUtils.getEditingDomain(model_object);
domain.getCommandStack().execute(new RecordingCommand(domain) {
public void doExecute() {
// lets start the second transaction here
try {
domain.getCommandStack().execute(new RecordingCommand(domain) {
public void doExecute() {
// here we can throw an exception to cancel the inner transaction.
throw new OperationCanceledException("Rollback please");
}
});
} catch(OperationCanceledException exception) {
// if exception not catched outer transaction is canceled too
}
}
});
Update: Threads
You might also get the IllegalStateException when trying to execute a nested RecordingCommand in a different thread than the transaction's one.
Workspace wide configuration (this is the one you should get from the Activator's getPreferenceStore if not overridden)
Stored in the .metadata/.plugin folder of the workspace
Note related to Mac Export Tricks post: To get all the preferences in the path specified with the -data parameter use the InstanceScope. This should be the default you get when calling Activator.getDefault().getPreferenceStore().
I will use a hidden checkbox, some sibling combinators and CSS3's :checked pseudo class to do the magic. The buttons to show and dismiss are only labels for the checkbox. Click on the button below to show the dialog:
The CSS for the actual display of the dialog and opaque background:
/** if nothing else do not show the dialog container */
.expand, .bg {
display: none;
}
/** an .expand class immediately following a checked checkbox */
/** this will show the dialog container when the checkbox is checked */
input.check:checked + .expand {
position: fixed;
top: 0px; bottom:0px; left: 0px; right: 0px;
z-index: 10;
display: block !important;
}
/** a .bg class that follows (not necessarily immediately) a checked checkbox */
/** this is the opaque background layer. active when the dialog is visible. */
input.check:checked ~ .bg {
position: fixed;
top: 0px; bottom:0px; left: 0px; right: 0px;
opacity: 0.5;
background-color: black;
z-index: 9;
display: block !important;
}
/** do not show the checkbox that holds the visibility state of the dialog */
input.check {
display: none;
}
We used the direct sibling combinator (+) for the .expand class and the general sibling combinator (~) for the background. We could have also used the general one for both. The general matches any sibling, while the direct only the sibling right next to the checkbox.
The code above could be made a little more compact by merging the .expand and .bg common parts.
All the rest of the CSS is to make the dialog look a little like a dialog.
Just a bunch of div placed in a square. Their CSS defines animations when they are shown and when hovered. The hovering effect will quickly darken the background color to black (0.1s). When unhovered the background is set back to white this time a little slower, 1 second. The 400 cells of the example above are created with a script.
The toggle effect uses a hidden checkbox. CSS3 introduces the :checked pseudo class. This combined with the Adjacent sibling combinators will allow us to behave differently when the check box is selected and when not. To make check box change state upon a click on some text we will use a label for the checkbox. In HTML this translates to:
<input type="checkbox" class="check" id="check1"/>
<label for="check1" class="expand">
Click here: no javascript involved
<div class="details">
Just HTML and CSS3 being awesome!
</div>
<label>
While in this example the part that will expand is the label itself, this is not at all a requirement.
The CSS part includes also some transition effect. For the sake of simplicity the code below shows only important parts (no borders, shadows and colors):
NOTE: all code is non vendor specific CSS3. You will have to add -moz- and similar to get to work on the different browsers.
Quite powerful
This method turns out to be quite powerful. The label does not have to be next to the checkbox so we can place it where ever we want () and the element next to the hidden checkbox will still get expanded. We can even have multiple label pointing to the same checkbox ().
Clicking here wont do much
on the label in the text it does
Even more
There are many more things involved and many more applications of this method. The major advantage is that it will not require javascript to be enabled.
Here a post about an alert dialog without javascript.
A search in google will give you also many other uses of this "hack".
Accessibility
If not implemented correctly, this method is not very accesibility friendly. Multiple labels for a check box might confuse a screen reader and labels are not focussable. One quick fix for the latter could be:
You will need a browser that supports CSS3 to see this page properly.
A method to add an outline around some text is to define some solid shadows of the color that we want as border. This shadow will have no blurring and will have to be positioned shifted in all directions.
The quick brown fox jumps over the lazy dog
.bordershadow {
color: #d11;
text-shadow:
white 1px 1px 0px, /* right down */
white -1px 1px 0px, /* left down */
white -1px -1px 0px, /* right up */
white 1px -1px 0px, /* left up */
/** next 4 shadows improve rendering */
white 1px 0px 0px, /* right */
white -1px 0px 0px, /* left */
white 0px 1px 0px, /* down */
white 0px -1px 0px, /* up */
/** lets add some blurred shadow to make it
look a little nicer */
black 3px 3px 7px;
letter-spacing:1px;
}
4 vs 8 outline shadows
The comment in the code says that second 4 shadows improve rendering. This is especially true for sharp corners. Lets have a closer look: (Left with 4 shadows, right with all 8)
xt
xt
Letter spacing
Letter-spacing was added since, with the "border", the characters are now 2 pixels taller and broader.