ClipProvenance.java
Created with JBuilder |
package multivalent.std;
import multivalent.*;
import multivalent.gui.VCheckbox;
/**
Augment selection for clipboard with author, title.
Elaborately commented to serve as a simple example of translating Multivalent protocols into methods.
*/
public class ClipProvenance extends Behavior {
protected boolean active_ = false;
/**
When the Clipboard menu announces it is being built by sending a semantic event with
message "createWidget/Clipboard" and the node of the menu root in the out field,
add an entry. The entry uses createUI method defined in Behavior
with the right parameters to create a "checkbox" widget with title "Provenance",
which when invoked will execute the script which sends a semantic event named "toggleProvenance",
added to the menu in category "AuxSelect", and which is not disabled (diabled flag = false).
*/
public boolean semanticEventBefore(SemanticEvent se, String msg) {
// call superclass. In before protocols, this call is usually done before the subclass.
// If the superclass is short-circuiting (returns true), respect that.
// (In this case, we could have omitted this since we're inheriting directly from Behavior, and Behavior doesn't have any default behavior, but that's dangerous.)
if (super.semanticEventBefore(se, msg)) return true;
else if ("createWidget/Clipboard"==msg) {
INode menu = (INode)se.getOut();
VCheckbox cb = (VCheckbox)createUI("checkbox", "Provenance", "event toggleProvenance", menu, "AuxSelect", false);
cb.setState(active_);
}
// returning true would short-circuit other behaviors, which is seldom the right thing
return false;
}
/**
Catch the "toggleProvenance" event sent in semanticEventBefore,
assuming it hasn't been short-circuited by some other behavior.
This just toggles the internal active flag, to determine whether
to take action in the next clipboard procotol. Note that any behavior
can communicate with ClipProvenance at this high level by sending
the message it understands, namely "toggleProvenance"; other behaviors
don't have to work through its GUI or have hardcoded to some particular
method signature--they just send in the event the right String
as socially agreed upon (or proclaimed, that is, documented, by ClipProvenance).
*/
public boolean semanticEventAfter(SemanticEvent se, String msg) {
if ("toggleProvenance"==msg) active_=!active_;
// in after phases, we invoke the superclass afterwards,
// and unless we want to short-circuit, the overall short-circuit is the superclass's short-circuit
return super.semanticEventAfter(se, msg);
}
/**
This behavior has its effect (if it's active) during the clipboard protocol,
but that protocol is based on a tree walk, so if it is to know of the tree
walk, it has to hook into the tree. It registers interest during buildAfter,
as we know the tree will have been built by this point, and registers
interest on the root of the document, which is passed as a parameter,
in order to pick up clipboard extractions everywhere in the tree.
It's common for a behavior to register interest at the root as opposed to
smaller subtrees.
*/
public void buildAfter(Document doc) {
doc.addObserver(this);
super.buildAfter(doc);
}
/**
The clipboard protocol builds up the text in a StringBuffer.
Since this is the after phase, we know that the tree walk has taken place,
and therefore the StringBuffer holds the text one expects from
copying the selection into the clipboard. If the behavior is active (as
set by its GUI, slip the URL in at the head of the StringBuffer.
*/
public boolean clipboardAfter(StringBuffer sb, Node node) {
//System.out.println("ClipProvenance clipboardAfter "+node);
if (active_) {
Browser br = getBrowser();
// simple action: insert URL at head
// if excerpt is long, insert a blank line too.
sb.insert(0, "From "+br.getCurDocument().getURL()+(sb.length()<80*4? "\n": "\n\n"));
// If we had more metadata, such as author and title, that would be great.
// If some convention were established, another behavior could check and further augment the clipboard.
// Maybe the metadata is kept in a database and can be fetched with an ISBN attached to the document,
// or perhaps one or more particular new document formats carry this metadata,
// in which case site- or genre-specific behavior could take advantage of it.
//Node root = getBrowser().getCurDocument();
//sb.insert(0, "From \""+root.getAttr("title")+"\" by "+root.getAttr("author")+" in "+root.getAttr("source")+":\n\n");
}
return false;
}
}
ClipProvenance.java
Created with JBuilder |