]> git.lyx.org Git - lyx.git/blob - src/BufferView.h
Avoid full metrics computation with Update:FitCursor
[lyx.git] / src / BufferView.h
1 // -*- C++ -*-
2 /**
3  * \file BufferView.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Alfredo Braustein
8  * \author Lars Gullik Bjønnes
9  * \author John Levon
10  * \author Jürgen Vigna
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #ifndef BUFFER_VIEW_H
16 #define BUFFER_VIEW_H
17
18 #include "CoordCache.h"
19 #include "DocumentClassPtr.h"
20 #include "TexRow.h"
21 #include "update_flags.h"
22
23 #include "support/strfwd.h"
24 #include "support/types.h"
25
26 namespace lyx {
27
28 namespace support { class FileName; }
29
30 namespace frontend { struct CaretGeometry; }
31 namespace frontend { class Painter; }
32 namespace frontend { class GuiBufferViewDelegate; }
33
34 class Buffer;
35 class Change;
36 class Cursor;
37 class CursorSlice;
38 class Dimension;
39 class DispatchResult;
40 class DocIterator;
41 class FuncRequest;
42 class FuncStatus;
43 class Intl;
44 class Inset;
45 class InsetMathNest;
46 class Length;
47 class MathData;
48 class MathRow;
49 class ParagraphMetrics;
50 class Point;
51 class Text;
52 class TextMetrics;
53
54 enum CursorStatus {
55         CUR_INSIDE,
56         CUR_ABOVE,
57         CUR_BELOW
58 };
59
60 /// How to show cursor
61 enum ScrollType {
62         // Make sure row if visible (do nothing if it is visible already)
63         SCROLL_VISIBLE,
64         // Force cursor to be on top of screen
65         SCROLL_TOP,
66         // Force cursor to be at center of screen
67         SCROLL_CENTER
68 };
69
70 /// Scrollbar Parameters.
71 struct ScrollbarParameters
72 {
73         // These parameters are normalized against the screen geometry and pixel
74         // coordinates. Position 0 corresponds to the top the the screen.
75         ScrollbarParameters()
76                 : min(0), max(0), single_step(1), page_step(1)
77         {}
78         /// Minimum scrollbar position in pixels.
79         int min;
80         /// Maximum scrollbar position in pixels.
81         int max;
82         /// Line-scroll amount in pixels.
83         int single_step;
84         /// Page-scroll amount in pixels.
85         int page_step;
86 };
87
88 /// Screen view of a Buffer.
89 /**
90  * A BufferView encapsulates a view onto a particular
91  * buffer, and allows access to operate upon it. A view
92  * is a sliding window of the entire document rendering.
93  * It is the official interface between the LyX core and
94  * the frontend WorkArea.
95  *
96  * \sa WorkArea
97  * \sa Buffer
98  * \sa CoordCache
99  */
100 class BufferView {
101 public:
102         ///
103         explicit BufferView(Buffer & buffer);
104         ///
105         ~BufferView();
106
107         /// return the buffer being viewed.
108         Buffer & buffer();
109         Buffer const & buffer() const;
110
111         /// Copy cursor and vertical offset information from \c bv
112         void copySettingsFrom(BufferView const & bv);
113
114         ///
115         void setFullScreen(bool full_screen) { full_screen_ = full_screen; }
116
117         /// default value for the margins
118         int defaultMargin() const;
119         /// right margin
120         int rightMargin() const;
121         /// left margin
122         int leftMargin() const;
123         /// top margin
124         int topMargin() const;
125         /// bottom margin
126         int bottomMargin() const;
127
128         docstring const & searchRequestCache() const;
129         void setSearchRequestCache(docstring const & text);
130
131         /// return the on-screen size of this length
132         /*
133          *  This is a wrapper around Length::inPixels that uses the
134          *  bufferview width as width and the EM value of the default
135          *  document font.
136          */
137         int inPixels(Length const & len) const;
138
139         /** Return the number of pixels equivalent to \c pix pixels at
140          * 100dpi and 100% zoom.
141          */
142         int zoomedPixels(int pix) const;
143
144         /// \return true if the BufferView is at the top of the document.
145         bool isTopScreen() const;
146
147         /// \return true if the BufferView is at the bottom of the document.
148         bool isBottomScreen() const;
149
150         /// Add \p flags to current update flags and trigger an update.
151         /* If this method is invoked several times before the update
152          * actually takes place, the effect is cumulative.
153          * \c Update::FitCursor means first to do a FitCursor, and to
154          * force an update if screen position changes.
155          * \c Update::Force means to force an update in any case.
156          */
157         void processUpdateFlags(Update::flags flags);
158
159         /// return true if one shall move the screen to fit the cursor.
160         /// Only to be called with good y coordinates (after a bv::metrics)
161         bool needsFitCursor() const;
162
163         // Returns the amount of horizontal scrolling applied to the
164         // top-level row where the cursor lies
165         int horizScrollOffset() const;
166         // Returns the amount of horizontal scrolling applied to the
167         // row of text starting at (pit, pos)
168         int horizScrollOffset(Text const * text,
169                               pit_type pit, pos_type pos) const;
170
171         /// reset the scrollbar parameters to reflect current view position.
172         void updateScrollbarParameters();
173         /// return the Scrollbar Parameters.
174         ScrollbarParameters const & scrollbarParameters() const;
175         /// \return Tool tip for the given position.
176         docstring toolTip(int x, int y) const;
177         /// \return the context menu for the given position.
178         std::string contextMenu(int x, int y) const;
179         /// \return the math inset with a context menu for the given position
180         Inset const * mathContextMenu(InsetMathNest const * inset,
181                 CoordCache::Insets const & inset_cache, int x, int y) const;
182         /// \return the clickable math inset for the given position
183         Inset const * clickableMathInset(InsetMathNest const * inset,
184                 CoordCache::Insets const & inset_cache, int x, int y) const;
185
186         /// Save the current position as bookmark.
187         /// if idx == 0, save to temp_bookmark
188         void saveBookmark(unsigned int idx);
189         /// goto a specified position, try top_id first, and then bottom_pit.
190         /// \return true if success
191         bool moveToPosition(
192                 pit_type bottom_pit, ///< Paragraph pit, used when par_id is zero or invalid.
193                 pos_type bottom_pos, ///< Paragraph pit, used when par_id is zero or invalid.
194                 int top_id, ///< Paragraph ID, \sa Paragraph
195                 pos_type top_pos ///< Position in the \c Paragraph
196                 );
197         /// return the current change at the cursor.
198         Change const getCurrentChange() const;
199
200         /// move cursor to the named label.
201         void gotoLabel(docstring const & label);
202
203         /// set the cursor based on the given TeX source row.
204         bool setCursorFromRow(int row);
205         /// set the cursor based on the given start and end TextEntries.
206         bool setCursorFromEntries(TexRow::TextEntry start, TexRow::TextEntry end);
207
208         /// set cursor to the given inset. Return true if found.
209         bool setCursorFromInset(Inset const *);
210         /// Recenters the BufferView such that the passed cursor
211         /// is in the center.
212         void recenter();
213         /// Ensure that the BufferView cursor is visible.
214         /// This method will automatically scroll and update the BufferView
215         /// (metrics+drawing) if needed.
216         void showCursor();
217
218         /// Ensure the passed cursor \p dit is visible.
219         /// This method will automatically scroll and update the BufferView
220         /// (metrics+drawing) if needed.
221         /// \param how Use this scroll strategy
222         /// \param force If true, update screen after scrolling
223         void showCursor(DocIterator const & dit, ScrollType how, bool update);
224         /// Scroll to the cursor.
225         /// \param how Use this scroll strategy
226         /// \return true if screen was scrolled
227         bool scrollToCursor(DocIterator const & dit, ScrollType how);
228         /// scroll down document by the given number of pixels.
229         int scrollDown(int pixels);
230         /// scroll up document by the given number of pixels.
231         int scrollUp(int pixels);
232         /// scroll document by the given number of pixels.
233         int scroll(int pixels);
234         /// Scroll the view by a number of pixels.
235         void scrollDocView(int pixels, bool update);
236         /// Set the cursor position based on the scrollbar one.
237         void setCursorFromScrollbar();
238
239         /// return the pixel width of the document view.
240         int workWidth() const;
241         /// return the pixel height of the document view.
242         int workHeight() const;
243
244         /// return the inline completion postfix.
245         docstring const & inlineCompletion() const;
246         /// return the number of unique characters in the inline completion.
247         size_t inlineCompletionUniqueChars() const;
248         /// return the position in the buffer of the inline completion postfix.
249         DocIterator const & inlineCompletionPos() const;
250         /// make sure inline completion position is OK
251         void resetInlineCompletionPos();
252         /// set the inline completion postfix and its position in the buffer.
253         /// Updates the updateFlags in \c cur.
254         void setInlineCompletion(Cursor const & cur, DocIterator const & pos,
255                 docstring const & completion, size_t uniqueChars = 0);
256
257         /// translate and insert a character, using the correct keymap.
258         void translateAndInsert(char_type c, Text * t, Cursor & cur);
259
260         /// \return true if we've made a decision
261         bool getStatus(FuncRequest const & cmd, FuncStatus & flag);
262         /// execute the given function.
263         void dispatch(FuncRequest const & cmd, DispatchResult & dr);
264
265         /// request an X11 selection.
266         /// \return the selected string.
267         docstring requestSelection();
268         /// clear the X11 selection.
269         void clearSelection();
270
271         /// resize the BufferView.
272         /// \sa WorkArea
273         void resize(int width, int height);
274
275         /// dispatch method helper for \c WorkArea
276         /// \sa WorkArea
277         void mouseEventDispatch(FuncRequest const & ev);
278
279         ///
280         CursorStatus cursorStatus(DocIterator const & dit) const;
281         /// access to full cursor.
282         Cursor & cursor();
283         /// access to full cursor.
284         Cursor const & cursor() const;
285         /// sets cursor.
286         /// This will also open all relevant collapsible insets.
287         void setCursor(DocIterator const &);
288         /// set the selection up to dit.
289         void setCursorSelectionTo(DocIterator const & dit);
290         /// Check deleteEmptyParagraphMechanism and update metrics if needed.
291         /// \retval true if an update was needed.
292         bool checkDepm(Cursor & cur, Cursor & old);
293         /// sets cursor.
294         /// This is used when handling LFUN_MOUSE_PRESS.
295         bool mouseSetCursor(Cursor & cur, bool select = false);
296
297         /// sets the selection.
298         /* When \c backwards == false, set anchor
299          * to \c cur and cursor to \c cur + \c length. When \c
300          * backwards == true, set anchor to \c cur and cursor to \c
301          * cur + \c length.
302          */
303         void putSelectionAt(DocIterator const & cur,
304                 int length, bool backwards);
305         /// set a selection between \p from and \p to
306         void setSelection(DocIterator const & from,
307                          DocIterator const & to);
308
309         /// selects the item at cursor if its paragraph is empty.
310         bool selectIfEmpty(DocIterator & cur);
311
312         /// Ditch all metrics information and rebuild it. Set the update
313         /// flags and the draw strategy flags accordingly.
314         void updateMetrics();
315
316         // this is the "nodraw" drawing stage: only set the positions of the
317         // insets in metrics cache.
318         void updatePosCache();
319
320         ///
321         TextMetrics const & textMetrics(Text const * t) const;
322         TextMetrics & textMetrics(Text const * t);
323         ///
324         ParagraphMetrics const & parMetrics(Text const *, pit_type) const;
325
326         ///
327         CoordCache & coordCache();
328         ///
329         CoordCache const & coordCache() const;
330
331         ///
332         bool hasMathRow(MathData const * cell) const;
333         ///
334         MathRow const & mathRow(MathData const * cell) const;
335         ///
336         void setMathRow(MathData const * cell, MathRow const & mrow);
337
338         ///
339         Point getPos(DocIterator const & dit) const;
340         /// is the paragraph of the cursor visible ?
341         bool paragraphVisible(DocIterator const & dit) const;
342         /// is the caret currently visible in the view
343         bool caretInView() const;
344         /// get the position and height of the caret
345         void caretPosAndDim(Point & p, Dimension & dim) const;
346         /// compute the shape of the caret
347         void buildCaretGeometry(bool complet);
348         /// the shape of the caret
349         frontend::CaretGeometry const & caretGeometry() const;
350
351         /// Returns true when metrics have been computed at least once
352         bool ready() const { return width_ > 0 && height_ > 0; }
353         /// Returns true when the BufferView is not ready for drawing
354         bool busy() const;
355         ///
356         void draw(frontend::Painter & pain, bool paint_caret);
357
358         /// get this view's keyboard map handler.
359         Intl & getIntl();
360         ///
361         Intl const & getIntl() const;
362
363         //
364         // Messages to the GUI
365         //
366         /// This signal is emitted when some message shows up.
367         void message(docstring const & msg);
368
369         /// This signal is emitted when some dialog needs to be shown.
370         void showDialog(std::string const & name);
371
372         /// This signal is emitted when some dialog needs to be shown with
373         /// some data.
374         void showDialog(std::string const & name, std::string const & data,
375                 Inset * inset = nullptr);
376
377         /// This signal is emitted when some dialogs needs to be updated.
378         void updateDialog(std::string const & name, std::string const & data);
379
380         ///
381         void setGuiDelegate(frontend::GuiBufferViewDelegate *);
382
383         ///
384         docstring contentsOfPlaintextFile(support::FileName const & f);
385         // Insert plain text file (if filename is empty, prompt for one)
386         void insertPlaintextFile(support::FileName const & f, bool asParagraph);
387         ///
388         void insertLyXFile(support::FileName const & f, bool const ignorelang = false);
389         /// save temporary bookmark for jump back navigation
390         void bookmarkEditPosition();
391         /// Find and return the inset associated with given dialog name.
392         Inset * editedInset(std::string const & name) const;
393         /// Associate an inset associated with given dialog name.
394         void editInset(std::string const & name, Inset * inset);
395         ///
396         void clearLastInset(Inset * inset) const;
397         /// Is the mouse hovering a clickable inset or element?
398         bool clickableInset() const;
399         ///
400         void makeDocumentClass();
401         /// Are we currently performing a selection with the mouse?
402         bool mouseSelecting() const;
403
404         /// Reference value for statistics (essentially subtract this from the actual value to see relative counts)
405         /// (words/chars/chars no blanks)
406         int stats_ref_value_w() const;
407         int stats_ref_value_c() const;
408         int stats_ref_value_nb() const;
409         //signals need for update in gui
410         bool stats_update_trigger();
411
412 private:
413         /// noncopyable
414         BufferView(BufferView const &);
415         void operator=(BufferView const &);
416
417         /// the position relative to (0, baseline) of outermost paragraph
418         Point coordOffset(DocIterator const & dit) const;
419         /// Update current paragraph metrics.
420         /// \return true if no further update is needed.
421         bool singleParUpdate();
422         /** Helper for the public updateMetrics() and for processUpdateFlags()
423          * * When \c force is true, get rid of all paragraph metrics and
424          rebuild them anew.
425          * * When it is false, keep the paragraphs that are still visible in
426          *   WorkArea and rebuild the missing ones.
427          *
428          * This does also set the anchor paragraph and its position correctly
429         */
430         void updateMetrics(bool force);
431
432         // Set the row on which the cursor lives.
433         void setCurrentRowSlice(CursorSlice const & rowSlice);
434
435         // Check whether the row where the cursor lives needs to be scrolled.
436         // Update the drawing strategy if needed.
437         void checkCursorScrollOffset();
438
439         /// The minimal size of the document that is visible. Used
440         /// when it is allowed to scroll below the document.
441         int minVisiblePart();
442
443         /// Search recursively for the innermost inset that covers (x, y) position.
444         /// \retval 0 if no inset is found.
445         Inset const * getCoveringInset(
446                 Text const & text, //< The Text where we start searching.
447                 int x, //< x-coordinate on screen
448                 int y  //< y-coordinate on screen
449                 ) const;
450
451         /// Update the hovering status of the insets. This is called when
452         /// either the screen is updated or when the buffer has scolled.
453         void updateHoveredInset() const;
454
455         ///
456         void updateDocumentClass(DocumentClassConstPtr olddc);
457         ///
458         int width_;
459         ///
460         int height_;
461         ///
462         bool full_screen_;
463         ///
464         Buffer & buffer_;
465
466         struct Private;
467         Private * const d;
468 };
469
470 /// some space for drawing the 'nested' markers (in pixel)
471 inline int nestMargin() { return 15; }
472
473 /// margin for changebar
474 inline int changebarMargin() { return 12; }
475
476 } // namespace lyx
477
478 #endif // BUFFERVIEW_H