summaryrefslogtreecommitdiffstats
path: root/krita/ui/kobirdeyepanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'krita/ui/kobirdeyepanel.cpp')
-rw-r--r--krita/ui/kobirdeyepanel.cpp619
1 files changed, 619 insertions, 0 deletions
diff --git a/krita/ui/kobirdeyepanel.cpp b/krita/ui/kobirdeyepanel.cpp
new file mode 100644
index 00000000..fda95945
--- /dev/null
+++ b/krita/ui/kobirdeyepanel.cpp
@@ -0,0 +1,619 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qslider.h>
+#include <qcursor.h>
+
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <kaction.h>
+#include <ktoolbar.h>
+#include <knuminput.h>
+#include <klocale.h>
+
+#include <KoDocument.h>
+
+#include "wdgbirdeye.h"
+#include "kobirdeyepanel.h"
+#include "kis_int_spinbox.h"
+
+KoCanvasAdapter::KoCanvasAdapter() {}
+KoCanvasAdapter::~KoCanvasAdapter() {}
+
+KoZoomAdapter::KoZoomAdapter() {}
+KoZoomAdapter::~KoZoomAdapter() {}
+
+KoThumbnailAdapter::KoThumbnailAdapter() {}
+KoThumbnailAdapter::~KoThumbnailAdapter() {}
+
+KoBirdEyePanel::KoBirdEyePanel( KoZoomAdapter * zoomListener,
+ KoThumbnailAdapter * thumbnailProvider,
+ KoCanvasAdapter * canvas,
+ QWidget * parent,
+ const char * name,
+ WFlags f)
+ : QWidget(parent, name, f)
+ , m_zoomListener(zoomListener)
+ , m_thumbnailProvider(thumbnailProvider)
+ , m_canvas(canvas)
+ , m_dragging(false)
+{
+ QHBoxLayout * l = new QHBoxLayout(this);
+ m_page = new WdgBirdEye(this);
+ m_page->zoom->setRange((int) (QMAX(1, 100 * zoomListener->getMinZoom())), (int) (100 * zoomListener->getMaxZoom()));
+ m_page->zoom->setValue(100);
+ m_page->zoom->setSuffix("%");
+
+ m_page->toolbar->setIconSize(16);
+ m_page->view->installEventFilter(this);
+ m_page->view->setBackgroundMode(Qt::NoBackground);
+
+ m_zoomIn = new KAction( i18n("Zoom In"), "birdeye_zoom_plus", 0, this, SLOT(zoomPlus()), this, "zoomIn" );
+ m_zoomOut = new KAction( i18n("Zoom Out"), "birdeye_zoom_minus", 0, this, SLOT(zoomMinus()), this, "zoomOut" );
+
+ l->addWidget(m_page);
+
+ connect(m_page->zoom, SIGNAL(valueChanged(int)), SLOT(zoomValueChanged(int)));
+ connect(m_page->bn100, SIGNAL(clicked()), SLOT(zoom100()));
+ connect(m_page->slZoom, SIGNAL(valueChanged(int)), SLOT(sliderChanged( int )));
+}
+
+KoBirdEyePanel::~KoBirdEyePanel()
+{
+ delete m_canvas;
+ delete m_thumbnailProvider;
+ delete m_zoomListener;
+}
+
+void KoBirdEyePanel::setZoom(int zoom)
+{
+ m_page->zoom->blockSignals(true);
+ m_page->slZoom->blockSignals(true);
+
+ m_page->zoom->setValue(zoom);
+
+ if (zoom < 10) {
+ m_page->slZoom->setValue(0);
+ }
+ else if (zoom > 10 && zoom < 100) {
+ m_page->slZoom->setValue(zoom / 10);
+ }
+ else if (zoom >= 100 && zoom < 150) {
+ m_page->slZoom->setValue(10);
+ }
+ else if (zoom >= 150 && zoom < 250) {
+ m_page->slZoom->setValue(11);
+ }
+ else if (zoom >= 250 && zoom < 350) {
+ m_page->slZoom->setValue(12);
+ }
+ else if (zoom >= 350 && zoom < 450) {
+ m_page->slZoom->setValue(13);
+ }
+ else if (zoom >= 450 && zoom < 550) {
+ m_page->slZoom->setValue(14);
+ }
+ else if (zoom >= 550 && zoom < 650) {
+ m_page->slZoom->setValue(15);
+ }
+ else if (zoom >= 650 && zoom < 875) {
+ m_page->slZoom->setValue(16);
+ }
+ else if (zoom >= 875 && zoom < 1150) {
+ m_page->slZoom->setValue(17);
+ }
+ else if (zoom >= 1150 && zoom < 1450) {
+ m_page->slZoom->setValue(18);
+ }
+ else if (zoom >= 1450) {
+ m_page->slZoom->setValue(19);
+ }
+
+
+ m_page->zoom->blockSignals(false);
+ m_page->slZoom->blockSignals(false);
+
+
+}
+
+void KoBirdEyePanel::zoomValueChanged(int zoom)
+{
+ KoPoint center;
+ center = m_canvas->visibleArea().center();
+ m_zoomListener->zoomTo(center.x(), center.y(), zoom / 100.0);
+ setZoom(zoom);
+}
+
+void KoBirdEyePanel::zoom100()
+{
+ zoomValueChanged( 100 );
+}
+
+void KoBirdEyePanel::sliderChanged( int v )
+{
+ if (v < 10) {
+ zoomValueChanged((v + 1) * 10);
+ }
+ else {
+ switch(v) {
+ case 10:
+ zoomValueChanged(100);
+ break;
+ case 11:
+ zoomValueChanged(200);
+ break;
+ case 12:
+ zoomValueChanged(300);
+ case 13:
+ zoomValueChanged(400);
+ break;
+ case 14:
+ zoomValueChanged(500);
+ break;
+ case 15:
+ zoomValueChanged(600);
+ break;
+ case 16:
+ zoomValueChanged(750);
+ break;
+ case 17:
+ zoomValueChanged(1000);
+ break;
+ case 18:
+ zoomValueChanged(1300);
+ break;
+ case 19:
+ zoomValueChanged(1600);
+ break;
+ }
+ }
+}
+
+void KoBirdEyePanel::cursorPosChanged(Q_INT32 xpos, Q_INT32 ypos)
+{
+ m_page->txtX->setText(QString("%L1").arg(xpos, 5));
+ m_page->txtY->setText(QString("%L1").arg(ypos, 5));
+}
+
+void KoBirdEyePanel::setThumbnailProvider(KoThumbnailAdapter * thumbnailProvider)
+{
+ delete m_thumbnailProvider;
+ m_thumbnailProvider = thumbnailProvider;
+}
+
+void KoBirdEyePanel::slotViewTransformationChanged()
+{
+ updateVisibleArea();
+ renderView();
+ m_page->view->update();
+ setZoom(qRound(m_canvas->zoomFactor() * 100));
+}
+
+void KoBirdEyePanel::slotUpdate(const QRect & r)
+{
+ QRect updateRect = r;
+
+ if (m_thumbnailProvider->pixelSize() != m_documentSize) {
+ m_documentSize = m_thumbnailProvider->pixelSize();
+ fitThumbnailToView();
+ updateRect = QRect(0, 0, m_documentSize.width(), m_documentSize.height());
+ }
+
+ updateRect &= QRect(0, 0, m_documentSize.width(), m_documentSize.height());
+
+ if (!updateRect.isEmpty() && !m_documentSize.isEmpty()) {
+
+ QRect thumbnailRect = documentToThumbnail(KoRect::fromQRect(updateRect));
+
+ if (!thumbnailRect.isEmpty()) {
+
+ QImage thumbnailImage = m_thumbnailProvider->image(thumbnailRect, m_thumbnail.size());
+
+ if (!thumbnailImage.isNull()) {
+
+ Q_ASSERT(thumbnailImage.size() == thumbnailRect.size());
+
+ QPainter painter(&m_thumbnail);
+
+ painter.fillRect(thumbnailRect, colorGroup().mid());
+ painter.drawImage(thumbnailRect.x(), thumbnailRect.y(), thumbnailImage);
+ }
+ }
+ }
+
+ renderView();
+ m_page->view->update();
+}
+
+QRect KoBirdEyePanel::documentToThumbnail(const KoRect& docRect)
+{
+ if (docRect.isEmpty() || m_documentSize.isEmpty() || m_thumbnail.isNull()) {
+ return QRect();
+ }
+
+ Q_INT32 thumbnailLeft = static_cast<Q_INT32>((docRect.left() * m_thumbnail.width()) / m_documentSize.width());
+ Q_INT32 thumbnailRight = static_cast<Q_INT32>(((docRect.right() + 1) * m_thumbnail.width()) / m_documentSize.width());
+ Q_INT32 thumbnailTop = static_cast<Q_INT32>((docRect.top() * m_thumbnail.height()) / m_documentSize.height());
+ Q_INT32 thumbnailBottom = static_cast<Q_INT32>(((docRect.bottom() + 1) * m_thumbnail.height()) / m_documentSize.height());
+
+ QRect thumbnailRect(thumbnailLeft, thumbnailTop, thumbnailRight - thumbnailLeft + 1, thumbnailBottom - thumbnailTop + 1);
+ thumbnailRect &= m_thumbnail.rect();
+
+ return thumbnailRect;
+}
+
+KoRect KoBirdEyePanel::thumbnailToDocument(const QRect& thumbnailRect)
+{
+ if (thumbnailRect.isEmpty() || m_documentSize.isEmpty() || m_thumbnail.isNull()) {
+ return KoRect();
+ }
+
+ double docLeft = (static_cast<double>(thumbnailRect.left()) * m_documentSize.width()) / m_thumbnail.width();
+ double docRight = (static_cast<double>(thumbnailRect.right() + 1) * m_documentSize.width()) / m_thumbnail.width();
+ double docTop = (static_cast<double>(thumbnailRect.top()) * m_documentSize.height()) / m_thumbnail.height();
+ double docBottom = (static_cast<double>(thumbnailRect.bottom() + 1) * m_documentSize.height()) / m_thumbnail.height();
+
+ KoRect docRect(docLeft, docTop, docRight - docLeft + 1, docBottom - docTop + 1);
+ docRect &= KoRect(0, 0, m_documentSize.width(), m_documentSize.height());
+
+ return docRect;
+}
+
+QPoint KoBirdEyePanel::viewToThumbnail(const QPoint& viewPoint)
+{
+ int thumbnailX = (m_viewBuffer.width() - m_thumbnail.width()) / 2;
+ int thumbnailY = (m_viewBuffer.height() - m_thumbnail.height()) / 2;
+
+ return QPoint(viewPoint.x() - thumbnailX, viewPoint.y() - thumbnailY);
+}
+
+
+void KoBirdEyePanel::zoomMinus()
+{
+}
+
+void KoBirdEyePanel::zoomPlus()
+{
+}
+
+void KoBirdEyePanel::updateVisibleArea()
+{
+ m_visibleAreaInThumbnail = documentToThumbnail(m_canvas->visibleArea());
+}
+
+
+bool KoBirdEyePanel::eventFilter(QObject* o, QEvent* ev)
+{
+ if (o == m_page->view && ev->type() == QEvent::Resize) {
+ resizeViewEvent(static_cast<QResizeEvent *>(ev)->size());
+ }
+
+ if (o == m_page->view && ev->type() == QEvent::Paint) {
+ paintViewEvent(static_cast<QPaintEvent *>(ev));
+ }
+
+ if (o == m_page->view && ev->type() == QEvent::MouseMove) {
+
+ QMouseEvent* me = (QMouseEvent*)ev;
+ QPoint thumbnailPos = viewToThumbnail(me->pos());
+
+ if (m_dragging) {
+ handleMouseMoveAction(thumbnailPos);
+ } else {
+ handleMouseMove(thumbnailPos);
+ }
+
+ return true;
+ }
+
+ if (o == m_page->view && ev->type() == QEvent::MouseButtonPress) {
+
+ QMouseEvent* me = (QMouseEvent*)ev;
+ QPoint thumbnailPos = viewToThumbnail(me->pos());
+
+ if (me->button() == LeftButton) {
+ handleMousePress(thumbnailPos);
+ }
+
+ return true;
+ }
+
+ if (o == m_page->view && ev->type() == QEvent::MouseButtonRelease) {
+
+ QMouseEvent* me = (QMouseEvent*)ev;
+
+ if (me->button() == LeftButton) {
+ m_dragging = false;
+ }
+
+ return true;
+ }
+
+ return m_page->eventFilter(o, ev);
+}
+
+KoBirdEyePanel::enumDragHandle KoBirdEyePanel::dragHandleAt(QPoint p)
+{
+ QRect left = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.top()-1, 3, m_visibleAreaInThumbnail.height()+2);
+ QRect right = QRect(m_visibleAreaInThumbnail.right()-1, m_visibleAreaInThumbnail.top()-1, 3, m_visibleAreaInThumbnail.height()+2);
+ QRect top = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.top()-1, m_visibleAreaInThumbnail.width()+2, 3);
+ QRect bottom = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.bottom()-1, m_visibleAreaInThumbnail.width()+2, 3);
+
+ if (left.contains(p)) {
+ return DragHandleLeft;
+ }
+
+ if (right.contains(p)) {
+ return DragHandleRight;
+ }
+
+ if (top.contains(p)) {
+ return DragHandleTop;
+ }
+
+ if (bottom.contains(p)) {
+ return DragHandleBottom;
+ }
+
+ if (m_visibleAreaInThumbnail.contains(p)) {
+ return DragHandleCentre;
+ }
+
+ return DragHandleNone;
+}
+
+void KoBirdEyePanel::handleMouseMove(QPoint p)
+{
+ QCursor cursor;
+
+ switch (dragHandleAt(p)) {
+ case DragHandleLeft:
+ case DragHandleRight:
+ cursor = Qt::sizeHorCursor;
+ break;
+ case DragHandleTop:
+ case DragHandleBottom:
+ cursor = Qt::sizeVerCursor;
+ break;
+ case DragHandleCentre:
+ cursor = Qt::sizeAllCursor;
+ break;
+ default:
+ case DragHandleNone:
+ if (m_thumbnail.rect().contains(p)) {
+ cursor = Qt::PointingHandCursor;
+ } else {
+ cursor = Qt::arrowCursor;
+ }
+ break;
+ }
+
+ m_page->view->setCursor(cursor);
+}
+
+void KoBirdEyePanel::handleMouseMoveAction(QPoint p)
+{
+ if (m_dragging) {
+
+ Q_INT32 dx = p.x() - m_lastDragPos.x();
+ Q_INT32 dy = p.y() - m_lastDragPos.y();
+
+ m_lastDragPos = p;
+
+ QRect thumbnailRect = m_visibleAreaInThumbnail;
+
+ switch (m_dragHandle) {
+ case DragHandleLeft: {
+ thumbnailRect.setLeft(thumbnailRect.left()+dx);
+ break;
+ }
+ case DragHandleRight: {
+ thumbnailRect.setRight(thumbnailRect.right()+dx);
+ break;
+ }
+ case DragHandleTop: {
+ thumbnailRect.setTop(thumbnailRect.top()+dy);
+ break;
+ }
+ case DragHandleBottom: {
+ thumbnailRect.setBottom(thumbnailRect.bottom()+dy);
+ break;
+ }
+ case DragHandleCentre: {
+ thumbnailRect.moveBy(dx, dy);
+ break;
+ }
+ default:
+ case DragHandleNone:
+ break;
+ }
+
+ makeThumbnailRectVisible(thumbnailRect);
+ }
+}
+
+void KoBirdEyePanel::handleMousePress(QPoint p)
+{
+ if (!m_dragging) {
+
+ enumDragHandle dragHandle = dragHandleAt(p);
+
+ if (dragHandle == DragHandleNone) {
+ if (m_thumbnail.rect().contains(p)) {
+
+ // Snap visible area centre to p and begin a centre drag.
+
+ QRect thumbnailRect = m_visibleAreaInThumbnail;
+ thumbnailRect.moveCenter(p);
+ makeThumbnailRectVisible(thumbnailRect);
+
+ m_dragHandle = DragHandleCentre;
+ m_page->view->setCursor(Qt::sizeAllCursor);
+ m_dragging = true;
+ }
+ } else {
+ m_dragHandle = dragHandle;
+ m_dragging = true;
+ }
+ m_lastDragPos = p;
+ }
+}
+
+void KoBirdEyePanel::makeThumbnailRectVisible(const QRect& r)
+{
+ if (r.isEmpty()) {
+ return;
+ }
+
+ QRect thumbnailRect = r;
+
+ if (thumbnailRect.left() < m_thumbnail.rect().left()) {
+ thumbnailRect.moveLeft(m_thumbnail.rect().left());
+ }
+ if (thumbnailRect.right() > m_thumbnail.rect().right()) {
+ thumbnailRect.moveRight(m_thumbnail.rect().right());
+ }
+ if (thumbnailRect.top() < m_thumbnail.rect().top()) {
+ thumbnailRect.moveTop(m_thumbnail.rect().top());
+ }
+ if (thumbnailRect.bottom() > m_thumbnail.rect().bottom()) {
+ thumbnailRect.moveBottom(m_thumbnail.rect().bottom());
+ }
+
+ if (thumbnailRect.width() > m_thumbnail.rect().width()) {
+ thumbnailRect.setLeft(m_thumbnail.rect().left());
+ thumbnailRect.setRight(m_thumbnail.rect().right());
+ }
+ if (thumbnailRect.height() > m_thumbnail.rect().height()) {
+ thumbnailRect.setTop(m_thumbnail.rect().top());
+ thumbnailRect.setBottom(m_thumbnail.rect().bottom());
+ }
+
+ double zoomFactor = m_canvas->zoomFactor();
+
+ if (thumbnailRect.size() == m_visibleAreaInThumbnail.size()) {
+ // No change to zoom
+ } else if (thumbnailRect.width() != m_visibleAreaInThumbnail.width()) {
+
+ Q_ASSERT(thumbnailRect.height() == m_visibleAreaInThumbnail.height());
+
+ zoomFactor *= static_cast<double>(m_visibleAreaInThumbnail.width()) / thumbnailRect.width();
+ } else {
+
+ Q_ASSERT(thumbnailRect.width() == m_visibleAreaInThumbnail.width());
+
+ zoomFactor *= static_cast<double>(m_visibleAreaInThumbnail.height()) / thumbnailRect.height();
+ }
+
+ if (zoomFactor < m_zoomListener->getMinZoom()) {
+ zoomFactor = m_zoomListener->getMinZoom();
+ } else if (zoomFactor > m_zoomListener->getMaxZoom()) {
+ zoomFactor = m_zoomListener->getMaxZoom();
+ }
+
+ KoRect docRect = thumbnailToDocument(thumbnailRect);
+ m_zoomListener->zoomTo(docRect.center().x(), docRect.center().y(), zoomFactor);
+}
+
+void KoBirdEyePanel::resizeViewEvent(QSize size)
+{
+ m_viewBuffer.resize(size);
+ fitThumbnailToView();
+ slotUpdate(QRect(0, 0, m_documentSize.width(), m_documentSize.height()));
+}
+
+void KoBirdEyePanel::fitThumbnailToView()
+{
+ QRect docRect = QRect(0, 0, m_thumbnailProvider->pixelSize().width(), m_thumbnailProvider->pixelSize().height());
+ Q_INT32 thumbnailWidth;
+ Q_INT32 thumbnailHeight;
+
+ if (docRect.isEmpty()) {
+ thumbnailWidth = 0;
+ thumbnailHeight = 0;
+ } else {
+ const int thumbnailBorderPixels = 4;
+
+ double xScale = double(m_page->view->contentsRect().width() - thumbnailBorderPixels) / docRect.width();
+ double yScale = double(m_page->view->contentsRect().height() - thumbnailBorderPixels) / docRect.height();
+
+ if (xScale < yScale) {
+ thumbnailWidth = m_page->view->contentsRect().width() - thumbnailBorderPixels;
+ thumbnailHeight = Q_INT32(ceil(docRect.height() * xScale));
+ } else {
+ thumbnailWidth = Q_INT32(ceil(docRect.width() * yScale));
+ thumbnailHeight = m_page->view->contentsRect().height() - thumbnailBorderPixels;
+ }
+ }
+
+ m_thumbnail.resize(thumbnailWidth, thumbnailHeight);
+ updateVisibleArea();
+}
+
+void KoBirdEyePanel::renderView()
+{
+ Q_ASSERT(!m_viewBuffer.isNull());
+
+ if (!m_viewBuffer.isNull()) {
+
+ updateVisibleArea();
+
+ QPainter painter(&m_viewBuffer);
+
+ painter.fillRect(0, 0, m_viewBuffer.width(), m_viewBuffer.height(), colorGroup().mid());
+
+ if (!m_thumbnail.isNull()) {
+
+ int thumbnailX = (m_viewBuffer.width() - m_thumbnail.width()) / 2;
+ int thumbnailY = (m_viewBuffer.height() - m_thumbnail.height()) / 2;
+
+ painter.drawPixmap(thumbnailX, thumbnailY, m_thumbnail);
+
+ painter.setPen(Qt::red);
+ painter.drawRect(thumbnailX + m_visibleAreaInThumbnail.x() - 1,
+ thumbnailY + m_visibleAreaInThumbnail.y() - 1,
+ m_visibleAreaInThumbnail.width() + 2,
+ m_visibleAreaInThumbnail.height() + 2);
+ painter.setPen(Qt::red.light());
+ painter.drawRect(thumbnailX + m_visibleAreaInThumbnail.x() - 2,
+ thumbnailY + m_visibleAreaInThumbnail.y() - 2,
+ m_visibleAreaInThumbnail.width() + 4,
+ m_visibleAreaInThumbnail.height() + 4);
+ }
+ }
+}
+
+void KoBirdEyePanel::paintViewEvent(QPaintEvent *e)
+{
+ Q_ASSERT(!m_viewBuffer.isNull());
+
+ if (!m_viewBuffer.isNull()) {
+ bitBlt(m_page->view, e->rect().x(), e->rect().y(), &m_viewBuffer,
+ e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
+ }
+}
+
+#include "kobirdeyepanel.moc"