4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
7 * \author Lars Gullik Bjønnes
8 * \author Matthias Ettrich
10 * \author Jürgen Vigna
11 * \author Edwin Leuven
14 * Full author contact details are available in file CREDITS.
17 // Things to think of when designing the new tabular support:
18 // - color support (colortbl, color)
19 // - decimal alignment (dcloumn)
20 // - custom lines (hhline)
23 #ifndef INSET_TABULAR_H
24 #define INSET_TABULAR_H
27 #include "InsetText.h"
31 #include "support/shared_ptr.h"
51 class InsetTableCell : public InsetText
55 InsetTableCell(Buffer * buf);
57 InsetCode lyxCode() const { return CELL_CODE; }
59 Inset * clone() { return new InsetTableCell(*this); }
61 bool getStatus(Cursor & cur, FuncRequest const & cmd,
62 FuncStatus & status) const;
64 void toggleFixedWidth(bool fw) { isFixedWidth = fw; }
66 void setContentAlignment(LyXAlignment al) {contentAlign = al; }
67 /// writes the contents of the cell as a string, optionally
68 /// descending into insets
69 docstring asString(bool intoInsets = true);
71 docstring xhtml(XHTMLStream &, OutputParams const &) const;
76 void operator=(InsetTableCell const &);
78 // This boolean is supposed to track whether the cell has had its
79 // width explicitly set. We need to know this to determine whether
80 // layout changes and paragraph customization are allowed---that is,
81 // we need it in forcePlainLayout() and allowParagraphCustomization().
82 // Unfortunately, that information is not readily available in
83 // InsetTableCell. In the case of multicolumn cells, it is present
84 // in CellData, and so would be available here if CellData were to
85 // become a member of InsetTableCell. But in the other case, it isn't
86 // even available there, but is held in Tabular::ColumnData.
87 // So, the present solution uses this boolean to track the information
88 // we need to track, and tries to keep it updated. This is not ideal,
89 // but the other solutions are no better. These are:
90 // (i) Keep a pointer in InsetTableCell to the table;
91 // (ii) Find the table by iterating over the Buffer's insets.
92 // Solution (i) raises the problem of updating the pointer when an
93 // InsetTableCell is copied, and we'd therefore need a copy constructor
94 // in InsetTabular and then in Tabular, which seems messy, given how
95 // complicated those classes are. Solution (ii) involves a lot of
96 // iterating, since this information is needed quite often, and so may
98 // So, well, if someone can do better, please do!
102 // FIXME: Here the thoughts from the comment above also apply.
104 LyXAlignment contentAlign;
105 /// should paragraph indendation be omitted in any case?
106 bool neverIndent() const { return true; }
108 LyXAlignment contentAlignment() const { return contentAlign; }
110 virtual bool usePlainLayout() const { return true; }
112 virtual bool forcePlainLayout(idx_type = 0) const;
114 virtual bool allowParagraphCustomization(idx_type = 0) const;
115 /// Is the width forced to some value?
116 bool hasFixedWidth() const { return isFixedWidth; }
121 // A helper struct for tables
210 UNSET_ROTATE_TABULAR,
212 TOGGLE_ROTATE_TABULAR,
244 SET_SPECIAL_MULTICOLUMN,
246 SET_SPECIAL_MULTIROW,
262 TABULAR_VALIGN_MIDDLE,
264 TABULAR_VALIGN_BOTTOM,
266 LONGTABULAR_ALIGN_LEFT,
268 LONGTABULAR_ALIGN_CENTER,
270 LONGTABULAR_ALIGN_RIGHT,
281 CELL_BEGIN_OF_MULTICOLUMN,
283 CELL_PART_OF_MULTICOLUMN,
285 CELL_BEGIN_OF_MULTIROW,
287 CELL_PART_OF_MULTIROW
295 LYX_VALIGN_MIDDLE = 1,
297 LYX_VALIGN_BOTTOM = 2
303 LYX_LONGTABULAR_ALIGN_LEFT = 0,
305 LYX_LONGTABULAR_ALIGN_CENTER = 1,
307 LYX_LONGTABULAR_ALIGN_RIGHT = 2
323 // we have this header type (is set in the getLT... functions)
325 // double borders on top
327 // double borders on bottom
329 // used for FirstHeader & LastFooter and if this is true
330 // all the rows marked as FirstHeader or LastFooter are
331 // ignored in the output and it is set to be empty!
335 /// type for row numbers
336 typedef size_t row_type;
337 /// type for column numbers
338 typedef size_t col_type;
339 /// type for cell indices
340 typedef size_t idx_type;
341 /// index indicating an invalid position
342 static const idx_type npos = static_cast<idx_type>(-1);
345 Tabular(Buffer * buf, col_type columns_arg, row_type rows_arg);
347 /// Returns true if there is a topline, returns false if not
348 bool topLine(idx_type cell) const;
349 /// Returns true if there is a topline, returns false if not
350 bool bottomLine(idx_type cell) const;
351 /// Returns true if there is a topline, returns false if not
352 bool leftLine(idx_type cell) const;
353 /// Returns true if there is a topline, returns false if not
354 bool rightLine(idx_type cell) const;
356 /// return space occupied by the second horizontal line and
357 /// interline space above row \p row in pixels
358 int interRowSpace(row_type row) const;
360 int interColumnSpace(idx_type cell) const;
362 /* returns the maximum over all rows */
364 int cellWidth(idx_type cell) const;
366 int cellHeight(idx_type cell) const;
372 row_type nrows() const {return row_info.size();}
374 col_type ncols() const {return column_info.size();}
376 int rowAscent(row_type row) const;
378 int rowDescent(row_type row) const;
380 void setRowAscent(row_type row, int height);
382 void setRowDescent(row_type row, int height);
384 void setTopLine(idx_type cell, bool line);
386 void setBottomLine(idx_type cell, bool line);
388 void setLeftLine(idx_type cell, bool line);
390 void setRightLine(idx_type cell, bool line);
392 bool rowTopLine(row_type row) const;
394 bool rowBottomLine(row_type row) const;
396 bool columnLeftLine(col_type column) const;
398 bool columnRightLine(col_type column) const;
400 void setAlignment(idx_type cell, LyXAlignment align,
401 bool onlycolumn = false);
403 void setVAlignment(idx_type cell, VAlignment align,
404 bool onlycolumn = false);
406 void setColumnPWidth(Cursor &, idx_type, Length const &);
408 bool setMColumnPWidth(Cursor &, idx_type, Length const &);
410 void setAlignSpecial(idx_type cell, docstring const & special,
413 LyXAlignment getAlignment(idx_type cell,
414 bool onlycolumn = false) const;
416 VAlignment getVAlignment(idx_type cell,
417 bool onlycolumn = false) const;
419 Length const getPWidth(idx_type cell) const;
421 int textHOffset(idx_type cell) const;
423 int textVOffset(idx_type cell) const;
425 void appendRow(idx_type cell);
427 void deleteRow(row_type row);
429 void copyRow(row_type);
431 void appendColumn(idx_type cell);
433 void deleteColumn(col_type column);
435 void copyColumn(col_type);
437 idx_type getFirstCellInRow(row_type row) const;
439 idx_type getLastCellInRow(row_type row) const;
441 idx_type numberOfCellsInRow(row_type row) const;
443 void write(std::ostream &) const;
447 int latex(odocstream &, OutputParams const &) const;
449 int docbook(odocstream & os, OutputParams const &) const;
451 docstring xhtml(XHTMLStream & os, OutputParams const &) const;
453 void plaintext(odocstream &,
454 OutputParams const & runparams, int const depth,
455 bool onlydata, char_type delim) const;
457 bool isMultiColumn(idx_type cell) const;
459 idx_type setMultiColumn(idx_type cell, idx_type number);
461 void unsetMultiColumn(idx_type cell);
463 bool isPartOfMultiColumn(row_type row, col_type column) const;
465 bool isPartOfMultiRow(row_type row, col_type column) const;
467 bool isMultiRow(idx_type cell) const;
469 idx_type setMultiRow(idx_type cell, idx_type number);
471 void unsetMultiRow(idx_type cell);
473 row_type cellRow(idx_type cell) const;
475 col_type cellColumn(idx_type cell) const;
477 void setRotateCell(idx_type cell, bool);
479 bool getRotateCell(idx_type cell) const;
481 bool needRotating() const;
483 bool isLastCell(idx_type cell) const;
485 idx_type cellAbove(idx_type cell) const;
487 idx_type cellBelow(idx_type cell) const;
489 idx_type cellIndex(row_type row, col_type column) const;
491 void setUsebox(idx_type cell, BoxType);
493 BoxType getUsebox(idx_type cell) const;
495 // Long Tabular Options support functions
497 bool checkLTType(row_type row, ltType const &) const;
499 void setLTHead(row_type row, bool flag, ltType const &, bool first);
501 bool getRowOfLTHead(row_type row, ltType &) const;
503 bool getRowOfLTFirstHead(row_type row, ltType &) const;
505 void setLTFoot(row_type row, bool flag, ltType const &, bool last);
507 bool getRowOfLTFoot(row_type row, ltType &) const;
509 bool getRowOfLTLastFoot(row_type row, ltType &) const;
511 void setLTNewPage(row_type row, bool what);
513 bool getLTNewPage(row_type row) const;
515 idx_type setLTCaption(row_type row, bool what);
517 bool ltCaption(row_type row) const;
519 bool haveLTHead() const;
521 bool haveLTFirstHead() const;
523 bool haveLTFoot() const;
525 bool haveLTLastFoot() const;
527 bool haveLTCaption() const;
529 // end longtable support
531 shared_ptr<InsetTableCell> cellInset(idx_type cell) const;
533 shared_ptr<InsetTableCell> cellInset(row_type row,
534 col_type column) const;
536 void setCellInset(row_type row, col_type column,
537 shared_ptr<InsetTableCell>) const;
538 /// Search for \param inset in the tabular, with the
540 void validate(LaTeXFeatures &) const;
542 // FIXME Now that cells have an InsetTableCell as their insets, rather
543 // than an InsetText, it'd be possible to reverse the relationship here,
544 // so that cell_vector was a vector<InsetTableCell> rather than a
545 // vector<CellData>, and an InsetTableCell had a CellData as a member,
546 // or perhaps just had its members as members.
553 CellData(CellData const &);
555 CellData & operator=(CellData);
557 void swap(CellData & rhs);
567 LyXAlignment alignment;
569 VAlignment valignment;
570 /// width of the part before the decimal
572 /// width of the decimal part
589 docstring align_special;
591 Length p_width; // this is only set for multicolumn!!!
593 shared_ptr<InsetTableCell> inset;
595 CellData & cellInfo(idx_type cell) const;
597 typedef std::vector<CellData> cell_vector;
599 typedef std::vector<cell_vector> cell_vvector;
610 /// Extra space between the top line and this row
612 /// Ignore top_space if true and use the default top space
613 bool top_space_default;
614 /// Extra space between this row and the bottom line
616 /// Ignore bottom_space if true and use the default bottom space
617 bool bottom_space_default;
618 /// Extra space between the bottom line and the next top line
619 Length interline_space;
620 /// Ignore interline_space if true and use the default interline space
621 bool interline_space_default;
622 /// This are for longtabulars only
625 /// a row of endfirsthead
629 /// row of endlastfoot
631 /// row for a newpage
637 typedef std::vector<RowData> row_vector;
645 LyXAlignment alignment;
647 VAlignment valignment;
653 docstring align_special;
655 docstring decimal_point;
658 typedef std::vector<ColumnData> column_vector;
661 idx_type numberofcells;
663 std::vector<row_type> rowofcell;
665 std::vector<col_type> columnofcell;
669 column_vector column_info;
671 mutable cell_vvector cell_info;
677 VAlignment tabular_valignment;
681 HAlignment longtabular_alignment;
683 bool is_long_tabular;
686 /// endfirsthead data
694 void init(Buffer *, row_type rows_arg,
695 col_type columns_arg);
697 void updateIndexes();
699 bool setFixedWidth(row_type r, col_type c);
700 /// return true of update is needed
701 bool updateColumnWidths();
703 idx_type columnSpan(idx_type cell) const;
705 idx_type rowSpan(idx_type cell) const;
707 BoxType useParbox(idx_type cell) const;
709 // helper function for Latex returns number of newlines
711 int TeXTopHLine(odocstream &, row_type row, std::string const lang) const;
713 int TeXBottomHLine(odocstream &, row_type row, std::string const lang) const;
715 int TeXCellPreamble(odocstream &, idx_type cell, bool & ismulticol, bool & ismultirow) const;
717 int TeXCellPostamble(odocstream &, idx_type cell, bool ismulticol, bool ismultirow) const;
719 int TeXLongtableHeaderFooter(odocstream &, OutputParams const &) const;
721 bool isValidRow(row_type const row) const;
723 int TeXRow(odocstream &, row_type const row,
724 OutputParams const &) const;
726 // helper functions for plain text
728 bool plaintextTopHLine(odocstream &, row_type row,
729 std::vector<unsigned int> const &) const;
731 bool plaintextBottomHLine(odocstream &, row_type row,
732 std::vector<unsigned int> const &) const;
734 void plaintextPrintCell(odocstream &,
735 OutputParams const &,
736 idx_type cell, row_type row, col_type column,
737 std::vector<unsigned int> const &,
738 bool onlydata) const;
739 /// auxiliary function for docbook
740 int docbookRow(odocstream & os, row_type, OutputParams const &) const;
742 docstring xhtmlRow(XHTMLStream & xs, row_type, OutputParams const &) const;
744 /// change associated Buffer
745 void setBuffer(Buffer & buffer);
746 /// retrieve associated Buffer
747 Buffer & buffer() const { return *buffer_; }
755 class InsetTabular : public Inset
759 InsetTabular(Buffer *, row_type rows = 1,
760 col_type columns = 1);
764 void setBuffer(Buffer & buffer);
767 static void string2params(std::string const &, InsetTabular &);
769 static std::string params2string(InsetTabular const &);
773 void write(std::ostream &) const;
775 void metrics(MetricsInfo &, Dimension &) const;
777 void draw(PainterInfo & pi, int x, int y) const;
779 void drawSelection(PainterInfo & pi, int x, int y) const;
781 bool editable() const { return true; }
783 bool hasSettings() const { return true; }
785 bool insetAllowed(InsetCode code) const;
787 bool allowSpellCheck() const { return true; }
789 bool canTrackChanges() const { return true; }
790 /** returns true if, when outputing LaTeX, font changes should
791 be closed before generating this inset. This is needed for
792 insets that may contain several paragraphs */
793 bool noFontChange() const { return true; }
795 DisplayType display() const;
797 int latex(odocstream &, OutputParams const &) const;
799 int plaintext(odocstream &, OutputParams const &) const;
801 int docbook(odocstream &, OutputParams const &) const;
803 docstring xhtml(XHTMLStream &, OutputParams const &) const;
805 void validate(LaTeXFeatures & features) const;
807 InsetCode lyxCode() const { return TABULAR_CODE; }
809 docstring contextMenu(BufferView const & bv, int x, int y) const;
810 /// get offset of this cursor slice relative to our upper left corner
811 void cursorPos(BufferView const & bv, CursorSlice const & sl,
812 bool boundary, int & x, int & y) const;
814 bool tabularFeatures(Cursor & cur, std::string const & what);
816 void tabularFeatures(Cursor & cur, Tabular::Feature feature,
817 std::string const & val = std::string());
819 size_t nargs() const { return tabular.numberofcells; }
821 shared_ptr<InsetTableCell const> cell(idx_type) const;
823 shared_ptr<InsetTableCell> cell(idx_type);
825 Text * getText(int) const;
827 /// set the change for the entire inset
828 void setChange(Change const & change);
829 /// accept the changes within the inset
830 void acceptChanges();
831 /// reject the changes within the inset
832 void rejectChanges();
834 // this should return true if we have a "normal" cell, otherwise false.
835 // "normal" means without width set!
836 /// should all paragraphs be output with "Standard" layout?
837 virtual bool allowParagraphCustomization(idx_type cell = 0) const;
839 virtual bool forcePlainLayout(idx_type cell = 0) const;
841 void addPreview(DocIterator const & inset_pos,
842 graphics::PreviewLoader &) const;
844 /// lock cell with given index
845 void edit(Cursor & cur, bool front, EntryDirection entry_from);
846 /// get table row from x coordinate
847 int rowFromY(Cursor & cur, int y) const;
848 /// get table column from y coordinate
849 int columnFromX(Cursor & cur, int x) const;
851 Inset * editXY(Cursor & cur, int x, int y);
852 /// can we go further down on mouse click?
853 bool descendable(BufferView const &) const { return true; }
854 /// Update the counters of this inset and of its contents
855 void updateBuffer(ParIterator const &, UpdateType);
857 void addToToc(DocIterator const &);
860 bool completionSupported(Cursor const &) const;
862 bool inlineCompletionSupported(Cursor const & cur) const;
864 bool automaticInlineCompletion() const;
866 bool automaticPopupCompletion() const;
868 bool showCompletionCursor() const;
870 CompletionList const * createCompletionList(Cursor const & cur) const;
872 docstring completionPrefix(Cursor const & cur) const;
874 bool insertCompletion(Cursor & cur, docstring const & s, bool finished);
876 void completionPosAndDim(Cursor const &, int & x, int & y, Dimension & dim) const;
878 virtual bool usePlainLayout() const { return true; }
881 InsetTabular * asInsetTabular() { return this; }
883 InsetTabular const * asInsetTabular() const { return this; }
885 bool isRightToLeft(Cursor & cur) const;
886 /// writes the cells between stidx and enidx as a string, optionally
887 /// descending into the insets
888 docstring asString(idx_type stidx, idx_type enidx, bool intoInsets = true);
890 /// Returns whether the cell in the specified row and column is selected.
891 bool isCellSelected(Cursor & cur, row_type row, col_type col) const;
893 // Public structures and variables
895 mutable Tabular tabular;
899 InsetTabular(InsetTabular const &);
901 void doDispatch(Cursor & cur, FuncRequest & cmd);
903 bool getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus &) const;
905 int scroll() const { return scx_; }
907 Inset * clone() const { return new InsetTabular(*this); }
910 void drawCellLines(PainterInfo &, int x, int y, row_type row,
911 idx_type cell) const;
913 void setCursorFromCoordinates(Cursor & cur, int x, int y) const;
916 void moveNextCell(Cursor & cur,
917 EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);
919 void movePrevCell(Cursor & cur,
920 EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);
922 int cellXPos(idx_type cell) const;
924 void resetPos(Cursor & cur) const;
926 bool copySelection(Cursor & cur);
928 bool pasteClipboard(Cursor & cur);
930 void cutSelection(Cursor & cur);
932 void getSelection(Cursor & cur, row_type & rs, row_type & re,
933 col_type & cs, col_type & ce) const;
935 bool insertPlaintextString(BufferView &, docstring const & buf, bool usePaste);
937 /// return the "Manhattan distance" to nearest corner
938 int dist(BufferView &, idx_type cell, int x, int y) const;
939 /// return the cell nearest to x, y
940 idx_type getNearestCell(BufferView &, int x, int y) const;
942 /// test the rotation state of the give cell range.
943 bool oneCellHasRotationState(bool rotated,
944 row_type row_start, row_type row_end,
945 col_type col_start, col_type col_end) const;
947 mutable idx_type first_visible_cell;
950 /// true when selecting rows with the mouse
952 /// true when selecting columns with the mouse
956 std::string const featureAsString(Tabular::Feature feature);
958 /// Split cell on decimal symbol
959 InsetTableCell splitCell(InsetTableCell & head, docstring const decimal_sym, bool & hassep);
963 #endif // INSET_TABULAR_H