예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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);
        }
    }
}
예제 #4
0
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);
    }
예제 #5
0
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);
	}
}
예제 #6
0
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();
}
예제 #7
0
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);
    }
}
예제 #8
0
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();
}
예제 #9
0
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);
    }
}