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
26class QMutex;
27
28namespace KTextEditor
29{
30class Document;
31class View;
32class 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 */
118class 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
503Q_DECLARE_INTERFACE(KTextEditor::SmartInterface, "org.kde.KTextEditor.SmartInterface")
504
505#endif
506
507// kate: space-indent on; indent-width 2; replace-tabs on;
508