~ubuntu-branches/debian/lenny/ecb/lenny

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
<html lang="en">
<head>
<title>ECB - the Emacs Code Browser</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name=description content="ECB - the Emacs Code Browser">
<meta name=generator content="makeinfo 4.2">
<link href="http://www.gnu.org/software/texinfo/" rel=generator-home>
</head>
<body>
<p>
Node:<a name="Programming%20special%20windows">Programming special windows</a>,
Next:<a rel=next accesskey=n href="Possible-layout-outlines.html#Possible%20layout-outlines">Possible layout-outlines</a>,
Previous:<a rel=previous accesskey=p href="Programming-a-new-layout.html#Programming%20a%20new%20layout">Programming a new layout</a>,
Up:<a rel=up accesskey=u href="The-layout-engine.html#The%20layout-engine">The layout-engine</a>
<hr><br>

<h4>All aspects of programming special windows</h4>

<p>ECB offers a flexible programmable layout-engine for other packages to
display their own contents and informations in special ECB-windows. An
example could be a graphical debugger which offers a special window for
displaying local variables and another special window for messages
from the debugger-process (like JDEbug of JDEE<a rel=footnote href="#fn-1"><sup>1</sup></a>).

<p>This section explains all aspects of programming new special windows,
adding them to a new layout and synchronizing them with edit-window of
ECB. This can be done best with an easy example which nevertheless
covers all necessary aspects to be a good example and skeleton for
complex tools (like a graphical debugger) which want to use the
layout-engine of ECB do display their own information.

<p>Here comes the example:

<h5>The outline of the example layout:</h5>

<br><pre>-------------------------------------------------------
|Bufferinfo for &lt;filename&gt;:            |[prior]       |
|Type: file                            |[next]        |
|Size: 23456                           |              |
|Modes: rw-rw-rw-                      |              |
|-----------------------------------------------------|
|                                                     |
|                                                     |
|                                                     |
|                                                     |
|                 edit-window                         |
|                                                     |
|                                                     |
|                                                     |
|                                                     |
-------------------------------------------------------
|                                                     |
|                 compilation-window                  |
|                                                     |
-------------------------------------------------------
</pre>

<h5>The description of the layout-contents</h5>

<p>The top-left window always displays informations about the current
buffer in the selected edit-window. This window demonstrates how
autom. synchronizing a special window/buffer of a layout with current
edit-window.

<p>The top-right window contains an read-only "action-buffer" and
offers two buttons which can be used with the middle mouse-button to
scroll the edit-window. This is not very senseful but it demonstrates
how to control the edit-window with actions performed in a special
window/buffer of a layout.

<p>(If you have not set a compilation-window in
<code>ecb-compile-window-height</code> then the layout contains no durable
compilation window and the other windows get a little more place).

<h5>The example code</h5>

<p>Now let have us a look at the several parts of the Elisp-program
needed to program this new example layout. ECB contains a library
<code>ecb-examples.el</code> which contains the full working code of this
example. To test this example and to play with it you can load this
library into Emacs (with <code>load-library</code> for example) and then
calling <code>ecb-change-layout</code> (bound to <kbd>C-c . lc</kbd>) and
inserting "example-layout1" as layout-name. An alternative is
calling <code>ecb-examples-activate</code> and
<code>ecb-examples-deactivate</code>. For details see file
<code>ecb-examples.el</code>.

<p>The following steps only contain code-skeletons to demonstrate the
principle. The full working code is available in
<code>ecb-examples.el</code>.

<h5>The bufferinfo buffer of the example</h5>

<p>The name of the bufferinfo buffer:

<br><pre>(defconst ecb-examples-bufferinfo-buffer-name " *ECB buffer info*")
</pre>

<p>Two helper functions for displaying infos in a special buffer:

<br><pre>(defun ecb-examples-print-file-attributes (buffer filename)
  (ecb-with-readonly-buffer buffer
    (erase-buffer)
    (insert (format "Bufferinfo for %s:\n\n" filename))
    ;; insert with the function `file-attributes' some
    ;; informations about FILENAME.
    ))

(defun ecb-examples-print-non-filebuffer (buffer buffer-name)
  (ecb-with-readonly-buffer buffer
    (erase-buffer)
    ;; analogous to `ecb-examples-print-file-attributes'
    ))
</pre>

<p>The main synchronizing function added to
<code>ecb-current-buffer-sync-hook</code> for autom. evaluation by
<code>ecb-current-buffer-sync</code> which runs dependent on the values of
<code>ecb-window-sync</code> and <code>ecb-window-sync-delay</code>. This function
synchronizes the bufferinfo buffer with the current buffer of the
edit-window if that buffer has changed.

<br><pre>(defun ecb-examples-bufferinfo-sync ()
  (ecb-do-if-buffer-visible-in-ecb-frame
      'ecb-examples-bufferinfo-buffer-name

    ;; here we can be sure that the buffer with name
    ;; `ecb-examples-bufferinfo-buffer-name' is displayed in a
    ;; window of `ecb-frame'

    ;; The macro `ecb-do-if-buffer-visible-in-ecb-frame' locally
    ;; binds the variables visible-buffer and visible-window!! See
    ;; documentation of this macro!

    (let ((filename (buffer-file-name (current-buffer))))

      (if (and filename (file-readable-p filename))

          ;; real filebuffers
          ;; here we could add a smarter mechanism;
          ;; see ecb-examples.el
          (ecb-examples-print-file-attributes visible-buffer
                                              filename)

        ;; non file buffers like help-buffers etc...
        (setq ecb-examples-bufferinfo-last-file nil)
        (ecb-examples-print-non-filebuffer visible-buffer
                                           (buffer-name
                                             (current-buffer)))
        ))))
</pre>

<p>The function which makes the bufferinfo-buffer dedicated to a window.

<br><pre>(defun ecb-examples-set-bufferinfo-buffer ()
  (ecb-with-dedicated-window
      ecb-examples-bufferinfo-buffer-name
      'ecb-examples-set-bufferinfo-buffer
    (switch-to-buffer (get-buffer-create
                       ecb-examples-bufferinfo-buffer-name))
    (setq buffer-read-only t)))
</pre>

<p>This is all what we need for the special bufferinfo buffer. We have
demonstrated already three of the important functions/macros of the
layout-engine API of ECB: <code>ecb-with-readonly-buffer</code>,
<code>ecb-do-if-buffer-visible-in-ecb-frame</code> and
<code>ecb-with-dedicated-window</code> (see <a href="The-layout-engine-API.html#The%20layout-engine%20API">The layout-engine API</a>. Especially the second macro is strongly recommended for
programming good synchronizing functions which do not waste CPU!

<h5>The action buffer of the example</h5>

<p>The name of the action-buffer:

<br><pre>(defconst ecb-examples-action-buffer-name " *ECB action buffer*")
</pre>

<p>Two helper functions for creating a readonly action-buffer with a
special local key-map for the middle-mouse-button and two buttons
[prior] and [next]:

<br><pre>(defun ecb-examples-insert-text-in-action-buffer (text)
  (let ((p (point)))
    (insert text)
    (put-text-property p (+ p (length text)) 'mouse-face
                                             'highlight)))

(defun ecb-examples-action-buffer-create ()
  (save-excursion
    (if (get-buffer ecb-examples-action-buffer-name)
        (get-buffer ecb-examples-action-buffer-name)

      (set-buffer (get-buffer-create
                    ecb-examples-action-buffer-name))

      ;; we setup a local key-map and bind middle-mouse-button
      ;; see ecb-examples.el for the full code

      ;; insert the action buttons [prior] and [next] and
      ;; make it read-only

      (ecb-with-readonly-buffer (current-buffer)
        (erase-buffer)
        (ecb-examples-insert-text-in-action-buffer "[prior]")
        ;; analogous for the [next] button
        )

      (current-buffer))))
</pre>

<p>The function which performs the actions in the action-buffer if
clicked with the middle-mouse button onto a button [next] or [prior].

<br><pre>(defun ecb-examples-action-buffer-clicked (e)
  (interactive "e")
  (mouse-set-point e)
  (let ((line (buffer-substring (ecb-line-beginning-pos)
                                (ecb-line-end-pos))))
    (cond ((string-match "prior" line)
           (ecb-select-edit-window)
           (call-interactively 'scroll-down))
          ((string-match "next" line)
           ;; analogous for [next]
           ))))
</pre>

<p>The function which makes the action-buffer dedicated to a window.

<br><pre>(defun ecb-examples-set-action-buffer ()
  (let ((buf-name (buffer-name (ecb-examples-action-buffer-create))))
    (ecb-with-dedicated-window buf-name 'ecb-examples-set-action-buffer
      (switch-to-buffer (buffer-name
                         (ecb-examples-action-buffer-create))))))
</pre>

<p>We do not need more code for the action buffer. All of the code is
standard emacs-lisp which would also needed if used without ECB.

<h5>Adding the bufferinfo- and action-buffer to a new layout</h5>

<p>Now we add the bufferinfo- and the action-buffer to a new layout of
type top with name "example-layout1":

<br><pre>(ecb-layout-define "example-layout1" top

  ;; dedicating the bufferinfo window to the bufferinfo-buffer
  (ecb-examples-set-bufferinfo-buffer)

  ;; creating the action-window
  (ecb-split-hor 0.75)

  ;; dedicate the action window to the action-buffer
  (ecb-examples-set-action-buffer)

  ;; select the edit-window
  (select-window (next-window)))
</pre>

<p>This all what we need to define the new layout. See <a href="Programming-a-new-layout.html#Programming%20a%20new%20layout">Programming a new layout</a> for more details of the pure layout-programming task.

<h5>Synchronizing the bufferinfo-buffer automatically</h5>

<p>The last thing we have to do is to synchronize the bufferinfo-buffer
with current edit-window. We do this by adding
<code>ecb-examples-bufferinfo-sync</code> to the hook
<code>ecb-current-buffer-sync-hook'</code> (The file <code>ecb-examples.el</code>
shows a smarter mechanism for (de)activating the new layout and the
synchronization but this works also very well).

<br><pre>(add-hook 'ecb-current-buffer-sync-hook 'ecb-examples-bufferinfo-sync)
</pre>

<h5>Activating and deactivating new layouts</h5>

<p>Because a set of new special windows integrated in a new layout is
often just the GUI of a complete tool (like a graphical debugger) we
demonstrate here the complete activation and deactivation of such a
tool or at least of the tool-GUI. We decide that the GUI of our
example "tool" needs a compile-window with height 5 lines and the
height of the special windows "row" on top should be exactly 6 lines
(normally width and height of the special windows should be a fraction
of the frame, but here we use 6 lines<a rel=footnote href="#fn-2"><sup>2</sup></a>

<p>Here comes the (de)activation code.

<p>The code for saving and restoring the state before activation (the
full code is available in <code>ecb-examples.el</code>:

<br><pre>(defun ecb-examples-preactivation-state(action)
  (cond ((equal action 'save)
         ;; code for saving the state
         )
        ((equal action 'restore)
        ;; code for restoring the state
        )))
</pre>

<p>The following function activates the GUI of our example tool:

<br><pre>(defun ecb-examples-activate ()
  (interactive)

  ;; activating the synchronization of the bufferinfo-window
  (add-hook 'ecb-current-buffer-sync-hook
            'ecb-examples-bufferinfo-sync)

  ;; saving the state
  (ecb-examples-preactivation-state 'save)

  ;; switch to our preferred layout
  (setq ecb-windows-height 6)
  (setq ecb-compile-window-height 5)
  (ecb-layout-switch "example-layout1"))
</pre>

<p>This function deactivates the GUI of our example-tool and restores the
state as before activation:

<br><pre>(defun ecb-examples-deactivate ()
  (interactive)

  (remove-hook 'ecb-current-buffer-sync-hook
               'ecb-examples-bufferinfo-sync)
  (ecb-examples-preactivation-state 'restore)
  (ecb-layout-switch ecb-layout-name))
</pre>

<p>Now we have all code for the new layout and the new layout-buffers. 
The example is ready for use; just load <code>ecb-examples.el</code> (s.a.).

<hr><h4>Footnotes</h4>
<ol type="1">
<li><a name="fn-1"></a>
<p>JDEE is
available at
<a href="http://jdee.sunsite.dk/">http://jdee.sunsite.dk/</a>
</p>

<li><a name="fn-2"></a>
<p>You can change the code
in the file <code>ecb-examples.el</code> to use a frame-fraction of 0.2
instead of 6 hard lines, just try it!</p>

</ol><hr>

</body></html>