aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThien-Thi Nguyen2006-05-27 17:58:26 +0000
committerThien-Thi Nguyen2006-05-27 17:58:26 +0000
commitf3dffabb22006885c815cb496215b642cb8131e0 (patch)
treec64b8cc0a6b5d115f57e1d0d271b10ee55dd0e68
parent047ad6f5a2bedb0dab47ee0cbb25b82ef058ed08 (diff)
downloademacs-f3dffabb22006885c815cb496215b642cb8131e0.tar.gz
emacs-f3dffabb22006885c815cb496215b642cb8131e0.zip
(Display): Add "Abstract Display" to menu.
(Abstract Display, Abstract Display Functions) (Abstract Display Example): New nodes.
-rw-r--r--lispref/display.texi334
1 files changed, 334 insertions, 0 deletions
diff --git a/lispref/display.texi b/lispref/display.texi
index a77c895276e..3a8b8c1b7c0 100644
--- a/lispref/display.texi
+++ b/lispref/display.texi
@@ -29,6 +29,7 @@ that Emacs presents to the user.
29* Display Property:: Enabling special display features. 29* Display Property:: Enabling special display features.
30* Images:: Displaying images in Emacs buffers. 30* Images:: Displaying images in Emacs buffers.
31* Buttons:: Adding clickable buttons to Emacs buffers. 31* Buttons:: Adding clickable buttons to Emacs buffers.
32* Abstract Display:: Emacs' Widget for Object Collections.
32* Blinking:: How Emacs shows the matching open parenthesis. 33* Blinking:: How Emacs shows the matching open parenthesis.
33* Usual Display:: The usual conventions for displaying nonprinting chars. 34* Usual Display:: The usual conventions for displaying nonprinting chars.
34* Display Tables:: How to specify other conventions. 35* Display Tables:: How to specify other conventions.
@@ -4621,6 +4622,339 @@ buffer. If @var{count-current} is non-@code{nil}, count any button at
4621@var{pos} in the search, instead of starting at the next button. 4622@var{pos} in the search, instead of starting at the next button.
4622@end defun 4623@end defun
4623 4624
4625@node Abstract Display
4626@section Abstract Display
4627@cindex ewoc
4628@cindex display, abstract
4629@cindex display, arbitrary objects
4630@cindex model/view/controller
4631@cindex view part, model/view/controller
4632
4633 The Ewoc package constructs buffer text that represents a structure
4634of Lisp objects, and updates the text to follow changes in that
4635structure. This is like the ``view'' component in the the
4636``model/view/controller'' design paradigm.
4637
4638 An @dfn{ewoc} is a structure that organizes information required to
4639construct buffer text that represents certain Lisp data. The buffer
4640text of the ewoc has three parts, in order: first, fixed @dfn{header}
4641text; next, textual descriptions of a series of data elements (Lisp
4642objects that you specify); and last, fixed @dfn{footer} text.
4643Specifically, an ewoc contains information on:
4644
4645@itemize @bullet
4646@item
4647The buffer which its text is generated in.
4648
4649@item
4650The text's start position in the buffer.
4651
4652@item
4653The header and footer strings.
4654
4655@item
4656A doubly-linked chain of @dfn{nodes}, each of which contains:
4657
4658@itemize
4659@item
4660A @dfn{data element}, a single Lisp object.
4661
4662@item
4663Links to the preceding and following nodes in the chain.
4664@end itemize
4665
4666@item
4667A @dfn{pretty-printer} function which is responsible for
4668inserting the textual representation of a data
4669element value into the current buffer.
4670@end itemize
4671
4672 Typically, you define an ewoc with @code{ewoc-create}, and then pass
4673the resulting ewoc structure to other functions in the Ewoc package to
4674build nodes within it, and display it in the buffer. Once it is
4675displayed in the buffer, other functions determine the correspondance
4676between buffer positions and nodes, move point from one node's textual
4677representation to another, and so forth. @xref{Abstract Display
4678Functions}.
4679
4680 A node @dfn{encapsulates} a data element much the way a variable
4681holds a value. Normally, encapsulation occurs as a part of adding a
4682node to the ewoc. You can retrieve the data element value and place a
4683new value in its place, like so:
4684
4685@lisp
4686(ewoc-data @var{node})
4687@result{} value
4688
4689(ewoc-set-data @var{node} @var{new-value})
4690@result{} @var{new-value}
4691@end lisp
4692
4693@noindent
4694You can also use, as the data element value, a Lisp object (list or
4695vector) that is a container for the ``real'' value, or an index into
4696some other structure. The example (@pxref{Abstract Display Example})
4697uses the latter approach.
4698
4699 When the data changes, you will want to update the text in the
4700buffer. You can update all nodes by calling @code{ewoc-refresh}, or
4701just specific nodes using @code{ewoc-invalidate}, or all nodes
4702satisfying a predicate using @code{ewoc-map}. Alternatively, you can
4703delete invalid nodes using @code{ewoc-delete} or @code{ewoc-filter},
4704and add new nodes in their place. Deleting a node from an ewoc deletes
4705its associated textual description from buffer, as well.
4706
4707@menu
4708* Abstract Display Functions::
4709* Abstract Display Example::
4710@end menu
4711
4712@node Abstract Display Functions
4713@subsection Abstract Display Functions
4714
4715 In this subsection, @var{ewoc} and @var{node} stand for the
4716structures described above (@pxref{Abstract Display}), while
4717@var{data} stands for an arbitrary Lisp object used as a data element.
4718
4719@defun ewoc-create pretty-printer &optional header footer nosep
4720This constructs and returns a new ewoc, with no nodes (and thus no data
4721elements). @var{pretty-printer} should be a function that takes one
4722argument, a data element of the sort you plan to use in this ewoc, and
4723inserts its textual description at point using @code{insert} (and never
4724@code{insert-before-markers}, because that would interfere with the
4725Ewoc package's internal mechanisms).
4726
4727Normally, a newline is automatically inserted after the header,
4728the footer and every node's textual description. If @var{nosep}
4729is non-@code{nil}, no newline is inserted. This may be useful for
4730displaying an entire ewoc on a single line, for example, or for
4731making nodes ``invisible'' by arranging for @var{pretty-printer}
4732to do nothing for those nodes.
4733
4734An ewoc maintains its text in the buffer that is current when
4735you create it, so switch to the intended buffer before calling
4736@code{ewoc-create}.
4737@end defun
4738
4739@defun ewoc-buffer ewoc
4740This returns the buffer where @var{ewoc} maintains its text.
4741@end defun
4742
4743@defun ewoc-get-hf ewoc
4744This returns a cons cell @code{(@var{header} . @var{footer})}
4745made from @var{ewoc}'s header and footer.
4746@end defun
4747
4748@defun ewoc-set-hf ewoc header footer
4749This sets the header and footer of @var{ewoc} to the strings
4750@var{header} and @var{footer}, respectively.
4751@end defun
4752
4753@defun ewoc-enter-first ewoc data
4754@defunx ewoc-enter-last ewoc data
4755These add a new node encapsulating @var{data}, putting it, respectively,
4756at the beginning or end of @var{ewoc}'s chain of nodes.
4757@end defun
4758
4759@defun ewoc-enter-before ewoc node data
4760@defunx ewoc-enter-after ewoc node data
4761These add a new node encapsulating @var{data}, adding it to
4762@var{ewoc} before or after @var{node}, respectively.
4763@end defun
4764
4765@defun ewoc-prev ewoc node
4766@defunx ewoc-next ewoc node
4767These return, respectively, the previous node and the next node of @var{node}
4768in @var{ewoc}.
4769@end defun
4770
4771@defun ewoc-nth ewoc n
4772This returns the node in @var{ewoc} found at zero-based index @var{n}.
4773A negative @var{n} means count from the end. @code{ewoc-nth} returns
4774@code{nil} if @var{n} is out of range.
4775@end defun
4776
4777@defun ewoc-data node
4778This extracts the data encapsulated by @var{node} and returns it.
4779@end defun
4780
4781@defun ewoc-set-data node data
4782This sets the data encapsulated by @var{node} to @var{data}.
4783@end defun
4784
4785@defun ewoc-locate ewoc &optional pos guess
4786This determines the node in @var{ewoc} which contains point (or
4787@var{pos} if specified), and returns that node. If @var{ewoc} has no
4788nodes, it returns @code{nil}. If @var{pos} is before the first node,
4789it returns the first node; if @var{pos} is after the last node, it returns
4790the last node. The optional third arg @var{guess}
4791should be a node that is likely to be near @var{pos}; this doesn't
4792alter the result, but makes the function run faster.
4793@end defun
4794
4795@defun ewoc-location node
4796This returns the start position of @var{node}.
4797@end defun
4798
4799@defun ewoc-goto-prev ewoc arg
4800@defunx ewoc-goto-next ewoc arg
4801These move point to the previous or next, respectively, @var{arg}th node
4802in @var{ewoc}. @code{ewoc-goto-prev} does not move if it is already at
4803the first node or if @var{ewoc} is empty, whereas @code{ewoc-goto-next}
4804moves past the last node, returning @code{nil}. Excepting this special
4805case, these functions return the node moved to.
4806@end defun
4807
4808@defun ewoc-goto-node ewoc node
4809This moves point to the start of @var{node} in @var{ewoc}.
4810@end defun
4811
4812@defun ewoc-refresh ewoc
4813This function regenerates the text of @var{ewoc}. It works by
4814deleting the text between the header and the footer, i.e., all the
4815data elements' representations, and then calling the pretty-printer
4816function for each node, one by one, in order.
4817@end defun
4818
4819@defun ewoc-invalidate ewoc &rest nodes
4820This is similar to @code{ewoc-refresh}, except that only @var{nodes} in
4821@var{ewoc} are updated instead of the entire set.
4822@end defun
4823
4824@defun ewoc-delete ewoc &rest nodes
4825This deletes each node in @var{nodes} from @var{ewoc}.
4826@end defun
4827
4828@defun ewoc-filter ewoc predicate &rest args
4829This calls @var{predicate} for each data element in @var{ewoc} and
4830deletes those nodes for which @var{predicate} returns @code{nil}.
4831Any @var{args} are passed to @var{predicate}.
4832@end defun
4833
4834@defun ewoc-collect ewoc predicate &rest args
4835This calls @var{predicate} for each data element in @var{ewoc}
4836and returns a list of those elements for which @var{predicate}
4837returns non-@code{nil}. The elements in the list are ordered
4838as in the buffer. Any @var{args} are passed to @var{predicate}.
4839@end defun
4840
4841@defun ewoc-map map-function ewoc &rest args
4842This calls @var{map-function} for each data element in @var{ewoc} and
4843updates those nodes for which @var{map-function} returns non-@code{nil}.
4844Any @var{args} are passed to @var{map-function}.
4845@end defun
4846
4847@node Abstract Display Example
4848@subsection Abstract Display Example
4849
4850 Here is a simple example using functions of the ewoc package to
4851implement a ``color components display'', an area in a buffer that
4852represents a vector of three integers (itself representing a 24-bit RGB
4853value) in various ways.
4854
4855@example
4856(setq colorcomp-ewoc nil
4857 colorcomp-data nil
4858 colorcomp-mode-map nil
4859 colorcomp-labels ["Red" "Green" "Blue"])
4860
4861(defun colorcomp-pp (data)
4862 (if data
4863 (let ((comp (aref colorcomp-data data)))
4864 (insert (aref colorcomp-labels data) "\t: #x"
4865 (format "%02X" comp) " "
4866 (make-string (ash comp -2) ?#) "\n"))
4867 (let ((cstr (format "#%02X%02X%02X"
4868 (aref colorcomp-data 0)
4869 (aref colorcomp-data 1)
4870 (aref colorcomp-data 2)))
4871 (samp " (sample text) "))
4872 (insert "Color\t: "
4873 (propertize samp 'face `(foreground-color . ,cstr))
4874 (propertize samp 'face `(background-color . ,cstr))
4875 "\n"))))
4876
4877(defun colorcomp (color)
4878 "Allow fiddling with COLOR in a new buffer.
4879The buffer is in Color Components mode."
4880 (interactive "sColor (name or #RGB or #RRGGBB): ")
4881 (when (string= "" color)
4882 (setq color "green"))
4883 (unless (color-values color)
4884 (error "No such color: %S" color))
4885 (switch-to-buffer
4886 (generate-new-buffer (format "originally: %s" color)))
4887 (kill-all-local-variables)
4888 (setq major-mode 'colorcomp-mode
4889 mode-name "Color Components")
4890 (use-local-map colorcomp-mode-map)
4891 (erase-buffer)
4892 (buffer-disable-undo)
4893 (let ((data (apply 'vector (mapcar (lambda (n) (ash n -8))
4894 (color-values color))))
4895 (ewoc (ewoc-create 'colorcomp-pp
4896 "\nColor Components\n\n"
4897 (substitute-command-keys
4898 "\n\\@{colorcomp-mode-map@}"))))
4899 (set (make-local-variable 'colorcomp-data) data)
4900 (set (make-local-variable 'colorcomp-ewoc) ewoc)
4901 (ewoc-enter-last ewoc 0)
4902 (ewoc-enter-last ewoc 1)
4903 (ewoc-enter-last ewoc 2)
4904 (ewoc-enter-last ewoc nil)))
4905@end example
4906
4907@cindex controller part, model/view/controller
4908 This example can be extended to be a ``color selection widget'' (in
4909other words, the controller part of the ``model/view/controller''
4910design paradigm) by defining commands to modify @code{colorcomp-data}
4911and to ``finish'' the selection process, and a keymap to tie it all
4912together conveniently.
4913
4914@example
4915(defun colorcomp-mod (index limit delta)
4916 (let ((cur (aref colorcomp-data index)))
4917 (unless (= limit cur)
4918 (aset colorcomp-data index (+ cur delta)))
4919 (ewoc-invalidate
4920 colorcomp-ewoc
4921 (ewoc-nth colorcomp-ewoc index)
4922 (ewoc-nth colorcomp-ewoc -1))))
4923
4924(defun colorcomp-R-more () (interactive) (colorcomp-mod 0 255 1))
4925(defun colorcomp-G-more () (interactive) (colorcomp-mod 1 255 1))
4926(defun colorcomp-B-more () (interactive) (colorcomp-mod 2 255 1))
4927(defun colorcomp-R-less () (interactive) (colorcomp-mod 0 0 -1))
4928(defun colorcomp-G-less () (interactive) (colorcomp-mod 1 0 -1))
4929(defun colorcomp-B-less () (interactive) (colorcomp-mod 2 0 -1))
4930
4931(defun colorcomp-copy-as-kill-and-exit ()
4932 "Copy the color components into the kill ring and kill the buffer.
4933The string is formatted #RRGGBB (hash followed by six hex digits)."
4934 (interactive)
4935 (kill-new (format "#%02X%02X%02X"
4936 (aref colorcomp-data 0)
4937 (aref colorcomp-data 1)
4938 (aref colorcomp-data 2)))
4939 (kill-buffer nil))
4940
4941(setq colorcomp-mode-map
4942 (let ((m (make-sparse-keymap)))
4943 (suppress-keymap m)
4944 (define-key m "i" 'colorcomp-R-less)
4945 (define-key m "o" 'colorcomp-R-more)
4946 (define-key m "k" 'colorcomp-G-less)
4947 (define-key m "l" 'colorcomp-G-more)
4948 (define-key m "," 'colorcomp-B-less)
4949 (define-key m "." 'colorcomp-B-more)
4950 (define-key m " " 'colorcomp-copy-as-kill-and-exit)
4951 m))
4952@end example
4953
4954Note that we never modify the data in each node, which is fixed when the
4955ewoc is created to be either @code{nil} or an index into the vector
4956@code{colorcomp-data}, the actual color components.
4957
4624@node Blinking 4958@node Blinking
4625@section Blinking Parentheses 4959@section Blinking Parentheses
4626@cindex parenthesis matching 4960@cindex parenthesis matching