Mercurial > hg > svgui
comparison layer/RegionLayer.cpp @ 550:d666f5f8b154
* Make a better job of picking the proper point to drag, edit, delete etc
in note and region layers
* Some work to do with region dragging, but this still needs more thought
| author | Chris Cannam |
|---|---|
| date | Mon, 28 Sep 2009 12:29:12 +0000 |
| parents | b73f486fc2e4 |
| children | c2ba2796cbee |
comparison
equal
deleted
inserted
replaced
| 549:e6122e4999a3 | 550:d666f5f8b154 |
|---|---|
| 323 usePoints.clear(); | 323 usePoints.clear(); |
| 324 } | 324 } |
| 325 } | 325 } |
| 326 | 326 |
| 327 return usePoints; | 327 return usePoints; |
| 328 } | |
| 329 | |
| 330 bool | |
| 331 RegionLayer::getPointToDrag(View *v, int x, int y, RegionModel::Point &p) const | |
| 332 { | |
| 333 if (!m_model) return false; | |
| 334 | |
| 335 long frame = v->getFrameForX(x); | |
| 336 | |
| 337 RegionModel::PointList onPoints = m_model->getPoints(frame); | |
| 338 if (onPoints.empty()) return false; | |
| 339 | |
| 340 int nearestDistance = -1; | |
| 341 | |
| 342 for (RegionModel::PointList::const_iterator i = onPoints.begin(); | |
| 343 i != onPoints.end(); ++i) { | |
| 344 | |
| 345 int distance = getYForValue(v, (*i).value) - y; | |
| 346 if (distance < 0) distance = -distance; | |
| 347 if (nearestDistance == -1 || distance < nearestDistance) { | |
| 348 nearestDistance = distance; | |
| 349 p = *i; | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 return true; | |
| 328 } | 354 } |
| 329 | 355 |
| 330 QString | 356 QString |
| 331 RegionLayer::getFeatureDescription(View *v, QPoint &pos) const | 357 RegionLayer::getFeatureDescription(View *v, QPoint &pos) const |
| 332 { | 358 { |
| 758 int textY = 0; | 784 int textY = 0; |
| 759 if (m_plotStyle == PlotSegmentation) { | 785 if (m_plotStyle == PlotSegmentation) { |
| 760 textY = v->getTextLabelHeight(this, paint); | 786 textY = v->getTextLabelHeight(this, paint); |
| 761 } | 787 } |
| 762 | 788 |
| 789 int fontHeight = paint.fontMetrics().height(); | |
| 790 int fontAscent = paint.fontMetrics().ascent(); | |
| 791 | |
| 763 for (RegionModel::PointList::const_iterator i = points.begin(); | 792 for (RegionModel::PointList::const_iterator i = points.begin(); |
| 764 i != points.end(); ++i) { | 793 i != points.end(); ++i) { |
| 765 | 794 |
| 766 const RegionModel::Point &p(*i); | 795 const RegionModel::Point &p(*i); |
| 767 | 796 |
| 779 int nx = v->getXForFrame(q.frame); | 808 int nx = v->getXForFrame(q.frame); |
| 780 if (nx < ex) ex = nx; | 809 if (nx < ex) ex = nx; |
| 781 } | 810 } |
| 782 | 811 |
| 783 if (m_plotStyle != PlotSegmentation) { | 812 if (m_plotStyle != PlotSegmentation) { |
| 784 textY = y - paint.fontMetrics().height() | 813 textY = y - fontHeight + fontAscent; |
| 785 + paint.fontMetrics().ascent(); | 814 if (textY < fontAscent + 1) { |
| 786 if (textY < paint.fontMetrics().ascent() + 1) { | 815 textY = fontAscent + 1; |
| 787 textY = paint.fontMetrics().ascent() + 1; | |
| 788 } | 816 } |
| 789 } | 817 } |
| 790 | 818 |
| 791 if (m_model->getValueQuantization() != 0.0) { | 819 if (m_model->getValueQuantization() != 0.0) { |
| 792 h = y - getYForValue(v, p.value + m_model->getValueQuantization()); | 820 h = y - getYForValue(v, p.value + m_model->getValueQuantization()); |
| 827 paint.drawLine(x, y+1, x + w, y+1); | 855 paint.drawLine(x, y+1, x + w, y+1); |
| 828 paint.drawLine(x, y - h/2, x, y + h/2); | 856 paint.drawLine(x, y - h/2, x, y + h/2); |
| 829 paint.drawLine(x+w, y - h/2, x + w, y + h/2); | 857 paint.drawLine(x+w, y - h/2, x + w, y + h/2); |
| 830 } | 858 } |
| 831 | 859 |
| 832 if (p.label != "") { | 860 QString label = p.label; |
| 833 // if (ex > x + 6 + paint.fontMetrics().width(p.label)) { | 861 if (label == "") { |
| 834 paint.drawText(x + 5, textY, p.label); | 862 label = QString("[%1]").arg(p.value); |
| 835 // } | 863 } |
| 836 } | 864 v->drawVisibleText(paint, x + 5, textY, label, View::OutlinedText); |
| 837 } | 865 } |
| 838 | 866 |
| 839 paint.restore(); | 867 paint.restore(); |
| 840 } | 868 } |
| 841 | 869 |
| 850 if (frame < 0) frame = 0; | 878 if (frame < 0) frame = 0; |
| 851 frame = frame / m_model->getResolution() * m_model->getResolution(); | 879 frame = frame / m_model->getResolution() * m_model->getResolution(); |
| 852 | 880 |
| 853 float value = getValueForY(v, e->y()); | 881 float value = getValueForY(v, e->y()); |
| 854 | 882 |
| 855 m_editingPoint = RegionModel::Point(frame, value, 0, tr("New Region")); | 883 m_editingPoint = RegionModel::Point(frame, value, 0, ""); |
| 856 m_originalPoint = m_editingPoint; | 884 m_originalPoint = m_editingPoint; |
| 857 | 885 |
| 858 if (m_editingCommand) finish(m_editingCommand); | 886 if (m_editingCommand) finish(m_editingCommand); |
| 859 m_editingCommand = new RegionModel::EditCommand(m_model, | 887 m_editingCommand = new RegionModel::EditCommand(m_model, |
| 860 tr("Draw Region")); | 888 tr("Draw Region")); |
| 861 m_editingCommand->addPoint(m_editingPoint); | 889 m_editingCommand->addPoint(m_editingPoint); |
| 890 | |
| 891 recalcSpacing(); | |
| 862 | 892 |
| 863 m_editing = true; | 893 m_editing = true; |
| 864 } | 894 } |
| 865 | 895 |
| 866 void | 896 void |
| 889 m_editingCommand->deletePoint(m_editingPoint); | 919 m_editingCommand->deletePoint(m_editingPoint); |
| 890 m_editingPoint.frame = newFrame; | 920 m_editingPoint.frame = newFrame; |
| 891 m_editingPoint.value = newValue; | 921 m_editingPoint.value = newValue; |
| 892 m_editingPoint.duration = newDuration; | 922 m_editingPoint.duration = newDuration; |
| 893 m_editingCommand->addPoint(m_editingPoint); | 923 m_editingCommand->addPoint(m_editingPoint); |
| 924 | |
| 925 // recalcSpacing(); | |
| 894 } | 926 } |
| 895 | 927 |
| 896 void | 928 void |
| 897 RegionLayer::drawEnd(View *, QMouseEvent *) | 929 RegionLayer::drawEnd(View *, QMouseEvent *) |
| 898 { | 930 { |
| 899 // std::cerr << "RegionLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl; | 931 // std::cerr << "RegionLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl; |
| 900 if (!m_model || !m_editing) return; | 932 if (!m_model || !m_editing) return; |
| 901 finish(m_editingCommand); | 933 finish(m_editingCommand); |
| 902 m_editingCommand = 0; | 934 m_editingCommand = 0; |
| 903 m_editing = false; | 935 m_editing = false; |
| 936 | |
| 937 recalcSpacing(); | |
| 904 } | 938 } |
| 905 | 939 |
| 906 void | 940 void |
| 907 RegionLayer::eraseStart(View *v, QMouseEvent *e) | 941 RegionLayer::eraseStart(View *v, QMouseEvent *e) |
| 908 { | 942 { |
| 909 if (!m_model) return; | 943 if (!m_model) return; |
| 910 | 944 |
| 945 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; | |
| 946 /* | |
| 911 RegionModel::PointList points = getLocalPoints(v, e->x()); | 947 RegionModel::PointList points = getLocalPoints(v, e->x()); |
| 912 if (points.empty()) return; | 948 if (points.empty()) return; |
| 913 | 949 |
| 914 m_editingPoint = *points.begin(); | 950 m_editingPoint = *points.begin(); |
| 915 | 951 */ |
| 916 if (m_editingCommand) { | 952 if (m_editingCommand) { |
| 917 finish(m_editingCommand); | 953 finish(m_editingCommand); |
| 918 m_editingCommand = 0; | 954 m_editingCommand = 0; |
| 919 } | 955 } |
| 920 | 956 |
| 921 m_editing = true; | 957 m_editing = true; |
| 958 recalcSpacing(); | |
| 922 } | 959 } |
| 923 | 960 |
| 924 void | 961 void |
| 925 RegionLayer::eraseDrag(View *v, QMouseEvent *e) | 962 RegionLayer::eraseDrag(View *v, QMouseEvent *e) |
| 926 { | 963 { |
| 930 RegionLayer::eraseEnd(View *v, QMouseEvent *e) | 967 RegionLayer::eraseEnd(View *v, QMouseEvent *e) |
| 931 { | 968 { |
| 932 if (!m_model || !m_editing) return; | 969 if (!m_model || !m_editing) return; |
| 933 | 970 |
| 934 m_editing = false; | 971 m_editing = false; |
| 935 | 972 /* |
| 936 RegionModel::PointList points = getLocalPoints(v, e->x()); | 973 RegionModel::PointList points = getLocalPoints(v, e->x()); |
| 937 if (points.empty()) return; | 974 if (points.empty()) return; |
| 938 if (points.begin()->frame != m_editingPoint.frame || | 975 if (points.begin()->frame != m_editingPoint.frame || |
| 939 points.begin()->value != m_editingPoint.value) return; | 976 points.begin()->value != m_editingPoint.value) return; |
| 977 */ | |
| 978 RegionModel::Point p(0); | |
| 979 if (!getPointToDrag(v, e->x(), e->y(), p)) return; | |
| 980 if (p.frame != m_editingPoint.frame || p.value != m_editingPoint.value) return; | |
| 940 | 981 |
| 941 m_editingCommand = new RegionModel::EditCommand | 982 m_editingCommand = new RegionModel::EditCommand |
| 942 (m_model, tr("Erase Region")); | 983 (m_model, tr("Erase Region")); |
| 943 | 984 |
| 944 m_editingCommand->deletePoint(m_editingPoint); | 985 m_editingCommand->deletePoint(m_editingPoint); |
| 945 | 986 |
| 946 finish(m_editingCommand); | 987 finish(m_editingCommand); |
| 947 m_editingCommand = 0; | 988 m_editingCommand = 0; |
| 948 m_editing = false; | 989 m_editing = false; |
| 990 recalcSpacing(); | |
| 949 } | 991 } |
| 950 | 992 |
| 951 void | 993 void |
| 952 RegionLayer::editStart(View *v, QMouseEvent *e) | 994 RegionLayer::editStart(View *v, QMouseEvent *e) |
| 953 { | 995 { |
| 954 // std::cerr << "RegionLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; | 996 std::cerr << "RegionLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; |
| 955 | 997 |
| 956 if (!m_model) return; | 998 if (!m_model) return; |
| 957 | 999 |
| 958 RegionModel::PointList points = getLocalPoints(v, e->x()); | 1000 // OrderedPointList opoints = getNearbyPoints(v, e->x(), e->y()); |
| 959 if (points.empty()) return; | 1001 // RegionLayer: |
| 960 | 1002 |
| 961 m_editingPoint = *points.begin(); | 1003 // RegionModel::PointList points = getLocalPoints(v, e->x()); |
| 1004 // if (points.empty()) return; | |
| 1005 | |
| 1006 // m_editingPoint = *points.begin(); | |
| 1007 | |
| 1008 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { | |
| 1009 return; | |
| 1010 } | |
| 1011 | |
| 962 m_originalPoint = m_editingPoint; | 1012 m_originalPoint = m_editingPoint; |
| 963 | 1013 |
| 964 if (m_editingCommand) { | 1014 if (m_editingCommand) { |
| 965 finish(m_editingCommand); | 1015 finish(m_editingCommand); |
| 966 m_editingCommand = 0; | 1016 m_editingCommand = 0; |
| 967 } | 1017 } |
| 968 | 1018 |
| 969 m_editing = true; | 1019 m_editing = true; |
| 1020 m_dragYOrigin = e->y(); | |
| 1021 m_dragYRebase = e->y(); | |
| 1022 recalcSpacing(); | |
| 970 } | 1023 } |
| 971 | 1024 |
| 972 void | 1025 void |
| 973 RegionLayer::editDrag(View *v, QMouseEvent *e) | 1026 RegionLayer::editDrag(View *v, QMouseEvent *e) |
| 974 { | 1027 { |
| 975 // std::cerr << "RegionLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl; | 1028 std::cerr << "RegionLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl; |
| 976 | 1029 |
| 977 if (!m_model || !m_editing) return; | 1030 if (!m_model || !m_editing) return; |
| 978 | 1031 |
| 979 long frame = v->getFrameForX(e->x()); | 1032 long frame = v->getFrameForX(e->x()); |
| 980 if (frame < 0) frame = 0; | 1033 if (frame < 0) frame = 0; |
| 981 frame = frame / m_model->getResolution() * m_model->getResolution(); | 1034 frame = frame / m_model->getResolution() * m_model->getResolution(); |
| 982 | 1035 |
| 983 float value = getValueForY(v, e->y()); | 1036 int activeY = e->y() + (m_dragYRebase - m_dragYOrigin); |
| 1037 float value = getValueForY(v, activeY); | |
| 984 | 1038 |
| 985 if (!m_editingCommand) { | 1039 if (!m_editingCommand) { |
| 986 m_editingCommand = new RegionModel::EditCommand(m_model, | 1040 m_editingCommand = new RegionModel::EditCommand(m_model, |
| 987 tr("Drag Region")); | 1041 tr("Drag Region")); |
| 1042 } | |
| 1043 | |
| 1044 if (m_verticalScale == EqualSpaced) { | |
| 1045 if (getYForValue(v, value) != getYForValue(v, m_editingPoint.value)) { | |
| 1046 m_dragYRebase = e->y(); | |
| 1047 } | |
| 988 } | 1048 } |
| 989 | 1049 |
| 990 m_editingCommand->deletePoint(m_editingPoint); | 1050 m_editingCommand->deletePoint(m_editingPoint); |
| 991 m_editingPoint.frame = frame; | 1051 m_editingPoint.frame = frame; |
| 992 m_editingPoint.value = value; | 1052 m_editingPoint.value = value; |
| 993 m_editingCommand->addPoint(m_editingPoint); | 1053 m_editingCommand->addPoint(m_editingPoint); |
| 994 } | 1054 recalcSpacing(); |
| 995 | 1055 } |
| 996 void | 1056 |
| 997 RegionLayer::editEnd(View *, QMouseEvent *) | 1057 void |
| 998 { | 1058 RegionLayer::editEnd(View *, QMouseEvent *e) |
| 999 // std::cerr << "RegionLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl; | 1059 { |
| 1060 std::cerr << "RegionLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl; | |
| 1000 if (!m_model || !m_editing) return; | 1061 if (!m_model || !m_editing) return; |
| 1001 | 1062 |
| 1002 if (m_editingCommand) { | 1063 if (m_editingCommand) { |
| 1003 | 1064 |
| 1004 QString newName = m_editingCommand->getName(); | 1065 QString newName = m_editingCommand->getName(); |
| 1017 finish(m_editingCommand); | 1078 finish(m_editingCommand); |
| 1018 } | 1079 } |
| 1019 | 1080 |
| 1020 m_editingCommand = 0; | 1081 m_editingCommand = 0; |
| 1021 m_editing = false; | 1082 m_editing = false; |
| 1083 recalcSpacing(); | |
| 1022 } | 1084 } |
| 1023 | 1085 |
| 1024 bool | 1086 bool |
| 1025 RegionLayer::editOpen(View *v, QMouseEvent *e) | 1087 RegionLayer::editOpen(View *v, QMouseEvent *e) |
| 1026 { | 1088 { |
| 1027 if (!m_model) return false; | 1089 if (!m_model) return false; |
| 1028 | 1090 /* |
| 1029 RegionModel::PointList points = getLocalPoints(v, e->x()); | 1091 RegionModel::PointList points = getLocalPoints(v, e->x()); |
| 1030 if (points.empty()) return false; | 1092 if (points.empty()) return false; |
| 1031 | 1093 */ |
| 1032 RegionModel::Point region = *points.begin(); | 1094 |
| 1095 RegionModel::Point region(0); | |
| 1096 if (!getPointToDrag(v, e->x(), e->y(), region)) return false; | |
| 1097 | |
| 1098 // RegionModel::Point region = *points.begin(); | |
| 1033 | 1099 |
| 1034 ItemEditDialog *dialog = new ItemEditDialog | 1100 ItemEditDialog *dialog = new ItemEditDialog |
| 1035 (m_model->getSampleRate(), | 1101 (m_model->getSampleRate(), |
| 1036 ItemEditDialog::ShowTime | | 1102 ItemEditDialog::ShowTime | |
| 1037 ItemEditDialog::ShowDuration | | 1103 ItemEditDialog::ShowDuration | |
| 1058 command->addPoint(newRegion); | 1124 command->addPoint(newRegion); |
| 1059 finish(command); | 1125 finish(command); |
| 1060 } | 1126 } |
| 1061 | 1127 |
| 1062 delete dialog; | 1128 delete dialog; |
| 1129 recalcSpacing(); | |
| 1063 return true; | 1130 return true; |
| 1064 } | 1131 } |
| 1065 | 1132 |
| 1066 void | 1133 void |
| 1067 RegionLayer::moveSelection(Selection s, size_t newStartFrame) | 1134 RegionLayer::moveSelection(Selection s, size_t newStartFrame) |
| 1084 command->addPoint(newPoint); | 1151 command->addPoint(newPoint); |
| 1085 } | 1152 } |
| 1086 } | 1153 } |
| 1087 | 1154 |
| 1088 finish(command); | 1155 finish(command); |
| 1156 recalcSpacing(); | |
| 1089 } | 1157 } |
| 1090 | 1158 |
| 1091 void | 1159 void |
| 1092 RegionLayer::resizeSelection(Selection s, Selection newSize) | 1160 RegionLayer::resizeSelection(Selection s, Selection newSize) |
| 1093 { | 1161 { |
| 1123 command->addPoint(newPoint); | 1191 command->addPoint(newPoint); |
| 1124 } | 1192 } |
| 1125 } | 1193 } |
| 1126 | 1194 |
| 1127 finish(command); | 1195 finish(command); |
| 1196 recalcSpacing(); | |
| 1128 } | 1197 } |
| 1129 | 1198 |
| 1130 void | 1199 void |
| 1131 RegionLayer::deleteSelection(Selection s) | 1200 RegionLayer::deleteSelection(Selection s) |
| 1132 { | 1201 { |
| 1145 command->deletePoint(*i); | 1214 command->deletePoint(*i); |
| 1146 } | 1215 } |
| 1147 } | 1216 } |
| 1148 | 1217 |
| 1149 finish(command); | 1218 finish(command); |
| 1219 recalcSpacing(); | |
| 1150 } | 1220 } |
| 1151 | 1221 |
| 1152 void | 1222 void |
| 1153 RegionLayer::copy(View *v, Selection s, Clipboard &to) | 1223 RegionLayer::copy(View *v, Selection s, Clipboard &to) |
| 1154 { | 1224 { |
| 1242 | 1312 |
| 1243 command->addPoint(newPoint); | 1313 command->addPoint(newPoint); |
| 1244 } | 1314 } |
| 1245 | 1315 |
| 1246 finish(command); | 1316 finish(command); |
| 1317 recalcSpacing(); | |
| 1247 return true; | 1318 return true; |
| 1248 } | 1319 } |
| 1249 | 1320 |
| 1250 void | 1321 void |
| 1251 RegionLayer::toXml(QTextStream &stream, | 1322 RegionLayer::toXml(QTextStream &stream, |
