This patch provides a new XBL binding that extends a textbox with an
integrated "annotation".  The annotation is arbitrary text that
appears in the textbox, to the right of the input.  It is styled
differently to the input (oblique by default) and shifts out of the
way as the input grows.  This will be applied to a minibuffer-input
feature in a following patch.

When a textbox is bound to annotated-textbox it gains two properties.
The annotate property is a boolean that determines whether the
annotation is shown.  When false (the default) the annotated-textbox
behaves just like a regular textbox.  The annotation property is a
string that determines the displayed text.

Implementing the annotated-textbox binding to extend the textbox
binding is simpler than encapsulating it; all the properties from the
textbox apply to the new binding with no effort.  Many more inherits
properties would otherwise need to be set and maintained as the
xulrunner platform evolves.

However there is the disadvantage that the content element needs to be
copied from the textbox binding; there is no way in XBL to include the
content when extending a binding.  The textbox content (an hbox and an
input element) has changed only slightly between xulrunner 1.9.1 and
11.0.  There are new properties to be inherited and the setting of
flex on the input element has gone.  The content in annotated-textbox
specifies all the properties to inherit from 11.0 and includes the
flex on the input element; the latter does no harm in recent xulrunner
and is required to handle growing correctly in 1.9.1.

Internally, the annotated-textbox makes a deck of the input textbox
with a "strut" label, then continually updates the label with the
input text, so that the strut width controls the input width.  The
strut is placed in a box with hidden overflow; this prevents wide text
from expanding the minibuffer, thus causing re-layout of the content
buffer.  The annotation is given a much larger flex value than the
input, so that as the minibuffer fills, the annotation will be
truncated before the input.  The strut has right padding which acts as
a spacer between the input and annotation and also allows room for the
cursor.

It is assumed that the annotation will only be enabled with an initial
blank input value.  This is true of the minibuffer-input use case.
However, in the more general case where it is enabled later during an
input, the strut will be wrong until the next keystroke.  It does not
work to set the strut to the input value when enabled, because in the
usual case the input field may not yet have had a prior value cleared.

The implementation looks more complicated than might be wished, but
largely this is merely due to the verbosity of the XML representation
and the awkwardness of XBL.

Development note: To check that the strut label matches the input,
change the deck to a stack and use the following css:

textbox [anonid="strut"] {
  color: red;
  font-style: oblique;
}

Thanks to John Foerch for many suggestions.  The idea for using a deck
and strut is from http://www.blackfishsoftware.com/node/47.
---
 content/annotated-textbox.css |   16 +++++++++
 content/annotated-textbox.xml |   75 +++++++++++++++++++++++++++++++++++++++++
 content/minibuffer.css        |    4 ++
 3 files changed, 95 insertions(+), 0 deletions(-)
 create mode 100644 content/annotated-textbox.css
 create mode 100644 content/annotated-textbox.xml

diff --git a/content/annotated-textbox.css b/content/annotated-textbox.css
new file mode 100644
index 0000000..f41e665
--- /dev/null
+++ b/content/annotated-textbox.css
@@ -0,0 +1,16 @@
+/**
+ * (C) Copyright 2012 David Kettler
+ *
+ * Use, modification, and distribution are subject to the terms specified in 
the
+ * COPYING file.
+**/
+
+/* Note: the binding is applied to a textbox, so that selector is used. */
+
+textbox [anonid="annotation"] {
+  font-style: oblique;
+}
+
+textbox [anonid="strut"] {
+  padding-right: 1em !important;
+}
diff --git a/content/annotated-textbox.xml b/content/annotated-textbox.xml
new file mode 100644
index 0000000..66b6b43
--- /dev/null
+++ b/content/annotated-textbox.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+(C) Copyright 2012 David Kettler
+
+Use, modification, and distribution are subject to the terms specified in the
+COPYING file.
+-->
+<bindings
+    xmlns="http://www.mozilla.org/xbl";
+    xmlns:html="http://www.w3.org/1999/xhtml";
+    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+    xmlns:xbl="http://www.mozilla.org/xbl";>
+
+  <binding id="annotated-textbox"
+           extends="chrome://global/content/bindings/textbox.xml#textbox">
+
+    <resources>  
+      <stylesheet src="annotated-textbox.css"/>  
+    </resources>  
+
+    <content>
+      <children/>
+      <xul:deck flex="1">
+        <xul:hbox class="textbox-input-box" flex="1" 
xbl:inherits="context,spellcheck">
+          <html:input class="textbox-input" flex="1" anonid="input"
+                      
xbl:inherits="onfocus,onblur,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,noinitialfocus,mozactionhint,spellcheck"/>
+        </xul:hbox>
+        <xul:hbox style="overflow: hidden">
+          <xul:label class="plain" anonid="strut"/>
+        </xul:hbox>
+      </xul:deck>
+      <xul:label class="plain" anonid="annotation"
+                 xbl:inherits="value=annotation"
+                 flex="1000" crop="right" collapsed="true"/>
+    </content>
+
+    <implementation>
+
+      <field name="_annotate"> false </field>
+      <field name="_annot" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "annotation");
+      </field>
+      <field name="_strut" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "strut");
+      </field>
+
+      <property name="annotate">
+        <getter>
+          return this._annotate;
+        </getter>
+        <setter><![CDATA[
+          this._annotate = !!val;
+          this.annotation = "";
+          this._strut.setAttribute("value", "");
+          this._annot.setAttribute("collapsed",
+                                   this._annotate ? "false" : "true");
+          return this._annotate;
+        ]]></setter>
+      </property>
+
+      <property name="annotation"
+                onset="this.setAttribute('annotation', val); return val;"
+                onget="return this.getAttribute('annotation');"/>
+
+    </implementation>
+
+    <handlers>
+      <handler event="input">
+        if (this._annotate)
+          this._strut.setAttribute("value", this.value);
+      </handler>
+    </handlers>
+
+  </binding>
+</bindings>
diff --git a/content/minibuffer.css b/content/minibuffer.css
index 17ee1b2..71105fd 100644
--- a/content/minibuffer.css
+++ b/content/minibuffer.css
@@ -13,3 +13,7 @@
 #minibuffer[minibuffermode="input"] #minibuffer-mode-indicator {
   visibility: collapse;
 }
+
+#minibuffer-input {
+    -moz-binding: 
url("chrome://conkeror-gui/content/annotated-textbox.xml#annotated-textbox");
+}
-- 
1.7.9

_______________________________________________
Conkeror mailing list
[email protected]
https://www.mozdev.org/mailman/listinfo/conkeror

Reply via email to