void BifurcationPlot::OnMouseUp(wxMouseEvent& evt) { /** * Event handler for the mouse up on a plot. * This event sets the zoom level for a graph based on the zooming * rectangle drawn by the user. This function will only zoom if the * rectangle is greater than min_delta and if zooming will not give * a higher difference between the minimum and maximum values than * MAX_ZOOM. * * Overrides the MouseUp function in ChaosPlot because the * Bifurcation plots the largest X value on the left. */ const int min_delta = 10; const int MAX_ZOOM = 50; if(mouse_dragging == true) { int x_position = evt.m_x; int y_position = evt.m_y; if(drag_start.x < x_position && x_position - drag_start.x > min_delta) { int tmp2 = xToValue(drag_start.x); int tmp1 = xToValue(x_position); if(tmp2 - tmp1 > MAX_ZOOM) { smallest_x_value = tmp1; largest_x_value = tmp2; ChaosSettings::BifRedraw = true; } } else if(drag_start.x > x_position && drag_start.x - x_position > min_delta) { int tmp2 = xToValue(x_position); int tmp1 = xToValue(drag_start.x); if(tmp2 - tmp1 > MAX_ZOOM) { smallest_x_value = tmp1; largest_x_value = tmp2; ChaosSettings::BifRedraw = true; } } if(drag_start.y < y_position && y_position - drag_start.y > min_delta) { int tmp1 = yToValue(drag_start.y); int tmp2 = yToValue(y_position); if(tmp1 - tmp2 > MAX_ZOOM) { largest_y_value = tmp1; smallest_y_value = tmp2; ChaosSettings::BifRedraw = true; } } else if(drag_start.y > y_position && drag_start.y - y_position > min_delta) { int tmp1 = yToValue(y_position); int tmp2 = yToValue(drag_start.y); if(tmp1 - tmp2 > MAX_ZOOM) { largest_y_value = tmp1; smallest_y_value = tmp2; ChaosSettings::BifRedraw = true; } } wxLogMessage(wxT("y_min: %d\ny_max: %d"), smallest_y_value, largest_y_value); wxLogMessage(wxT("x_min: %d\nx_max: %d"), smallest_x_value, largest_x_value); } mouse_dragging = false; }
void ChaosPlot::OnMouseUp(wxMouseEvent& evt) { /** * Event handler for the mouse up on a plot. * This event sets the zoom level for a graph based on the zooming * rectangle drawn by the user. This function will only zoom if the * rectangle is greater than min_delta and if zooming will not give * a higher difference between the minimum and maximum values than * MAX_ZOOM. */ const int min_delta = 10; const int MAX_ZOOM = 25; if(mouse_dragging == true) { int x_position = evt.m_x; int y_position = evt.m_y; // Initialize tmp1 and tmp2 int tmp1 = smallest_x_value; int tmp2 = largest_x_value; // Calculate the new X boundaries based on if we dragged a box left or right if(drag_start.x < x_position && x_position - drag_start.x > min_delta) { tmp1 = xToValue(drag_start.x); tmp2 = xToValue(x_position); } else if(drag_start.x > x_position && drag_start.x - x_position > min_delta) { tmp1 = xToValue(x_position); tmp2 = xToValue(drag_start.x); } // Update the largest and smallest values if(tmp2 - tmp1 > MAX_ZOOM) { smallest_x_value = tmp1; largest_x_value = tmp2; } // Calculate the new Y boundaries based on if we dragged a box up or down if(drag_start.y < y_position && y_position - drag_start.y > min_delta) { tmp1 = yToValue(drag_start.y); tmp2 = yToValue(y_position); } else if(drag_start.y > y_position && drag_start.y - y_position > min_delta) { tmp1 = yToValue(y_position); tmp2 = yToValue(drag_start.y); } // Update the largest and smallest values if(tmp1 - tmp2 > MAX_ZOOM) { largest_y_value = tmp1; smallest_y_value = tmp2; } // Write zoom to log wxLogMessage(wxT("y_min: %d\ny_max: %d"), smallest_y_value, largest_y_value); wxLogMessage(wxT("x_min: %d\nx_max: %d"), smallest_x_value, largest_x_value); } // We aren't dragging the mouse anymore mouse_dragging = false; }
void BifurcationPlot::UpdateStatusBar(int m_x, int m_y) { /** * Updates the cursor information in the status bar */ float x, y; if(statusBar) { x = xToValue(m_x); y = yToValue(m_y); if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) { y = y*3.3/1024 - 1.2; } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) { y = y*3.3/1024; } if(ChaosSettings::BifXAxis == ChaosSettings::RESISTANCE_VALUES) { x = libchaos_mdacToResistance((int)x)/1000; statusBar->SetStatusText(wxString::Format(wxT("(%.3fk,%.3f)"), x, y), 3); } else { statusBar->SetStatusText(wxString::Format(wxT("(%d,%.3f)"), (int)x, y), 3); } } }
Event *ControllerEventsRuler::insertEvent(float x, float y) { timeT insertTime = m_rulerScale->getTimeForX(x/m_xScale); Event* controllerEvent = new Event(m_controller->getType(), insertTime); long initialValue = yToValue(y); RG_DEBUG << "ControllerEventsRuler::insertControllerEvent() : inserting event at " << insertTime << " - initial value = " << initialValue << endl; // ask controller number to user long number = 0; if (m_controller) { number = m_controller->getControllerValue(); } else { //!!! // Weird. I've never seen this in action in eight years. I guess this // is some out there failsafe that never gets used in practice. The // code looks wrong anyway. 0 to 128? // // Noting it with raised eyebrows and moving along for now. bool ok = false; QIntValidator intValidator(0, 128, this); // QString res = KLineEditDlg::getText(tr("Controller Event Number"), "0", // &ok, this, &intValidator); QString res = InputDialog::getText(this, "", tr("Controller Event Number"), LineEdit::Normal, "0", &ok); if (ok) number = res.toULong(); } if (m_controller->getType() == Rosegarden::Controller::EventType) { controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::VALUE, initialValue); controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::NUMBER, number); } else if (m_controller->getType() == Rosegarden::PitchBend::EventType) { // Convert to PitchBend MSB/LSB int lsb = initialValue & 0x7f; int msb = (initialValue >> 7) & 0x7f; controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::MSB, msb); controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::LSB, lsb); }
void TransitionWidget::mouseDoubleClickEvent(QMouseEvent* event) { if (pointList_ == nullptr) { return; } #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QPointF pos = event->localPos(); #else QPointF pos = event->posF(); #endif double time = xToTime(pos.x()); double value = yToValue(pos.y()); const double minValue = special_ ? -140.0 : -20.0; const double maxValue = special_ ? 140.0 : 120.0; if (time >= 0.0 && time <= ruleDuration_ && value >= minValue && value <= maxValue) { unsigned int pointType; switch (transitionType_) { case TRMControlModel::Transition::TYPE_DIPHONE: pointType = 2; break; case TRMControlModel::Transition::TYPE_TRIPHONE: if (time <= mark1_) { pointType = 2; } else { pointType = 3; } break; case TRMControlModel::Transition::TYPE_TETRAPHONE: if (time <= mark1_) { pointType = 2; } else if (time <= mark2_) { pointType = 3; } else { pointType = 4; } break; default: return; } qDebug("mouseDoubleClickEvent type=%u time=%f value=%f", pointType, time, value); emit pointCreationRequested(pointType, time, value); } }
void IntonationWidget::mouseDoubleClickEvent(QMouseEvent* event) { qDebug("IntonationWidget::mouseDoubleClickEvent"); if (eventList_ == nullptr || eventList_->list().empty() || intonationPointList_.empty()) { return; } if (event->button() != Qt::LeftButton) return; #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QPointF clickPoint = event->localPos(); #else QPointF clickPoint = event->posF(); #endif double clickTime = xToTime(clickPoint.x()); unsigned int ruleIndex = 0; double minDist = 1.0e10; for (unsigned int i = 0, size = eventList_->numberOfRules(); i < size; ++i) { auto* ruleData = eventList_->getRuleAtIndex(i); double distance = std::abs(clickTime - ruleData->beat); if (distance <= minDist) { minDist = distance; ruleIndex = i; } else { break; } } auto* ruleData = eventList_->getRuleAtIndex(ruleIndex); TRMControlModel::IntonationPoint newPoint(eventList_); newPoint.setRuleIndex(ruleIndex); newPoint.setOffsetTime(clickTime - ruleData->beat); newPoint.setSemitone(yToValue(clickPoint.y())); selectedPoint_ = addIntonationPoint(newPoint); qDebug("selectedPoint_ = %d", selectedPoint_); sendSelectedPointData(); update(); }
void ChaosPlot::UpdateStatusBar(int m_x, int m_y) { /** * Updates the cursor information in the status bar */ float x, y; if(statusBar) { x = xToValue(m_x); y = yToValue(m_y); if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) { y = y*3.3/1024 - 1.2; } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) { y = y*3.3/1024; } statusBar->SetStatusText(wxString::Format(wxT("(%.3f,%.3f)"), x, y), 3); } }
void ControllerEventsRuler::addControlLine(float x1, float y1, float x2, float y2, bool eraseExistingControllers) { std::cout << "ControllerEventsRuler::addControlLine()"; clearSelectedItems(); // get a timeT for one end point of our line timeT originTime = m_rulerScale->getTimeForX(x1); // get a timeT for the other end point of our line timeT destinationTime = m_rulerScale->getTimeForX(x2); // get a value for one end point of our line long originValue = yToValue(y1); // get a value for the other end point long destinationValue = yToValue(y2); if (originTime == destinationTime || originValue == destinationValue) return; // If the "anchor point" was to the right of the newly clicked destination // point, we're drawing a line from right to left. We simply swap origin // for destination and calculate all lines as drawn from left to right, for // convenience and sanity. if (originTime > destinationTime) { timeT swapTime = originTime; originTime = destinationTime; destinationTime = swapTime; long swapValue = originValue; originValue = destinationValue; destinationValue = swapValue; } // save a list of existing events that occur within the span of the new line // for later deletion, if desired std::vector<Event*> eventsToClear; if (eraseExistingControllers) { for (Segment::iterator si = m_segment->begin(); si != m_segment->end(); ++si) { timeT t = (*si)->getNotationAbsoluteTime(); if (t >= originTime && t <= destinationTime) { eventsToClear.push_back(*si); } } } // rise and run long rise = destinationValue - originValue; timeT run = destinationTime - originTime; std::cout << "Drawing a line from origin time: " << originTime << " to " << destinationTime << " rising from: " << originValue << " to " << destinationValue << " with a rise of: " << rise << " and run of: " << run << std::endl; // avoid divide by 0 potential, rise is always at least 1 if (rise == 0) rise = 1; // are we rising or falling? bool rising = (rise > 0); // always calculate step on a positive value for rise, and make sure it's at // least 1 float step = run / (float)(rising ? rise : rise * -1); // Trying this with pitch bend with a rise approaching the maximum over a // span of around four bars generated over 15,000 pitch bend events! That's // super duper fine resolution, but it's too much for anything to handle. // Let's try to do some sensible thinning without getting too complicated... // bool isPitchBend = (m_controller->getType() == Rosegarden::PitchBend::EventType); int thinningHackCounter = 1; long intermediateValue = originValue; long controllerNumber = 0; if (m_controller) { controllerNumber = m_controller->getControllerValue(); } else { std::cout << "No controller number set. Time to panic! Line drawing aborted." << std::endl; return; } MacroCommand *macro = new MacroCommand(tr("Insert Line of Controllers")); bool failsafe = false; // if we're clearing existing events, add that to the macro command for (std::vector<Event*>::iterator ei = eventsToClear.begin(); ei != eventsToClear.end(); ++ei) { // if the event was a controller or pitch bend, and it is on this ruler, // add it to the list if (((*ei)->isa(Controller::EventType) || (*ei)->isa(PitchBend::EventType)) && isOnThisRuler(*ei)) { bool collapseRests = true; macro->addCommand(new EraseEventCommand(*m_segment, *ei, collapseRests)); } } if (macro->haveCommands()) { CommandHistory::getInstance()->addCommand(macro); macro = new MacroCommand(tr("Insert Line of Controllers")); } for (float i = originTime; i <= destinationTime; i += step) { if (failsafe) continue; if (rising) intermediateValue++; else intermediateValue--; if (rising && intermediateValue > destinationValue) failsafe = true; else if (!rising && intermediateValue < destinationValue) failsafe = true; // std::cout << "creating event at time: " << i << " of value: " << intermediateValue << std::endl; // continue; Event *controllerEvent = new Event(m_controller->getType(), (timeT) i); if (m_controller->getType() == Rosegarden::Controller::EventType) { controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::VALUE, intermediateValue); controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::NUMBER, controllerNumber); } else if (m_controller->getType() == Rosegarden::PitchBend::EventType) { // always set the first and last events, then only set every 25th, // 50th, and 75th event for pitch bend if (thinningHackCounter++ > 100) thinningHackCounter = 1; if (thinningHackCounter != 25 && thinningHackCounter != 50 && thinningHackCounter != 75 && i != originTime && i != destinationTime) continue; std::cout << "intermediate value: " << intermediateValue << std::endl; // Convert to PitchBend MSB/LSB int lsb = intermediateValue & 0x7f; int msb = (intermediateValue >> 7) & 0x7f; controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::MSB, msb); controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::LSB, lsb); } if (failsafe) std::cout << "intermediate value: " << intermediateValue << " exceeded target: " << destinationValue << std::endl; macro->addCommand(new EventInsertionCommand (*m_segment, controllerEvent)); } m_moddingSegment = true; CommandHistory::getInstance()->addCommand(macro); m_moddingSegment = false; // How else to re-initialize and bring things into view? I'm missing // something, but this works... init(); }
void ControllerEventsRuler::paintEvent(QPaintEvent *event) { ControlRuler::paintEvent(event); // If this is the first time we've drawn this view, // reconfigure all items to make sure their icons // come out the right size ///@TODO Only reconfigure all items if zoom has changed if (m_lastDrawnRect != m_pannedRect) { EventControlItem *item; for (ControlItemMap::iterator it = m_controlItemMap.begin(); it != m_controlItemMap.end(); ++it) { item = static_cast <EventControlItem *> (it->second); item->reconfigure(); } m_lastDrawnRect = m_pannedRect; } QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QBrush brush(GUIPalette::getColour(GUIPalette::ControlItem),Qt::SolidPattern); // QPen highlightPen(GUIPalette::getColour(GUIPalette::SelectedElement), // 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); QPen pen(GUIPalette::getColour(GUIPalette::MatrixElementBorder), 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); painter.setBrush(brush); painter.setPen(pen); QString str; // str = QString::fromStdString(m_controller->getName()); // painter.drawText(10,20,str.toUpper()); ControlItemMap::iterator mapIt; float lastX, lastY; lastX = m_rulerScale->getXForTime(m_segment->getStartTime()); if (m_nextItemLeft != m_controlItemMap.end()) { EventControlItem *item = static_cast<EventControlItem*> (m_nextItemLeft->second); lastY = item->y(); } else { lastY = valueToY(m_controller->getDefault()); } mapIt = m_firstVisibleItem; while (mapIt != m_controlItemMap.end()) { EventControlItem *item = static_cast<EventControlItem*> (mapIt->second); painter.drawLine(mapXToWidget(lastX),mapYToWidget(lastY), mapXToWidget(item->xStart()),mapYToWidget(lastY)); painter.drawLine(mapXToWidget(item->xStart()),mapYToWidget(lastY), mapXToWidget(item->xStart()),mapYToWidget(item->y())); lastX = item->xStart(); lastY = item->y(); if (mapIt == m_lastVisibleItem) { mapIt = m_controlItemMap.end(); } else { ++mapIt; } } painter.drawLine(mapXToWidget(lastX),mapYToWidget(lastY), mapXToWidget(m_rulerScale->getXForTime(m_segment->getEndTime())*m_xScale), mapYToWidget(lastY)); // Use a fast vector list to record selected items that are currently visible so that they // can be drawn last - can't use m_selectedItems as this covers all selected, visible or not std::vector<ControlItem*> selectedvector; for (ControlItemList::iterator it = m_visibleItems.begin(); it != m_visibleItems.end(); ++it) { if (!(*it)->isSelected()) { painter.drawPolygon(mapItemToWidget(*it)); } else { selectedvector.push_back(*it); } } // painter.setBrush(brush); pen.setColor(GUIPalette::getColour(GUIPalette::SelectedElement)); pen.setWidthF(2.0); painter.setPen(pen); QFontMetrics fontMetrics(painter.font()); int fontHeight = fontMetrics.height(); int fontOffset = fontMetrics.width('+'); for (std::vector<ControlItem*>::iterator it = selectedvector.begin(); it != selectedvector.end(); ++it) { // Draw the marker painter.drawPolygon(mapItemToWidget(*it)); // For selected items, draw the value in text alongside the marker // By preference, this should sit on top of the new line that represents this value change str = QString::number(yToValue((*it)->y())-m_controller->getDefault()); int x = mapXToWidget((*it)->xStart())+0.4*fontOffset; int y = std::max(mapYToWidget((*it)->y())-0.2f*fontHeight,float(fontHeight)); painter.setPen(QPen(Qt::NoPen)); painter.setBrush(QBrush(Qt::white)); painter.drawRect(QRect(x,y+2,fontMetrics.width(str),-(fontMetrics.height()-2))); painter.setPen(pen); painter.setBrush(brush); painter.drawText(x,y,str); } if (m_selectionRect) { pen.setColor(GUIPalette::getColour(GUIPalette::MatrixElementBorder)); pen.setWidthF(0.5); painter.setPen(pen); brush.setStyle(Qt::NoBrush); painter.setBrush(brush); painter.drawRect(mapItemToWidget(m_selectionRect)); } // draw the rubber band indicating where a line of controllers will go if (m_rubberBand && m_rubberBandVisible) { int x1 = mapXToWidget(m_rubberBand->x1()); int y1 = mapYToWidget(m_rubberBand->y1()); int x2 = mapXToWidget(m_rubberBand->x2()); int y2 = mapYToWidget(m_rubberBand->y2()); painter.setPen(Qt::red); painter.drawLine(x1, y1, x2, y2); } }