]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
Pure HTML output for math macros.
[lyx.git] / src / insets / InsetTabular.cpp
index 57a1926a0e80acfab0036dd92618500938d2582d..d398c87f4c40bffe1d332f733c0bf493e1fb4aa5 100644 (file)
@@ -518,6 +518,7 @@ Tabular::CellData::CellData(Buffer * buf)
          multirow(Tabular::CELL_NORMAL),
          alignment(LYX_ALIGN_CENTER),
          valignment(LYX_VALIGN_TOP),
+         voffset(0),
          top_line(false),
          bottom_line(false),
          left_line(false),
@@ -537,6 +538,7 @@ Tabular::CellData::CellData(CellData const & cs)
          multirow(cs.multirow),
          alignment(cs.alignment),
          valignment(cs.valignment),
+         voffset(cs.voffset),
          top_line(cs.top_line),
          bottom_line(cs.bottom_line),
          left_line(cs.left_line),
@@ -563,6 +565,7 @@ void Tabular::CellData::swap(CellData & rhs)
        std::swap(multirow, rhs.multirow);
        std::swap(alignment, rhs.alignment);
        std::swap(valignment, rhs.valignment);
+       std::swap(voffset, rhs.voffset);
        std::swap(top_line, rhs.top_line);
        std::swap(bottom_line, rhs.bottom_line);
        std::swap(left_line, rhs.left_line);
@@ -696,8 +699,8 @@ void Tabular::deleteRow(row_type const row)
                // Care about multirow cells
                if (row + 1 < nrows() &&
                    cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW &&
-                   cell_info[row][c + 1].multirow == CELL_PART_OF_MULTIROW) {
-                               cell_info[row][c + 1].multirow = CELL_BEGIN_OF_MULTIROW;
+                   cell_info[row + 1][c].multirow == CELL_PART_OF_MULTIROW) {
+                               cell_info[row + 1][c].multirow = CELL_BEGIN_OF_MULTIROW;
                }
        }
        row_info.erase(row_info.begin() + row);
@@ -891,7 +894,7 @@ int Tabular::columnWidth(idx_type cell) const
 }
 
 
-int Tabular::rowHeight(idx_type cell) const
+int Tabular::cellHeight(idx_type cell) const
 {
        row_type const span = rowSpan(cell);
        row_type const row = cellRow(cell);
@@ -1221,25 +1224,7 @@ int Tabular::textHOffset(idx_type cell) const
 
 int Tabular::textVOffset(idx_type cell) const
 {
-       int h = rowHeight(cell);
-
-       row_type const r = cellRow(cell);
-       if (rowSpan(cell) > 1)
-               h -= rowDescent(r) + rowAscent(r);
-
-       int y = 0;
-       switch (getVAlignment(cell)) {
-          case LYX_VALIGN_TOP:
-                  break;
-          case LYX_VALIGN_MIDDLE:
-                  y += h/2;
-                  break;
-          case LYX_VALIGN_BOTTOM:
-                  y += h;
-                  break;
-       }
-       
-       return y;
+       return cellInfo(cell).voffset;
 }
 
 
@@ -1504,17 +1489,20 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell) const
 }
 
 
-void Tabular::setMultiColumn(idx_type cell, idx_type number)
+Tabular::idx_type Tabular::setMultiColumn(idx_type cell, idx_type number)
 {
        idx_type const col = cellColumn(cell);
        idx_type const row = cellRow(cell);
        for (idx_type i = 0; i < number; ++i)
                unsetMultiRow(cellIndex(row, col + i));
 
+       // unsetting of multirow may have invalidated cell index
+       cell = cellIndex(row, col);
        CellData & cs = cellInfo(cell);
        cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
-       cs.alignment = column_info[cellColumn(cell)].alignment;
-       setRightLine(cell, rightLine(cell + number - 1));
+       cs.alignment = column_info[col].alignment;
+       if (col > 0)
+               setRightLine(cell, rightLine(cellIndex(row, col - 1)));
 
        for (idx_type i = 1; i < number; ++i) {
                CellData & cs1 = cellInfo(cell + i);
@@ -1523,6 +1511,7 @@ void Tabular::setMultiColumn(idx_type cell, idx_type number)
                cs1.inset->clear();
        }
        updateIndexes();
+       return cell;
 }
 
 
@@ -1533,16 +1522,25 @@ bool Tabular::isMultiRow(idx_type cell) const
 }
 
 
-void Tabular::setMultiRow(idx_type cell, idx_type number)
+Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number)
 {
        idx_type const col = cellColumn(cell);
        idx_type const row = cellRow(cell);
        for (idx_type i = 0; i < number; ++i)
                unsetMultiColumn(cellIndex(row + i, col));
 
+       // unsetting of multicol may have invalidated cell index
+       cell = cellIndex(row, col);
        CellData & cs = cellInfo(cell);
        cs.multirow = CELL_BEGIN_OF_MULTIROW;
        cs.valignment = LYX_VALIGN_MIDDLE;
+       // FIXME: the horizontal alignment of multirow cells can only
+       // be changed for the whole table,
+       // support for this needs to be implemented but us a fileformat
+       // change (assigning this to uwestoehr)
+       // until LyX supports this, use the deault alignment of multirow
+       // cells: left
+       cs.alignment = LYX_ALIGN_LEFT; 
 
        // set the bottom row of the last selected cell
        setBottomLine(cell, bottomLine(cell + (number - 1)*ncols()));
@@ -1554,6 +1552,7 @@ void Tabular::setMultiRow(idx_type cell, idx_type number)
                cs1.inset->clear();
        }
        updateIndexes();
+       return cell;
 }
 
 
@@ -1599,6 +1598,7 @@ void Tabular::unsetMultiRow(idx_type cell)
                return;
 
        cellInfo(cell).valignment = LYX_VALIGN_TOP;
+       cellInfo(cell).alignment = LYX_ALIGN_CENTER;
        row_type const row = cellRow(cell);
        col_type const col = cellColumn(cell);
        row_type const span = rowSpan(cell);
@@ -2110,7 +2110,7 @@ int Tabular::TeXCellPreamble(odocstream & os, idx_type cell,
                else
                        // we need to set a default value
                        // needs to be discussed
-                       os << "2.0cm";
+                       os << "*";
                os << "}{";
                } // end if ismultirow
 
@@ -3203,8 +3203,8 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
        }
 
        for (row_type r = 0; r < tabular.nrows(); ++r) {
-               int maxAsc = 0;
-               int maxDesc = 0;
+               int maxasc = 0;
+               int maxdes = 0;
                for (col_type c = 0; c < tabular.ncols(); ++c) {
                        if (tabular.isPartOfMultiColumn(r, c)
                                || tabular.isPartOfMultiRow(r, c))
@@ -3213,29 +3213,44 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
                        idx_type const cell = tabular.cellIndex(r, c);
                        Dimension dim;
                        MetricsInfo m = mi;
-                       Length p_width;
-                       if (tabular.cell_info[r][c].multicolumn ==
-                               Tabular::CELL_BEGIN_OF_MULTICOLUMN)
-                               p_width = tabular.cellInfo(cell).p_width;
-                       else
-                               p_width = tabular.column_info[c].p_width;
+                       Length const p_width = tabular.getPWidth(cell);
                        if (!p_width.zero())
                                m.base.textwidth = p_width.inPixels(mi.base.textwidth);
                        tabular.cellInset(cell)->metrics(m, dim);
                        if (!p_width.zero())
                                dim.wid = m.base.textwidth;
                        tabular.setCellWidth(cell, dim.wid);
-                       maxAsc  = max(maxAsc, dim.asc);
-                       maxDesc = max(maxDesc, dim.des);
+
+                       // FIXME(?): do we need a second metrics call?
+                       TextMetrics const & tm = 
+                               mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0));
+                       // with LYX_VALIGN_BOTTOM the descent is relative to the last par
+                       // = descent of text in last par + TEXT_TO_INSET_OFFSET:
+                       int const lastpardes = tm.last().second->descent()
+                               + TEXT_TO_INSET_OFFSET;
+                       int offset = 0;
+                       switch (tabular.getVAlignment(cell)) { 
+                               case Tabular::LYX_VALIGN_TOP:
+                                       break; 
+                               case Tabular::LYX_VALIGN_MIDDLE:
+                                       offset = -(dim.des - lastpardes)/2; 
+                                       break; 
+                               case Tabular::LYX_VALIGN_BOTTOM:
+                                       offset = -(dim.des - lastpardes); 
+                                       break;
+                       }
+                       tabular.cell_info[r][c].voffset = offset;
+                       maxasc = max(maxasc, dim.asc - offset);
+                       maxdes = max(maxdes, dim.des + offset);
                }
                int const top_space = tabular.row_info[r].top_space_default ?
                        default_line_space :
                        tabular.row_info[r].top_space.inPixels(mi.base.textwidth);
-               tabular.setRowAscent(r, maxAsc + ADD_TO_HEIGHT + top_space);
+               tabular.setRowAscent(r, maxasc + ADD_TO_HEIGHT + top_space);
                int const bottom_space = tabular.row_info[r].bottom_space_default ?
                        default_line_space :
                        tabular.row_info[r].bottom_space.inPixels(mi.base.textwidth);
-               tabular.setRowDescent(r, maxDesc + ADD_TO_HEIGHT + bottom_space);
+               tabular.setRowDescent(r, maxdes + ADD_TO_HEIGHT + bottom_space);
        }
        tabular.updateColumnWidths();
        dim.asc = tabular.rowAscent(0);
@@ -3243,6 +3258,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
        dim.wid = tabular.width() + 2 * ADD_TO_TABULAR_WIDTH;
 }
 
+
 bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) 
        const
 {
@@ -3252,7 +3268,11 @@ bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col)
                        col_type cs, ce;
                        getSelection(cur, rs, re, cs, ce);
                        
-                       if (col >= cs && col <= ce && row >= rs && row <= re)
+                       idx_type const cell = tabular.cellIndex(row, col);
+                       col_type const cspan = tabular.columnSpan(cell);
+                       row_type const rspan = tabular.rowSpan(cell);
+                       if (col + cspan - 1 >= cs && col <= ce 
+                               && row + rspan - 1 >= rs && row <= re)
                                return true;
                } else 
                        if (col == tabular.cellColumn(cur.idx()) 
@@ -3306,7 +3326,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
                        int const cx = nx + tabular.textHOffset(idx);
                        int const cy = y  + tabular.textVOffset(idx);
                        // Cache the Inset position.
-                       bv->coordCache().insets().add(cell(idx).get(), cx, y);
+                       bv->coordCache().insets().add(cell(idx).get(), cx, cy);
                        cell(idx)->draw(pi, cx, cy);
                        drawCellLines(pi.pain, nx, y, r, idx, pi.change_);
                        nx += tabular.columnWidth(idx);
@@ -3360,7 +3380,7 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
                                        continue;
                                }
                                int const w = tabular.columnWidth(cell);
-                               int const h = tabular.rowHeight(cell);
+                               int const h = tabular.cellHeight(cell);
                                int const yy = y - tabular.rowAscent(r);
                                if (isCellSelected(cur, r, c))
                                        pi.pain.fillRectangle(xx, yy, w, h, Color_selection);
@@ -3380,49 +3400,43 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 
 
 void InsetTabular::drawCellLines(Painter & pain, int x, int y,
-                                row_type row, idx_type cell, Change const & change) const
+                                                                row_type row, idx_type cell, Change const & change) const
 {
-       y = y - tabular.rowAscent(row);
+       y -= tabular.rowAscent(row);
        int const w = tabular.columnWidth(cell);
-       int const h = tabular.rowHeight(cell);
-       bool on_off = false;
-       Color col = Color_tabularline;
-       Color onoffcol = Color_tabularonoffline;
-
-       if (change.changed()) {
-               col = change.color();
-               onoffcol = change.color();
-       }
+       int const h = tabular.cellHeight(cell);
+       Color linecolor = change.changed() ? change.color() : Color_tabularline;
+       Color gridcolor = change.changed() ? change.color() : Color_tabularonoffline;
+
+       // Top
+       bool drawline = tabular.topLine(cell)
+               || (row > 0 && tabular.bottomLine(tabular.cellAbove(cell)));
+       pain.line(x, y, x + w, y,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
+
+       // Bottom
+       drawline = tabular.bottomLine(cell);
+       pain.line(x, y + h, x + w, y + h,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 
-       bool topalreadydrawn = row > 0 && !tabular.rowTopLine(row) 
-               && tabular.bottomLine(tabular.cellAbove(cell));
+       // Left
+       col_type const col = tabular.cellColumn(cell);
+       drawline = tabular.leftLine(cell)
+               || (col > 0 && tabular.rightLine(tabular.cellIndex(row, col - 1)));
+       pain.line(x, y, x, y + h,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 
-       if (!topalreadydrawn) {
-               on_off = !tabular.topLine(cell);
-               pain.line(x, y, x + w, y,
-                       on_off ? onoffcol : col,
-                       on_off ? Painter::line_onoffdash : Painter::line_solid);
-       }
-       on_off = !tabular.bottomLine(cell);
-       pain.line(x, y + h, x + w, y + h,
-               on_off ? onoffcol : col,
-               on_off ? Painter::line_onoffdash : Painter::line_solid);
-
-       col_type const column = tabular.cellColumn(cell);
-       bool leftalreadydrawn = column > 0  && !tabular.leftLine(cell)
-               && tabular.rightLine(tabular.cellIndex(row, column - 1));
-
-       if (!leftalreadydrawn) {
-               on_off = !tabular.leftLine(cell);
-               pain.line(x, y, x, y + h,
-                       on_off ? onoffcol : col,
-                       on_off ? Painter::line_onoffdash : Painter::line_solid);
-       }
-       on_off = !tabular.rightLine(cell);
-       pain.line(x + w - tabular.interColumnSpace(cell), y,
-               x + w - tabular.interColumnSpace(cell), y + h,
-               on_off ? onoffcol : col,
-               on_off ? Painter::line_onoffdash : Painter::line_solid);
+       // Right
+       x -= tabular.interColumnSpace(cell);
+       drawline = tabular.rightLine(cell)
+                  || (col + 1 < tabular.ncols()
+                      && tabular.leftLine(tabular.cellIndex(row, col + 1)));
+       pain.line(x + w, y, x + w, y + h,
+               drawline ? linecolor : gridcolor,
+               drawline ? Painter::line_solid : Painter::line_onoffdash);
 }
 
 
@@ -4274,6 +4288,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_BRANCH_INSERT:
        case LFUN_PHANTOM_INSERT:
        case LFUN_WRAP_INSERT:
+       case LFUN_PREVIEW_INSERT:
        case LFUN_ERT_INSERT: {
                if (cur.selIsMultiCell()) {
                        status.setEnabled(false);
@@ -4461,7 +4476,7 @@ int InsetTabular::dist(BufferView & bv, idx_type const cell, int x, int y) const
        row_type const row = tabular.cellRow(cell);
        int const ybeg = o.y_ - tabular.rowAscent(row)
                - tabular.interRowSpace(row);
-       int const yend = ybeg + tabular.rowHeight(cell);
+       int const yend = ybeg + tabular.cellHeight(cell);
 
        if (x < xbeg)
                xx = xbeg - x;
@@ -4833,7 +4848,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                break;
 
        case Tabular::SET_SPECIAL_MULTIROW:
-               //FIXME: noting to do here?
+               // nothing to do
                break;
 
        case Tabular::APPEND_ROW:
@@ -4958,8 +4973,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                idx_type const s_start = cur.selBegin().idx();
                row_type const col_start = tabular.cellColumn(s_start);
                row_type const col_end = tabular.cellColumn(cur.selEnd().idx());
-               tabular.setMultiColumn(s_start, col_end - col_start + 1);
-               cur.idx() = s_start;
+               cur.idx() = tabular.setMultiColumn(s_start, col_end - col_start + 1);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.setSelection(false);
@@ -4981,8 +4995,7 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                idx_type const s_start = cur.selBegin().idx();
                row_type const row_start = tabular.cellRow(s_start);
                row_type const row_end = tabular.cellRow(cur.selEnd().idx());
-               tabular.setMultiRow(s_start, row_end - row_start + 1);
-               cur.idx() = s_start;
+               cur.idx() = tabular.setMultiRow(s_start, row_end - row_start + 1);
                cur.pit() = 0;
                cur.pos() = 0;
                cur.setSelection(false);