comparison layer/RegionLayer.cpp @ 1216:dc2af6616c83

Merge from branch 3.0-integration
author Chris Cannam
date Fri, 13 Jan 2017 10:29:50 +0000
parents ee01a4062747
children a34a2a25907c
comparison
equal deleted inserted replaced
1048:e8102ff5573b 1216:dc2af6616c83
17 17
18 #include "data/model/Model.h" 18 #include "data/model/Model.h"
19 #include "base/RealTime.h" 19 #include "base/RealTime.h"
20 #include "base/Profiler.h" 20 #include "base/Profiler.h"
21 #include "base/LogRange.h" 21 #include "base/LogRange.h"
22
22 #include "ColourDatabase.h" 23 #include "ColourDatabase.h"
23
24 #include "ColourMapper.h" 24 #include "ColourMapper.h"
25 #include "LinearNumericalScale.h" 25 #include "LinearNumericalScale.h"
26 #include "LogNumericalScale.h" 26 #include "LogNumericalScale.h"
27 #include "LinearColourScale.h" 27 #include "LinearColourScale.h"
28 #include "LogColourScale.h" 28 #include "LogColourScale.h"
29 #include "PaintAssistant.h"
29 30
30 #include "view/View.h" 31 #include "view/View.h"
31 32
32 #include "data/model/RegionModel.h" 33 #include "data/model/RegionModel.h"
33 34
242 m_verticalScale = scale; 243 m_verticalScale = scale;
243 emit layerParametersChanged(); 244 emit layerParametersChanged();
244 } 245 }
245 246
246 bool 247 bool
247 RegionLayer::isLayerScrollable(const View *v) const 248 RegionLayer::isLayerScrollable(const LayerGeometryProvider *v) const
248 { 249 {
249 QPoint discard; 250 QPoint discard;
250 return !v->shouldIlluminateLocalFeatures(this, discard); 251 return !v->shouldIlluminateLocalFeatures(this, discard);
251 } 252 }
252 253
300 301
301 return true; 302 return true;
302 } 303 }
303 304
304 RegionModel::PointList 305 RegionModel::PointList
305 RegionLayer::getLocalPoints(View *v, int x) const 306 RegionLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
306 { 307 {
307 if (!m_model) return RegionModel::PointList(); 308 if (!m_model) return RegionModel::PointList();
308 309
309 sv_frame_t frame = v->getFrameForX(x); 310 sv_frame_t frame = v->getFrameForX(x);
310 311
343 344
344 return usePoints; 345 return usePoints;
345 } 346 }
346 347
347 bool 348 bool
348 RegionLayer::getPointToDrag(View *v, int x, int y, RegionModel::Point &p) const 349 RegionLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, RegionModel::Point &p) const
349 { 350 {
350 if (!m_model) return false; 351 if (!m_model) return false;
351 352
352 sv_frame_t frame = v->getFrameForX(x); 353 sv_frame_t frame = v->getFrameForX(x);
353 354
381 } 382 }
382 return ""; 383 return "";
383 } 384 }
384 385
385 QString 386 QString
386 RegionLayer::getFeatureDescription(View *v, QPoint &pos) const 387 RegionLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
387 { 388 {
388 int x = pos.x(); 389 int x = pos.x();
389 390
390 if (!m_model || !m_model->getSampleRate()) return ""; 391 if (!m_model || !m_model->getSampleRate()) return "";
391 392
451 getYForValue(v, region.value)); 452 getYForValue(v, region.value));
452 return text; 453 return text;
453 } 454 }
454 455
455 bool 456 bool
456 RegionLayer::snapToFeatureFrame(View *v, sv_frame_t &frame, 457 RegionLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
457 int &resolution, 458 int &resolution,
458 SnapType snap) const 459 SnapType snap) const
459 { 460 {
460 if (!m_model) { 461 if (!m_model) {
461 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 462 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
534 frame = snapped; 535 frame = snapped;
535 return found; 536 return found;
536 } 537 }
537 538
538 bool 539 bool
539 RegionLayer::snapToSimilarFeature(View *v, sv_frame_t &frame, 540 RegionLayer::snapToSimilarFeature(LayerGeometryProvider *v, sv_frame_t &frame,
540 int &resolution, 541 int &resolution,
541 SnapType snap) const 542 SnapType snap) const
542 { 543 {
543 if (!m_model) { 544 if (!m_model) {
544 return Layer::snapToSimilarFeature(v, frame, resolution, snap); 545 return Layer::snapToSimilarFeature(v, frame, resolution, snap);
622 if (m_model) return m_model->getScaleUnits(); 623 if (m_model) return m_model->getScaleUnits();
623 else return ""; 624 else return "";
624 } 625 }
625 626
626 void 627 void
627 RegionLayer::getScaleExtents(View *v, double &min, double &max, bool &log) const 628 RegionLayer::getScaleExtents(LayerGeometryProvider *v, double &min, double &max, bool &log) const
628 { 629 {
629 min = 0.0; 630 min = 0.0;
630 max = 0.0; 631 max = 0.0;
631 log = false; 632 log = false;
632 633
674 675
675 if (max == min) max = min + 1.0; 676 if (max == min) max = min + 1.0;
676 } 677 }
677 678
678 int 679 int
679 RegionLayer::spacingIndexToY(View *v, int i) const 680 RegionLayer::spacingIndexToY(LayerGeometryProvider *v, int i) const
680 { 681 {
681 int h = v->height(); 682 int h = v->getPaintHeight();
682 int n = int(m_spacingMap.size()); 683 int n = int(m_spacingMap.size());
683 // this maps from i (spacing of the value from the spacing 684 // this maps from i (spacing of the value from the spacing
684 // map) and n (number of region types) to y 685 // map) and n (number of region types) to y
685 int y = h - (((h * i) / n) + (h / (2 * n))); 686 int y = h - (((h * i) / n) + (h / (2 * n)));
686 return y; 687 return y;
687 } 688 }
688 689
689 double 690 double
690 RegionLayer::yToSpacingIndex(View *v, int y) const 691 RegionLayer::yToSpacingIndex(LayerGeometryProvider *v, int y) const
691 { 692 {
692 // we return an inexact result here (double rather than int) 693 // we return an inexact result here (double rather than int)
693 int h = v->height(); 694 int h = v->getPaintHeight();
694 int n = int(m_spacingMap.size()); 695 int n = int(m_spacingMap.size());
695 // from y = h - ((h * i) / n) + (h / (2 * n)) as above (vh taking place of i) 696 // from y = h - ((h * i) / n) + (h / (2 * n)) as above (vh taking place of i)
696 double vh = double(2*h*n - h - 2*n*y) / double(2*h); 697 double vh = double(2*h*n - h - 2*n*y) / double(2*h);
697 return vh; 698 return vh;
698 } 699 }
699 700
700 int 701 int
701 RegionLayer::getYForValue(View *v, double val) const 702 RegionLayer::getYForValue(LayerGeometryProvider *v, double val) const
702 { 703 {
703 double min = 0.0, max = 0.0; 704 double min = 0.0, max = 0.0;
704 bool logarithmic = false; 705 bool logarithmic = false;
705 int h = v->height(); 706 int h = v->getPaintHeight();
706 707
707 if (m_verticalScale == EqualSpaced) { 708 if (m_verticalScale == EqualSpaced) {
708 709
709 if (m_spacingMap.empty()) return h/2; 710 if (m_spacingMap.empty()) return h/2;
710 711
731 return int(h - ((val - min) * h) / (max - min)); 732 return int(h - ((val - min) * h) / (max - min));
732 } 733 }
733 } 734 }
734 735
735 double 736 double
736 RegionLayer::getValueForY(View *v, int y) const 737 RegionLayer::getValueForY(LayerGeometryProvider *v, int y) const
737 { 738 {
738 return getValueForY(v, y, -1); 739 return getValueForY(v, y, -1);
739 } 740 }
740 741
741 double 742 double
742 RegionLayer::getValueForY(View *v, int y, int avoid) const 743 RegionLayer::getValueForY(LayerGeometryProvider *v, int y, int avoid) const
743 { 744 {
744 double min = 0.0, max = 0.0; 745 double min = 0.0, max = 0.0;
745 bool logarithmic = false; 746 bool logarithmic = false;
746 int h = v->height(); 747 int h = v->getPaintHeight();
747 748
748 if (m_verticalScale == EqualSpaced) { 749 if (m_verticalScale == EqualSpaced) {
749 750
750 // if we're equal spaced, we probably want to snap to the 751 // if we're equal spaced, we probably want to snap to the
751 // nearest item when close to it, and give some notification 752 // nearest item when close to it, and give some notification
834 return val; 835 return val;
835 } 836 }
836 } 837 }
837 838
838 QColor 839 QColor
839 RegionLayer::getColourForValue(View *v, double val) const 840 RegionLayer::getColourForValue(LayerGeometryProvider *v, double val) const
840 { 841 {
841 double min, max; 842 double min, max;
842 bool log; 843 bool log;
843 getScaleExtents(v, min, max, log); 844 getScaleExtents(v, min, max, log);
844 845
864 return ColourDatabase::getInstance()->getColourIndex 865 return ColourDatabase::getInstance()->getColourIndex
865 (QString(darkbg ? "Bright Blue" : "Blue")); 866 (QString(darkbg ? "Bright Blue" : "Blue"));
866 } 867 }
867 868
868 void 869 void
869 RegionLayer::paint(View *v, QPainter &paint, QRect rect) const 870 RegionLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
870 { 871 {
871 if (!m_model || !m_model->isOK()) return; 872 if (!m_model || !m_model->isOK()) return;
872 873
873 sv_samplerate_t sampleRate = m_model->getSampleRate(); 874 sv_samplerate_t sampleRate = m_model->getSampleRate();
874 if (!sampleRate) return; 875 if (!sampleRate) return;
940 } 941 }
941 942
942 if (w < 1) w = 1; 943 if (w < 1) w = 1;
943 944
944 if (m_plotStyle == PlotSegmentation) { 945 if (m_plotStyle == PlotSegmentation) {
945 paint.setPen(getForegroundQColor(v)); 946 paint.setPen(getForegroundQColor(v->getView()));
946 paint.setBrush(getColourForValue(v, p.value)); 947 paint.setBrush(getColourForValue(v, p.value));
947 } else { 948 } else {
948 paint.setPen(getBaseQColor()); 949 paint.setPen(getBaseQColor());
949 paint.setBrush(brushColour); 950 paint.setBrush(brushColour);
950 } 951 }
956 if (!shouldIlluminate || 957 if (!shouldIlluminate ||
957 // "illuminatePoint != p" 958 // "illuminatePoint != p"
958 RegionModel::Point::Comparator()(illuminatePoint, p) || 959 RegionModel::Point::Comparator()(illuminatePoint, p) ||
959 RegionModel::Point::Comparator()(p, illuminatePoint)) { 960 RegionModel::Point::Comparator()(p, illuminatePoint)) {
960 961
961 paint.setPen(QPen(getForegroundQColor(v), 1)); 962 paint.setPen(QPen(getForegroundQColor(v->getView()), 1));
962 paint.drawLine(x, 0, x, v->height()); 963 paint.drawLine(x, 0, x, v->getPaintHeight());
963 paint.setPen(Qt::NoPen); 964 paint.setPen(Qt::NoPen);
964 965
965 } else { 966 } else {
966 paint.setPen(QPen(getForegroundQColor(v), 2)); 967 paint.setPen(QPen(getForegroundQColor(v->getView()), 2));
967 } 968 }
968 969
969 paint.drawRect(x, -1, ex - x, v->height() + 2); 970 paint.drawRect(x, -1, ex - x, v->getPaintHeight() + 2);
970 971
971 } else { 972 } else {
972 973
973 if (shouldIlluminate && 974 if (shouldIlluminate &&
974 // "illuminatePoint == p" 975 // "illuminatePoint == p"
977 978
978 paint.setPen(v->getForeground()); 979 paint.setPen(v->getForeground());
979 paint.setBrush(v->getForeground()); 980 paint.setBrush(v->getForeground());
980 981
981 QString vlabel = QString("%1%2").arg(p.value).arg(getScaleUnits()); 982 QString vlabel = QString("%1%2").arg(p.value).arg(getScaleUnits());
982 v->drawVisibleText(paint, 983 PaintAssistant::drawVisibleText(v, paint,
983 x - paint.fontMetrics().width(vlabel) - 2, 984 x - paint.fontMetrics().width(vlabel) - 2,
984 y + paint.fontMetrics().height()/2 985 y + paint.fontMetrics().height()/2
985 - paint.fontMetrics().descent(), 986 - paint.fontMetrics().descent(),
986 vlabel, View::OutlinedText); 987 vlabel, PaintAssistant::OutlinedText);
987 988
988 QString hlabel = RealTime::frame2RealTime 989 QString hlabel = RealTime::frame2RealTime
989 (p.frame, m_model->getSampleRate()).toText(true).c_str(); 990 (p.frame, m_model->getSampleRate()).toText(true).c_str();
990 v->drawVisibleText(paint, 991 PaintAssistant::drawVisibleText(v, paint,
991 x, 992 x,
992 y - h/2 - paint.fontMetrics().descent() - 2, 993 y - h/2 - paint.fontMetrics().descent() - 2,
993 hlabel, View::OutlinedText); 994 hlabel, PaintAssistant::OutlinedText);
994 } 995 }
995 996
996 paint.drawLine(x, y-1, x + w, y-1); 997 paint.drawLine(x, y-1, x + w, y-1);
997 paint.drawLine(x, y+1, x + w, y+1); 998 paint.drawLine(x, y+1, x + w, y+1);
998 paint.drawLine(x, y - h/2, x, y + h/2); 999 paint.drawLine(x, y - h/2, x, y + h/2);
1038 - paint.fontMetrics().descent(); 1039 - paint.fontMetrics().descent();
1039 } else { 1040 } else {
1040 labelX = x + 5; 1041 labelX = x + 5;
1041 labelY = v->getTextLabelHeight(this, paint); 1042 labelY = v->getTextLabelHeight(this, paint);
1042 if (labelX < nextLabelMinX) { 1043 if (labelX < nextLabelMinX) {
1043 if (lastLabelY < v->height()/2) { 1044 if (lastLabelY < v->getPaintHeight()/2) {
1044 labelY = lastLabelY + fontHeight; 1045 labelY = lastLabelY + fontHeight;
1045 } 1046 }
1046 } 1047 }
1047 lastLabelY = labelY; 1048 lastLabelY = labelY;
1048 nextLabelMinX = labelX + paint.fontMetrics().width(label); 1049 nextLabelMinX = labelX + paint.fontMetrics().width(label);
1049 } 1050 }
1050 1051
1051 v->drawVisibleText(paint, labelX, labelY, label, View::OutlinedText); 1052 PaintAssistant::drawVisibleText(v, paint, labelX, labelY, label, PaintAssistant::OutlinedText);
1052 } 1053 }
1053 } 1054 }
1054 1055
1055 paint.restore(); 1056 paint.restore();
1056 } 1057 }
1057 1058
1058 int 1059 int
1059 RegionLayer::getVerticalScaleWidth(View *v, bool, QPainter &paint) const 1060 RegionLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const
1060 { 1061 {
1061 if (!m_model || 1062 if (!m_model ||
1062 m_verticalScale == AutoAlignScale || 1063 m_verticalScale == AutoAlignScale ||
1063 m_verticalScale == EqualSpaced) { 1064 m_verticalScale == EqualSpaced) {
1064 return 0; 1065 return 0;
1076 } 1077 }
1077 } 1078 }
1078 } 1079 }
1079 1080
1080 void 1081 void
1081 RegionLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect) const 1082 RegionLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
1082 { 1083 {
1083 if (!m_model || m_model->getPoints().empty()) return; 1084 if (!m_model || m_model->getPoints().empty()) return;
1084 1085
1085 QString unit; 1086 QString unit;
1086 double min, max; 1087 double min, max;
1119 mw)); 1120 mw));
1120 } 1121 }
1121 } 1122 }
1122 1123
1123 void 1124 void
1124 RegionLayer::drawStart(View *v, QMouseEvent *e) 1125 RegionLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e)
1125 { 1126 {
1126 if (!m_model) return; 1127 if (!m_model) return;
1127 1128
1128 sv_frame_t frame = v->getFrameForX(e->x()); 1129 sv_frame_t frame = v->getFrameForX(e->x());
1129 if (frame < 0) frame = 0; 1130 if (frame < 0) frame = 0;
1143 1144
1144 m_editing = true; 1145 m_editing = true;
1145 } 1146 }
1146 1147
1147 void 1148 void
1148 RegionLayer::drawDrag(View *v, QMouseEvent *e) 1149 RegionLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e)
1149 { 1150 {
1150 if (!m_model || !m_editing) return; 1151 if (!m_model || !m_editing) return;
1151 1152
1152 sv_frame_t frame = v->getFrameForX(e->x()); 1153 sv_frame_t frame = v->getFrameForX(e->x());
1153 if (frame < 0) frame = 0; 1154 if (frame < 0) frame = 0;
1173 1174
1174 recalcSpacing(); 1175 recalcSpacing();
1175 } 1176 }
1176 1177
1177 void 1178 void
1178 RegionLayer::drawEnd(View *, QMouseEvent *) 1179 RegionLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
1179 { 1180 {
1180 if (!m_model || !m_editing) return; 1181 if (!m_model || !m_editing) return;
1181 finish(m_editingCommand); 1182 finish(m_editingCommand);
1182 m_editingCommand = 0; 1183 m_editingCommand = 0;
1183 m_editing = false; 1184 m_editing = false;
1184 1185
1185 recalcSpacing(); 1186 recalcSpacing();
1186 } 1187 }
1187 1188
1188 void 1189 void
1189 RegionLayer::eraseStart(View *v, QMouseEvent *e) 1190 RegionLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
1190 { 1191 {
1191 if (!m_model) return; 1192 if (!m_model) return;
1192 1193
1193 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1194 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1194 1195
1200 m_editing = true; 1201 m_editing = true;
1201 recalcSpacing(); 1202 recalcSpacing();
1202 } 1203 }
1203 1204
1204 void 1205 void
1205 RegionLayer::eraseDrag(View *, QMouseEvent *) 1206 RegionLayer::eraseDrag(LayerGeometryProvider *, QMouseEvent *)
1206 { 1207 {
1207 } 1208 }
1208 1209
1209 void 1210 void
1210 RegionLayer::eraseEnd(View *v, QMouseEvent *e) 1211 RegionLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e)
1211 { 1212 {
1212 if (!m_model || !m_editing) return; 1213 if (!m_model || !m_editing) return;
1213 1214
1214 m_editing = false; 1215 m_editing = false;
1215 1216
1227 m_editing = false; 1228 m_editing = false;
1228 recalcSpacing(); 1229 recalcSpacing();
1229 } 1230 }
1230 1231
1231 void 1232 void
1232 RegionLayer::editStart(View *v, QMouseEvent *e) 1233 RegionLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e)
1233 { 1234 {
1234 if (!m_model) return; 1235 if (!m_model) return;
1235 1236
1236 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { 1237 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) {
1237 return; 1238 return;
1252 m_dragStartY = e->y(); 1253 m_dragStartY = e->y();
1253 recalcSpacing(); 1254 recalcSpacing();
1254 } 1255 }
1255 1256
1256 void 1257 void
1257 RegionLayer::editDrag(View *v, QMouseEvent *e) 1258 RegionLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e)
1258 { 1259 {
1259 if (!m_model || !m_editing) return; 1260 if (!m_model || !m_editing) return;
1260 1261
1261 int xdist = e->x() - m_dragStartX; 1262 int xdist = e->x() - m_dragStartX;
1262 int ydist = e->y() - m_dragStartY; 1263 int ydist = e->y() - m_dragStartY;
1287 m_editingCommand->addPoint(m_editingPoint); 1288 m_editingCommand->addPoint(m_editingPoint);
1288 recalcSpacing(); 1289 recalcSpacing();
1289 } 1290 }
1290 1291
1291 void 1292 void
1292 RegionLayer::editEnd(View *, QMouseEvent *) 1293 RegionLayer::editEnd(LayerGeometryProvider *, QMouseEvent *)
1293 { 1294 {
1294 if (!m_model || !m_editing) return; 1295 if (!m_model || !m_editing) return;
1295 1296
1296 if (m_editingCommand) { 1297 if (m_editingCommand) {
1297 1298
1315 m_editing = false; 1316 m_editing = false;
1316 recalcSpacing(); 1317 recalcSpacing();
1317 } 1318 }
1318 1319
1319 bool 1320 bool
1320 RegionLayer::editOpen(View *v, QMouseEvent *e) 1321 RegionLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1321 { 1322 {
1322 if (!m_model) return false; 1323 if (!m_model) return false;
1323 1324
1324 RegionModel::Point region(0); 1325 RegionModel::Point region(0);
1325 if (!getPointToDrag(v, e->x(), e->y(), region)) return false; 1326 if (!getPointToDrag(v, e->x(), e->y(), region)) return false;
1445 finish(command); 1446 finish(command);
1446 recalcSpacing(); 1447 recalcSpacing();
1447 } 1448 }
1448 1449
1449 void 1450 void
1450 RegionLayer::copy(View *v, Selection s, Clipboard &to) 1451 RegionLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1451 { 1452 {
1452 if (!m_model) return; 1453 if (!m_model) return;
1453 1454
1454 RegionModel::PointList points = 1455 RegionModel::PointList points =
1455 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1456 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1463 } 1464 }
1464 } 1465 }
1465 } 1466 }
1466 1467
1467 bool 1468 bool
1468 RegionLayer::paste(View *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) 1469 RegionLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */)
1469 { 1470 {
1470 if (!m_model) return false; 1471 if (!m_model) return false;
1471 1472
1472 const Clipboard::PointList &points = from.getPoints(); 1473 const Clipboard::PointList &points = from.getPoints();
1473 1474
1474 bool realign = false; 1475 bool realign = false;
1475 1476
1476 if (clipboardHasDifferentAlignment(v, from)) { 1477 if (clipboardHasDifferentAlignment(v, from)) {
1477 1478
1478 QMessageBox::StandardButton button = 1479 QMessageBox::StandardButton button =
1479 QMessageBox::question(v, tr("Re-align pasted items?"), 1480 QMessageBox::question(v->getView(), tr("Re-align pasted items?"),
1480 tr("The items you are pasting came from a layer with different source material from this one. Do you want to re-align them in time, to match the source material for this layer?"), 1481 tr("The items you are pasting came from a layer with different source material from this one. Do you want to re-align them in time, to match the source material for this layer?"),
1481 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, 1482 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
1482 QMessageBox::Yes); 1483 QMessageBox::Yes);
1483 1484
1484 if (button == QMessageBox::Cancel) { 1485 if (button == QMessageBox::Cancel) {