1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "RowHeightController.h"
23
24 #include "U2Core/U2SafePoints.h"
25
26 #include "ScrollController.h"
27 #include "ov_msa/MaCollapseModel.h"
28 #include "ov_msa/MaEditor.h"
29 #include "ov_msa/view_rendering/MaEditorWgt.h"
30
31 namespace U2 {
32
RowHeightController(MaEditorWgt * maEditorWgt)33 RowHeightController::RowHeightController(MaEditorWgt *maEditorWgt)
34 : QObject(maEditorWgt),
35 ui(maEditorWgt) {
36 }
37
getGlobalYPositionByMaRowIndex(int maRowIndex) const38 int RowHeightController::getGlobalYPositionByMaRowIndex(int maRowIndex) const {
39 const MaCollapseModel *collapseModel = ui->getEditor()->getCollapseModel();
40 int viewRowIndex = collapseModel->getViewRowIndexByMaRowIndex(maRowIndex);
41 int offset = 0;
42 for (int viewRow = 0; viewRow < viewRowIndex; viewRow++) {
43 int maRow = collapseModel->getMaRowIndexByViewRowIndex(viewRow);
44 offset += getRowHeightByMaIndex(maRow);
45 }
46 return offset;
47 }
48
getGlobalYPositionByMaRowIndex(int maRowIndex,const QList<int> & maRowIndexes) const49 int RowHeightController::getGlobalYPositionByMaRowIndex(int maRowIndex, const QList<int> &maRowIndexes) const {
50 int offset = 0;
51 foreach (int currentIndex, maRowIndexes) {
52 if (currentIndex == maRowIndex) {
53 return offset;
54 }
55 offset += getRowHeightByMaIndex(currentIndex);
56 }
57 FAIL(false, 0);
58 }
59
getGlobalYPositionOfTheFirstVisibleRow(bool countClipped) const60 int RowHeightController::getGlobalYPositionOfTheFirstVisibleRow(bool countClipped) const {
61 return getGlobalYPositionByMaRowIndex(ui->getScrollController()->getFirstVisibleMaRowIndex(countClipped));
62 }
63
getScreenYPositionOfTheFirstVisibleRow(bool countClipped) const64 int RowHeightController::getScreenYPositionOfTheFirstVisibleRow(bool countClipped) const {
65 const int globalYPositionOfTheFirstVisibleRow = getGlobalYPositionOfTheFirstVisibleRow(countClipped);
66 return globalYPositionOfTheFirstVisibleRow - ui->getScrollController()->getScreenPosition().y();
67 }
68
getRowHeightByViewRowIndex(int viewRowIndex) const69 int RowHeightController::getRowHeightByViewRowIndex(int viewRowIndex) const {
70 int maRowIndex = ui->getEditor()->getCollapseModel()->getMaRowIndexByViewRowIndex(viewRowIndex);
71 return getRowHeightByMaIndex(maRowIndex);
72 }
73
getSumOfRowHeightsByMaIndexes(const QList<int> & maRowIndexes) const74 int RowHeightController::getSumOfRowHeightsByMaIndexes(const QList<int> &maRowIndexes) const {
75 int sumHeight = 0;
76 foreach (int maRowIndex, maRowIndexes) {
77 sumHeight += getRowHeightByMaIndex(maRowIndex);
78 }
79 return sumHeight;
80 }
81
getTotalAlignmentHeight() const82 int RowHeightController::getTotalAlignmentHeight() const {
83 int viewRowCount = ui->getEditor()->getCollapseModel()->getViewRowCount();
84 U2Region globalYRegion = getGlobalYRegionByViewRowsRegion(U2Region(0, viewRowCount));
85 return static_cast<int>(globalYRegion.length);
86 }
87
getSingleRowHeight() const88 int RowHeightController::getSingleRowHeight() const {
89 const int fontHeight = QFontMetrics(ui->getEditor()->getFont(), ui).height();
90 const float zoomMult = ui->getEditor()->zoomMult;
91 return qRound(fontHeight * zoomMult);
92 }
93
getMaRowIndexByGlobalYPosition(int y) const94 int RowHeightController::getMaRowIndexByGlobalYPosition(int y) const {
95 int viewRowIndex = getViewRowIndexByGlobalYPosition(y);
96 return ui->getEditor()->getCollapseModel()->getMaRowIndexByViewRowIndex(viewRowIndex);
97 }
98
getViewRowIndexByGlobalYPosition(int y) const99 int RowHeightController::getViewRowIndexByGlobalYPosition(int y) const {
100 const int viewRowCount = ui->getEditor()->getCollapseModel()->getViewRowCount();
101 int accumulatedHeight = 0;
102 for (int viewRowIndex = 0; viewRowIndex < viewRowCount; viewRowIndex++) {
103 const int rowHeight = getRowHeightByViewRowIndex(viewRowIndex);
104 if (accumulatedHeight + rowHeight <= y) {
105 accumulatedHeight += rowHeight;
106 } else {
107 return viewRowIndex;
108 }
109 }
110 return -1;
111 }
112
getViewRowIndexByScreenYPosition(int y) const113 int RowHeightController::getViewRowIndexByScreenYPosition(int y) const {
114 return getViewRowIndexByGlobalYPosition(y + ui->getScrollController()->getScreenPosition().y());
115 }
116
getGlobalYRegionByMaRowIndex(int maRowIndex) const117 U2Region RowHeightController::getGlobalYRegionByMaRowIndex(int maRowIndex) const {
118 int globalYPosition = getGlobalYPositionByMaRowIndex(maRowIndex);
119 int rowHeight = getRowHeightByMaIndex(maRowIndex);
120 return U2Region(globalYPosition, rowHeight);
121 }
122
getGlobalYRegionByMaRowIndex(int maRowIndex,const QList<int> & maRowIndexes) const123 U2Region RowHeightController::getGlobalYRegionByMaRowIndex(int maRowIndex, const QList<int> &maRowIndexes) const {
124 int globalYPosition = getGlobalYPositionByMaRowIndex(maRowIndex, maRowIndexes);
125 int rowHeight = getRowHeightByMaIndex(maRowIndex);
126 return U2Region(globalYPosition, rowHeight);
127 }
128
129 // The OUT_OF_RANGE_OFFSET used to build safe coordinates out of the view.
130 // We can't use 0 offset, because the value will overlap with the first or the last row.
131 //
132 // GUI tests notice: GUI tests call RowHeightController to compute initial mouse positioning for overflows.
133 // In this case the offset must be big enough to skip rubber band.
134 #define OUT_OF_RANGE_OFFSET 5
135
getGlobalYRegionByViewRowIndex(int viewRowIndex) const136 U2Region RowHeightController::getGlobalYRegionByViewRowIndex(int viewRowIndex) const {
137 MaCollapseModel *collapseModel = ui->getEditor()->getCollapseModel();
138 if (collapseModel->getViewRowCount() == 0) { // empty alignment.
139 return U2Region(-OUT_OF_RANGE_OFFSET, 0);
140 }
141 int viewRowCount = collapseModel->getViewRowCount();
142 // Return an empty region after the view for viewRowIndexes > maxRows
143 // and a region before the view for viewRowIndex < 0. Use OUT_OF_RANGE_OFFSET for the out of range regions.
144 if (viewRowIndex < 0) {
145 U2Region startOfView = getGlobalYRegionByViewRowIndex(0);
146 return U2Region(startOfView.startPos - OUT_OF_RANGE_OFFSET, 0);
147 } else if (viewRowIndex >= viewRowCount) {
148 U2Region endOfView = getGlobalYRegionByViewRowIndex(viewRowCount - 1);
149 return U2Region(endOfView.endPos() + OUT_OF_RANGE_OFFSET, 0);
150 }
151 int maRow = collapseModel->getMaRowIndexByViewRowIndex(viewRowIndex);
152 return getGlobalYRegionByMaRowIndex(maRow);
153 }
154
getGlobalYRegionByViewRowsRegion(const U2Region & viewRowsRegion) const155 U2Region RowHeightController::getGlobalYRegionByViewRowsRegion(const U2Region &viewRowsRegion) const {
156 U2Region startPosRegion = getGlobalYRegionByViewRowIndex(viewRowsRegion.startPos);
157 U2Region endPosRegion = getGlobalYRegionByViewRowIndex(viewRowsRegion.endPos() - 1);
158 return U2Region::containingRegion(startPosRegion, endPosRegion);
159 }
160
getScreenYRegionByViewRowsRegion(const U2Region & viewRowsRegion) const161 U2Region RowHeightController::getScreenYRegionByViewRowsRegion(const U2Region &viewRowsRegion) const {
162 U2Region startPosRegion = getScreenYRegionByViewRowIndex(viewRowsRegion.startPos);
163 U2Region endPosRegion = getScreenYRegionByViewRowIndex(viewRowsRegion.endPos() - 1);
164 return U2Region::containingRegion(startPosRegion, endPosRegion);
165 }
166
getScreenYRegionByMaRowIndex(int maRowIndex) const167 U2Region RowHeightController::getScreenYRegionByMaRowIndex(int maRowIndex) const {
168 return getScreenYRegionByMaRowIndex(maRowIndex, ui->getScrollController()->getScreenPosition().y());
169 }
170
getScreenYRegionByMaRowIndex(int maRowIndex,int screenYOrigin) const171 U2Region RowHeightController::getScreenYRegionByMaRowIndex(int maRowIndex, int screenYOrigin) const {
172 U2Region rowRange = getGlobalYRegionByMaRowIndex(maRowIndex);
173 return U2Region(rowRange.startPos - screenYOrigin, rowRange.length);
174 }
175
mapGlobalToScreen(const U2Region & globalRegion) const176 U2Region RowHeightController::mapGlobalToScreen(const U2Region &globalRegion) const {
177 int screenYOrigin = ui->getScrollController()->getScreenPosition().y();
178 return U2Region(globalRegion.startPos - screenYOrigin, globalRegion.length);
179 }
180
getScreenYRegionByViewRowIndex(int viewRowIndex) const181 U2Region RowHeightController::getScreenYRegionByViewRowIndex(int viewRowIndex) const {
182 return mapGlobalToScreen(getGlobalYRegionByViewRowIndex(viewRowIndex));
183 }
184
185 } // namespace U2
186