[Kst] branches/work/kst/portto4/kst/src/libkstapp

Mike Fenton mike at staikos.net
Thu Jan 8 20:50:12 CET 2009


SVN commit 907830 by fenton:

Add custom layout support and updated margin handling for SharedAxisBoxItem's.


 M  +32 -4     plotitem.cpp  
 M  +6 -0      plotitem.h  
 M  +195 -52   viewgridlayout.cpp  
 M  +1 -1      viewgridlayout.h  
 M  +0 -62     viewitem.cpp  
 M  +0 -16     viewitem.h  


--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.cpp #907829:907830
@@ -71,6 +71,8 @@
   _calculatedAxisMarginHeight(0.0),
   _leftPadding(0.0),
   _bottomPadding(0.0),
+  _rightPadding(0.0),
+  _topPadding(0.0),
   _showLegend(false),
   _legend(0),
   _zoomMenu(0),
@@ -885,11 +887,15 @@
   QRectF plot = plotAxisRect();
   qreal xOffset = _xAxis->isAxisVisible() ? axisMarginHeight() : 0.0;
   qreal yOffset = _yAxis->isAxisVisible() ? axisMarginWidth() : 0.0;
-  qreal xPadding = _xAxis->isAxisVisible() ? _bottomPadding : 0.0;
-  qreal yPadding = _yAxis->isAxisVisible() ? _leftPadding : 0.0;
+  qreal bottomPadding = _xAxis->isAxisVisible() ? _bottomPadding : 0.0;
+  qreal leftPadding = _yAxis->isAxisVisible() ? _leftPadding : 0.0;
+  qreal rightPadding = isRightLabelVisible() ? _rightPadding : 0.0;
+  qreal topPadding = isTopLabelVisible() ? _topPadding : 0.0;
 
-  plot.setLeft(plot.left() + yOffset + yPadding);
-  plot.setBottom(plot.bottom() - xOffset - xPadding);
+  plot.setLeft(plot.left() + yOffset + leftPadding);
+  plot.setBottom(plot.bottom() - xOffset - bottomPadding);
+  plot.setRight(plot.right() - rightPadding);
+  plot.setTop(plot.top() + topPadding);
   return plot;
 }
 
@@ -910,6 +916,18 @@
 }
 
 
+qreal PlotItem::rightMarginSize() const {
+  qreal margin = isRightLabelVisible() ? rightLabelMargin() : 0.0;
+  return margin;
+}
+
+
+qreal PlotItem::topMarginSize() const {
+  qreal margin = isTopLabelVisible() ? topLabelMargin() : 0.0;
+  return margin;
+}
+
+
 void PlotItem::setLeftPadding(const qreal padding) {
   _leftPadding = padding;
 }
@@ -920,6 +938,16 @@
 }
 
 
+void PlotItem::setRightPadding(const qreal padding) {
+  _rightPadding = padding;
+}
+
+
+void PlotItem::setTopPadding(const qreal padding) {
+  _topPadding = padding;
+}
+
+
 QRectF PlotItem::projectionRect() const {
   return _projectionRect;
 }
--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.h #907829:907830
@@ -89,6 +89,10 @@
     void setLeftPadding(const qreal);
     qreal bottomMarginSize() const;
     void setBottomPadding(const qreal);
+    qreal rightMarginSize() const;
+    void setRightPadding(const qreal);
+    qreal topMarginSize() const;
+    void setTopPadding(const qreal);
 
     qreal leftLabelMargin() const;
     qreal rightLabelMargin() const;
@@ -358,6 +362,8 @@
 
     qreal _leftPadding;
     qreal _bottomPadding;
+    qreal _rightPadding;
+    qreal _topPadding;
 
     PlotAxis *_xAxis;
     PlotAxis *_yAxis;
--- branches/work/kst/portto4/kst/src/libkstapp/viewgridlayout.cpp #907829:907830
@@ -22,6 +22,7 @@
 // 0 off, 1 On
 #define DEBUG_LAYOUT 0
 #define DEBUG_PLOT_STANDARDIZATION 0
+#define DEBUG_SHAREDAXIS 0
 
 static qreal DEFAULT_STRUT = 20.0;
 
@@ -195,6 +196,7 @@
   Q_ASSERT(item);
   Q_ASSERT(item->parentView());
 
+  // Gather all children of the SharedAxisBoxItem.
   QList<ViewItem*> viewItems;
   QList<QGraphicsItem*> list = item->QGraphicsItem::children();
   if (list.isEmpty())
@@ -210,6 +212,8 @@
   if (viewItems.isEmpty())
     return; //not added to undostack
 
+
+  // Build an automatic layout to try to maintain the existing layout.
   Grid *grid = Grid::buildGrid(viewItems, 0);
   Q_ASSERT(grid);
 
@@ -228,8 +232,33 @@
       }
     }
   }
-  layout->applyAxis();
-  layout->applyAxis();
+  layout->apply();
+  layout->apply();
+
+  // Using the automatic layout as a basis, build a custom grid with the same column count,
+  // this will remove all spans, making each plot the same size.  When this is built, the 
+  // sharedAxis layout will be applied.
+  int columnCount = layout->columnCount();
+  grid = Grid::buildGrid(viewItems, columnCount);
+  Q_ASSERT(grid);
+
+  layout = new ViewGridLayout(item);
+
+  foreach (ViewItem *v, viewItems) {
+    int r = 0, c = 0, rs = 0, cs = 0;
+    if (grid->locateWidget(v, r, c, rs, cs)) {
+      layout->addViewItem(v, r, c, rs, cs);
+    } else {
+      grid->appendItem(v);
+      if (grid->locateWidget(v, r, c, rs, cs)) {
+        layout->addViewItem(v, r, c, rs, cs);
+      } else {
+        qDebug() << "ooops, viewItem does not fit in layout" << endl;
+      }
+    }
+  }
+  layout->shareAxis();
+  layout->shareAxis();
 }
 
 
@@ -371,83 +400,197 @@
 }
 
 
-void ViewGridLayout::applyAxis() {
-  updatePlotMargins();
+void ViewGridLayout::shareAxis() {
+  calculateSharing();
+  updateSharedAxis();
 
-  //For now we divide up equally... can do stretch factors and such later...
-
-  QSizeF layoutSize(parentItem()->width() - _margin.width() * 2,
-                    parentItem()->height() - _margin.height() * 2);
-
+  // Determine area of layout.  Minimal spacing on SharedAxisBoxItems.
+  QSizeF layoutSize(parentItem()->width() - 1, parentItem()->height() - 1);
   QPointF layoutTopLeft = parentItem()->rect().topLeft();
-  layoutTopLeft += QPointF(_margin.width(), _margin.height());
+  layoutTopLeft += QPointF(0, 1);
 
   QRectF layoutRect(layoutTopLeft, layoutSize);
 
-  qreal itemWidth = layoutSize.width() / columnCount();
-  qreal itemHeight = layoutSize.height() / rowCount();
+  QMap<int, int> leftLabelBounds;
+  QMap<int, int> rightLabelBounds;
+  QMap<int, int> topLabelBounds;
+  QMap<int, int> bottomLabelBounds;
 
-#if DEBUG_LAYOUT
-  qDebug() << "layouting" << _items.count()
-           << "itemWidth:" << itemWidth
-           << "itemHeight:" << itemHeight
-           << endl;
+#if DEBUG_SHAREDAXIS
+  qDebug() << "Creating Shared Axis Layout in rect " << layoutRect
+           << "rowCount" << rowCount() << "columnCount" << columnCount();
 #endif
 
   foreach (LayoutItem item, _items) {
-    QPointF topLeft(itemWidth * item.column, itemHeight * item.row);
-    QSizeF size(itemWidth * item.columnSpan, itemHeight * item.rowSpan);
-    topLeft += layoutTopLeft;
+    if (PlotItem *plotItem = qobject_cast<PlotItem*>(item.viewItem)) {
+      if (plotItem->leftMarginSize() > leftLabelBounds[item.column]) {
+        leftLabelBounds[item.column] = plotItem->leftMarginSize();
+      }
+      if (plotItem->rightMarginSize() > rightLabelBounds[item.column]) {
+        rightLabelBounds[item.column] = plotItem->rightMarginSize();
+      }
+      if (plotItem->topMarginSize() > topLabelBounds[item.row]) {
+        topLabelBounds[item.row] = plotItem->topMarginSize();
+      }
+      if (plotItem->bottomMarginSize() > bottomLabelBounds[item.row]) {
+        bottomLabelBounds[item.row] = plotItem->bottomMarginSize();
+      }
+    }
+  }
 
-    QRectF itemRect(topLeft, size);
+#if DEBUG_SHAREDAXIS
+  qDebug() << "Calculated maximum bounds for labels."
+  qDebug() << "Left bounds by column" << leftLabelBounds;
+  qDebug() << "Right bounds by column" << rightLabelBounds;
+  qDebug() << "Top bounds by row" << topLabelBounds;
+  qDebug() << "Bottom bounds by row" << bottomLabelBounds;
+#endif
 
-    if (itemRect.top() != layoutRect.top())
-      itemRect.setTop(itemRect.top() + _spacing.height() / 2);
-    if (itemRect.left() != layoutRect.left())
-      itemRect.setLeft(itemRect.left() + _spacing.width() / 2);
-    if (itemRect.bottom() != layoutRect.bottom())
-      itemRect.setBottom(itemRect.bottom() - _spacing.height() / 2);
-    if (itemRect.right() != layoutRect.right())
-      itemRect.setRight(itemRect.right() - _spacing.width() / 2);
+  bool blockMode = false;
+  bool rowMode = false;
+  bool colMode = false;
 
-    item.viewItem->resetTransform();
-    item.viewItem->setPos(itemRect.topLeft());
+#if DEBUG_SHAREDAXIS
+  qDebug() << "Calculated sharing modes" << "sharing X = " << _shareX << "sharing Y = " << _shareY;
+#endif
 
-    if (item.viewItem->fixedSize()) {
-      itemRect.setBottom(itemRect.top() + item.viewItem->rect().height());
-      itemRect.setRight(itemRect.left() + item.viewItem->rect().width());
-    } else if (item.viewItem->lockAspectRatio()) {
-      qreal newHeight = itemRect.height();
-      qreal newWidth = itemRect.width();
+  if (_shareX && _shareY) {
+#if DEBUG_SHAREDAXIS
+    qDebug() << "Sharing X & Y, one block, all projectionRect's inside frame";
+#endif
+    blockMode = true;
+  } else if (_shareX) {
+    if (columnCount() == 1) {
+#if DEBUG_SHAREDAXIS
+      qDebug() << "Sharing only X, one column, use block logic";
+#endif
+      blockMode = true;
+    } else {
+#if DEBUG_SHAREDAXIS
+      qDebug() << "Sharing only X, multiple columns, use block for each column, columns divide space equally - number of columns" << columnCount();
+#endif
+      colMode = true;
+    }
+  } else if (_shareY) {
+    if (rowCount() == 1) {
+#if DEBUG_SHAREDAXIS
+      qDebug() << "Sharing only Y, one row, use block logic";
+#endif
+      blockMode = true;
+    } else {
+#if DEBUG_SHAREDAXIS
+      qDebug() << "Sharing only Y, multiple rows, use block for each row, rows divide space equally - number of rows" << rowCount();
+#endif
+      rowMode = true;
+    }
+  }
 
-      qreal aspectRatio = item.viewItem->rect().width() / item.viewItem->rect().height();
-      if ((newWidth / newHeight) > aspectRatio) {
-        // newWidth is too large.  Use newHeight as key.
-        newWidth = newHeight * aspectRatio;
-      } else {
-        // newHeight is either too large, or perfect.  use newWidth as key.
-        newHeight = newWidth / aspectRatio;
+  int totalProjWidth;
+  int totalProjHeight;
+
+  if (blockMode) {
+    totalProjWidth = (layoutRect.width() - leftLabelBounds[0]) - rightLabelBounds[columnCount() - 1];
+    totalProjHeight = (layoutRect.height() - topLabelBounds[0]) - bottomLabelBounds[rowCount() - 1];
+  } else if (rowMode) {
+    int totalHeight = 0;
+    for (int i = 0; i < rowCount(); i++) {
+      totalHeight = topLabelBounds[i] + bottomLabelBounds[i];
+    }
+    totalProjWidth = layoutRect.width() - leftLabelBounds[0] - rightLabelBounds[columnCount() - 1];
+    totalProjHeight = layoutRect.height() - totalHeight;
+
+  } else if (colMode) {
+    int totalWidth = 0;
+    for (int i = 0; i < columnCount(); i++) {
+      totalWidth = leftLabelBounds[i] + rightLabelBounds[i];
+    }
+    totalProjWidth = layoutRect.width() - totalWidth;
+    totalProjHeight = layoutRect.height() - topLabelBounds[0] - bottomLabelBounds[columnCount() - 1];
+  } else {
+    return;
+  }
+
+  int columnProjWidth = totalProjWidth / (columnCount());
+  int rowProjHeight = totalProjHeight / (rowCount());
+
+  QMap<int, QMap<int, int> > cellHeights;
+  QMap<int, QMap<int, int> > cellWidths;
+
+  foreach (LayoutItem item, _items) {
+    if (PlotItem *plotItem = qobject_cast<PlotItem*>(item.viewItem)) {
+      int width = columnProjWidth;
+      if (plotItem->isLeftLabelVisible()) {
+        width += leftLabelBounds[item.column];
       }
-      itemRect.setBottom(itemRect.top() + newHeight);
-      itemRect.setRight(itemRect.left() + newWidth);
+      if (plotItem->isRightLabelVisible()) {
+        width += rightLabelBounds[item.column];
+      }
+      cellWidths[item.row][item.column] = width;
+
+      int height = rowProjHeight;
+      if (plotItem->isTopLabelVisible()) {
+        height += topLabelBounds[item.row];
+      }
+      if (plotItem->isBottomLabelVisible()) {
+        height += bottomLabelBounds[item.row];
+      }
+      cellHeights[item.row][item.column] = height;
     }
+  }
+
+#if DEBUG_SHAREDAXIS
+  qDebug() << "Calculated Total projectRect values - width = " << totalProjWidth << " height = " << totalProjHeight;
+  qDebug() << "Column Projection Width" << columnProjWidth << "Row Projection Height" << rowProjHeight;
+  qDebug() << "Calculated cell widths (row x column)" << cellWidths;
+  qDebug() << "Calculated cell heights (row x column)" << cellHeights;
+#endif
+
+  foreach (LayoutItem item, _items) {
+    int columnStart = 0;
+    for (int i = 0; i < item.column; i++) {
+      columnStart += cellWidths[item.row][i];
+    }
+
+    int rowStart = 0;
+    for (int i = 0; i < item.row; i++) {
+      rowStart += cellHeights[i][item.column];
+    }
+
+    QPointF itemTopLeft(columnStart, rowStart);
+    itemTopLeft += layoutTopLeft;
+    QSizeF itemSize(cellWidths[item.row][item.column], cellHeights[item.row][item.column]);
+    QRectF itemRect(itemTopLeft, itemSize);
+
+    if (PlotItem *plotItem = qobject_cast<PlotItem*>(item.viewItem)) {
+      if (plotItem->isLeftLabelVisible()) {
+        plotItem->setLeftPadding(leftLabelBounds[item.column] - plotItem->leftMarginSize());
+      }
+      if (plotItem->isRightLabelVisible()) {
+        plotItem->setRightPadding(rightLabelBounds[item.column] - plotItem->rightMarginSize());
+      }
+      if (plotItem->isTopLabelVisible()) {
+        plotItem->setTopPadding(topLabelBounds[item.row] - plotItem->topMarginSize());
+      }
+      if (plotItem->isBottomLabelVisible()) {
+        plotItem->setBottomPadding(bottomLabelBounds[item.row] - plotItem->bottomMarginSize());
+      }
+    }
+
+    item.viewItem->resetTransform();
+    item.viewItem->setPos(itemRect.topLeft());
     item.viewItem->setViewRect(QRectF(QPoint(0,0), itemRect.size()));
 
     if (PlotItem *plotItem = qobject_cast<PlotItem*>(item.viewItem))
       emit plotItem->updatePlotRect();
 
-#if DEBUG_LAYOUT
-    qDebug() << "layout"
+#if DEBUG_SHAREDAXIS
+    qDebug() << "Shared Axis Plot item details:"
              << "row:" << item.row
              << "column:" << item.column
-             << "rowSpan:" << item.rowSpan
-             << "columnSpan:" << item.columnSpan
              << "itemRect:" << itemRect
              << endl;
 #endif
   }
-  calculateSharing();
-  updateSharedAxis();
 }
 
 
--- branches/work/kst/portto4/kst/src/libkstapp/viewgridlayout.h #907829:907830
@@ -67,7 +67,7 @@
     void reset();
     void resetSharedAxis();
     void apply();
-    void applyAxis();
+    void shareAxis();
 
   Q_SIGNALS:
     void enabledChanged(bool enabled);
--- branches/work/kst/portto4/kst/src/libkstapp/viewitem.cpp #907829:907830
@@ -1918,68 +1918,6 @@
 }
 
 
-
-void SharedAxisCommand::undo() {
-  Q_ASSERT(_layout);
-  _layout->reset();
-}
-
-
-void SharedAxisCommand::redo() {
-  Q_ASSERT(_layout);
-  _layout->applyAxis();
-}
-
-
-void SharedAxisCommand::createLayout(int columns) {
-  Q_ASSERT(_item);
-  Q_ASSERT(_item->parentView());
-
-  QList<ViewItem*> viewItems;
-  QList<QGraphicsItem*> list = _item->QGraphicsItem::children();
-  if (list.isEmpty())
-    return; //not added to undostack
-
-  foreach (QGraphicsItem *item, list) {
-    ViewItem *viewItem = qgraphicsitem_cast<ViewItem*>(item);
-    if (!viewItem || viewItem->hasStaticGeometry() || !viewItem->allowsLayout() || viewItem->parentItem() != _item)
-      continue;
-    viewItems.append(viewItem);
-  }
-
-  if (viewItems.isEmpty())
-    return; //not added to undostack
-
-  Grid *grid = Grid::buildGrid(viewItems, columns);
-  Q_ASSERT(grid);
-
-  _layout = new ViewGridLayout(_item);
-
-  foreach (ViewItem *v, viewItems) {
-    int r = 0, c = 0, rs = 0, cs = 0;
-    if (grid->locateWidget(v, r, c, rs, cs)) {
-      _layout->addViewItem(v, r, c, rs, cs);
-    } else {
-      grid->appendItem(v);
-      if (grid->locateWidget(v, r, c, rs, cs)) {
-        _layout->addViewItem(v, r, c, rs, cs);
-      } else {
-        qDebug() << "ooops, viewItem does not fit in layout" << endl;
-      }
-    }
-  }
-
-  if (qobject_cast<LayoutBoxItem*>(_item)) {
-    _layout->setMargin((_item->sizeOfGrip() / 2.0));
-    _layout->setSpacing((_item->sizeOfGrip() / 2.0));
-    QObject::connect(_layout, SIGNAL(enabledChanged(bool)),
-                     _item, SLOT(setEnabled(bool)));
-  }
-
-  _layout->applyAxis();
-  _item->parentView()->undoStack()->push(this);
-}
-
 void AppendLayoutCommand::undo() {
   Q_ASSERT(_layout);
   _layout->reset();
--- branches/work/kst/portto4/kst/src/libkstapp/viewitem.h #907829:907830
@@ -300,22 +300,6 @@
     QPointer<ViewGridLayout> _layout;
 };
 
-class KST_EXPORT SharedAxisCommand : public ViewItemCommand
-{
-  public:
-    SharedAxisCommand(ViewItem *item)
-        : ViewItemCommand(item, QObject::tr("Share Axis"), false) {}
-
-    virtual ~SharedAxisCommand() {}
-
-    virtual void undo();
-    virtual void redo();
-    void createLayout(int columns = 0);
-
-  private:
-    QPointer<ViewGridLayout> _layout;
-};
-
 class KST_EXPORT AppendLayoutCommand : public ViewItemCommand
 {
   public:


More information about the Kst mailing list