📄 gradientview.cpp
字号:
/**************************************************************************\ * * This file is part of the Coin 3D visualization library. * Copyright (C) 1998-2003 by Systems in Motion. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * ("GPL") version 2 as published by the Free Software Foundation. * See the file LICENSE.GPL at the root directory of this source * distribution for additional information about the GNU GPL. * * For using Coin with software that can not be combined with the GNU * GPL, and for taking advantage of the additional benefits of our * support services, please contact Systems in Motion about acquiring * a Coin Professional Edition License. * * See <URL:http://www.coin3d.org> for more information. * * Systems in Motion, Teknobyen, Abels Gate 5, 7030 Trondheim, NORWAY. * <URL:http://www.sim.no>. *\**************************************************************************//*! \class GradientView GradientView.h \brief The GradientView class wraps a Gradient in UI controls. \ingroup components Provides visualization of and controls on a Gradient object. The UI controls makes it possible to change the color values of the underlying gradient.*/// FIXME: I wonder if this shouldn't rather just have been a class for// displaying a gradient, and the actual UI controls better be placed// in the GradientEditor class. Discuss with frodo. 20031008 mortene.// *************************************************************************#include <stdlib.h>#include <assert.h>#include "../qtsupport.h"#include <qimage.h>#include <qpixmap.h>#include <qpainter.h>#include <qcolordialog.h>#include <qlayout.h>#include <qlabel.h>#include <qstatusbar.h>#include <qevent.h>#include "Gradient.h"#include "GradientView.h"#include "TickMark.h"#include "ImageItem.h"#include "moc_GradientView.icc"// *************************************************************************GradientView::GradientView(QCanvas * c, const Gradient & g, QWidget * parent, const char * name, Qt::WFlags f) : QCanvasView(c, parent, name, f){ this->canvas = c; this->canvas->resize(this->sizeHint().width(), this->sizeHint().height()); this->setMinimumHeight(75); this->setMaximumHeight(100); this->grad = g; this->graditem = NULL; this->selectionmarker = NULL; this->currenttick = -1; this->menu = NULL; this->segmentidx = 0; this->mousepressed = FALSE; this->min = 0; this->max = 255; QVBoxLayout * topLayout = new QVBoxLayout(this, 0); topLayout->setAlignment(Qt::AlignBottom); this->statusbar = new QStatusBar(this); this->statusbar->setSizeGripEnabled(FALSE); this->selectionmarker = new ImageItem(this->canvas); this->graditem = new ImageItem(this->canvas); this->graditem->show(); topLayout->addWidget(this->statusbar); connect(this, SIGNAL(viewChanged()), this, SLOT(updateView())); connect(this, SIGNAL(ticksChanged()), this, SLOT(updateTicks())); this->viewport()->setMouseTracking(TRUE); this->updateTicks(); emit this->viewChanged();}GradientView::~GradientView(){ delete this->graditem; delete this->selectionmarker; delete this->canvas; delete this->menu;}QSizeGradientView::sizeHint() const{ return QSize(450, 75);}voidGradientView::viewportResizeEvent(QResizeEvent * e){ this->canvas->resize(e->size().width(), e->size().height()); this->updateTicks(); emit this->viewChanged();}voidGradientView::updateView(void){ const int width = this->canvas->width(); const int height = this->canvas->height(); int h = this->statusbar->height(); const QImage gradImage = this->grad.getImage(width, height-10-h, 32); this->graditem->setImage(gradImage); // FIXME: tell the graditem to redraw all of itself // not just those parts that have been touched by another item // in a more elegant way. 20030910 frodo this->graditem->setVisible(FALSE); this->graditem->setVisible(TRUE); if (this->segmentidx != -1) { const int selectstart = (int) (this->tickmarks[this->segmentidx]->x()); const int selectend = (int) (this->tickmarks[this->segmentidx + 1]->x()); QImage selectedimage(selectend - selectstart, 10, 32); selectedimage.fill(QColor(100,100,245).rgb()); this->selectionmarker->setImage(selectedimage); this->selectionmarker->move(selectstart, height-10-h); this->selectionmarker->setZ(2); this->selectionmarker->show(); } else { this->selectionmarker->hide(); } this->canvas->update();}voidGradientView::contentsMousePressEvent(QMouseEvent * e){ QPoint p = inverseWorldMatrix().map(e->pos()); switch (e->button()) { case Qt::LeftButton: { this->mousepressed = TRUE; this->unselectAll(); this->currenttick = -1; this->segmentidx = -1; const unsigned int nrticks = this->tickmarks.size(); for (unsigned int idx = 0; idx < nrticks; idx++) { if (this->tickmarks[idx]->x() < p.x()) { this->segmentidx++; } // We don't want it to be possible to pick up the invisible // first and last (left and right border) tickmarks. if (idx == 0) continue; if (idx == nrticks - 1) continue; if (this->tickmarks[idx]->hit(p)) { this->moving_start = p; this->currenttick = idx; this->segmentidx = -1; this->tickmarks[idx]->setBrush(Qt::blue); break; // only one tick mark should be selected (and blue) at a time } } emit this->viewChanged(); } break; case Qt::RightButton: if ((this->currenttick != -1) || (this->segmentidx != -1)) { this->buildMenu(); if (this->menu->exec(e->globalPos())) { // FIXME: this seems unnecessary. 20031008 mortene. delete this->menu; this->menu = NULL; } } break; default: // do nothing break; }}voidGradientView::contentsMouseReleaseEvent(QMouseEvent * e){ this->mousepressed = FALSE;}voidGradientView::contentsMouseMoveEvent(QMouseEvent * e){ if (this->mousepressed) { if (this->currenttick == -1) { return; } QPoint p = inverseWorldMatrix().map(e->pos()); int x = p.x(); assert(this->currenttick > 0); assert(this->currenttick < (int)(this->tickmarks.size() - 1)); TickMark * left = this->tickmarks[this->currenttick - 1]; TickMark * current = this->tickmarks[this->currenttick]; TickMark * right = this->tickmarks[this->currenttick + 1]; const int movex = x - this->moving_start.x(); const int newpos = (int) (current->x() + movex); if ((newpos >= left->x()) && newpos <= right->x()) { current->moveBy(movex, 0); this->moving_start = QPoint(x, p.y()); const float t = current->getPos(); this->grad.moveTick(this->currenttick, t); const float value = t * (this->max - this->min) + 0.5f; QString s; s.sprintf("Color table index: %d", (int)(value + 0.5f)); this->statusbar->message(s); emit this->viewChanged(); } } else { QPoint p = inverseWorldMatrix().map(e->pos()); float t = (float)p.x() / (float)this->canvas->width(); // this test should not be necessary, however the mouse coordinates from // the mouse event can sometimes be out of bounds, i.e. they can sometimes // be smaller than 0 or larger than canvas.width or canvas.height. if ((t >= 0.0f) && (t <= 1.0f)) { QRgb col = this->grad.eval(t); QString s; s.sprintf("RGBA: 0x%02x%02x%02x%02x", qRed(col), qGreen(col), qBlue(col), qAlpha(col)); this->statusbar->message(s); } }}voidGradientView::unselectAll(void){ QValueList<TickMark*>::Iterator it = this->tickmarks.begin();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -