Index: ADVGraphModel.cpp =================================================================== --- ADVGraphModel.cpp (revision 1951) +++ ADVGraphModel.cpp (working copy) @@ -24,12 +24,12 @@ #include "GraphSettingsDialog.h" #include "WindowStepSelectorWidget.h" #include "SaveGraphCutoffsDialogController.h" - #include namespace U2 { -GSequenceGraphData::GSequenceGraphData(const QString& _graphName) : graphName(_graphName), ga(NULL) +GSequenceGraphData::GSequenceGraphData(const QString& _graphName) : graphName(_graphName), ga(NULL), +movingLabel(-1, QRect(-1,-1,-1,-1), "") { cachedFrom = cachedLen = cachedW = cachedS = 0;; } @@ -141,11 +141,16 @@ const QString GSequenceGraphDrawer::DEFAULT_COLOR(tr("Default color")); const int GSequenceGraphDrawer::UNKNOWN_VAL = -1; - GSequenceGraphDrawer::GSequenceGraphDrawer(GSequenceGraphView* v, const GSequenceGraphWindowData& wd, - QMap colors) -: QObject(v), view(v), lineColors(colors), wdata(wd) + QMap colors) +: QObject(v), view(v), lineColors(colors), wdata(wd), sLabelUpdating(true), mLabelUpdating(false) { + connect(v, SIGNAL(si_frameRangeChanged()), + this, SLOT(sl_frameRangeChanged())); + connect(v, SIGNAL(si_labelAdded()), + this, SLOT(sl_labelAdded())); + connect(v, SIGNAL(si_labelMoved()), + this, SLOT(sl_labelMoved())); defFont = new QFont("Arial", 8); if (colors.isEmpty()) { lineColors.insert(DEFAULT_COLOR, Qt::black); @@ -160,10 +165,15 @@ globalMin = 0; globalMax = 0; + labelPos = rect.right(); foreach (GSequenceGraphData* graph, graphs) { drawGraph(p, graph, rect); } + + foreach (GSequenceGraphData* graph, graphs) { + drawStaticLabels(p, graph, rect); + } { //draw min/max @@ -181,8 +191,22 @@ p.drawLine(rect.bottomLeft(), rect.bottomRight()); QRect minTextRect(rect.x(), rect.bottom()-12, rect.width(), 12); p.drawText(minTextRect, Qt::AlignRight, QString::number((double) globalMin, 'g', 4)); - } + } + sLabelUpdating = false; + mLabelUpdating = false; } +void GSequenceGraphDrawer::sl_frameRangeChanged() +{ + sLabelUpdating = true; +} +void GSequenceGraphDrawer::sl_labelAdded() +{ + sLabelUpdating = true; +} +void GSequenceGraphDrawer::sl_labelMoved() +{ + mLabelUpdating = true; +} void GSequenceGraphDrawer::drawGraph( QPainter& p, GSequenceGraphData* d, const QRect& rect ) @@ -204,17 +228,24 @@ globalMin = min; globalMax = max; + QBrush usualBrush(lineColors.value(DEFAULT_COLOR)); + QBrush marqueeBrush(Qt::darkGray); QPen graphPen(Qt::SolidLine); if (lineColors.contains(d->graphName)) { graphPen.setColor(lineColors.value(d->graphName)); + usualBrush.setColor(lineColors.value(d->graphName)); } else { graphPen.setColor(lineColors.value(DEFAULT_COLOR)); } + d->graphLabels.setLabelPainter(usualBrush, marqueeBrush); + graphPen.setWidth(1); p.setPen(graphPen); + drawMovingLabels(p, d, rect, points); + int graphHeight = rect.bottom() - rect.top() - 2; float kh = (min == max) ? 1 : graphHeight / (max - min); @@ -263,7 +294,6 @@ float fy, fy2; int prevFY = -1; bool rp = false, lp = false; - int ymid = rect.bottom() - 1 - qRound((fymid - min) * kh); if(!points.useIntervals){ for (int i=0, n = points.firstPoints.size(); i < n; i++) { fy = points.firstPoints[i]; @@ -361,10 +391,108 @@ } } +} +const int mLabelCoordY = 2; +void GSequenceGraphDrawer::drawStaticLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect) +{ + if(sLabelUpdating) { + updateStaticLabels(p, d, rect); + } + QBrush backgroundBrush(Qt::yellow); + QBrush oldbackgroundBrush = p.background(); + p.setBackground(backgroundBrush); + p.setBackgroundMode(Qt::OpaqueMode); + + foreach (BasicLabel* label, d->graphLabels.labels) { + d->graphLabels.drawLabel(&p, label); + } + + p.setBackgroundMode(Qt::OpaqueMode); + p.setBackground(oldbackgroundBrush); } +void GSequenceGraphDrawer::updateStaticLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect) +{ + int nPoints = rect.width(); + PairVector points; + calculatePoints(d, points, globalMin, globalMax, nPoints); + qint64 sequenceLength = view->getSequenceLength(); + foreach (BasicLabel* label, d->graphLabels.labels) { + int position = label->getPosition() * nPoints / sequenceLength; + if(0 > position || position >= nPoints) { + continue; + } + calculateLabelData(rect, points, label); + int x = label->getCoord().x(); + int y = label->getCoord().y(); + QRectF bRect = p.boundingRect( QRect(0, 0, 10, 10), label->getHintText()); + label->setHintRect(QRect(x - bRect.width()/2, y + label->getSize() + 1, x + bRect.width()/2, + y + label->getSize() + bRect.height())); + } +} + +void GSequenceGraphDrawer::drawMovingLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect, const PairVector& points) +{ + BasicLabel* movingLabel = &(d->movingLabel); + + if(mLabelUpdating) { + updateMovingLabels(p, movingLabel, rect, points); + } + + d->graphLabels.drawLabel(&p, movingLabel); +} +void GSequenceGraphDrawer::updateMovingLabels(QPainter& p, BasicLabel* movingLabel, const QRect& rect, const PairVector& points) +{ + qint64 sequenceLength = view->getSequenceLength(); + int nPoints = rect.width(); + + int position = movingLabel->getPosition() * nPoints / sequenceLength; + if(0 > position || position >= nPoints) { + return; + } + + calculateLabelData(rect, points, movingLabel); + + QRectF bRect = p.boundingRect( QRect(0, 0, 10, 10), movingLabel->getHintText()); + movingLabel->setHintRect(QRect(labelPos-bRect.width(), mLabelCoordY, labelPos, mLabelCoordY+bRect.height())); + labelPos -= bRect.width(); +} + +void GSequenceGraphDrawer::calculateLabelData(const QRect& rect, const PairVector& points, BasicLabel* label) +{ + int graphHeight = rect.bottom() - rect.top() - 2; + int nPoints = rect.width(); + float heightScalingFactor = (globalMin == globalMax) ? 1 : graphHeight / (globalMax - globalMin); + int xcoordInRect = label->getPosition() * rect.width() / view->getSequenceLength(); + float value = points.firstPoints.at(xcoordInRect); + float prevValue = value; + int prevX; + for(prevX = xcoordInRect; UNKNOWN_VAL == prevValue; prevX--) { + if(prevX <= 0) + return; + prevValue = points.firstPoints.at(prevX); + } + float nextValue = points.firstPoints.at(xcoordInRect); + int nextX; + for(nextX = xcoordInRect; UNKNOWN_VAL == nextValue; nextX++) { + if(nextX >= nPoints) + return; + nextValue = points.firstPoints.at(nextX); + } + if(prevX != nextX) + value = prevValue + (nextValue-prevValue)*(xcoordInRect - prevX)/(nextX-prevX); + + + int ycoordInRect = qRound((value - globalMin) * heightScalingFactor); + QPoint labelCoord(rect.left() + xcoordInRect, rect.bottom() - 1 - ycoordInRect); + QString text = GSequenceGraphView::tr("[%1,%2]").arg(QString::number(label->getPosition())).arg(QString::number(value)); + + label->setCoord(labelCoord); + label->setHintText(text); +} + static void align(int start, int end, int win, int step, int seqLen, int& alignedFirst, int& alignedLast) { int win2 = (win + 1) / 2; int notAlignedFirst = start - win2; @@ -485,7 +613,6 @@ points.cutoffPoints.clear(); d->ga->calculate(points.cutoffPoints, view->getSequenceObject(), U2Region(view->getVisibleRange()), &wdata); } - void GSequenceGraphDrawer::calculateWithFit(GSequenceGraphData* d, PairVector& points, int alignedFirst, int alignedLast) { int nPoints = points.firstPoints.size(); float basesPerPoint = (alignedLast - alignedFirst) / float(nPoints); @@ -584,4 +711,7 @@ } } + + + } // namespace Index: ADVGraphModel.h =================================================================== --- ADVGraphModel.h (revision 1951) +++ ADVGraphModel.h (working copy) @@ -24,6 +24,7 @@ #include #include +#include "LabelModel.h" #include #include @@ -88,7 +89,6 @@ float getGlobalMin(){return globalMin;}; float getGlobalMax(){return globalMax;}; - const GSequenceGraphWindowData& getWindowData() {return wdata;} const GSequenceGraphMinMaxCutOffData& getCutOffData() {return commdata;} const ColorMap& getColors() {return lineColors;} @@ -108,11 +108,23 @@ void calculateWithExpand(GSequenceGraphData* d, PairVector& points, int alignedStart, int alignedEnd); void calculateCutoffPoints(GSequenceGraphData* d, PairVector& points, int alignedFirst, int alignedLast); + void drawStaticLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect); + void drawMovingLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect, const PairVector& points); + void calculateLabelData(const QRect& rect, const PairVector& points, BasicLabel* label); + void updateMovingLabels(QPainter& p, BasicLabel* movingLabel, const QRect& rect, const PairVector& points); + void updateStaticLabels(QPainter& p, GSequenceGraphData* d, const QRect& rect); +protected slots: + void sl_frameRangeChanged(); + void sl_labelAdded(); + void sl_labelMoved(); protected: GSequenceGraphView* view; QFont* defFont; ColorMap lineColors; float globalMin, globalMax; + int labelPos; + bool sLabelUpdating; + bool mLabelUpdating; GSequenceGraphWindowData wdata; GSequenceGraphMinMaxCutOffData commdata; @@ -130,6 +142,9 @@ int cachedFrom, cachedLen, cachedW, cachedS; int alignedFC, alignedLC; PairVector cachedData; + + MultiLabel graphLabels; + RoundLabel movingLabel; }; @@ -148,4 +163,4 @@ } // namespace -#endif +#endif \ No newline at end of file Index: GSequenceGraphView.cpp =================================================================== --- GSequenceGraphView.cpp (revision 1951) +++ GSequenceGraphView.cpp (working copy) @@ -50,7 +50,7 @@ assert(baseView); - visualPropertiesAction = new QAction(tr("Graph settings..."), this); + visualPropertiesAction = new QAction(tr("Graph settings"), this); visualPropertiesAction->setObjectName("visual_properties_action"); connect(visualPropertiesAction, SIGNAL(triggered(bool)), SLOT(sl_onShowVisualProperties(bool))); @@ -63,6 +63,9 @@ scrollBar->setDisabled(true); renderArea = new GSequenceGraphViewRA(this); + renderArea->setMouseTracking(true); + setMouseTracking(true); + visibleRange = baseView->getVisibleRange(); setCoherentRangeView(baseView); setFrameView(baseView->getFrameView()); @@ -81,6 +84,48 @@ update(); } +void GSequenceGraphView::addLabel(int xPos) { + foreach (GSequenceGraphData* graph, graphs) + { + RoundLabel* newLabel = new RoundLabel(xPos, QRect(0,0,0,0), ""); + graph->graphLabels.addLabel(newLabel); + } + emit si_labelAdded(); +} +void GSequenceGraphView::moveLabel(int xPos) { + foreach (GSequenceGraphData* graph, graphs) + { + graph->movingLabel.setPosition(xPos); + } + emit si_labelMoved(); +} + +bool GSequenceGraphView::deleteLabel(int xPos) { + bool res = false; + foreach (GSequenceGraphData* graph, graphs) + { + foreach (BasicLabel* label, graph->graphLabels.labels) + { + if(label->selected(xPos)) + { + res = true; + graph->graphLabels.removeLabel(label); + } + } + } + return res; +} +void GSequenceGraphView::selectLabel(int xPos) +{ + foreach (GSequenceGraphData* graph, graphs) + { + foreach (BasicLabel* label, graph->graphLabels.labels) + { + label->selected(xPos); + } + } +} + void GSequenceGraphView::pack() { assert(layout() == NULL); QVBoxLayout *vLayout = new QVBoxLayout(); Index: GSequenceGraphView.h =================================================================== --- GSequenceGraphView.h (revision 1951) +++ GSequenceGraphView.h (working copy) @@ -57,7 +57,14 @@ protected: virtual void pack(); virtual void addActionsToGraphMenu(QMenu* graphMenu); + void addLabel(int xPos); + bool deleteLabel(int xPos); + void selectLabel(int xPos); + void moveLabel(int xPos); +signals: + void si_labelAdded(); + void si_labelMoved(); private slots: void sl_onShowVisualProperties(bool); void sl_onSaveGraphCutoffs(bool); Index: GSequenceLineView.cpp =================================================================== --- GSequenceLineView.cpp (revision 1951) +++ GSequenceLineView.cpp (working copy) @@ -39,7 +39,7 @@ GSequenceLineView::GSequenceLineView(QWidget* p, ADVSequenceObjectContext* _ctx) : QWidget(p), ctx(_ctx), renderArea(NULL), scrollBar(NULL), lastPressPos(-1), lastUpdateFlags(GSLV_UF_ViewResized), featureFlags(GSLV_FF_SupportsCustomRange), -frameView(NULL), coherentRangeView(NULL), ignoreMouseSelectionEvents(false) +frameView(NULL), coherentRangeView(NULL), shiftIsHeld (false) { seqLen = ctx->getSequenceLength(); setFocusPolicy(Qt::WheelFocus); @@ -149,12 +149,19 @@ void GSequenceLineView::mousePressEvent(QMouseEvent* me) { setFocus(); - + if (me->button() == Qt::RightButton) { QWidget::mousePressEvent(me); return; } + if(true == shiftIsHeld ) { + int xPos = toRenderAreaPoint(me->pos()).x(); + if(false == deleteLabel(renderArea->coordToPos(xPos))) { + addLabel(renderArea->coordToPos(xPos)); + } + } + QPoint renderAreaPos = toRenderAreaPoint(me->pos()); if (!renderArea->rect().contains(renderAreaPos)) { scrollBar->setupRepeatAction(QAbstractSlider::SliderNoAction); @@ -200,13 +207,23 @@ } void GSequenceLineView::mouseMoveEvent(QMouseEvent* me) { - if (lastPressPos == -1) { + QPoint areaPoint = toRenderAreaPoint(me->pos()); + if (renderArea->rect().contains(areaPoint)) { + if(true == shiftIsHeld ) { + selectLabel(renderArea->coordToPos(areaPoint.x())); + } + else + { + moveLabel(renderArea->coordToPos(areaPoint.x())); + } + + update(); + } + if (lastPressPos == -1) { QWidget::mouseMoveEvent(me); return; } - if (me->buttons() & Qt::LeftButton) { - QPoint areaPoint = toRenderAreaPoint(me->pos()); - + if (me->buttons() & Qt::LeftButton) { // manage scrollbar auto-scrolling if (areaPoint.x() > width()) { scrollBar->setupRepeatAction(QAbstractSlider::SliderSingleStepAdd); @@ -273,6 +290,10 @@ view->scrollBar->triggerAction(QAbstractSlider::SliderPageStepAdd); accepted = true; break; + case Qt::Key_Shift: + shiftIsHeld = true; + accepted = true; + break; } if (accepted) { e->accept(); @@ -280,6 +301,24 @@ QWidget::keyPressEvent(e); } } +void GSequenceLineView::keyReleaseEvent(QKeyEvent *e) +{ + int key = e->key(); + bool accepted = false; + switch(key) { + case Qt::Key_Shift: + selectLabel(-1); + shiftIsHeld = false; + accepted = true; + update(); + break; + } + if (accepted) { + e->accept(); + } else { + QWidget::keyReleaseEvent(e); + } +} void GSequenceLineView::setCenterPos(qint64 centerPos) { SAFE_POINT(centerPos <= seqLen && centerPos >= 0, QString("Center pos is out of sequence range! value: %1").arg(centerPos),); @@ -408,6 +447,7 @@ const U2Region& newRange = frameView->getVisibleRange(); assert(newRange.startPos >= 0 && newRange.endPos() <= ctx->getSequenceLength() && newRange.length >= 0); #endif + emit si_frameRangeChanged(); addUpdateFlags(GSLV_UF_FrameChanged); update(); } Index: GSequenceLineView.h =================================================================== --- GSequenceLineView.h (revision 1951) +++ GSequenceLineView.h (working copy) @@ -113,6 +113,7 @@ signals: void si_visibleRangeChanged(); void si_centerPosition(qint64 pos); + void si_frameRangeChanged(); protected: void resizeEvent(QResizeEvent* e); @@ -124,6 +125,7 @@ void focusInEvent(QFocusEvent* fe); void focusOutEvent(QFocusEvent* fe); void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); virtual void onVisibleRangeChanged(bool signal = true); @@ -147,6 +149,10 @@ virtual void pack(); virtual int getSingleStep() const; virtual int getPageStep() const; + virtual void addLabel(int ){} + virtual void moveLabel(int ){} + virtual bool deleteLabel(int ){return false;} + virtual void selectLabel(int ){} ADVSequenceObjectContext* ctx; GSequenceLineViewRenderArea* renderArea; @@ -163,8 +169,8 @@ // special flag setup by child classes that tells to this class do or skip // any changes to selection on mouse ops bool ignoreMouseSelectionEvents; + bool shiftIsHeld; - }; class U2VIEW_EXPORT GSequenceLineViewRenderArea : public QWidget { Index: LabelModel.cpp =================================================================== --- LabelModel.cpp (revision 0) +++ LabelModel.cpp (working copy) @@ -0,0 +1,242 @@ +/** + * UGENE - Integrated Bioinformatics Tools. + * Copyright (C) 2008-2012 UniPro + * http://ugene.unipro.ru + * + * 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 +#include +#include "LabelModel.h" +#include + +namespace U2 { + +Hint::Hint(const QRect& _boundingRect, const QString& _text) : boundingRect(_boundingRect), text(_text) +{ +} +Hint::Hint(const QString& _text) : text(_text) +{ +} + +QRect Hint::getBoundingRect() const +{ + return boundingRect; +} +void Hint::setBoundingRect(const QRect& _boundingRect) +{ + boundingRect = _boundingRect; +} +void Hint::draw(QPainter* painter) const +{ + _ASSERT(_CrtIsValidPointer(painter, sizeof(QPainter), TRUE)); + painter->drawText(boundingRect, text); +} +const QString& Hint::getText() const +{ + return text; +} +void Hint::setText(const QString& _text) +{ + text = _text; +} + + + +BasicLabel::BasicLabel(int pos, const QRect& hintRect, const QString& hintText) : + position(pos), coord(0,0), hint(hintRect, hintText) +{ +} +void BasicLabel::setCoord(const QPoint& _coord) +{ + coord = _coord; +} +void BasicLabel::setPosition(int pos) +{ + position = pos; +} +int BasicLabel::getPosition() const +{ + return position; +} +void BasicLabel::setHintText(const QString& _hintText) +{ + hint.setText(_hintText); +} +const QString& BasicLabel::getHintText() const +{ + return hint.getText(); +} +void BasicLabel::setHintRect(const QRect& _hintRect) +{ + hint.setBoundingRect(_hintRect); +} +QRect BasicLabel::getHintCoord() +{ + return hint.getBoundingRect(); +} +QPoint BasicLabel::getCoord() const +{ + return coord; +} +void BasicLabel::drawHint(QPainter* painter) const +{ + _ASSERT(_CrtIsValidPointer(painter, sizeof(QPainter), TRUE)); + hint.draw(painter); +} + + + +RoundLabel::RoundLabel(int pos, const QRect& hintRect, const QString& hintText, int _radius) + : BasicLabel(pos, hintRect, hintText), radius(_radius), marqueeFlag(false) +{ +} +bool RoundLabel::selected(const QPoint& _coord) +{ + QPoint dif = _coord - getCoord(); + if(dif.manhattanLength() <= radius) + { + return true; + } + return false; +} +bool RoundLabel::selected(int x, int y) +{ + QPoint dif(x, y); + return selected(dif); +} +bool RoundLabel::selected(int position) +{ + int dif = position - getPosition(); + if(abs(dif) <= radius) + { + marqueeFlag = true; + return true; + } + marqueeFlag = false; + return false; +} +bool RoundLabel::isSelected() const +{ + return marqueeFlag; +} +int RoundLabel::getSize() const +{ + return radius; +} +void RoundLabel::draw(QPainter* painter, const QBrush& brush) const +{ + _ASSERT(_CrtIsValidPointer(painter, sizeof(QPainter), TRUE)); + QPainterPath path; + QPoint _coord = getCoord(); + path.addEllipse(_coord.x() - radius/2, _coord.y(), radius, radius); + drawHint(painter); + painter->fillPath(path, brush); +} + + + + +Draw::Draw(): usualBrush(Qt::black), markqueeBrush(Qt::darkGray) +{ +} +Draw::Draw(const QBrush& _usualBrush, const QBrush& _markqueeBrush): + usualBrush(_usualBrush), markqueeBrush(_markqueeBrush) +{ +} + +void Draw::changeParameter(const QBrush& _usualBrush, const QBrush& _markqueeBrush) +{ + usualBrush = _usualBrush; + markqueeBrush = _markqueeBrush; +} + +void Draw::drawLabel(QPainter* _painter, BasicLabel* label) const +{ + _ASSERT(_CrtIsValidPointer(_painter, sizeof(QPainter), TRUE)); + if(true == label->isSelected()) + { + label->draw(_painter, markqueeBrush); + } + else + { + label->draw(_painter, usualBrush); + } +} + + + + +MultiLabel::MultiLabel(const QBrush& usualBrush, const QBrush& markqueeBrush): + draw(usualBrush, markqueeBrush) +{ +} +MultiLabel::~MultiLabel() +{ + foreach(BasicLabel* currentLabel, labels) + { + removeLabel(currentLabel); + } +} +void MultiLabel::setLabelPainter(const QBrush& usualBrush, const QBrush& markqueeBrush) +{ + draw.changeParameter(usualBrush, markqueeBrush); +} +void MultiLabel::addLabel(BasicLabel* pLabel) +{ + _ASSERT(_CrtIsValidPointer(pLabel, sizeof(BasicLabel), TRUE)); + labels.push_back(pLabel); +} +void MultiLabel::removeLabel(BasicLabel* pLabel) +{ + _ASSERT(_CrtIsValidPointer(pLabel, sizeof(BasicLabel), TRUE)); + delete pLabel; + labels.removeAll(pLabel); +} +const Labels& MultiLabel::getLabels() const +{ + return labels; +} +BasicLabel* MultiLabel::findLabelByCoord(const QPoint& coord) const +{ + foreach(BasicLabel* currentLabel, labels) + { + if (currentLabel->selected(coord)) + { + return currentLabel; + } + } + return NULL; +} +BasicLabel* MultiLabel::at(int i) const +{ + return labels.at(i); +} +void MultiLabel::drawLabel(QPainter* _painter, BasicLabel* label) const +{ + _ASSERT(_CrtIsValidPointer(_painter, sizeof(QPainter), TRUE)); + _ASSERT(_CrtIsValidPointer(label, sizeof(BasicLabel), TRUE)); + draw.drawLabel(_painter, label); +} +void MultiLabel::drawAllLabel(QPainter* _painter) const +{ + _ASSERT(_CrtIsValidPointer(_painter, sizeof(QPainter), TRUE)); + foreach(BasicLabel* currentLabel, labels) + { + draw.drawLabel(_painter, currentLabel); + } +} +}//namespace \ No newline at end of file Index: LabelModel.h =================================================================== --- LabelModel.h (revision 0) +++ LabelModel.h (working copy) @@ -0,0 +1,154 @@ +/** + * UGENE - Integrated Bioinformatics Tools. + * Copyright (C) 2008-2012 UniPro + * http://ugene.unipro.ru + * + * 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. + */ + +#ifndef _U2_LABEL_MODEL_H_ +#define _U2_LABEL_MODEL_H_ + +#include +#include + +namespace U2 { + +class Hint { +public: + Hint() {} + + Hint(const QRect& _boundingRect, const QString& _text); + Hint(const QString& _text); + + QRect getBoundingRect() const; + void setBoundingRect(const QRect& _boundingRect); + + const QString& getText() const; + void setText(const QString& _text); + + virtual void draw(QPainter* painter) const; + +private: + QString text; + QRect boundingRect; +}; + +class BasicLabel { +public: + + BasicLabel(int pos, const QRect& hintRect, const QString& hintText); + ~BasicLabel() {} + + virtual bool selected(const QPoint& _coord) = 0; + virtual bool selected(int x, int y) = 0; + virtual bool selected(int _position) = 0; + virtual bool isSelected() const = 0; + + virtual void draw(QPainter* painter, const QBrush& brush) const = 0; + + void setCoord(const QPoint& _coord); + QPoint getCoord() const; + + void setPosition(int pos); + int getPosition() const; + + void setHintText(const QString& _hintText); + const QString& getHintText() const; + + void setHintRect(const QRect& _hintRect); + QRect getHintCoord(); + + virtual int getSize() const = 0; + + void drawHint(QPainter* painter) const; + +private: + int position; + QPoint coord; + Hint hint; +}; + +const int defaultRadius = 7; + + +class RoundLabel: public BasicLabel{ +public: + RoundLabel(int pos, const QRect& hintRect, const QString& hintText, int _radius = defaultRadius); + + ~RoundLabel() { } + + bool selected(const QPoint& _coord); + bool selected(int x, int y); + bool selected(int position); + bool isSelected() const; + + int getSize() const; + + void draw(QPainter* painter, const QBrush& brush) const; + +private: + int radius; + bool marqueeFlag; +}; + + +class Draw +{ +public: + Draw(); + Draw(const QBrush& _brush, const QBrush& _markOutBrush); + ~Draw() {} + + void changeParameter(const QBrush& _brush, const QBrush& _markOutBrush); + + void drawLabel(QPainter* _painter, BasicLabel* label) const; + +private: + QBrush usualBrush; + QBrush markqueeBrush; +}; + +typedef QList Labels; + +class MultiLabel { +public: + MultiLabel(){} + MultiLabel(const QBrush& usualBrush, const QBrush& markqueeBrush); + ~MultiLabel(); + + void setLabelPainter(const QBrush& usualBrush, const QBrush& markqueeBrush); + + void addLabel(BasicLabel* pLabel); + void removeLabel(BasicLabel* pLabel); + + BasicLabel* findLabelByCoord(const QPoint& coord) const; + BasicLabel* at(int i) const; + + void drawLabel(QPainter* _painter, BasicLabel* pLabel) const; + void drawAllLabel(QPainter* _painter) const; + + const Labels& getLabels() const; + + Labels labels; + +private: + + Draw draw; +}; + +}//namespace +#endif \ No newline at end of file