// Return ColourScalePoint corresponding to label under mouse (if any)
ColourScalePoint* TColourScaleEditor::labelUnderMouse(QPoint pos)
{
	// Get the size of the textrect we need
	QRect masterTextRect = style()->itemTextRect(fontMetrics(), QRect(), Qt::AlignRight | Qt::AlignVCenter, true, QString::number(-0.123456, 'e', 6));
	int margin = masterTextRect.height()*0.5;
	masterTextRect.setLeft(margin);
	masterTextRect.setRight(width() - gradientBarWidth_ - 3*margin - handleRadius_*2);

	// Draw text and line elements
	if (colourScale_.nPoints() > 0)
	{
		double zero = colourScale_.firstPoint()->value();
		double span = colourScale_.lastPoint()->value() - zero;
		for (ColourScalePoint* csp = colourScale_.firstPoint(); csp != NULL; csp = csp->next)
		{
			int y = (1.0 - (csp->value() - zero) / span) * (height() - 2*margin) + margin;
			QString numberText = QString::number(csp->value(), 'e', 6);
			masterTextRect.moveBottom(y + 0.5*masterTextRect.height());

			QRect textRect = style()->itemTextRect(fontMetrics(), masterTextRect, Qt::AlignRight | Qt::AlignVCenter, true, numberText);
			if (textRect.contains(pos)) return csp;
		}
	}

	return NULL;
}
// Paint event callback
void TColourScaleEditor::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);

	// Get the size of the textrect we need
	QRect masterTextRect = style()->itemTextRect(fontMetrics(), QRect(), Qt::AlignRight | Qt::AlignVCenter, true, QString::number(-0.123456, 'e', 6));
	int margin = masterTextRect.height()*0.5;
	masterTextRect.setLeft(margin);
	masterTextRect.setRight(width() - gradientBarWidth_ - 3*margin - handleRadius_*2);

	// Set up the basic handle style option
	QStyleOption handleOption;
	handleOption.rect.setRight(width()-margin);
	handleOption.rect.setLeft(width()-margin-handleRadius_*2);
	handleOption.rect.setHeight(masterTextRect.height());

	// Draw gradient bar
	QBrush brush(gradient_);
	QPen pen(Qt::black);
	QRect gradientRect;
	gradientRect.setHeight(height()-2*margin);
	gradientRect.setWidth(gradientBarWidth_);
	gradientRect.moveTop(margin);
	gradientRect.moveRight(width() - 2*margin - handleRadius_*2);
	painter.setBrush(brush);
	painter.setPen(pen);
	painter.drawRect(gradientRect);

	// Define regions
	gradientBarRegion_ = QRegion(gradientRect);
	// -- Handle and label region spans top to bottom of the widget (i.e. excluding margins)
	handleRegion_ = QRegion(QRect(width() - margin - 2*handleRadius_, 0, 2*handleRadius_, height()));
	labelRegion_ = QRegion(QRect(0, 0, width() - gradientRect.right() - margin, height()));

	// Draw text and line elements
	if (colourScale_.nPoints() > 0)
	{
		double zero = colourScale_.firstPoint()->value();
		double span = colourScale_.lastPoint()->value() - zero;
		for (ColourScalePoint* csp = colourScale_.firstPoint(); csp != NULL; csp = csp->next)
		{
			int y = (1.0 - (csp->value() - zero) / span) * (height() - 2*margin) + margin;
			QString numberText = QString::number(csp->value(), 'e', 6);
			masterTextRect.moveBottom(y + 0.5*masterTextRect.height());
			painter.setPen(palette().text().color());
			style()->drawItemText(&painter, masterTextRect, Qt::AlignRight | Qt::AlignVCenter, palette(), true, numberText);
			painter.drawLine(gradientRect.left()-margin, y, gradientRect.right()+margin, y);

			// Draw handle for this point
			handleOption.rect.moveBottom(y + 0.5*masterTextRect.height());
			if (csp == currentColourScalePoint_) handleOption.state = QStyle::State_Enabled;
			else if (csp == hoverColourScalePoint_) handleOption.state = QStyle::State_MouseOver;
			else handleOption.state = 0;
			drawHandle(handleOption, painter);
		}
	}

	painter.end();
}
Exemple #3
0
// Get colour associated with value supplied (as Vec4<GLfloat>)
void ColourScale::colour(double value, Vec4<GLfloat>& target) const
{
    // Step through points associated to scale and find the two that we are inbetween.
    // Check for no points being defined
    if (points_.nItems() == 0)
    {
        target.x = 0.0;
        target.y = 0.0;
        target.z = 0.0;
        target.w = 1.0;
        return;
    }

    ColourScalePoint* csp = points_.first();
    // Is supplied value less than the value at the first point?
    if (value < csp->value())
    {
        csp->colour(target);
        return;
    }

    // Find the correct delta to use
    for (ColourScaleDelta* delta = deltas_.first(); delta != NULL; delta = delta->next)
    {
        if (delta->containsValue(value))
        {
            delta->colour(interpolated_ ? value : delta->start(), useHSV_, target);
            return;
        }
    }

    // If we get to here then the supplied value is outside the range of all values, so take colour from the endpoint
    //printf("OUTSIDE RANGE\n");
    points_.last()->colour(target);
}
Exemple #4
0
// Return colour associated with value provided
void ColourScale::colour(double v, GLfloat* target)
{
	// Step through points associated to scale and find the two that we are inbetween.
	// Check for no points being defined
	if (points_.nItems() == 0)
	{
		target[0] = (GLfloat) 0.0;
		target[1] = (GLfloat) 0.0;
		target[2] = (GLfloat) 0.0;
		target[3] = (GLfloat) 0.0;
		return;
	}
	ColourScalePoint* csp = points_.first();

	// Is supplied value less than the value at the first point?
	if (v < csp->value())
	{
		csp->copyColour(target);
		return;
	}

	// Find the correct delta to use
	for (ColourScaleDelta* delta = deltas_.first(); delta != NULL; delta = delta->next)
	{
		if (delta->containsValue(v))
		{
			delta->colour( interpolated_ ? v : delta->start(), target);
			return;
		}
	}

	// If we get to here then the supplied value is outside the range of all values, so take colour from the endpoint
	points_.last()->copyColour(target);
}
void TColourScaleEditor::contextMenuRequested(const QPoint& point)
{
	// Get handle at clicked point
	ColourScalePoint* clickedPoint = handleUnderMouse(point);
	if (!clickedPoint) return;

	// Build the context menu to display
	QMenu contextMenu;
	QAction* valueAction = contextMenu.addAction("&Set value...");
	QAction* deleteAction = contextMenu.addAction("&Delete");
	QAction* spaceAction = contextMenu.addAction("&Set to midpoint");
	if ((!clickedPoint->prev) || (!clickedPoint->next)) spaceAction->setEnabled(false);

	// Show it
	QPoint menuPosition = mapToGlobal(point);
	QAction* menuResult = contextMenu.exec(menuPosition);

	// What was clicked?
	if (menuResult == valueAction)
	{
		bool ok;
		double newValue = QInputDialog::getDouble(this, "Set point value", "New value: ", clickedPoint->value(), -1.0e7, 1.0e7, 6, &ok);
		if (ok)
		{
			colourScale_.setValue(clickedPoint, newValue);

			updateGradient();
			repaint();

			emit(colourScaleChanged());
		}
	}
	else if (menuResult == deleteAction)
	{
		colourScale_.removePoint(clickedPoint);
		
		updateGradient();
		repaint();

		emit(colourScaleChanged());
	}
	else if (menuResult == spaceAction)
	{
		// Get average values of next and previous points
		double averageValue = (clickedPoint->next->value() + clickedPoint->prev->value()) * 0.5;

		colourScale_.setValue(clickedPoint, averageValue);

		updateGradient();
		repaint();

		emit(colourScaleChanged());
	}
}
Exemple #6
0
// Set colour and value data for point
void ColourScale::setPoint(int position, double value, QColor colour, bool setval, bool setcol)
{
    // Check position supplied
    if ((position < 0) || (position >= points_.nItems()))
    {
        printf("Scale point position to set (%i) is invalid - nItems = %i.\n", position, points_.nItems());
        return;
    }
    if (setcol) points_[position]->setColour(colour);
    if (setval)
    {
        points_[position]->setValue(value);
        // Position in list may have changed - check...
        bool minBad = true, maxBad = true;
        ColourScalePoint* csp = points_[position];
        int dummy = 0;
        do
        {
// 			printf("BEFORE SHIFT Prev = %f, current= %f, next = %f\n", csp->prev ? csp->prev->value() : -999, csp->value(), csp->next ? csp->next->value() : -999);
            // Shift item if necessary
            if (csp->prev && (csp->prev->value() > csp->value()))
            {
                points_.shiftUp(csp);
                minBad = (csp->prev ? (csp->prev->value() > csp->value()) : false);
            }
            else minBad = false;
            if (csp->next && (csp->next->value() < csp->value()))
            {
                points_.shiftDown(csp);
                maxBad = (csp->next ? (csp->next->value() < csp->value()) : false);
            }
            else maxBad = false;
// 			printf("AFTER SHIFT %i Prev = %f, current= %f, next = %f  B=%i %i\n", dummy, csp->prev ? csp->prev->value() : -999, csp->value(), csp->next ? csp->next->value() : -999, minBad, maxBad);
            if (++dummy == 10) break;

        } while (minBad || maxBad);
    }

    // Recalculate colour deltas
    calculateDeltas();
}
Exemple #7
0
// Return colour associated with value provided
QColor ColourScale::colour(double value) const
{
    // Step through points associated to scale and find the two that we are inbetween.
    // Check for no points being defined
    if (points_.nItems() == 0) return QColor(0,0,0);

    ColourScalePoint* csp = points_.first();
    // Is supplied value less than the value at the first point?
    if (value < csp->value()) return csp->colour();

    // Find the correct delta to use
    for (ColourScaleDelta* delta = deltas_.first(); delta != NULL; delta = delta->next)
    {
        if (delta->containsValue(value)) return delta->colour(interpolated_ ? value : delta->start(), useHSV_);
    }

    // If we get to here then the supplied value is outside the range of all values, so take colour from the endpoint
    return points_.last()->colour();
}
Exemple #8
0
// Add point to scale
ColourScalePoint* ColourScale::addPoint(double value, double r, double g, double b, double a)
{
	Messenger::enter("ColourScale::addPoint");

	// Find position to insert new point at
	ColourScalePoint* newPoint = NULL;
	if (points_.nItems() == 0) newPoint = points_.add();
	else if (value < points_.first()->value()) newPoint = points_.prepend();
	else if (value > points_.last()->value()) newPoint = points_.add();
	else
	{
		for (ColourScalePoint* point = points_.first()->next; point != NULL; point = point->next)
		{
			if (value < point->value())
			{
				newPoint = points_.insertBefore(point);
				break;
			}
		}
	}

	// Double-check we have a new point
	if (!newPoint)
	{
		printf("Internal Error: ColourScale::addPoint() failed to add a point.\n");
		return NULL;
	}

	// Now, set data in new point
	newPoint->setParent(this);
	newPoint->setColour(r, g, b, a);
	newPoint->setValue(value);

	// Recalculate colour deltas
	calculateDeltas();

	// Refresh linked objects
	refreshObjects();

	Messenger::exit("ColourScale::addPoint");
	return newPoint;
}
// Return ColourScalePoint corresponding to handle under mouse (if any)
ColourScalePoint* TColourScaleEditor::handleUnderMouse(QPoint pos)
{
	// Did we hit a handle?
	if (colourScale_.nPoints() > 0)
	{
		// Check x delta first
		if (abs(lastPos_.x() - handleRegion_.boundingRect().center().x()) > handleRadius_) return NULL;

		// Check distance from centre of handles...
		double zero = colourScale_.firstPoint()->value();
		double span = colourScale_.lastPoint()->value() - zero;
		for (ColourScalePoint* csp = colourScale_.firstPoint(); csp != NULL; csp = csp->next)
		{
			// Work out fractional position of colourscale value and get centre coordinates of handle
			double fracy = (1.0 - (csp->value() - zero) / span);
			int y = fracy * gradientBarRegion_.boundingRect().height() + gradientBarRegion_.boundingRect().top();
			if (abs(y - pos.y()) <= handleRadius_) return csp;
		}
	}

	return NULL;
}
// Update QGradient for display
void TColourScaleEditor::updateGradient()
{
	// Setup QGradient - in ObjectBoundingMode, 0.0 = top of rectangle, and 1.0 is bottom
	gradient_ = QLinearGradient(0.0, 1.0, 0.0, 0.0);
	gradient_.setCoordinateMode(QGradient::ObjectBoundingMode);

	// Add points
	if (colourScale_.nPoints() == 0)
	{
		gradient_.setColorAt(0.0, QColor(0,0,0));
		gradient_.setColorAt(1.0, QColor(0,0,0));
	}
	else if (colourScale_.nPoints() == 1)
	{
		gradient_.setColorAt(0.0, colourScale_.firstPoint()->colourAsQColor());
		gradient_.setColorAt(1.0, colourScale_.firstPoint()->colourAsQColor());
	}
	else
	{
		double zero = colourScale_.firstPoint()->value();
		double span = colourScale_.lastPoint()->value() - zero;
		for (ColourScalePoint* csp = colourScale_.firstPoint(); csp != NULL; csp = csp->next) gradient_.setColorAt((csp->value() - zero) / span, csp->colourAsQColor());
	}
}
Exemple #11
0
// Add point to scale
ColourScalePoint* ColourScale::addPoint(double value, QColor colour)
{
    ColourScalePoint* csp = NULL;

    // If supplied value is less than that at the start of the list, add it at the beginning.
    // If larget than the one at the end, then append it to the end of the list.
    // If neither of these, find the first existing value which is larger, and add it before that one
    if (points_.nItems() == 0) csp = points_.add();
    else if (value > points_.last()->value()) csp = points_.add();
    else for (ColourScalePoint* oldPoint = points_.first(); oldPoint != NULL; oldPoint = oldPoint->next) if (oldPoint->value() > value)
            {
                csp = points_.insertBefore(oldPoint);
                break;
            }
    if (csp == NULL) return NULL;

    // Now, set data in new point
    csp->setColour(colour);
    csp->setValue(value);

    // Recalculate colour deltas
    calculateDeltas();

    return csp;
}
Exemple #12
0
// Assignment operator
void ColourScale::operator=(const ColourScale& source)
{
    clear();
    useHSV_ = source.useHSV_;
    for (ColourScalePoint* csp = source.points_.first(); csp != NULL; csp = csp->next) addPoint( csp->value(), csp->colour() );
    interpolated_ = source.interpolated_;
}
Exemple #13
0
// Write CollectionBlock keywords
bool UChromaSession::writeCollectionBlock(LineParser& parser, Collection* collection, Collection::CollectionType type, int indentLevel)
{
	// Construct indent string
	char* indent = new char[indentLevel*2+1];
	for (int n=0; n<indentLevel*2; ++n) indent[n] = ' ';
	indent[indentLevel*2] = '\0';

	if (type == Collection::MasterCollection) parser.writeLineF("%s%s '%s'\n", indent, UChromaSession::inputBlock(UChromaSession::CollectionBlock), qPrintable(collection->name()));
	else if (type == Collection::FitCollection) parser.writeLineF("%s%s '%s'\n", indent, UChromaSession::collectionKeyword(UChromaSession::FitBlockKeyword), qPrintable(collection->name()));
	else if (type == Collection::ExtractedCollection) parser.writeLineF("%s%s '%s'\n", indent, UChromaSession::collectionKeyword(UChromaSession::SliceBlockKeyword), qPrintable(collection->name()));
	parser.writeLineF("%s  %s \"%s\"\n", indent, UChromaSession::collectionKeyword(UChromaSession::DataDirectoryKeyword), qPrintable(collection->dataFileDirectory().absolutePath()));

	// -- Transforms
	parser.writeLineF("%s  %s %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::TransformXKeyword), stringBool(collection->transformEnabled(0)), qPrintable(collection->transformEquation(0)));
	parser.writeLineF("%s  %s %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::TransformYKeyword), stringBool(collection->transformEnabled(1)), qPrintable(collection->transformEquation(1)));
	parser.writeLineF("%s  %s %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::TransformZKeyword), stringBool(collection->transformEnabled(2)), qPrintable(collection->transformEquation(2)));

	// -- Interpolation
	parser.writeLineF("%s  %s %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::InterpolateKeyword), stringBool(collection->interpolate(0)), stringBool(collection->interpolate(2)));
	parser.writeLineF("%s  %s %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::InterpolateConstrainKeyword), stringBool(collection->interpolateConstrained(0)), stringBool(collection->interpolateConstrained(2)));
	parser.writeLineF("%s  %s %f %f\n", indent, UChromaSession::collectionKeyword(UChromaSession::InterpolateStepKeyword), collection->interpolationStep(0), collection->interpolationStep(2));

	// Colour Setup
	parser.writeLineF("%s  %s '%s'\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourSourceKeyword), Collection::colourSource(collection->colourSource()));
	ColourScalePoint* csp;
	QColor colour;
	double value;
	// -- Single Colour
	colour = collection->colourScalePointColour(Collection::SingleColourSource);
	parser.writeLineF("%s  %s %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourSingleKeyword), colour.red(), colour.green(), colour.blue(), colour.alpha());
	// -- RGB Gradient
	colour = collection->colourScalePointColour(Collection::RGBGradientSource, 0);
	value = collection->colourScalePointValue(Collection::RGBGradientSource, 0);
	parser.writeLineF("%s  %s %f %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourRGBGradientAKeyword), value, colour.red(), colour.green(), colour.blue(), colour.alpha());
	colour = collection->colourScalePointColour(Collection::RGBGradientSource, 1);
	value = collection->colourScalePointValue(Collection::RGBGradientSource, 1);
	parser.writeLineF("%s  %s %f %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourRGBGradientBKeyword), value, colour.red(), colour.green(), colour.blue(), colour.alpha());
	// -- HSV Gradient
	colour = collection->colourScalePointColour(Collection::HSVGradientSource, 0);
	value = collection->colourScalePointValue(Collection::HSVGradientSource, 0);
	parser.writeLineF("%s  %s %f %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourHSVGradientAKeyword), value, colour.hue(), colour.saturation(), colour.value(), colour.alpha());
	colour = collection->colourScalePointColour(Collection::HSVGradientSource, 1);
	value = collection->colourScalePointValue(Collection::HSVGradientSource, 1);
	parser.writeLineF("%s  %s %f %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourHSVGradientBKeyword), value, colour.hue(), colour.saturation(), colour.value(), colour.alpha());
	// -- Custom Gradient
	for (csp = collection->customColourScalePoints(); csp != NULL; csp = csp->next)
	{
		parser.writeLineF("%s  %s %f %i %i %i %i\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourCustomGradientKeyword), csp->value(), csp->colour().red(), csp->colour().green(), csp->colour().blue(), csp->colour().alpha());
	}
	// -- Alpha control
	parser.writeLineF("%s  %s '%s'\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourAlphaControlKeyword), Collection::alphaControl(collection->alphaControl()));
	parser.writeLineF("%s  %s %f\n", indent, UChromaSession::collectionKeyword(UChromaSession::ColourAlphaFixedKeyword), collection->fixedAlpha());

	// Display
	parser.writeLineF("%s  %s %f '%s'\n", indent, UChromaSession::collectionKeyword(UChromaSession::LineStyleKeyword), collection->displayLineStyle().width(), LineStipple::stipple[collection->displayLineStyle().stipple()].name);
	parser.writeLineF("%s  %s %f\n", indent, UChromaSession::collectionKeyword(UChromaSession::ShininessKeyword), collection->displaySurfaceShininess());
	parser.writeLineF("%s  %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::StyleKeyword), Collection::displayStyle(collection->displayStyle()));
	parser.writeLineF("%s  %s %s\n", indent, UChromaSession::collectionKeyword(UChromaSession::VisibleCollectionKeyword), stringBool(collection->visible()));

	// Loop over datasets
	for (DataSet* dataSet = collection->dataSets(); dataSet != NULL; dataSet = dataSet->next) writeDataSetBlock(parser, dataSet, indentLevel);

	// Write FitKernel data if present
	if (collection->fitKernel()) writeFitParametersBlock(parser, collection->fitKernel(), indentLevel);

	// Additional data
	// -- Fits
	for (Collection* fit = collection->fits(); fit != NULL; fit = fit->next) writeCollectionBlock(parser, fit, Collection::FitCollection, indentLevel+1);
	// -- Extracted Data
	for (Collection* extract = collection->slices(); extract != NULL; extract = extract->next) writeCollectionBlock(parser, extract, Collection::ExtractedCollection, indentLevel+1);

	parser.writeLineF("%s%s\n", indent, UChromaSession::collectionKeyword(UChromaSession::EndCollectionKeyword));

	return true;
}