comparison view/Pane.cpp @ 174:96b8a790730a

* Wire up the Panner widget in the pane, and do some tidying in Pane
author Chris Cannam
date Thu, 19 Oct 2006 13:05:39 +0000
parents 9c40dc10c88c
children 42118892f428
comparison
equal deleted inserted replaced
173:9c40dc10c88c 174:96b8a790730a
95 95
96 m_vpan = new Panner; 96 m_vpan = new Panner;
97 layout->addWidget(m_vpan, 0, 1); 97 layout->addWidget(m_vpan, 0, 1);
98 m_vpan->setFixedWidth(12); 98 m_vpan->setFixedWidth(12);
99 m_vpan->setFixedHeight(70); 99 m_vpan->setFixedHeight(70);
100 // m_vpan->setRectExtents(0.1, 0.1, 0.4, 0.4); 100 m_vpan->setAlpha(80, 130);
101 connect(m_vpan, SIGNAL(rectExtentsChanged(float, float, float, float)),
102 this, SLOT(verticalPannerMoved(float, float, float, float)));
101 103
102 m_vthumb = new Thumbwheel(Qt::Vertical); 104 m_vthumb = new Thumbwheel(Qt::Vertical);
103 layout->addWidget(m_vthumb, 0, 2); 105 layout->addWidget(m_vthumb, 0, 2);
104 m_vthumb->setFixedWidth(16); 106 m_vthumb->setFixedWidth(16);
105 m_vthumb->setFixedHeight(70); 107 m_vthumb->setFixedHeight(70);
192 << m_vthumb->getValue() << std::endl; 194 << m_vthumb->getValue() << std::endl;
193 195
194 } 196 }
195 } 197 }
196 198
199 updateVerticalPanner();
200
197 if (m_manager && m_manager->getZoomWheelsEnabled() && 201 if (m_manager && m_manager->getZoomWheelsEnabled() &&
198 width() > 120 && height() > 100) { 202 width() > 120 && height() > 100) {
199 if (!m_headsUpDisplay->isVisible()) { 203 if (!m_headsUpDisplay->isVisible()) {
200 m_headsUpDisplay->show(); 204 m_headsUpDisplay->show();
201 connect(m_manager, SIGNAL(zoomLevelChanged()), 205 connect(m_manager, SIGNAL(zoomLevelChanged()),
210 m_headsUpDisplay->hide(); 214 m_headsUpDisplay->hide();
211 if (m_manager) { 215 if (m_manager) {
212 disconnect(m_manager, SIGNAL(zoomLevelChanged()), 216 disconnect(m_manager, SIGNAL(zoomLevelChanged()),
213 this, SLOT(zoomLevelChanged())); 217 this, SLOT(zoomLevelChanged()));
214 } 218 }
219 }
220 }
221
222 void
223 Pane::updateVerticalPanner()
224 {
225 if (!m_vpan || !m_manager || !m_manager->getZoomWheelsEnabled()) return;
226
227 float vmin, vmax, dmin, dmax;
228 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax) && vmax != vmin) {
229 float y0 = (dmin - vmin) / (vmax - vmin);
230 float y1 = (dmax - vmin) / (vmax - vmin);
231 m_vpan->blockSignals(true);
232 m_vpan->setRectExtents(0, 1.0 - y1, 1, y1 - y0);
233 m_vpan->blockSignals(false);
234 m_vpan->show();
235 } else {
236 m_vpan->hide();
215 } 237 }
216 } 238 }
217 239
218 bool 240 bool
219 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) const 241 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) const
661 if (x > rx - fuzz) closeToRightEdge = true; 683 if (x > rx - fuzz) closeToRightEdge = true;
662 684
663 return selection; 685 return selection;
664 } 686 }
665 687
688 bool
689 Pane::canTopLayerMoveVertical()
690 {
691 float vmin, vmax, dmin, dmax;
692 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return false;
693 if (dmin <= vmin && dmax >= vmax) return false;
694 return true;
695 }
696
697 bool
698 Pane::getTopLayerDisplayExtents(float &vmin, float &vmax,
699 float &dmin, float &dmax)
700 {
701 Layer *layer = 0;
702 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
703 if (!layer) return false;
704 bool vlog;
705 QString vunit;
706 return (layer->getValueExtents(vmin, vmax, vlog, vunit) &&
707 layer->getDisplayExtents(dmin, dmax));
708 }
709
710 bool
711 Pane::setTopLayerDisplayExtents(float dmin, float dmax)
712 {
713 Layer *layer = 0;
714 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
715 if (!layer) return false;
716 return layer->setDisplayExtents(dmin, dmax);
717 }
718
666 void 719 void
667 Pane::mousePressEvent(QMouseEvent *e) 720 Pane::mousePressEvent(QMouseEvent *e)
668 { 721 {
669 if (e->buttons() & Qt::RightButton) { 722 if (e->buttons() & Qt::RightButton) {
670 emit rightButtonMenuRequested(mapToGlobal(e->pos())); 723 emit rightButtonMenuRequested(mapToGlobal(e->pos()));
690 setCursor(Qt::PointingHandCursor); 743 setCursor(Qt::PointingHandCursor);
691 } 744 }
692 745
693 m_navigating = true; 746 m_navigating = true;
694 m_dragCentreFrame = m_centreFrame; 747 m_dragCentreFrame = m_centreFrame;
695
696 //!!! pull out into function to go with mouse move code
697
698 m_dragStartMinValue = 0; 748 m_dragStartMinValue = 0;
699 749
700 Layer *layer = 0; 750 float vmin, vmax, dmin, dmax;
701 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1); 751 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
702 752 m_dragStartMinValue = dmin;
703 if (layer) {
704 float min = 0.f, max = 0.f;
705 if (layer->getDisplayExtents(min, max)) {
706 m_dragStartMinValue = min;
707 }
708 } 753 }
709 754
710 } else if (mode == ViewManager::SelectMode) { 755 } else if (mode == ViewManager::SelectMode) {
711 756
712 bool closeToLeft = false, closeToRight = false; 757 bool closeToLeft = false, closeToRight = false;
795 840
796 if (m_shiftPressed) { 841 if (m_shiftPressed) {
797 842
798 int x0 = std::min(m_clickPos.x(), m_mousePos.x()); 843 int x0 = std::min(m_clickPos.x(), m_mousePos.x());
799 int x1 = std::max(m_clickPos.x(), m_mousePos.x()); 844 int x1 = std::max(m_clickPos.x(), m_mousePos.x());
800 int w = x1 - x0;
801 845
802 int y0 = std::min(m_clickPos.y(), m_mousePos.y()); 846 int y0 = std::min(m_clickPos.y(), m_mousePos.y());
803 int y1 = std::max(m_clickPos.y(), m_mousePos.y()); 847 int y1 = std::max(m_clickPos.y(), m_mousePos.y());
804 // int h = y1 - y0; 848
805 849 zoomToRegion(x0, y0, x1, y1);
806 long newStartFrame = getFrameForX(x0);
807
808 long visibleFrames = getEndFrame() - getStartFrame();
809 if (newStartFrame <= -visibleFrames) {
810 newStartFrame = -visibleFrames + 1;
811 }
812
813 if (newStartFrame >= long(getModelsEndFrame())) {
814 newStartFrame = getModelsEndFrame() - 1;
815 }
816
817 float ratio = float(w) / float(width());
818 // std::cerr << "ratio: " << ratio << std::endl;
819 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
820 if (newZoomLevel < 1) newZoomLevel = 1;
821
822 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
823 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
824 setStartFrame(newStartFrame);
825
826 //!!! lots of faff, shouldn't be here
827
828 QString unit;
829 float min, max;
830 bool log;
831 Layer *layer = 0;
832 for (LayerList::const_iterator i = m_layers.begin();
833 i != m_layers.end(); ++i) {
834 if ((*i)->getValueExtents(min, max, log, unit) &&
835 (*i)->getDisplayExtents(min, max)) {
836 layer = *i;
837 break;
838 }
839 }
840
841 if (layer) {
842 if (log) {
843 min = (min < 0.0) ? -log10f(-min) : (min == 0.0) ? 0.0 : log10f(min);
844 max = (max < 0.0) ? -log10f(-max) : (max == 0.0) ? 0.0 : log10f(max);
845 }
846 float rmin = min + ((max - min) * (height() - y1)) / height();
847 float rmax = min + ((max - min) * (height() - y0)) / height();
848 std::cerr << "min: " << min << ", max: " << max << ", y0: " << y0 << ", y1: " << y1 << ", h: " << height() << ", rmin: " << rmin << ", rmax: " << rmax << std::endl;
849 if (log) {
850 rmin = powf(10, rmin);
851 rmax = powf(10, rmax);
852 }
853 std::cerr << "finally: rmin: " << rmin << ", rmax: " << rmax << " " << unit.toStdString() << std::endl;
854
855 layer->setDisplayExtents(rmin, rmax);
856 }
857
858 //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl;
859 // update();
860 } 850 }
861 851
862 } else if (mode == ViewManager::SelectMode) { 852 } else if (mode == ViewManager::SelectMode) {
863 853
864 if (m_manager && m_manager->haveInProgressSelection()) { 854 if (m_manager && m_manager->haveInProgressSelection()) {
928 } else { 918 } else {
929 setCursor(Qt::ArrowCursor); 919 setCursor(Qt::ArrowCursor);
930 } 920 }
931 } 921 }
932 922
933 //!!! if (mode != ViewManager::DrawMode) {
934
935 if (!m_manager->isPlaying()) { 923 if (!m_manager->isPlaying()) {
936 924
937 if (getSelectedLayer()) { 925 if (getSelectedLayer()) {
938 926
939 bool previouslyIdentifying = m_identifyFeatures; 927 bool previouslyIdentifying = m_identifyFeatures;
940 m_identifyFeatures = true; 928 m_identifyFeatures = true;
941 929
942 if (m_identifyFeatures != previouslyIdentifying || 930 if (m_identifyFeatures != previouslyIdentifying ||
943 m_identifyPoint != prevPoint) { 931 m_identifyPoint != prevPoint) {
944 update(); 932 update();
945 } 933 }
946 } 934 }
947 935 }
948 }
949
950 // }
951 936
952 return; 937 return;
953 } 938 }
954 939
955 if (m_navigating || mode == ViewManager::NavigateMode) { 940 if (m_navigating || mode == ViewManager::NavigateMode) {
959 m_mousePos = e->pos(); 944 m_mousePos = e->pos();
960 update(); 945 update();
961 946
962 } else { 947 } else {
963 948
964 //!!! want to do some cleverness to avoid dragging left/right 949 dragTopLayer(e);
965 // at the same time as up/down when the user moves the mouse
966 // diagonally.
967 // e.g. have horizontal and vertical thresholds and a series
968 // of states: unknown, constrained, free
969 //
970 // -> when the mouse first moves we're in unknown state:
971 // what then? the thing we really want to avoid is moving
972 // a tiny amount in the wrong direction, because usually
973 // the problem is that to move at all is expensive -- so what
974 // do we do?
975 //
976 // -> when it's moved more than say 10px in h or v
977 // direction we lock into h or v constrained mode. If it
978 // moves more than say 20px in the other direction
979 // subsequently, then we switch into free mode.
980
981 int xdiff = e->x() - m_clickPos.x();
982 int ydiff = e->y() - m_clickPos.y();
983 int smallThreshold = 10, bigThreshold = 50;
984
985 bool canMoveVertical = true;
986 bool canMoveHorizontal = true;
987
988 //!!! need to test whether the layer is actually draggable
989 // vertically before we do any of this
990
991 if (m_dragMode == UnresolvedDrag) {
992
993 if (abs(ydiff) > smallThreshold &&
994 abs(ydiff) > abs(xdiff) * 2) {
995 m_dragMode = VerticalDrag;
996 } else if (abs(xdiff) > smallThreshold &&
997 abs(xdiff) > abs(ydiff) * 2) {
998 m_dragMode = HorizontalDrag;
999 } else if (abs(xdiff) > smallThreshold &&
1000 abs(ydiff) > smallThreshold) {
1001 m_dragMode = FreeDrag;
1002 } else {
1003 // When playing, we don't want to disturb the play
1004 // position too easily; when not playing, we don't
1005 // want to move up/down too easily
1006 if (m_manager && m_manager->isPlaying()) {
1007 canMoveHorizontal = false;
1008 } else {
1009 canMoveVertical = false;
1010 }
1011 }
1012 }
1013
1014 if (m_dragMode == VerticalDrag) {
1015 if (abs(xdiff) > bigThreshold) m_dragMode = FreeDrag;
1016 else canMoveHorizontal = false;
1017 }
1018
1019 if (m_dragMode == HorizontalDrag) {
1020 if (abs(ydiff) > bigThreshold) m_dragMode = FreeDrag;
1021 else canMoveVertical = false;
1022 }
1023
1024 if (canMoveHorizontal) {
1025
1026 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
1027
1028 size_t newCentreFrame = m_dragCentreFrame;
1029
1030 if (frameOff < 0) {
1031 newCentreFrame -= frameOff;
1032 } else if (newCentreFrame >= size_t(frameOff)) {
1033 newCentreFrame -= frameOff;
1034 } else {
1035 newCentreFrame = 0;
1036 }
1037
1038 if (newCentreFrame >= getModelsEndFrame()) {
1039 newCentreFrame = getModelsEndFrame();
1040 if (newCentreFrame > 0) --newCentreFrame;
1041 }
1042
1043 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) {
1044 setCentreFrame(newCentreFrame);
1045 }
1046 }
1047
1048 //!!! For drag up/down, we need to: call getValueExtents
1049 //and getDisplayExtents and see whether both return true
1050 //(we can only drag up/down if they do); and check whether
1051 //the ranges returned differ (likewise). Then, we know
1052 //the height of the layer, so...
1053
1054 //!!! this should have its own function
1055
1056 if (canMoveVertical) {
1057
1058 Layer *layer = 0;
1059 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
1060
1061 if (layer) {
1062
1063 float vmin = 0.f, vmax = 0.f;
1064 bool vlog = false;
1065 QString vunit;
1066
1067 float dmin = 0.f, dmax = 0.f;
1068
1069 if (layer->getValueExtents(vmin, vmax, vlog, vunit) &&
1070 layer->getDisplayExtents(dmin, dmax) &&
1071 (dmin > vmin || dmax < vmax)) {
1072
1073 std::cerr << "ydiff = " << ydiff << std::endl;
1074
1075 float perpix = (dmax - dmin) / height();
1076 float valdiff = ydiff * perpix;
1077 std::cerr << "valdiff = " << valdiff << std::endl;
1078
1079 float newmin = m_dragStartMinValue + valdiff;
1080 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff;
1081 if (newmin < vmin) {
1082 newmax += vmin - newmin;
1083 newmin += vmin - newmin;
1084 }
1085 if (newmax > vmax) {
1086 newmin -= newmax - vmax;
1087 newmax -= newmax - vmax;
1088 }
1089 std::cerr << "(" << dmin << ", " << dmax << ") -> ("
1090 << newmin << ", " << newmax << ") (drag start " << m_dragStartMinValue << ")" << std::endl;
1091 layer->setDisplayExtents(newmin, newmax);
1092 }
1093 }
1094 }
1095 } 950 }
1096 951
1097 } else if (mode == ViewManager::SelectMode) { 952 } else if (mode == ViewManager::SelectMode) {
1098 953
1099 int mouseFrame = getFrameForX(e->x()); 954 dragExtendSelection(e);
1100 size_t resolution = 1;
1101 int snapFrameLeft = mouseFrame;
1102 int snapFrameRight = mouseFrame;
1103
1104 Layer *layer = getSelectedLayer();
1105 if (layer && !m_shiftPressed) {
1106 layer->snapToFeatureFrame(this, snapFrameLeft,
1107 resolution, Layer::SnapLeft);
1108 layer->snapToFeatureFrame(this, snapFrameRight,
1109 resolution, Layer::SnapRight);
1110 }
1111
1112 // std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl;
1113
1114 if (snapFrameLeft < 0) snapFrameLeft = 0;
1115 if (snapFrameRight < 0) snapFrameRight = 0;
1116
1117 size_t min, max;
1118
1119 if (m_selectionStartFrame > snapFrameLeft) {
1120 min = snapFrameLeft;
1121 max = m_selectionStartFrame;
1122 } else if (snapFrameRight > m_selectionStartFrame) {
1123 min = m_selectionStartFrame;
1124 max = snapFrameRight;
1125 } else {
1126 min = snapFrameLeft;
1127 max = snapFrameRight;
1128 }
1129
1130 if (m_manager) {
1131 m_manager->setInProgressSelection(Selection(min, max),
1132 !m_resizing && !m_ctrlPressed);
1133 }
1134
1135 bool doScroll = false;
1136 if (!m_manager) doScroll = true;
1137 if (!m_manager->isPlaying()) doScroll = true;
1138 if (m_followPlay != PlaybackScrollContinuous) doScroll = true;
1139
1140 if (doScroll) {
1141 int offset = mouseFrame - getStartFrame();
1142 int available = getEndFrame() - getStartFrame();
1143 if (offset >= available * 0.95) {
1144 int move = int(offset - available * 0.95) + 1;
1145 setCentreFrame(m_centreFrame + move);
1146 } else if (offset <= available * 0.10) {
1147 int move = int(available * 0.10 - offset) + 1;
1148 if (m_centreFrame > move) {
1149 setCentreFrame(m_centreFrame - move);
1150 } else {
1151 setCentreFrame(0);
1152 }
1153 }
1154 }
1155
1156 update();
1157 955
1158 } else if (mode == ViewManager::DrawMode) { 956 } else if (mode == ViewManager::DrawMode) {
1159 957
1160 Layer *layer = getSelectedLayer(); 958 Layer *layer = getSelectedLayer();
1161 if (layer && layer->isLayerEditable()) { 959 if (layer && layer->isLayerEditable()) {
1169 if (layer && layer->isLayerEditable()) { 967 if (layer && layer->isLayerEditable()) {
1170 layer->editDrag(this, e); 968 layer->editDrag(this, e);
1171 } 969 }
1172 } 970 }
1173 } 971 }
972 }
973
974 void
975 Pane::zoomToRegion(int x0, int y0, int x1, int y1)
976 {
977 int w = x1 - x0;
978
979 long newStartFrame = getFrameForX(x0);
980
981 long visibleFrames = getEndFrame() - getStartFrame();
982 if (newStartFrame <= -visibleFrames) {
983 newStartFrame = -visibleFrames + 1;
984 }
985
986 if (newStartFrame >= long(getModelsEndFrame())) {
987 newStartFrame = getModelsEndFrame() - 1;
988 }
989
990 float ratio = float(w) / float(width());
991 // std::cerr << "ratio: " << ratio << std::endl;
992 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
993 if (newZoomLevel < 1) newZoomLevel = 1;
994
995 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
996 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
997 setStartFrame(newStartFrame);
998
999 QString unit;
1000 float min, max;
1001 bool log;
1002 Layer *layer = 0;
1003 for (LayerList::const_iterator i = m_layers.begin();
1004 i != m_layers.end(); ++i) {
1005 if ((*i)->getValueExtents(min, max, log, unit) &&
1006 (*i)->getDisplayExtents(min, max)) {
1007 layer = *i;
1008 break;
1009 }
1010 }
1011
1012 if (layer) {
1013 if (log) {
1014 min = (min < 0.0) ? -log10f(-min) : (min == 0.0) ? 0.0 : log10f(min);
1015 max = (max < 0.0) ? -log10f(-max) : (max == 0.0) ? 0.0 : log10f(max);
1016 }
1017 float rmin = min + ((max - min) * (height() - y1)) / height();
1018 float rmax = min + ((max - min) * (height() - y0)) / height();
1019 std::cerr << "min: " << min << ", max: " << max << ", y0: " << y0 << ", y1: " << y1 << ", h: " << height() << ", rmin: " << rmin << ", rmax: " << rmax << std::endl;
1020 if (log) {
1021 rmin = powf(10, rmin);
1022 rmax = powf(10, rmax);
1023 }
1024 std::cerr << "finally: rmin: " << rmin << ", rmax: " << rmax << " " << unit.toStdString() << std::endl;
1025
1026 layer->setDisplayExtents(rmin, rmax);
1027 updateVerticalPanner();
1028 }
1029 }
1030
1031 void
1032 Pane::dragTopLayer(QMouseEvent *e)
1033 {
1034 // We need to avoid making it too easy to drag both
1035 // horizontally and vertically, in the case where the
1036 // mouse is moved "mostly" in horizontal or vertical axis
1037 // with only a small variation in the other axis. This is
1038 // particularly important during playback (when we want to
1039 // avoid small horizontal motions) or in slow refresh
1040 // layers like spectrogram (when we want to avoid small
1041 // vertical motions).
1042 //
1043 // To this end we have horizontal and vertical thresholds
1044 // and a series of states: unresolved, horizontally or
1045 // vertically constrained, free.
1046 //
1047 // When the mouse first moves, we're unresolved: we
1048 // restrict ourselves to whichever direction seems safest,
1049 // until the mouse has passed a small threshold distance
1050 // from the click point. Then we lock in to one of the
1051 // constrained modes, based on which axis that distance
1052 // was measured in first. Finally, if it turns out we've
1053 // also moved more than a certain larger distance in the
1054 // other direction as well, we may switch into free mode.
1055 //
1056 // If the top layer is incapable of being dragged
1057 // vertically, the logic is short circuited.
1058
1059 int xdiff = e->x() - m_clickPos.x();
1060 int ydiff = e->y() - m_clickPos.y();
1061 int smallThreshold = 10, bigThreshold = 50;
1062
1063 bool canMoveVertical = canTopLayerMoveVertical();
1064 bool canMoveHorizontal = true;
1065
1066 if (!canMoveHorizontal) {
1067 m_dragMode = HorizontalDrag;
1068 }
1069
1070 if (m_dragMode == UnresolvedDrag) {
1071
1072 if (abs(ydiff) > smallThreshold &&
1073 abs(ydiff) > abs(xdiff) * 2) {
1074 m_dragMode = VerticalDrag;
1075 } else if (abs(xdiff) > smallThreshold &&
1076 abs(xdiff) > abs(ydiff) * 2) {
1077 m_dragMode = HorizontalDrag;
1078 } else if (abs(xdiff) > smallThreshold &&
1079 abs(ydiff) > smallThreshold) {
1080 m_dragMode = FreeDrag;
1081 } else {
1082 // When playing, we don't want to disturb the play
1083 // position too easily; when not playing, we don't
1084 // want to move up/down too easily
1085 if (m_manager && m_manager->isPlaying()) {
1086 canMoveHorizontal = false;
1087 } else {
1088 canMoveVertical = false;
1089 }
1090 }
1091 }
1092
1093 if (m_dragMode == VerticalDrag) {
1094 if (abs(xdiff) > bigThreshold) m_dragMode = FreeDrag;
1095 else canMoveHorizontal = false;
1096 }
1097
1098 if (m_dragMode == HorizontalDrag && canMoveVertical) {
1099 if (abs(ydiff) > bigThreshold) m_dragMode = FreeDrag;
1100 else canMoveVertical = false;
1101 }
1102
1103 if (canMoveHorizontal) {
1104
1105 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
1106
1107 size_t newCentreFrame = m_dragCentreFrame;
1108
1109 if (frameOff < 0) {
1110 newCentreFrame -= frameOff;
1111 } else if (newCentreFrame >= size_t(frameOff)) {
1112 newCentreFrame -= frameOff;
1113 } else {
1114 newCentreFrame = 0;
1115 }
1116
1117 if (newCentreFrame >= getModelsEndFrame()) {
1118 newCentreFrame = getModelsEndFrame();
1119 if (newCentreFrame > 0) --newCentreFrame;
1120 }
1121
1122 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) {
1123 setCentreFrame(newCentreFrame);
1124 }
1125 }
1126
1127 if (canMoveVertical) {
1128
1129 float vmin = 0.f, vmax = 0.f;
1130 float dmin = 0.f, dmax = 0.f;
1131
1132 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
1133
1134 std::cerr << "ydiff = " << ydiff << std::endl;
1135
1136 float perpix = (dmax - dmin) / height();
1137 float valdiff = ydiff * perpix;
1138 std::cerr << "valdiff = " << valdiff << std::endl;
1139
1140 float newmin = m_dragStartMinValue + valdiff;
1141 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff;
1142 if (newmin < vmin) {
1143 newmax += vmin - newmin;
1144 newmin += vmin - newmin;
1145 }
1146 if (newmax > vmax) {
1147 newmin -= newmax - vmax;
1148 newmax -= newmax - vmax;
1149 }
1150 std::cerr << "(" << dmin << ", " << dmax << ") -> ("
1151 << newmin << ", " << newmax << ") (drag start " << m_dragStartMinValue << ")" << std::endl;
1152
1153 setTopLayerDisplayExtents(newmin, newmax);
1154 updateVerticalPanner();
1155 }
1156 }
1157 }
1158
1159 void
1160 Pane::dragExtendSelection(QMouseEvent *e)
1161 {
1162 int mouseFrame = getFrameForX(e->x());
1163 size_t resolution = 1;
1164 int snapFrameLeft = mouseFrame;
1165 int snapFrameRight = mouseFrame;
1166
1167 Layer *layer = getSelectedLayer();
1168 if (layer && !m_shiftPressed) {
1169 layer->snapToFeatureFrame(this, snapFrameLeft,
1170 resolution, Layer::SnapLeft);
1171 layer->snapToFeatureFrame(this, snapFrameRight,
1172 resolution, Layer::SnapRight);
1173 }
1174
1175 // std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl;
1176
1177 if (snapFrameLeft < 0) snapFrameLeft = 0;
1178 if (snapFrameRight < 0) snapFrameRight = 0;
1179
1180 size_t min, max;
1181
1182 if (m_selectionStartFrame > snapFrameLeft) {
1183 min = snapFrameLeft;
1184 max = m_selectionStartFrame;
1185 } else if (snapFrameRight > m_selectionStartFrame) {
1186 min = m_selectionStartFrame;
1187 max = snapFrameRight;
1188 } else {
1189 min = snapFrameLeft;
1190 max = snapFrameRight;
1191 }
1192
1193 if (m_manager) {
1194 m_manager->setInProgressSelection(Selection(min, max),
1195 !m_resizing && !m_ctrlPressed);
1196 }
1197
1198 bool doScroll = false;
1199 if (!m_manager) doScroll = true;
1200 if (!m_manager->isPlaying()) doScroll = true;
1201 if (m_followPlay != PlaybackScrollContinuous) doScroll = true;
1202
1203 if (doScroll) {
1204 int offset = mouseFrame - getStartFrame();
1205 int available = getEndFrame() - getStartFrame();
1206 if (offset >= available * 0.95) {
1207 int move = int(offset - available * 0.95) + 1;
1208 setCentreFrame(m_centreFrame + move);
1209 } else if (offset <= available * 0.10) {
1210 int move = int(available * 0.10 - offset) + 1;
1211 if (m_centreFrame > move) {
1212 setCentreFrame(m_centreFrame - move);
1213 } else {
1214 setCentreFrame(0);
1215 }
1216 }
1217 }
1218
1219 update();
1174 } 1220 }
1175 1221
1176 void 1222 void
1177 Pane::mouseDoubleClickEvent(QMouseEvent *e) 1223 Pane::mouseDoubleClickEvent(QMouseEvent *e)
1178 { 1224 {
1344 } 1390 }
1345 if (value > max) { 1391 if (value > max) {
1346 value = max; 1392 value = max;
1347 } 1393 }
1348 layer->setVerticalZoomStep(value); 1394 layer->setVerticalZoomStep(value);
1395 updateVerticalPanner();
1349 } 1396 }
1350 } 1397 }
1398
1399 void
1400 Pane::verticalPannerMoved(float x0, float y0, float w, float h)
1401 {
1402 float vmin, vmax, dmin, dmax;
1403 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return;
1404 float y1 = y0 + h;
1405 float newmax = vmin + ((1.0 - y0) * (vmax - vmin));
1406 float newmin = vmin + ((1.0 - y1) * (vmax - vmin));
1407 std::cerr << "verticalPannerMoved: (" << x0 << "," << y0 << "," << w
1408 << "," << h << ") -> (" << newmin << "," << newmax << ")" << std::endl;
1409 setTopLayerDisplayExtents(newmin, newmax);
1410 }
1351 1411
1352 bool 1412 bool
1353 Pane::editSelectionStart(QMouseEvent *e) 1413 Pane::editSelectionStart(QMouseEvent *e)
1354 { 1414 {
1355 if (!m_identifyFeatures || 1415 if (!m_identifyFeatures ||