void CollapsedTablePainterEx::paintCellFill(const TableCell& cell, ScPainterExBase* p) const { QString colorName = cell.fillColor(); if (colorName == CommonStrings::None) return; p->save(); ScribusDoc* doc = m_table->doc(); ScColorShade colorShade(doc->PageColors[colorName], (int) cell.fillShade()); p->setBrush(colorShade); p->setFillMode(ScPainterExBase::Solid); p->setStrokeMode(ScPainterExBase::None); int row = cell.row(); int col = cell.column(); int lastRow = row + cell.rowSpan() - 1; int lastCol = col + cell.columnSpan() - 1; double x = m_table->columnPosition(col); double y = m_table->rowPosition(row); double width = m_table->columnPosition(lastCol) + m_table->columnWidth(lastCol) - x; double height = m_table->rowPosition(lastRow) + m_table->rowHeight(lastRow) - y; p->drawRect(x, y, width, height); p->restore(); }
void CollapsedTablePainter::paintCellFill(const TableCell& cell, ScPainter* p) const { QString colorName = cell.fillColor(); if (colorName == CommonStrings::None) return; p->save(); QColor color; table()->SetQColor(&color, colorName, 100.0); // TODO: Support shade. p->setBrush(color); p->setFillMode(ScPainter::Solid); p->setStrokeMode(ScPainter::None); int row = cell.row(); int col = cell.column(); int lastRow = row + cell.rowSpan() - 1; int lastCol = col + cell.columnSpan() - 1; qreal x = table()->columnPosition(col); qreal y = table()->rowPosition(row); qreal width = table()->columnPosition(lastCol) + table()->columnWidth(lastCol) - x; qreal height = table()->rowPosition(lastRow) + table()->rowHeight(lastRow) - y; p->drawRect(x, y, width, height); p->restore(); }
void PageItem_Table::assertValid() const { // Check list sizes. Q_ASSERT(rows() == m_rowPositions.size()); Q_ASSERT(rows() == m_rowHeights.size()); Q_ASSERT(columns() == m_columnPositions.size()); Q_ASSERT(columns() == m_columnWidths.size()); Q_ASSERT(rows() == m_cellRows.size()); foreach (QList<TableCell> cellRow, m_cellRows) Q_ASSERT(columns() == cellRow.size()); for (int row = 0; row < rows(); ++row) { for (int col = 0; col < columns(); ++col) { TableCell cell = m_cellRows[row][col]; // Check that the cell reports correct row and column. Q_ASSERT(cell.row() == row); Q_ASSERT(cell.column() == col); // Check that the row and column span is sane. Q_ASSERT(cell.rowSpan() >= 1 && cell.columnSpan() >= 1); if (cell.rowSpan() > 1 || cell.columnSpan() > 1) { // Check that there's exactly one matching cell area. CellArea expectedArea(cell.row(), cell.column(), cell.columnSpan(), cell.rowSpan()); Q_ASSERT(m_cellAreas.count(expectedArea) == 1); } } } // Check that the active position is in this table. Q_ASSERT(validCell(m_activeRow, m_activeColumn)); // Check that the active cell is valid. Q_ASSERT(m_activeCell.isValid()); Q_ASSERT(validCell(m_activeCell.row(), m_activeCell.column())); // Check that selected cells are valid. foreach (const TableCell& cell, m_selection) { Q_ASSERT(cell.isValid()); Q_ASSERT(validCell(cell.row(), cell.column())); }
double PageItem_Table::maxLeftBorderWidth() const { double maxWidth = 0.0; TableCell cell; for (int row = 0; row < rows(); row += cell.rowSpan()) { cell = cellAt(row, 0); maxWidth = qMax(maxWidth, TableUtils::collapseBorders(cell.leftBorder(), leftBorder()).width()); } return maxWidth; }
void PageItem_Table::selectCells(int startRow, int startColumn, int endRow, int endColumn) { if (!validCell(startRow, startColumn) || !validCell(endRow, endColumn)) return; const TableCell startCell = cellAt(startRow, startColumn); const TableCell endCell = cellAt(endRow, endColumn); const int topRow = qMin(startCell.row(), endCell.row()); const int bottomRow = qMax(startCell.row() + startCell.rowSpan() - 1, endCell.row() + endCell.rowSpan() - 1); const int leftCol = qMin(startCell.column(), endCell.column()); const int rightCol = qMax(startCell.column() + startCell.columnSpan() - 1, endCell.column() + endCell.columnSpan() - 1); for (int row = topRow; row <= bottomRow; ++row) for (int col = leftCol; col <= rightCol; ++col) selectCell(row, col); emit selectionChanged(); }
void CollapsedTablePainterEx::paintCellBottomBorders(const TableCell& cell, ScPainterExBase* p) const { /* * We are going to paint the border marked # in the following setup. * * +--------------------------+--------------------------+--------------------------+ * | | | | * | | | | * | topLeftCell topLeft cell topRight topRightCell | * | | | | * | | | | * +----------left------------+######### border-#########+----------right-----------+ * | | | | * | | | | * | bottomLeftCell bottomLeft bottomCell bottomRight bottomRightCell | * | | | | * | | | | * +--------------------------+--------------------------+--------------------------+ */ // The cell ends in this row. const int lastRow = cell.row() + cell.rowSpan() - 1; // The cell ends in this column. const int lastCol = cell.column() + cell.columnSpan() - 1; // The Y position of the border segments to paint. const double borderY = m_table->rowPosition(lastRow) + m_table->rowHeight(lastRow); // The start point of the border segment currently being painted. QPointF start(0.0, borderY); // The end point of the border segment currently being painted. QPointF end(0.0, borderY); // The start and end offset factors for the border segment currently being painted. QPointF startOffsetFactors, endOffsetFactors; // Start and end column of border segment currently being painted. int startCol, endCol; for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1) { // Get the neighboring cell below and determine border segment column interval. TableCell bottomCell = m_table->cellAt(lastRow + 1, col); startCol = qMax(cell.column(), bottomCell.column()); endCol = qMin(lastCol, bottomCell.isValid() ? bottomCell.column() + bottomCell.columnSpan() - 1 : lastCol); // Get the remaining neighboring cells. TableCell topLeftCell = m_table->cellAt(lastRow, startCol - 1); TableCell topRightCell = m_table->cellAt(lastRow, endCol + 1); TableCell bottomRightCell = m_table->cellAt(lastRow + 1, endCol + 1); TableCell bottomLeftCell = m_table->cellAt(lastRow + 1, startCol - 1); // Resolve borders between neighboring cells. TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight; resolveBordersHorizontal(topLeftCell, cell, topRightCell, bottomLeftCell, bottomCell, bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, m_table); if (border.isNull()) continue; // Quit early if the border is null. // Set initial coordinates. start.setX(m_table->columnPosition(startCol)); end.setX(m_table->columnPosition(endCol) + m_table->columnWidth(endCol)); // Adjust coordinates for joining. joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors); // Paint the border segment. paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, p); } }
void CollapsedTablePainterEx::paintCellRightBorders(const TableCell& cell, ScPainterExBase* p) const { /* * We are going to paint the border marked # in the following setup. * * +----------------------+----------------------+ * | | | * | | | * | topLeftCell top topRightCell | * | | | * | | | * +--------topLeft-------+-------topRight-------+ * | # | * | # | * | cell border rightCell | * | # | * | # | * +-------bottomLeft-----+------bottomRight-----+ * | | | * | | | * | bottomLeftCell bottom bottomRightCell | * | | | * | | | * +----------------------+----------------------+ */ // The cell ends in this row. const int lastRow = cell.row() + cell.rowSpan() - 1; // The cell ends in this column. const int lastCol = cell.column() + cell.columnSpan() - 1; // The X position of the border segments to paint. const double borderX = m_table->columnPosition(lastCol) + m_table->columnWidth(lastCol); // The start point of the border segment currently being painted. QPointF start(borderX, 0.0); // The end point of the border segment currently being painted. QPointF end(borderX, 0.0); // The start and end offset factors for the border segment currently being painted. QPointF startOffsetFactors, endOffsetFactors; // The start and end row of border segment currently being painted. int startRow, endRow; for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1) { // Get the neighboring cell to the right and determine border segment row interval. TableCell rightCell = m_table->cellAt(row, lastCol + 1); startRow = qMax(cell.row(), rightCell.row()); endRow = qMin(lastRow, rightCell.isValid() ? rightCell.row() + rightCell.rowSpan() - 1 : lastRow); // Get the remaining neighboring cells surrounding the segment. TableCell topLeftCell = m_table->cellAt(startRow - 1, lastCol); TableCell topRightCell = m_table->cellAt(startRow - 1, lastCol + 1); TableCell bottomRightCell = m_table->cellAt(endRow + 1, lastCol + 1); TableCell bottomLeftCell = m_table->cellAt(endRow + 1, lastCol); // Resolve borders between neighboring cells. TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight; resolveBordersVertical(topLeftCell, topRightCell, cell, rightCell, bottomLeftCell, bottomRightCell, &topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, m_table); if (border.isNull()) continue; // Quit early if the border to paint is null. // Set initial coordinates. start.setY(m_table->rowPosition(startRow)); end.setY(m_table->rowPosition(endRow) + m_table->rowHeight(endRow)); // Adjust coordinates for joining. joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors); // Paint the border. paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, p); } }
TableHandle PageItem_Table::hitTest(const QPointF& point, double threshold) const { const QPointF framePoint = getTransform().inverted().map(point); const QPointF gridPoint = framePoint - gridOffset(); const QRectF gridRect = QRectF(0.0, 0.0, tableWidth(), tableHeight()); // Test if hit is outside frame. if (!QRectF(0.0, 0.0, width(), height()).contains(framePoint)) return TableHandle(TableHandle::None); // Test if hit is outside table. if (!gridRect.adjusted(-threshold, -threshold, threshold, threshold).contains(gridPoint)) return TableHandle(TableHandle::None); const double tableHeight = this->tableHeight(); const double tableWidth = this->tableWidth(); const double x = gridPoint.x(); const double y = gridPoint.y(); // Test if hit is on left edge of table. if (x <= threshold) return TableHandle(TableHandle::RowSelect); // Test if hit is on top edge of table. if (y <= threshold) return TableHandle(TableHandle::ColumnSelect); // Test if hit is on bottom right corner of table. if (x >= tableWidth - threshold && y >= tableHeight - threshold) return TableHandle(TableHandle::TableResize); // Test if hit is on right edge of table. if (y >= tableHeight - threshold && y <= tableHeight + threshold) return TableHandle(TableHandle::RowResize, rows() - 1); // Test if hit is on bottom edge of table. if (x >= tableWidth - threshold && x <= tableWidth + threshold) return TableHandle(TableHandle::ColumnResize, columns() - 1); const TableCell hitCell = cellAt(point); const QRectF hitRect = hitCell.boundingRect(); // Test if hit is on cell interior. if (hitRect.adjusted(threshold, threshold, -threshold, -threshold).contains(gridPoint)) return TableHandle(TableHandle::CellSelect); // Hit interior of cell. const double toLeft = x - hitRect.left(); const double toRight = hitRect.right() - x; const double toTop = y - hitRect.top(); const double toBottom = hitRect.bottom() - y; TableHandle handle(TableHandle::None); // Test which side of the cell was hit. if (qMin(toLeft, toRight) < qMin(toTop, toBottom)) { handle.setType(TableHandle::ColumnResize); handle.setIndex((toLeft < toRight ? hitCell.column() : hitCell.column() + hitCell.columnSpan()) - 1); } else { handle.setType(TableHandle::RowResize); handle.setIndex((toTop < toBottom ? hitCell.row() : hitCell.row() + hitCell.rowSpan()) - 1); } return handle; }
void TableGesture::paintTableOutline( const QList<qreal>& rowHeights, const QList<qreal>& rowPositions, const QList<qreal>& columnWidths, const QList<qreal>& columnPositions, QPainter* p) { if (!m_table || !m_canvas || !p) return; p->save(); p->scale(m_canvas->scale(), m_canvas->scale()); p->translate(-m_doc->minCanvasCoordinate.x(), -m_doc->minCanvasCoordinate.y()); p->setTransform(m_table->getTransform(), true); p->setRenderHint(QPainter::Antialiasing); p->setPen(QPen(QColor(100, 200, 255), 3.0 / m_canvas->scale(), Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); QPointF offset = m_table->gridOffset(); // First draw a rect around the table. p->drawRect(QRectF(offset.x(), offset.y(), columnPositions.last() + columnWidths.last(), rowPositions.last() + rowHeights.last())); /** * cellAt() and cellRect() are fast, stroking is not. So we paint the * left and top edges of the cells in two passes as this allows us to * greatly minimize the number of strokes. */ TableCell cell; // Paint left edge(s) in each of the columns. for (int col = 1; col < m_table->columns(); ++col) { QPointF startPoint(columnPositions[col], 0.0); QPointF endPoint(startPoint); for (int row = 0; row < m_table->rows(); row += cell.rowSpan()) { cell = m_table->cellAt(row, col); int endRow = cell.row() + cell.rowSpan() - 1; qreal bottom = rowPositions[endRow] + rowHeights[endRow]; if (cell.column() == col) endPoint.setY(bottom); else { p->drawLine(startPoint + offset, endPoint + offset); startPoint.setY(bottom); endPoint.setY(bottom); } } if (endPoint.y() > startPoint.y()) p->drawLine(startPoint + offset, endPoint + offset); } // Paint top edge(s) in each of the rows. for (int row = 1; row < m_table->rows(); ++row) { QPointF startPoint(0.0, rowPositions[row]); QPointF endPoint(startPoint); for (int col = 0; col < m_table->columns(); col += cell.columnSpan()) { cell = m_table->cellAt(row, col); int endCol = cell.column() + cell.columnSpan() - 1; qreal right = columnPositions[endCol] + columnWidths[endCol]; if (cell.row() == row) endPoint.setX(right); else { p->drawLine(startPoint + offset, endPoint + offset); startPoint.setX(right); endPoint.setX(right); } } if (endPoint.x() > startPoint.x()) p->drawLine(startPoint + offset, endPoint + offset); } p->restore(); }
void CollapsedTablePainter::paintTable(ScPainter* p) { p->save(); p->translate(table()->gridOffset()); // Paint table fill. paintTableFill(p); /* * We paint the table in five passes: * * 1) Cell fills. * 2) Vertical borders. * 3) Horizontal borders * 4) Decorative grid lines. * 5) Cell content. */ // Pass 1: Paint cell fills. for (int row = 0; row < table()->rows(); ++row) { int colSpan = 0; for (int col = 0; col < table()->columns(); col += colSpan) { TableCell cell = table()->cellAt(row, col); if (row == cell.row()) paintCellFill(cell, p); colSpan = cell.columnSpan(); } } // Pass 2: Paint vertical borders. for (int row = 0; row < table()->rows(); ++row) { int colSpan = 0; for (int col = 0; col < table()->columns(); col += colSpan) { TableCell cell = table()->cellAt(row, col); if (row == cell.row()) { paintCellRightBorders(cell, p); if (col == 0) paintCellLeftBorders(cell, p); } colSpan = cell.columnSpan(); } } // Pass 3: Paint horizontal borders. for (int row = 0; row < table()->rows(); ++row) { int colSpan = 0; for (int col = 0; col < table()->columns(); col += colSpan) { TableCell cell = table()->cellAt(row, col); if (row == cell.row()) { paintCellBottomBorders(cell, p); if (row == 0) paintCellTopBorders(cell, p); } colSpan = cell.columnSpan(); } } // Pass 4: Paint grid lines. if (table()->m_Doc->guidesPrefs().framesShown) { for (int row = 0; row < table()->rows(); ++row) { int colSpan = 0; for (int col = 0; col < table()->columns(); col += colSpan) { TableCell cell = table()->cellAt(row, col); if (row == cell.row()) { int endCol = col + cell.columnSpan() - 1; int endRow = row + cell.rowSpan() - 1; qreal left = table()->columnPosition(col); qreal right = table()->columnPosition(endCol) + table()->columnWidth(endCol); qreal top = table()->rowPosition(row); qreal bottom = table()->rowPosition(endRow) + table()->rowHeight(endRow); // Paint right and bottom grid line. paintGridLine(QPointF(right, top), QPointF(right, bottom), p); paintGridLine(QPointF(left, bottom), QPointF(right, bottom), p); // Paint left and top grid line. if (col == 0) paintGridLine(QPointF(left, top), QPointF(left, bottom), p); if (row == 0) paintGridLine(QPointF(left, top), QPointF(right, top), p); } colSpan = cell.columnSpan(); } } } // Pass 5: Paint cell content. for (int row = 0; row < table()->rows(); ++row) { for (int col = 0; col < table()->columns(); col ++) { TableCell cell = table()->cellAt(row, col); if (cell.row() == row && cell.column() == col) { PageItem* textFrame = cell.textFrame(); textFrame->DrawObj(p, QRectF()); textFrame->DrawObj_Decoration(p); } } } p->restore(); }