1
// -*- mode: C++; tab-width: 2; -*-
4
// --------------------------------------------------------------------------
5
// OpenMS Mass Spectrometry Framework
6
// --------------------------------------------------------------------------
7
// Copyright (C) 2003-2011 -- Oliver Kohlbacher, Knut Reinert
9
// This library is free software; you can redistribute it and/or
10
// modify it under the terms of the GNU Lesser General Public
11
// License as published by the Free Software Foundation; either
12
// version 2.1 of the License, or (at your option) any later version.
14
// This library is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
// Lesser General Public License for more details.
19
// You should have received a copy of the GNU Lesser General Public
20
// License along with this library; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
// --------------------------------------------------------------------------
24
// $Maintainer: Timo Sachsenberg $
25
// $Authors: Timo Sachsenberg $
26
// --------------------------------------------------------------------------
28
#include <OpenMS/VISUAL/AxisPainter.h>
29
#include <OpenMS/MATH/MISC/MathFunctions.h>
37
void AxisPainter::paint(QPainter* painter, QPaintEvent*, const DoubleReal& min, const DoubleReal& max, const GridVector& grid,
38
const Int width, const Int height, const AxisPainter::Alignment alignment, const UInt margin,
39
bool show_legend, String legend, bool shorten_number,
40
bool is_log, bool is_inverse_orientation)
42
// position of the widget
43
bool horizontal_alignment = (alignment == BOTTOM || alignment == TOP);
45
// spacing between ticks and text
46
const UInt tick_spacing = 4;
48
// determine paintable area without margin
51
w = (horizontal_alignment) ? w - margin : w;
52
h = (horizontal_alignment) ? h : h - margin;
58
painter->drawLine(0, 0, w-1, 0);
61
painter->drawLine(0, h-1, w-1, h-1);
64
painter->drawLine(w-1, 0 , w-1, h-1);
67
painter->drawLine(0, 0 , 0, h-1);
71
// shrink font size if text does not fit
72
UInt font_size = painter->font().pointSize();
75
if (grid.size() >= 1) //check big intervals only
77
QFontMetrics metrics(QFont(painter->font().family(), font_size));
78
for (Size i = 0; i < grid[0].size(); i++)
83
getShortenedNumber_(tmp, scale_(grid[0][i], is_log));
86
tmp = QString("%1").arg(scale_(grid[0][i], is_log));
88
QRect rect = metrics.boundingRect(tmp);
89
max_width = std::max(max_width,(UInt)rect.width());
93
//shrink font if too much text it displayed
94
UInt overall_required_pixels = 0;
95
if (horizontal_alignment)
98
for (Size i=0; i<grid.size(); i++)
100
tick_count += grid[i].size();
102
overall_required_pixels = (UInt)(max_width*tick_count);
104
else // Shrink font if the largest text is too big
106
overall_required_pixels = UInt(max_width + 0.25*font_size + tick_spacing);
109
if (w < overall_required_pixels)
111
font_size = UInt(font_size * w / overall_required_pixels);
114
// Painting tick levels
115
for (Size i = 0; i != grid.size(); i++)
117
// Just draw text on big intervalls
125
QFontMetrics metrics(painter->font());
127
if (i == 0) // big intervals
129
painter->setFont(QFont(painter->font().family(), UInt(font_size)));
130
metrics = QFontMetrics(painter->font());
131
tick_size = UInt(0.33 * font_size);
132
text_color = QColor(0, 0, 0);
134
else // small intervals
136
painter->setFont(QFont(painter->font().family(), UInt(0.8*font_size)));
137
metrics = QFontMetrics(painter->font());
138
tick_size = UInt(0.25 * font_size);
139
text_color = QColor(20, 20, 20);
142
// painting all ticks of the level
143
UInt i_beg = (horizontal_alignment)? 0 : h;
144
UInt i_end = (horizontal_alignment)? w : 0;
145
for (Size j = 0; j != grid[i].size(); j++)
148
if (is_inverse_orientation)
150
tick_pos = UInt(intervalTransformation(grid[i][j], min, max, i_end, i_beg)) + ((alignment==LEFT || alignment==RIGHT)?-1:1)*margin;
154
tick_pos = UInt(intervalTransformation(grid[i][j], min, max, i_beg, i_end));
158
painter->setPen(QPen(Qt::black));
162
painter->drawLine(tick_pos, 0, tick_pos, tick_size);
165
painter->drawLine(tick_pos, h, tick_pos, h-tick_size);
168
painter->drawLine(w-tick_size, tick_pos+margin, w, tick_pos+margin);
171
painter->drawLine(0, tick_pos+margin, tick_size, tick_pos+margin);
175
// values at axis lines
177
// count number of grid lines
179
for (GridVector::const_iterator it = grid.begin(); it != grid.end(); ++it)
181
gl_count += it->size();
183
// if there are too many grid lines, hide every odd minor grid line value
184
if (gl_count >= 30 && i == 1)
186
// needed because skips occur in small grid lines at the position of big grid lines
187
DoubleReal dist_small = std::min<DoubleReal>(fabs(grid[1][1] - grid[1][0]), fabs(grid[1][2] - grid[1][1]));
188
UInt n = Math::round((grid[1][j] - grid[0][0]) / dist_small);
198
getShortenedNumber_(text, scale_(grid[i][j], is_log));
201
text = QString("%1").arg(scale_(grid[i][j], is_log));
204
painter->setPen(QPen(text_color));
206
// get bounding rectangle for text we want to layout
207
QRect textbound = metrics.boundingRect(text);
209
// Calculate text position
215
x_pos = tick_pos - UInt(0.5*textbound.width());
218
x_pos = w - (tick_size + tick_spacing) - textbound.width();
221
x_pos = tick_size + tick_spacing;
229
y_pos = tick_size + tick_spacing + UInt(0.5*textbound.height());
232
y_pos = h - (tick_size + tick_spacing);
236
y_pos = tick_pos + margin + UInt(0.25*textbound.height());
239
painter->drawText(x_pos, y_pos, text);
244
if (show_legend && legend != "")
247
painter->setPen(QPen(Qt::black));
252
painter->drawText(0, 0 , w, h, Qt::AlignBottom|Qt::AlignHCenter, legend.c_str());
255
painter->drawText(0, 0 , w, h, Qt::AlignTop|Qt::AlignHCenter, legend.c_str());
258
painter->rotate(270);
259
painter->drawText(-(int)h, 0 ,h ,w, Qt::AlignHCenter|Qt::AlignTop, legend.c_str());
262
painter->rotate(270);
263
painter->drawText(-(int)h, 0 ,h ,w, Qt::AlignHCenter|Qt::AlignBottom, legend.c_str());
269
void AxisPainter::getShortenedNumber_(QString& short_num, DoubleReal number)
273
short_num = QString("%1").arg(number);
275
else if (number < 1000000.0)
277
short_num = QString("%1k").arg(Math::roundDecimal(number/1000.0, -2));
279
else if (number < 1000000000.0)
281
short_num = QString("%1M").arg(number/1000000.0);
285
short_num = QString("%1G").arg(number/1000000000.0);
289
DoubleReal AxisPainter::scale_(DoubleReal x, bool is_log)
291
return (is_log) ? Math::roundDecimal(pow(10,x),-8) : Math::roundDecimal(x,-8);