// -*- C++ -*- /** * \file BufferView.h * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Alfredo Braustein * \author Lars Gullik Bjønnes * \author John Levon * \author Jürgen Vigna * * Full author contact details are available in file CREDITS. */ #ifndef BUFFER_VIEW_H #define BUFFER_VIEW_H #include "CoordCache.h" #include "DocumentClassPtr.h" #include "TexRow.h" #include "update_flags.h" #include "support/strfwd.h" #include "support/types.h" namespace lyx { namespace support { class FileName; } namespace frontend { struct CaretGeometry; } namespace frontend { class Painter; } namespace frontend { class GuiBufferViewDelegate; } class Buffer; class Change; class Cursor; class CursorSlice; class Dimension; class DispatchResult; class DocIterator; class FuncRequest; class FuncStatus; class Intl; class Inset; class InsetMathNest; class Length; class MathData; class MathRow; class ParagraphMetrics; class Point; class Text; class TextMetrics; enum CursorStatus { CUR_INSIDE, CUR_ABOVE, CUR_BELOW }; /// How to show cursor enum ScrollType { // Make sure row if visible (do nothing if it is visible already) SCROLL_VISIBLE, // Force cursor to be on top of screen SCROLL_TOP, // Force cursor to be at center of screen SCROLL_CENTER }; /// Scrollbar Parameters. struct ScrollbarParameters { // These parameters are normalized against the screen geometry and pixel // coordinates. Position 0 corresponds to the top the the screen. ScrollbarParameters() : min(0), max(0), single_step(1), page_step(1) {} /// Minimum scrollbar position in pixels. int min; /// Maximum scrollbar position in pixels. int max; /// Line-scroll amount in pixels. int single_step; /// Page-scroll amount in pixels. int page_step; }; /// Screen view of a Buffer. /** * A BufferView encapsulates a view onto a particular * buffer, and allows access to operate upon it. A view * is a sliding window of the entire document rendering. * It is the official interface between the LyX core and * the frontend WorkArea. * * \sa WorkArea * \sa Buffer * \sa CoordCache */ class BufferView { public: /// explicit BufferView(Buffer & buffer); /// ~BufferView(); /// return the buffer being viewed. Buffer & buffer(); Buffer const & buffer() const; /// Copy cursor and vertical offset information from \c bv void copySettingsFrom(BufferView const & bv); /// void setFullScreen(bool full_screen) { full_screen_ = full_screen; } /// default value for the margins int defaultMargin() const; /// right margin int rightMargin() const; /// left margin int leftMargin() const; /// top margin int topMargin() const; /// bottom margin int bottomMargin() const; docstring const & searchRequestCache() const; void setSearchRequestCache(docstring const & text); /// return the on-screen size of this length /* * This is a wrapper around Length::inPixels that uses the * bufferview width as width and the EM value of the default * document font. */ int inPixels(Length const & len) const; /** Return the number of pixels equivalent to \c pix pixels at * 100dpi and 100% zoom. */ int zoomedPixels(int pix) const; /// \return true if the BufferView is at the top of the document. bool isTopScreen() const; /// \return true if the BufferView is at the bottom of the document. bool isBottomScreen() const; /// Add \p flags to current update flags and trigger an update. /* If this method is invoked several times before the update * actually takes place, the effect is cumulative. * \c Update::FitCursor means first to do a FitCursor, and to * force an update if screen position changes. * \c Update::Force means to force an update in any case. */ void processUpdateFlags(Update::flags flags); /// return true if one shall move the screen to fit the cursor. /// Only to be called with good y coordinates (after a bv::metrics) bool needsFitCursor() const; // Returns the amount of horizontal scrolling applied to the // top-level row where the cursor lies int horizScrollOffset() const; // Returns the amount of horizontal scrolling applied to the // row of text starting at (pit, pos) int horizScrollOffset(Text const * text, pit_type pit, pos_type pos) const; /// reset the scrollbar parameters to reflect current view position. void updateScrollbarParameters(); /// return the Scrollbar Parameters. ScrollbarParameters const & scrollbarParameters() const; /// \return Tool tip for the given position. docstring toolTip(int x, int y) const; /// \return the context menu for the given position. std::string contextMenu(int x, int y) const; /// \return the math inset with a context menu for the given position Inset const * mathContextMenu(InsetMathNest const * inset, CoordCache::Insets const & inset_cache, int x, int y) const; /// \return the clickable math inset for the given position Inset const * clickableMathInset(InsetMathNest const * inset, CoordCache::Insets const & inset_cache, int x, int y) const; /// Save the current position as bookmark. /// if idx == 0, save to temp_bookmark void saveBookmark(unsigned int idx); /// goto a specified position, try top_id first, and then bottom_pit. /// \return true if success bool moveToPosition( pit_type bottom_pit, ///< Paragraph pit, used when par_id is zero or invalid. pos_type bottom_pos, ///< Paragraph pit, used when par_id is zero or invalid. int top_id, ///< Paragraph ID, \sa Paragraph pos_type top_pos ///< Position in the \c Paragraph ); /// return the current change at the cursor. Change const getCurrentChange() const; /// move cursor to the named label. void gotoLabel(docstring const & label); /// set the cursor based on the given TeX source row. bool setCursorFromRow(int row); /// set the cursor based on the given start and end TextEntries. bool setCursorFromEntries(TexRow::TextEntry start, TexRow::TextEntry end); /// set cursor to the given inset. Return true if found. bool setCursorFromInset(Inset const *); /// Recenters the BufferView such that the passed cursor /// is in the center. void recenter(); /// Ensure that the BufferView cursor is visible. /// This method will automatically scroll and update the BufferView /// (metrics+drawing) if needed. void showCursor(); /// Ensure the passed cursor \p dit is visible. /// This method will automatically scroll and update the BufferView /// (metrics+drawing) if needed. /// \param how Use this scroll strategy /// \param force If true, update screen after scrolling void showCursor(DocIterator const & dit, ScrollType how, bool update); /// Scroll to the cursor. /// \param how Use this scroll strategy /// \return true if screen was scrolled bool scrollToCursor(DocIterator const & dit, ScrollType how); /// scroll down document by the given number of pixels. int scrollDown(int pixels); /// scroll up document by the given number of pixels. int scrollUp(int pixels); /// scroll document by the given number of pixels. int scroll(int pixels); /// Scroll the view by a number of pixels. void scrollDocView(int pixels, bool update); /// Set the cursor position based on the scrollbar one. void setCursorFromScrollbar(); /// return the pixel width of the document view. int workWidth() const; /// return the pixel height of the document view. int workHeight() const; /// return the inline completion postfix. docstring const & inlineCompletion() const; /// return the number of unique characters in the inline completion. size_t inlineCompletionUniqueChars() const; /// return the position in the buffer of the inline completion postfix. DocIterator const & inlineCompletionPos() const; /// make sure inline completion position is OK void resetInlineCompletionPos(); /// set the inline completion postfix and its position in the buffer. /// Updates the updateFlags in \c cur. void setInlineCompletion(Cursor const & cur, DocIterator const & pos, docstring const & completion, size_t uniqueChars = 0); /// translate and insert a character, using the correct keymap. void translateAndInsert(char_type c, Text * t, Cursor & cur); /// \return true if we've made a decision bool getStatus(FuncRequest const & cmd, FuncStatus & flag); /// execute the given function. void dispatch(FuncRequest const & cmd, DispatchResult & dr); /// request an X11 selection. /// \return the selected string. docstring requestSelection(); /// clear the X11 selection. void clearSelection(); /// resize the BufferView. /// \sa WorkArea void resize(int width, int height); /// dispatch method helper for \c WorkArea /// \sa WorkArea void mouseEventDispatch(FuncRequest const & ev); /// CursorStatus cursorStatus(DocIterator const & dit) const; /// access to full cursor. Cursor & cursor(); /// access to full cursor. Cursor const & cursor() const; /// sets cursor. /// This will also open all relevant collapsible insets. void setCursor(DocIterator const &); /// set the selection up to dit. void setCursorSelectionTo(DocIterator const & dit); /// Check deleteEmptyParagraphMechanism and update metrics if needed. /// \retval true if an update was needed. bool checkDepm(Cursor & cur, Cursor & old); /// sets cursor. /// This is used when handling LFUN_MOUSE_PRESS. bool mouseSetCursor(Cursor & cur, bool select = false); /// sets the selection. /* When \c backwards == false, set anchor * to \c cur and cursor to \c cur + \c length. When \c * backwards == true, set anchor to \c cur and cursor to \c * cur + \c length. */ void putSelectionAt(DocIterator const & cur, int length, bool backwards); /// set a selection between \p from and \p to void setSelection(DocIterator const & from, DocIterator const & to); /// selects the item at cursor if its paragraph is empty. bool selectIfEmpty(DocIterator & cur); /// update the internal \c ViewMetricsInfo. void updateMetrics(); // this is the "nodraw" drawing stage: only set the positions of the // insets in metrics cache. void updatePosCache(); /// TextMetrics const & textMetrics(Text const * t) const; TextMetrics & textMetrics(Text const * t); /// ParagraphMetrics const & parMetrics(Text const *, pit_type) const; /// CoordCache & coordCache(); /// CoordCache const & coordCache() const; /// bool hasMathRow(MathData const * cell) const; /// MathRow const & mathRow(MathData const * cell) const; /// void setMathRow(MathData const * cell, MathRow const & mrow); /// Point getPos(DocIterator const & dit) const; /// is the paragraph of the cursor visible ? bool paragraphVisible(DocIterator const & dit) const; /// is the caret currently visible in the view bool caretInView() const; /// get the position and height of the caret void caretPosAndDim(Point & p, Dimension & dim) const; /// compute the shape of the caret void buildCaretGeometry(bool complet); /// the shape of the caret frontend::CaretGeometry const & caretGeometry() const; /// Returns true when the BufferView is not ready for drawing bool busy() const; /// void draw(frontend::Painter & pain, bool paint_caret); /// get this view's keyboard map handler. Intl & getIntl(); /// Intl const & getIntl() const; // // Messages to the GUI // /// This signal is emitted when some message shows up. void message(docstring const & msg); /// This signal is emitted when some dialog needs to be shown. void showDialog(std::string const & name); /// This signal is emitted when some dialog needs to be shown with /// some data. void showDialog(std::string const & name, std::string const & data, Inset * inset = nullptr); /// This signal is emitted when some dialogs needs to be updated. void updateDialog(std::string const & name, std::string const & data); /// void setGuiDelegate(frontend::GuiBufferViewDelegate *); /// docstring contentsOfPlaintextFile(support::FileName const & f); // Insert plain text file (if filename is empty, prompt for one) void insertPlaintextFile(support::FileName const & f, bool asParagraph); /// void insertLyXFile(support::FileName const & f, bool const ignorelang = false); /// save temporary bookmark for jump back navigation void bookmarkEditPosition(); /// Find and return the inset associated with given dialog name. Inset * editedInset(std::string const & name) const; /// Associate an inset associated with given dialog name. void editInset(std::string const & name, Inset * inset); /// void clearLastInset(Inset * inset) const; /// Is the mouse hovering a clickable inset or element? bool clickableInset() const; /// void makeDocumentClass(); /// Are we currently performing a selection with the mouse? bool mouseSelecting() const; private: /// noncopyable BufferView(BufferView const &); void operator=(BufferView const &); /// the position relative to (0, baseline) of outermost paragraph Point coordOffset(DocIterator const & dit) const; /// Update current paragraph metrics. /// \return true if no further update is needed. bool singleParUpdate(); /// do the work for the public updateMetrics() void updateMetrics(Update::flags & update_flags); // Set the row on which the cursor lives. void setCurrentRowSlice(CursorSlice const & rowSlice); // Check whether the row where the cursor lives needs to be scrolled. // Update the drawing strategy if needed. void checkCursorScrollOffset(); /// The minimal size of the document that is visible. Used /// when it is allowed to scroll below the document. int minVisiblePart(); /// Search recursively for the innermost inset that covers (x, y) position. /// \retval 0 if no inset is found. Inset const * getCoveringInset( Text const & text, //< The Text where we start searching. int x, //< x-coordinate on screen int y //< y-coordinate on screen ) const; /// Update the hovering status of the insets. This is called when /// either the screen is updated or when the buffer has scolled. void updateHoveredInset() const; /// void updateDocumentClass(DocumentClassConstPtr olddc); /// int width_; /// int height_; /// bool full_screen_; /// Buffer & buffer_; struct Private; Private * const d; }; /// some space for drawing the 'nested' markers (in pixel) inline int nestMargin() { return 15; } /// margin for changebar inline int changebarMargin() { return 12; } } // namespace lyx #endif // BUFFERVIEW_H