]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
correctly valign content of multirow cells
[lyx.git] / src / insets / InsetTabular.cpp
index fca719853f8b518071811216d5ba5fb78787bd43..d75e2a6ffe5e7118150020044bb53d4d52359024 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);
@@ -1221,20 +1224,12 @@ int Tabular::textHOffset(idx_type cell) const
 
 int Tabular::textVOffset(idx_type cell) const
 {
-       row_type const r = cellRow(cell);
-       int y = cellHeight(cell) - rowDescent(r) - rowAscent(r);
-       switch (getVAlignment(cell)) {
-          case LYX_VALIGN_TOP:
-                  y = 0;
-                  break;
-          case LYX_VALIGN_MIDDLE:
-                  y = y/2;
-                  break;
-          case LYX_VALIGN_BOTTOM:
-                  break;
+       int voffset = cellInfo(cell).voffset;
+       if (isMultiRow(cell)) {
+               row_type const row = cellRow(cell);
+               voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; 
        }
-
-       return y;
+       return voffset;
 }
 
 
@@ -3060,7 +3055,7 @@ bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
        bool enabled;
-       switch (cmd.action) {
+       switch (cmd.action()) {
        case LFUN_LAYOUT:
                enabled = !forcePlainLayout();
                break;
@@ -3213,8 +3208,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))
@@ -3223,29 +3218,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);
@@ -3253,6 +3263,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
 {
@@ -3499,14 +3510,16 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        CursorSlice sl = cur.top();
        Cursor & bvcur = cur.bv().cursor();
 
-       switch (cmd.action) {
+       FuncCode const act = cmd.action();
+       
+       switch (act) {
 
        case LFUN_MOUSE_PRESS: {
                //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
                // select row
-               if (cmd.x < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
-                       || cmd.x > xo(cur.bv()) + tabular.width()) {
-                       row_type r = rowFromY(cur, cmd.y);
+               if (cmd.x() < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
+                       || cmd.x() > xo(cur.bv()) + tabular.width()) {
+                       row_type r = rowFromY(cur, cmd.y());
                        cur.idx() = tabular.getFirstCellInRow(r);
                        cur.pos() = 0;
                        cur.resetAnchor();
@@ -3519,9 +3532,9 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                }
                // select column
                int const y0 = yo(cur.bv()) - tabular.rowAscent(0);
-               if (cmd.y < y0 + ADD_TO_TABULAR_WIDTH 
-                       || cmd.y > y0 + tabular.height()) {
-                       col_type c = columnFromX(cur, cmd.x);
+               if (cmd.y() < y0 + ADD_TO_TABULAR_WIDTH 
+                       || cmd.y() > y0 + tabular.height()) {
+                       col_type c = columnFromX(cur, cmd.x());
                        cur.idx() = tabular.cellIndex(0, c);
                        cur.pos() = 0;
                        cur.resetAnchor();
@@ -3553,7 +3566,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        }
                        // select (additional) row
                        if (rowselect_) {
-                               row_type r = rowFromY(cur, cmd.y);
+                               row_type r = rowFromY(cur, cmd.y());
                                cur.idx() = tabular.getLastCellInRow(r);
                                // we need to reset the cursor's pit and pos now, as the old ones
                                // may no longer be valid.
@@ -3565,7 +3578,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        }
                        // select (additional) column
                        if (colselect_) {
-                               col_type c = columnFromX(cur, cmd.x);
+                               col_type c = columnFromX(cur, cmd.x());
                                cur.idx() = tabular.cellIndex(tabular.nrows() - 1, c);
                                // we need to reset the cursor's pit and pos now, as the old ones
                                // may no longer be valid.
@@ -3579,7 +3592,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        if (bvcur.idx() == cur.idx() &&
                                !(bvcur.anchor_.idx() == cur.idx() && bvcur.pos() != cur.pos()))
                                cur.noUpdate();
-                       setCursorFromCoordinates(cur, cmd.x, cmd.y);
+                       setCursorFromCoordinates(cur, cmd.x(), cmd.y());
                        bvcur.setCursor(cur);
                        bvcur.setSelection(true);
                        // if this is a multicell selection, we just set the cursor to
@@ -3621,21 +3634,21 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                EntryDirection entry_from = ENTRY_DIRECTION_IGNORE;
                FuncCode finish_lfun;
 
-               if (cmd.action == LFUN_CHAR_FORWARD 
-                               || cmd.action == LFUN_CHAR_FORWARD_SELECT) {
+               if (act == LFUN_CHAR_FORWARD 
+                               || act == LFUN_CHAR_FORWARD_SELECT) {
                        next_cell = true;
                        finish_lfun = LFUN_FINISHED_FORWARD;
                }
-               else if (cmd.action == LFUN_CHAR_BACKWARD
-                               || cmd.action == LFUN_CHAR_BACKWARD_SELECT) {
+               else if (act == LFUN_CHAR_BACKWARD
+                               || act == LFUN_CHAR_BACKWARD_SELECT) {
                        next_cell = false;
                        finish_lfun = LFUN_FINISHED_BACKWARD;
                }
                // LEFT or RIGHT commands --- the interpretation will depend on the 
                // table's direction.
                else {
-                       bool const right = cmd.action == LFUN_CHAR_RIGHT
-                               || cmd.action == LFUN_CHAR_RIGHT_SELECT;
+                       bool const right = act == LFUN_CHAR_RIGHT
+                               || act == LFUN_CHAR_RIGHT_SELECT;
                        next_cell = isRightToLeft(cur) != right;
                        
                        if (lyxrc.visual_cursor)
@@ -3644,10 +3657,10 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        finish_lfun = right ? LFUN_FINISHED_RIGHT : LFUN_FINISHED_LEFT;
                }
 
-               bool const select = cmd.action == LFUN_CHAR_FORWARD_SELECT ||
-                   cmd.action == LFUN_CHAR_BACKWARD_SELECT ||
-                   cmd.action == LFUN_CHAR_RIGHT_SELECT ||
-                   cmd.action == LFUN_CHAR_LEFT_SELECT;
+               bool const select = act == LFUN_CHAR_FORWARD_SELECT ||
+                   act == LFUN_CHAR_BACKWARD_SELECT ||
+                   act == LFUN_CHAR_RIGHT_SELECT ||
+                   act == LFUN_CHAR_LEFT_SELECT;
 
                // If we have a multicell selection or we're 
                // not doing some LFUN_*_SELECT thing anyway...
@@ -3709,7 +3722,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        // if our Text didn't do anything to the cursor
                        // then we try to put the cursor into the cell below
                        // setting also the right targetX.
-                       cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
+                       cur.selHandle(act == LFUN_DOWN_SELECT);
                        if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) {
                                cur.idx() = tabular.cellBelow(cur.idx());
                                cur.pit() = 0;
@@ -3742,7 +3755,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        // if our Text didn't do anything to the cursor
                        // then we try to put the cursor into the cell above
                        // setting also the right targetX.
-                       cur.selHandle(cmd.action == LFUN_UP_SELECT);
+                       cur.selHandle(act == LFUN_UP_SELECT);
                        if (tabular.cellRow(cur.idx()) != 0) {
                                cur.idx() = tabular.cellAbove(cur.idx());
                                cur.pit() = cur.lastpit();
@@ -3870,7 +3883,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CLIPBOARD_PASTE:
        case LFUN_PRIMARY_SELECTION_PASTE: {
-               docstring const clip = (cmd.action == LFUN_CLIPBOARD_PASTE) ?
+               docstring const clip = (act == LFUN_CLIPBOARD_PASTE) ?
                        theClipboard().getAsText() :
                        theSelection().get();
                if (clip.empty())
@@ -3971,7 +3984,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
-       switch (cmd.action) {
+       switch (cmd.action()) {
        case LFUN_INSET_MODIFY: {
                if (&cur.inset() != this || cmd.getArg(0) != "tabular") 
                        break;
@@ -4282,6 +4295,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);
@@ -4841,7 +4855,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: