--- /dev/null
+// SUPERV SUPERVGUI : GUI for Supervisor component
+//
+// Copyright (C) 2003 CEA/DEN, EDF R&D
+//
+//
+//
+// File : SUPERVGUI_CanvasView.cxx
+// Author : Natalia KOPNOVA
+// Module : SUPERV
+
+using namespace std;
+#include "SUPERVGUI_CanvasView.h"
+#include "SUPERVGUI_Main.h"
+#include "SUPERVGUI_CanvasNode.h"
+#include "SUPERVGUI_CanvasPort.h"
+#include "SUPERVGUI_CanvasLink.h"
+#include "SUPERVGUI_CanvasNodePrs.h"
+#include "QAD_Config.h"
+
+#include <qpixmap.h>
+#include <qcolordialog.h>
+
+#define MARGIN 2
+
+
+/* XPM */
+const char* imageZoomCursor[] = {
+"32 32 3 1",
+". c None",
+"a c #000000",
+"# c #ffffff",
+"................................",
+"................................",
+".#######........................",
+"..aaaaaaa.......................",
+"................................",
+".............#####..............",
+"...........##.aaaa##............",
+"..........#.aa.....a#...........",
+".........#.a.........#..........",
+".........#a..........#a.........",
+"........#.a...........#.........",
+"........#a............#a........",
+"........#a............#a........",
+"........#a............#a........",
+"........#a............#a........",
+".........#...........#.a........",
+".........#a..........#a.........",
+".........##.........#.a.........",
+"........#####.....##.a..........",
+".......###aaa#####.aa...........",
+"......###aa...aaaaa.......#.....",
+".....###aa................#a....",
+"....###aa.................#a....",
+"...###aa...............#######..",
+"....#aa.................aa#aaaa.",
+".....a....................#a....",
+"..........................#a....",
+"...........................a....",
+"................................",
+"................................",
+"................................",
+"................................"};
+
+QPixmap zoomPix(imageZoomCursor);
+QCursor zoom2Cursor(zoomPix);
+
+#if QT_VERSION >= 0x030005
+QCursor pan2Cursor(Qt::SizeAllCursor);
+#else
+QCursor pan2Cursor(SizeAllCursor);
+#endif
+
+SUPERVGUI_CanvasView::SUPERVGUI_CanvasView(SUPERVGUI_Canvas* theCanvas, SUPERVGUI_Main* theMain):
+ QCanvasView(theCanvas, theMain),
+ myMain(theMain), myCurrentItem(0), myHilighted(0), myLinkBuilder(0)
+{
+ setName("CanvasView");
+
+ myIsPanActivated = false;
+ myIsZoomActivated = false;
+ myIsLinkCreating = false;
+
+ myAddStudyItem = 0;
+ myCursor = cursor();
+
+ myTimer = new QTimer(this);
+ connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
+
+ myPopup = new QPopupMenu(viewport());
+
+ if (myMain->isEditable()) {
+ myPopup->insertItem(tr("MSG_ADD_NODE"), myMain, SLOT(addNode()));
+ myPopup->insertItem(tr("MSG_INS_FILE"), myMain, SLOT(insertFile()));
+ myPopup->insertSeparator();
+ }
+
+ QPopupMenu* aViewPopup = new QPopupMenu(viewport());
+ // aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showFullGraph()));
+ aViewPopup->insertItem(tr("POP_FULLVIEW"), myMain, SLOT(showCanvas()));
+ aViewPopup->insertItem(tr("POP_CONTROLVIEW"), myMain, SLOT(showContolFlow()));
+ aViewPopup->insertItem(tr("POP_TABLEVIEW"), myMain, SLOT(showTable()));
+ // aViewPopup->insertItem("Previous Full View", myMain, SLOT(showFullGraph()));
+ // aViewPopup->insertItem(tr("POP_CANVASVIEW"), myMain, SLOT(showCanvas()));
+
+ myPopup->insertItem(tr("POP_VIEW"), aViewPopup);
+ myPopup->insertSeparator();
+
+ QPopupMenu* aZoomPopup = new QPopupMenu(viewport());
+ aZoomPopup->insertItem("200%", this, SLOT(zoomIn()));
+ aZoomPopup->insertItem("100%", this, SLOT(zoomReset()));
+ aZoomPopup->insertItem("50%", this, SLOT(zoomOut()));
+ aZoomPopup->insertSeparator();
+ aZoomPopup->insertItem("Fit All", this, SLOT(fitAll()));
+
+ myPopup->insertItem("Zoom", aZoomPopup);
+ myPopup->insertSeparator();
+
+ myAddStudyItem = myPopup->insertItem(tr("MSG_ADD_STUDY"), this, SLOT(addToStudy()));
+ myPopup->insertItem(tr("MSG_CHANGE_INFO"), myMain, SLOT(changeInformation()));
+ myPopup->insertSeparator();
+
+ myPopup->insertItem(tr("MSG_COPY_DATAFLOW"), myMain, SLOT(copy()));
+ myPopup->insertItem(tr("MSG_FILTER_NOTIFY"), myMain, SLOT(filterNotification()));
+
+ myPopup->insertSeparator();
+ myPopup->insertItem(tr("MSG_CHANGE_BACKGROUND"), this, SLOT(changeBackground()));
+
+ viewport()->setMouseTracking(true);
+
+ //create sketching popup menu
+ mySketchPopup = new QPopupMenu(viewport());
+ mySketchPopup->setCheckable(true);
+ myDelPntItem = mySketchPopup->insertItem(tr("MSG_DEL_LAST_PNT"), this, SLOT(deletePoint()));
+ mySketchPopup->insertItem(tr("MSG_DEL_LINK"), this, SLOT(cancelSketch()));
+ myOrtoItem = mySketchPopup->insertItem(tr("MSG_ORTHO_LINE"), this, SLOT(setOrthoMode()));
+}
+
+
+SUPERVGUI_CanvasView::~SUPERVGUI_CanvasView()
+{
+}
+
+void SUPERVGUI_CanvasView::contentsMousePressEvent(QMouseEvent* theEvent)
+{
+ // cout << "===> SUPERVGUI_CanvasView::contentsMousePressEvent(...) " << endl;
+ myPoint = inverseWorldMatrix().map(theEvent->pos());
+ myGlobalPoint = theEvent->globalPos();
+ myCurrentItem = 0;
+
+ // compute collision rectangle
+ QRect aSel(myPoint.x()-MARGIN, myPoint.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
+
+ if (((theEvent->button() == Qt::MidButton) &&
+ (theEvent->state() == Qt::ControlButton)) ||
+ myIsPanActivated) {
+ myIsPanActivated = true;
+ myCursor = cursor();
+ setCursor(pan2Cursor);
+ return;
+ }
+
+ if (((theEvent->button() == Qt::LeftButton) &&
+ (theEvent->state() == Qt::ControlButton)) ||
+ myIsZoomActivated) {
+ myIsZoomActivated = true;
+ myCursor = cursor();
+ setCursor(zoom2Cursor);
+ return;
+ }
+
+ if ( theEvent->button() == Qt::RightButton) {
+ if (myIsLinkCreating) {
+ myMain->showPopup(mySketchPopup, theEvent);
+ return;
+ }
+
+ QCanvasItemList l = canvas()->collisions(aSel);
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+ SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
+ QObject* anObj = aNodePrs->getObject(myPoint);
+ if (anObj->inherits("SUPERVGUI_CanvasNode")) {
+ myMain->showPopup(((SUPERVGUI_CanvasNode*)anObj)->getPopupMenu(viewport()),
+ theEvent);
+ return;
+ }
+ else if (anObj->inherits("SUPERVGUI_CanvasPort")) {
+ myMain->showPopup(((SUPERVGUI_CanvasPort*)anObj)->getPopupMenu(viewport()),
+ theEvent);
+ return;
+ }
+ }
+ if (myMain->isEditable() && !myMain->getCanvas()->isControlView()) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
+ SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
+ aPrs->getLink()->setSelectedObject(aPrs, myPoint);
+ myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
+ return;
+ }
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
+ SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
+ aPrs->getLink()->setSelectedObject(aPrs, myPoint);
+ myMain->showPopup(aPrs->getLink()->getPopupMenu(viewport()), theEvent);
+ return;
+ }
+ }
+ }
+
+ myPopup->setItemEnabled(myAddStudyItem, !myMain->isFromStudy());
+ myMain->showPopup(myPopup, theEvent);
+ return;
+ }
+
+ if (theEvent->button() == Qt::LeftButton) {
+ QCanvasItemList l = canvas()->collisions(myPoint);
+ if (myIsLinkCreating) {
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+ SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
+ QObject* anObj = aNodePrs->getObject(myPoint);
+ if (anObj->inherits("SUPERVGUI_CanvasPort")) {
+ endSketch((SUPERVGUI_CanvasPort*)anObj);
+ return;
+ }
+ else {
+ myCurrentItem = *it;
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
+ return;
+ }
+ }
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Hook) {
+ SUPERVGUI_CanvasHookPrs* aHookPrs = (SUPERVGUI_CanvasHookPrs*) (*it);
+ QObject* anObj = aHookPrs->getObject();
+ if (anObj->inherits("SUPERVGUI_CanvasPort")) {
+ endSketch((SUPERVGUI_CanvasPort*)anObj);
+ return;
+ }
+ }
+ }
+ if (myLinkBuilder) {
+ myLinkBuilder->addNextPoint(myPoint, mySketchPopup->isItemChecked(myOrtoItem));
+ canvas()->update();
+ mySketchPopup->setItemEnabled(myDelPntItem, true);
+ return;
+ }
+ }
+
+// if (myMain->isEditable()) { // allow to move nodes and link point on imported graph
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+ myCurrentItem = *it;
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(2);
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(true);
+ return;
+ }
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
+ SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
+ if (aPrs->getIndex() > 0) {
+ myCurrentItem = *it;
+ aPrs->setMoving(true);
+ return;
+ }
+ }
+ }
+// }
+ }
+}
+
+bool busy = false;
+
+void SUPERVGUI_CanvasView::contentsMouseMoveEvent(QMouseEvent* theEvent)
+{
+ if (busy) return;
+
+ busy = true;
+ QPoint p = inverseWorldMatrix().map(theEvent->pos());
+ QPoint g = theEvent->globalPos();
+
+ if (myTimer->isActive()) myTimer->stop();
+
+ if (myIsLinkCreating && myLinkBuilder) {
+ myLinkBuilder->setFloatPoint(p);
+ canvas()->update();
+ }
+
+ if (myCurrentItem) {
+ // setHilighted(0);
+ double cx = myCurrentItem->x() - myPoint.x();
+ double cy = myCurrentItem->y() - myPoint.y();
+ if (p.x()+cx < 0) p.setX(-(int)cx);
+ if (p.y()+cy < 0) p.setY(-(int)cy);
+ myCurrentItem->moveBy(p.x() - myPoint.x(),
+ p.y() - myPoint.y());
+ myPoint = p;
+ canvas()->update();
+
+ // scroll contents if mouse is outside
+ QRect r(contentsX(), contentsY(), visibleWidth(), visibleHeight());
+ if (!r.contains(theEvent->pos())) {
+ int dx = 0, dy = 0;
+ if (theEvent->pos().x() < r.left()) dx = theEvent->pos().x() - r.left();
+ if (theEvent->pos().x() > r.right()) dx = theEvent->pos().x() - r.right();
+ if (theEvent->pos().y() < r.top()) dy = theEvent->pos().y() - r.top();
+ if (theEvent->pos().y() > r.bottom()) dy = theEvent->pos().y() - r.bottom();
+ scrollBy(dx, dy);
+ // start timer to scroll in silent mode
+ myDX = dx; myDY = dy;
+ myTimer->start(100);
+ }
+ busy = false;
+ return;
+ }
+
+ if (myIsPanActivated) {
+ setHilighted(0);
+ scrollBy(myGlobalPoint.x() - g.x(),
+ myGlobalPoint.y() - g.y());
+ myGlobalPoint = g;
+ busy = false;
+ return;
+ }
+
+ if (myIsZoomActivated) {
+ setHilighted(0);
+ double dx = g.x() - myGlobalPoint.x();
+ double s = 1. + fabs(dx)/10.;
+ if (dx < 0) s = 1./s;
+
+ QWMatrix m = worldMatrix();
+ m.scale(s, s);
+ setWorldMatrix(m);
+
+ myGlobalPoint = g;
+ busy = false;
+ return;
+ }
+
+ if (!myIsLinkCreating && myMain->isEditable() &&
+ !myMain->getCanvas()->isControlView()) {
+ // compute collision rectangle
+ QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
+ QCanvasItemList l = canvas()->collisions(aSel);
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
+ SUPERVGUI_CanvasPointPrs* aPrs = (SUPERVGUI_CanvasPointPrs*) (*it);
+ setHilighted(aPrs->getLink());
+ busy = false;
+ return;
+ }
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_LinkEdge) {
+ SUPERVGUI_CanvasEdgePrs* aPrs = (SUPERVGUI_CanvasEdgePrs*) (*it);
+ setHilighted(aPrs->getLink());
+ busy = false;
+ return;
+ }
+ }
+ setHilighted(0);
+ }
+
+ busy = false;
+}
+
+void SUPERVGUI_CanvasView::contentsMouseReleaseEvent(QMouseEvent* theEvent)
+{
+ // cout << "===> SUPERVGUI_CanvasView::contentsMouseReleaseEvent(...) " << endl;
+ if (myTimer->isActive()) myTimer->stop();
+
+ if (myCurrentItem) {
+ if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setZ(0);
+ ((SUPERVGUI_CanvasNodePrs*)myCurrentItem)->setMoving(false);
+ canvas()->update();
+ }
+ if (myCurrentItem->rtti() == SUPERVGUI_Canvas::Rtti_LinkPoint) {
+ ((SUPERVGUI_CanvasPointPrs*)myCurrentItem)->setMoving(false);
+ }
+ }
+ myCurrentItem = 0;
+
+ if (myIsPanActivated) {
+ myIsPanActivated = false;
+ setCursor(myCursor);
+ }
+
+ if (myIsZoomActivated) {
+ myIsZoomActivated = false;
+ setCursor(myCursor);
+ }
+}
+
+void SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(QMouseEvent* theEvent)
+{
+ // cout << "===> SUPERVGUI_CanvasView::contentsMouseDoubleClickEvent(...) " << endl;
+ QPoint p = inverseWorldMatrix().map(theEvent->pos());
+
+ // compute collision rectangle
+ QRect aSel(p.x()-MARGIN, p.y()-MARGIN, 1+2*MARGIN, 1+2*MARGIN);
+
+ if (theEvent->button() == Qt::LeftButton) {
+ QCanvasItemList l = canvas()->collisions(p);
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ((*it)->rtti() == SUPERVGUI_Canvas::Rtti_Node) {
+ SUPERVGUI_CanvasNodePrs* aNodePrs = (SUPERVGUI_CanvasNodePrs*) (*it);
+ SUPERVGUI_CanvasNode* aNode = aNodePrs->getNode();
+ if (aNode->getEngine()->IsMacro() && !myIsLinkCreating) {
+ myMain->openSubGraph(aNode->getEngine(), true);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void SUPERVGUI_CanvasView::onDestroyed(QObject* theObject)
+{
+ if (theObject == myHilighted)
+ myHilighted = 0;
+}
+
+void SUPERVGUI_CanvasView::setHilighted(SUPERVGUI_CanvasLink* theLink)
+{
+ if (theLink == myHilighted) return;
+ if (myHilighted) {
+ disconnect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
+ myHilighted->setHilighted(false);
+ myHilighted = 0;
+ }
+ if (theLink) {
+ myHilighted = theLink;
+ myHilighted->setHilighted(true);
+ connect(myHilighted, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
+ }
+}
+
+void SUPERVGUI_CanvasView::onTimeout()
+{
+ if (myCurrentItem) {
+ scrollBy(myDX, myDY);
+
+ double cx, cy;
+ inverseWorldMatrix().map((double)myDX, (double)myDY, &cx, &cy);
+ if (myCurrentItem->x()+cx < 0) cx = -myCurrentItem->x();
+ if (myCurrentItem->y()+cy < 0) cy = -myCurrentItem->y();
+ myCurrentItem->moveBy(cx, cy);
+ myPoint.setX(myPoint.x()+(int)cx);
+ myPoint.setY(myPoint.y()+(int)cy);
+ canvas()->update();
+ }
+}
+
+void SUPERVGUI_CanvasView::changeBackground()
+{
+ QColor aColor = QColorDialog::getColor(canvas()->backgroundColor(), this );
+ if ( aColor.isValid() ) {
+ canvas()->setBackgroundColor(aColor);
+ setPaletteBackgroundColor(aColor.light(120));
+ }
+}
+
+void SUPERVGUI_CanvasView::ActivatePanning()
+{
+ myIsPanActivated = true;
+}
+
+void SUPERVGUI_CanvasView::ResetView()
+{
+ setContentsPos(0,0);
+ QWMatrix m;
+ setWorldMatrix(m);
+}
+
+void SUPERVGUI_CanvasView::startSketch(SUPERVGUI_CanvasPort* thePort)
+{
+ if (myIsLinkCreating) return;
+
+ myIsLinkCreating = true;
+ myLinkBuilder = new SUPERVGUI_CanvasLinkBuilder(canvas(), myMain, thePort);
+ mySketchPopup->setItemEnabled(myDelPntItem, false);
+}
+
+void SUPERVGUI_CanvasView::endSketch(SUPERVGUI_CanvasPort* thePort)
+{
+ // cout << "===> SUPERVGUI_CanvasView::endSketch(" << thePort->name() << ")" << endl;
+ if (!myIsLinkCreating) return;
+
+ if (myLinkBuilder && myLinkBuilder->canCreateEngine(thePort)) {
+ bool input = thePort->getEngine()->IsInput();
+ SUPERV_Link aLinkEngine;
+ if (thePort->getEngine()->Kind() == SUPERV::DataStreamParameter) {
+ SUPERVGUI_CanvasStreamPortIn* aInPort = (SUPERVGUI_CanvasStreamPortIn*)
+ (input ? thePort : myLinkBuilder->getStartPort());
+ SUPERVGUI_CanvasStreamPortOut* aOutPort = (SUPERVGUI_CanvasStreamPortOut*)
+ (input ? myLinkBuilder->getStartPort() : thePort);
+// aLinkEngine = myMain->getDataflow()->StreamLink(aOutPort->getStreamEngine(),
+// aInPort->getStreamEngine());
+ if (myMain->getDataflow()->IsStreamGraph()) {
+ SUPERV_StreamGraph aSGraph = myMain->getDataflow()->ToStreamGraph();
+ if (!SUPERV_isNull(aSGraph))
+ aLinkEngine = aSGraph->StreamLink(aOutPort->getStreamEngine(),
+ aInPort->getStreamEngine());
+ }
+ }
+ else {
+ SUPERVGUI_CanvasPort* aInPort = (input ? thePort : myLinkBuilder->getStartPort());
+ SUPERVGUI_CanvasPort* aOutPort = (input ? myLinkBuilder->getStartPort() : thePort);
+ aLinkEngine = myMain->getDataflow()->Link(aOutPort->getEngine(), aInPort->getEngine());
+ }
+ if (SUPERV_isNull(aLinkEngine)) return;
+
+ myLinkBuilder->setCoords(aLinkEngine.in());
+
+ delete myLinkBuilder;
+ myLinkBuilder = 0;
+
+ SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(canvas(), myMain, aLinkEngine);
+ aLink->show();
+
+ canvas()->update();
+ myIsLinkCreating = false;
+ }
+}
+
+void SUPERVGUI_CanvasView::cancelSketch()
+{
+ if (myLinkBuilder) {
+ delete myLinkBuilder;
+ myLinkBuilder = 0;
+ canvas()->update();
+ }
+ myIsLinkCreating = false;
+}
+
+void SUPERVGUI_CanvasView::deletePoint()
+{
+ if (myIsLinkCreating && myLinkBuilder) {
+ myLinkBuilder->removeLastPoint();
+ canvas()->update();
+ mySketchPopup->setItemEnabled(myDelPntItem, myLinkBuilder->getPointCount());
+ }
+}
+
+void SUPERVGUI_CanvasView::setOrthoMode()
+{
+ bool aIsOrtho = !mySketchPopup->isItemChecked(myOrtoItem);
+ mySketchPopup->setItemChecked(myOrtoItem, aIsOrtho);
+}
+
+
+void SUPERVGUI_CanvasView::addToStudy()
+{
+ if (myMain->addStudy()) myMain->setAsFromStudy(true);
+}
+
+void SUPERVGUI_CanvasView::zoomIn()
+{
+ QWMatrix m;
+ m.scale(2.0, 2.0);
+ setWorldMatrix(m);
+ canvas()->update();
+}
+
+void SUPERVGUI_CanvasView::zoomReset()
+{
+ QWMatrix m;
+ m.scale(1.0, 1.0);
+ setWorldMatrix(m);
+ canvas()->update();
+}
+
+void SUPERVGUI_CanvasView::zoomOut()
+{
+ QWMatrix m;
+ m.scale(0.5, 0.5);
+ setWorldMatrix(m);
+ canvas()->update();
+}
+
+void SUPERVGUI_CanvasView::fitAll()
+{
+ int w = 0, h = 0;
+ QCanvasItemList l = canvas()->allItems();
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ QRect r = (*it)->boundingRect();
+ if (w < r.right()) w = r.right();
+ if (h < r.bottom()) h = r.bottom();
+ }
+ w += GRAPH_MARGIN; h += GRAPH_MARGIN;
+ double s = ((double)visibleWidth())/((double)w);
+ double s1 = ((double)visibleHeight())/((double)h);
+ if (s > s1) s = s1;
+
+ setContentsPos(0,0);
+ QWMatrix m;
+ m.scale(s, s);
+ setWorldMatrix(m);
+ canvas()->update();
+}