1 | /* This file is part of the KDE project |
2 | Copyright (C) 2005 Hamish Rodda <rodda@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #ifndef KDELIBS_KTEXTEDITOR_SMARTINTERFACE_H |
21 | #define KDELIBS_KTEXTEDITOR_SMARTINTERFACE_H |
22 | |
23 | #include <ktexteditor/ktexteditor_export.h> |
24 | #include <ktexteditor/smartrange.h> |
25 | |
26 | class QMutex; |
27 | |
28 | namespace KTextEditor |
29 | { |
30 | class Document; |
31 | class View; |
32 | class SmartCursor; |
33 | |
34 | /** |
35 | * \brief A Document extension interface for handling SmartCursor%s and SmartRange%s. |
36 | * |
37 | * \ingroup kte_group_doc_extensions |
38 | * |
39 | * Topics: |
40 | * - \ref smartiface_intro |
41 | * - \ref smartiface_creation |
42 | * - \ref smartiface_highlight |
43 | * - \ref smartiface_action |
44 | * - \ref smartiface_access |
45 | * |
46 | * \section smartiface_intro Introduction |
47 | * Use this interface to: |
48 | * \li create new SmartCursor%s and SmartRange%s; |
49 | * \li create arbitrary highlighting; and |
50 | * \li associate KAction%s with ranges of text |
51 | * |
52 | * \section smartiface_creation Creation of SmartCursors and SmartRanges |
53 | * These functions must be used to create SmartCursor%s and SmartRange%s. This |
54 | * means that these objects cannot be derived from by third party applications. |
55 | * |
56 | * You then own these objects; upon deletion they de-register themselves from |
57 | * the Document with which they were associated. Alternatively, they are all |
58 | * deleted with the deletion of the owning Document. |
59 | * |
60 | * \section smartiface_highlight Arbitrary Highlighting |
61 | * Arbitrary highlighting of text can be achieved by creating SmartRange%s in a |
62 | * tree structure, and assigning appropriate Attributes to these ranges. |
63 | * |
64 | * To highlight all views, use addHighlightToDocument(); to highlight one or some |
65 | * of the views, use addHighlightToView(). You only need to call this function once |
66 | * per tree; just supply the top range you want to have highlighted. Calling |
67 | * this function more than once with ranges from the same tree may give undefined results. |
68 | * |
69 | * \section smartiface_action Action Binding |
70 | * Action binding can be used to associate KAction%s with specific ranges of text. |
71 | * These bound actions are automatically enabled and disabled when the caret enters |
72 | * their associated ranges, and context menus are automatically populated with the |
73 | * relevant actions. |
74 | * |
75 | * As with the arbitrary highlighting interface, to enable bound actions to be active, |
76 | * call addActionsToDocument() or addActionsToView() on the top SmartRange of a tree. |
77 | * If only small branches of a tree contain actions, it may be more efficient to simply add |
78 | * each of these branches instead (but this is unlikely unless the tree is complex). |
79 | * |
80 | * Note that actions can be bound either directly to the range via |
81 | * SmartRange::associateAction(), or indirectly via |
82 | * Attribute::associateAction(). Using attributes may be more convenient when |
83 | * you want all ranges of a specific type to have the same action associated |
84 | * with them. |
85 | * |
86 | * \todo extend this to provide a signal from the action indicating which range was |
87 | * used to activate it (if possible) |
88 | * |
89 | * \section smartiface_access Accessing the Interface |
90 | * |
91 | * The SmartInterface is supposed to be an extension interface for a Document, |
92 | * i.e. the Document inherits the interface \e provided that the |
93 | * KTextEditor library in use implements the interface. Use dynamic_cast to access |
94 | * the interface: |
95 | * \code |
96 | * // doc is of type KTextEditor::Document* |
97 | * KTextEditor::SmartInterface *iface = |
98 | * qobject_cast<KTextEditor::SmartInterface*>( doc ); |
99 | * |
100 | * if( iface ) { |
101 | * // the implementation supports the interface |
102 | * // do stuff |
103 | * } |
104 | * \endcode |
105 | * |
106 | * \section smartiface_threadsafety Thread safety |
107 | * The smart interface is designed to be usable in multithreaded environments. |
108 | * If you use the interface from threads other than the main thread, you must |
109 | * lock the smartMutex() whenever you are making a non-const call to a smart object. |
110 | * This allows the text editor to guarantee that the objects will not change |
111 | * when it locks the mutex (for example, when performing layout or rendering). |
112 | * The useRevision function has only effect for the thread calling it. It will |
113 | * store the selected revision in a thread local storage to allow multiple threads |
114 | * to have different views on the same document in respect to the smart interface. |
115 | * |
116 | * \author Hamish Rodda \<rodda@kde.org\> |
117 | */ |
118 | class KTEXTEDITOR_EXPORT SmartInterface |
119 | { |
120 | friend class Attribute; |
121 | |
122 | public: |
123 | SmartInterface(); |
124 | virtual ~SmartInterface(); |
125 | |
126 | /** |
127 | * Provides access to the recursive mutex used to protect write access to |
128 | * smart interface objects (cursors + ranges and their associated properties). |
129 | * If you use this interface from a thread other than the main thread, |
130 | * you must lock this mutex whenever you call a non-const function on a smart object. |
131 | */ |
132 | QMutex* smartMutex() const; |
133 | |
134 | /** |
135 | * Clears or deletes all instances of smart objects, ie: |
136 | * \li deletes all SmartCursor%s |
137 | * \li deletes all SmartRange%s |
138 | * \li clears all arbitrary highlight ranges |
139 | * \li clears all action binding |
140 | * |
141 | * Deletion occurs without modification to the underlying text. |
142 | */ |
143 | virtual void clearSmartInterface() = 0; |
144 | |
145 | /** |
146 | * Returns whether the smart interface will be cleared on reload of the document. |
147 | * |
148 | * Defaults to true. |
149 | */ |
150 | bool clearOnDocumentReload() const; |
151 | |
152 | /** |
153 | * Specify whether the smart interface should be cleared on reload of the document. |
154 | * |
155 | * \param clearOnReload set to true to enable clearing of the smart interface on reload (the default). |
156 | */ |
157 | void setClearOnDocumentReload(bool clearOnReload); |
158 | |
159 | //BEGIN New cursor methods |
160 | /** |
161 | * Retrieve a token representing the current version of the document. This can |
162 | * be used later to create cursors and ranges as they would have been at this revision. |
163 | * |
164 | * Once you have finished with the token, release it with releaseRevision(). |
165 | */ |
166 | virtual int currentRevision() const = 0; |
167 | |
168 | /** |
169 | * Release a revision token provided by currentRevision(). You will no longer be able to |
170 | * create cursors and ranges against this revision. |
171 | */ |
172 | virtual void releaseRevision(int revision) const = 0; |
173 | |
174 | /** |
175 | * Tell the smart interface to work against the given \a revision when creating cursors and |
176 | * ranges. This has only an effect for the thread calling this function, as this property |
177 | * is stored thread locally. This is not allowed to be called in the main gui thread. |
178 | * If you call it in the main gui thread, fatal error will occur. |
179 | * |
180 | * \param revision the token representing a revision retrieved by currentRevision(), or -1 to |
181 | * clear any previous setting and use the current document revision. |
182 | */ |
183 | virtual void useRevision(int revision) = 0; |
184 | |
185 | /** |
186 | * Clear any previous setting to use a specific revision. |
187 | * Convenience wrapper for useRevision (-1). |
188 | */ |
189 | void clearRevision(); |
190 | |
191 | /** |
192 | * Translate the given \a cursor against the revision specified through useRevision(), |
193 | * using the given \a insertBehavior. |
194 | * |
195 | * If no revision is set, simply returns the cursor. |
196 | */ |
197 | virtual KTextEditor::Cursor translateFromRevision(const KTextEditor::Cursor& cursor, KTextEditor::SmartCursor::InsertBehavior insertBehavior = KTextEditor::SmartCursor::StayOnInsert) const; |
198 | |
199 | /** |
200 | * Translate the given \a range against the revision specified through useRevision(), |
201 | * using the given \a insertBehavior. |
202 | * |
203 | * If no revision is set, simply returns the range. |
204 | */ |
205 | virtual KTextEditor::Range translateFromRevision(const KTextEditor::Range& range, KTextEditor::SmartRange::InsertBehaviors insertBehavior = KTextEditor::SmartRange::ExpandLeft | KTextEditor::SmartRange::ExpandRight) const; |
206 | |
207 | /** |
208 | * \name Smart Cursors |
209 | * |
210 | * The following functions allow for creation and deletion of SmartCursor%s. |
211 | * \{ |
212 | */ |
213 | /** |
214 | * Creates a new SmartCursor. |
215 | * |
216 | * You own this object, and may delete it when you are finished with it. |
217 | * Alternatively, you may call the various clear methods, or wait for the Document |
218 | * to be destroyed. |
219 | * |
220 | * \param position The initial cursor position assumed by the new cursor. |
221 | * If not specified, it will start at position (0, 0). |
222 | * \param insertBehavior Define whether the cursor should move when text is inserted at the cursor position. |
223 | */ |
224 | virtual SmartCursor* newSmartCursor(const Cursor& position = Cursor::start(), SmartCursor::InsertBehavior insertBehavior = SmartCursor::MoveOnInsert) = 0; |
225 | |
226 | /** |
227 | * \overload |
228 | * \n \n |
229 | * Creates a new SmartCursor. |
230 | * |
231 | * You own this object, and may delete it when you are finished with it. |
232 | * Alternatively, you may call the various clear methods, or wait for the Document |
233 | * to be destroyed. |
234 | * |
235 | * \param line the line number of the cursor's initial position |
236 | * \param column the line number of the cursor's initial position |
237 | * \param insertBehavior Define whether the cursor should move when text is inserted at the cursor position. |
238 | */ |
239 | SmartCursor* newSmartCursor(int line, int column, SmartCursor::InsertBehavior insertBehavior = SmartCursor::MoveOnInsert); |
240 | |
241 | /** |
242 | * Delete all SmartCursor%s from this document, with the exception of those |
243 | * cursors currently bound to ranges. |
244 | */ |
245 | virtual void deleteCursors() = 0; |
246 | //END |
247 | |
248 | //BEGIN New range methods |
249 | /** |
250 | * \} |
251 | * |
252 | * \name Smart Ranges |
253 | * |
254 | * The following functions allow for creation of new SmartRange%s. |
255 | * \{ |
256 | */ |
257 | /** |
258 | * Creates a new SmartRange. |
259 | * \param range The initial text range assumed by the new range. |
260 | * \param parent The parent SmartRange, if this is to be the child of an existing range. |
261 | * \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. |
262 | */ |
263 | virtual SmartRange* newSmartRange(const Range& range = Range(), |
264 | SmartRange* parent = 0L, |
265 | SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand) = 0; |
266 | |
267 | /** |
268 | * \overload |
269 | * \n \n |
270 | * Creates a new SmartRange. |
271 | * \param startPosition The start position assumed by the new range. |
272 | * \param endPosition The end position assumed by the new range. |
273 | * \param parent The parent SmartRange, if this is to be the child of an existing range. |
274 | * \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. |
275 | */ |
276 | SmartRange* newSmartRange(const Cursor& startPosition, |
277 | const Cursor& endPosition, |
278 | SmartRange* parent = 0L, |
279 | SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand); |
280 | |
281 | /** |
282 | * \overload |
283 | * \n \n |
284 | * Creates a new SmartRange. |
285 | * \param startLine The start line assumed by the new range. |
286 | * \param startColumn The start column assumed by the new range. |
287 | * \param endLine The end line assumed by the new range. |
288 | * \param endColumn The end column assumed by the new range. |
289 | * \param parent The parent SmartRange, if this is to be the child of an existing range. |
290 | * \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. |
291 | */ |
292 | SmartRange* newSmartRange(int startLine, int startColumn, int endLine, int endColumn, SmartRange* parent = 0L, SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand); |
293 | |
294 | /** |
295 | * Creates a new SmartRange from pre-existing SmartCursor%s. The cursors must not be part of any other range. |
296 | * |
297 | * \param start Start SmartCursor |
298 | * \param end End SmartCursor |
299 | * \param parent The parent SmartRange, if this is to be the child of an existing range. |
300 | * \param insertBehavior Define whether the range should expand when text is inserted at ends of the range. |
301 | */ |
302 | virtual SmartRange* newSmartRange(SmartCursor* start, SmartCursor* end, SmartRange* parent = 0L, SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand) = 0; |
303 | |
304 | /** |
305 | * Delete a SmartRange without deleting the SmartCursor%s which make up its start() and end(). |
306 | * |
307 | * First, extract the cursors yourself using: |
308 | * \code |
309 | * SmartCursor* start = &range->smartStart(); |
310 | * SmartCursor* end = &range->smartEnd(); |
311 | * \endcode |
312 | * |
313 | * Then, call this function to delete the SmartRange instance. The underlying text will not be affected. |
314 | * |
315 | * \param range the range to dissociate from its smart cursors, and delete |
316 | */ |
317 | virtual void unbindSmartRange(SmartRange* range) = 0; |
318 | |
319 | /** |
320 | * Delete all SmartRange%s from this document. This will also delete all |
321 | * cursors currently bound to ranges. |
322 | * |
323 | * This will not affect any underlying text. |
324 | */ |
325 | virtual void deleteRanges() = 0; |
326 | //END |
327 | |
328 | //BEGIN Syntax highlighting extension |
329 | /** |
330 | * \} |
331 | * |
332 | * \name Arbitrary Highlighting |
333 | * |
334 | * The following functions enable highlighting processing for SmartRange%s with arbitrary |
335 | * highlighting information. |
336 | * \{ |
337 | */ |
338 | /** |
339 | * Register a SmartRange tree as providing arbitrary highlighting information, |
340 | * and that it should be rendered on all of the views of a document. |
341 | * |
342 | * \param topRange the top range of the tree to add |
343 | * \param supportDynamic support dynamic highlighting attributes |
344 | */ |
345 | virtual void addHighlightToDocument(SmartRange* topRange, bool supportDynamic = false) = 0; |
346 | |
347 | /** |
348 | * Remove a SmartRange tree from providing arbitrary highlighting information |
349 | * to all of the views of a document. |
350 | * |
351 | * \param topRange the top range of the tree to remove |
352 | */ |
353 | virtual void removeHighlightFromDocument(SmartRange* topRange) = 0; |
354 | |
355 | /** |
356 | * Return a list of SmartRange%s which are currently registered as |
357 | * providing arbitrary highlighting information to all of the views of a |
358 | * document. |
359 | */ |
360 | virtual const QList<SmartRange*> documentHighlights() const = 0; |
361 | |
362 | /** |
363 | * Clear the highlight ranges from a Document. |
364 | */ |
365 | virtual void clearDocumentHighlights() = 0; |
366 | |
367 | /** |
368 | * Register a SmartRange tree as providing arbitrary highlighting information, |
369 | * and that it should be rendered on the specified \p view. |
370 | * |
371 | * \param view view on which to render the highlight |
372 | * \param topRange the top range of the tree to add |
373 | * \param supportDynamic support dynamic highlighting attributes |
374 | */ |
375 | virtual void addHighlightToView(View* view, SmartRange* topRange, bool supportDynamic = false) = 0; |
376 | |
377 | /** |
378 | * Remove a SmartRange tree from providing arbitrary highlighting information |
379 | * to a specific view of a document. |
380 | * |
381 | * \note implementations should not take into account document-bound |
382 | * highlighting ranges when calling this function; it is intended solely |
383 | * to be the counter of addHighlightToView() |
384 | * |
385 | * \param view view on which the highlight was previously rendered |
386 | * \param topRange the top range of the tree to remove |
387 | */ |
388 | virtual void removeHighlightFromView(View* view, SmartRange* topRange) = 0; |
389 | |
390 | /** |
391 | * Return a list of SmartRange%s which are currently registered as |
392 | * providing arbitrary highlighting information to a specific view of a |
393 | * document. |
394 | * |
395 | * \note implementations should not take into account document-bound |
396 | * highlighting ranges when returning the list; it is intended solely |
397 | * to show highlights added via addHighlightToView() |
398 | * |
399 | * \param view view to query for the highlight list |
400 | */ |
401 | virtual const QList<SmartRange*> viewHighlights(View* view) const = 0; |
402 | |
403 | /** |
404 | * Clear the highlight ranges from a View. |
405 | * |
406 | * \param view view to clear highlights from |
407 | */ |
408 | virtual void clearViewHighlights(View* view) = 0; |
409 | //END |
410 | |
411 | //BEGIN Action binding extension - not implemented |
412 | /* not implemented |
413 | * Register a SmartRange tree as providing bound actions, |
414 | * and that they should interact with all of the views of a document. |
415 | * |
416 | * \param topRange the top range of the tree to add |
417 | */ |
418 | virtual void addActionsToDocument(SmartRange* topRange) = 0; |
419 | |
420 | /* not implemented |
421 | * Remove a SmartRange tree from providing bound actions |
422 | * to all of the views of a document. |
423 | * |
424 | * \param topRange the top range of the tree to remove |
425 | */ |
426 | virtual void removeActionsFromDocument(SmartRange* topRange) = 0; |
427 | |
428 | /* not implemented |
429 | * Return a list of SmartRange%s which are currently registered as |
430 | * providing bound actions to all of the views of a document. |
431 | */ |
432 | virtual const QList<SmartRange*> documentActions() const = 0; |
433 | |
434 | /* not implemented |
435 | * Remove all bound SmartRange%s which provide actions to the document. |
436 | */ |
437 | virtual void clearDocumentActions() = 0; |
438 | |
439 | /* not implemented |
440 | * Register a SmartRange tree as providing bound actions, |
441 | * and that they should interact with the specified \p view. |
442 | * |
443 | * \param view view on which to use the actions |
444 | * \param topRange the top range of the tree to add |
445 | */ |
446 | virtual void addActionsToView(View* view, SmartRange* topRange) = 0; |
447 | |
448 | /* not implemented |
449 | * Remove a SmartRange tree from providing bound actions |
450 | * to the specified \p view. |
451 | * |
452 | * \note implementations should not take into account document-bound |
453 | * action ranges when calling this function; it is intended solely |
454 | * to be the counter of addActionsToView() |
455 | * |
456 | * \param view view on which the actions were previously used |
457 | * \param topRange the top range of the tree to remove |
458 | */ |
459 | virtual void removeActionsFromView(View* view, SmartRange* topRange) = 0; |
460 | |
461 | /* not implemented |
462 | * Return a list of SmartRange%s which are currently registered as |
463 | * providing bound actions to the specified \p view. |
464 | * |
465 | * \note implementations should not take into account document-bound |
466 | * action ranges when returning the list; it is intended solely |
467 | * to show actions added via addActionsToView() |
468 | * |
469 | * \param view view to query for the action list |
470 | */ |
471 | virtual const QList<SmartRange*> viewActions(View* view) const = 0; |
472 | |
473 | /* not implemented |
474 | * Remove all bound SmartRange%s which provide actions to the specified \p view. |
475 | * |
476 | * \param view view from which to remove actions |
477 | */ |
478 | virtual void clearViewActions(View* view) = 0; |
479 | //END |
480 | |
481 | protected: |
482 | /** |
483 | * \internal |
484 | * Used to notify implementations that an Attribute has gained |
485 | * a dynamic component and needs to be included in mouse and/or cursor |
486 | * tracking. |
487 | */ |
488 | virtual void attributeDynamic(Attribute::Ptr a) = 0; |
489 | /** |
490 | * \internal |
491 | * Used to notify implementations that an Attribute has lost |
492 | * all dynamic components and no longer needs to be included in mouse and cursor |
493 | * tracking. |
494 | */ |
495 | virtual void attributeNotDynamic(Attribute::Ptr a) = 0; |
496 | |
497 | private: |
498 | class SmartInterfacePrivate* const d; |
499 | }; |
500 | |
501 | } |
502 | |
503 | Q_DECLARE_INTERFACE(KTextEditor::SmartInterface, "org.kde.KTextEditor.SmartInterface" ) |
504 | |
505 | #endif |
506 | |
507 | // kate: space-indent on; indent-width 2; replace-tabs on; |
508 | |