Beispiel #1
0
void MLMultiSlider::paint (Graphics& g)
{
	MLLookAndFeel* myLookAndFeel = (&(getRootViewResources(this).mLookAndFeel));
	if (isOpaque()) myLookAndFeel->drawBackground(g, this);	
	float outlineThickness = myLookAndFeel->getGridUnitSize() / 64.f;
	MLRect r = mPos.getLocalOutline();
	const Colour outlineColor (findColour(MLLookAndFeel::outlineColor).withAlpha (isEnabled() ? 1.f : 0.5f));
	
	// draw fills
	// vertical only
	Path full, empty;
	Colour fullColor, emptyColor;
	MLRect fullRect, emptyRect;
	float dialY;
	
	MLRange drawRange(mRange);
	drawRange.convertTo(MLRange(r.height(), 0.));
	
	for (int i=0; i<mNumSliders; ++i)
	{
		MLRect sr = (mPos.getElementBounds(i));

		dialY = drawRange(getFloatProperty(ml::textUtils::addFinalNumber(ml::Symbol("value"), i)));
		fullRect = sr;
		emptyRect = sr;		
		fullRect.setTop(dialY);
	
		fullColor = findColour(trackFullDarkColor);
		emptyColor = findColour(trackEmptyDarkColor);
		
		// groups of 4 
		if (!(i&4))
		{
			emptyColor = emptyColor.brighter(0.10f);
			fullColor = fullColor.brighter(0.20f);
		}
		
		empty.clear();
		empty.addRectangle(MLToJuceRect(emptyRect));
		g.setColour(emptyColor);
		g.fillPath(empty);	
		
		full.clear();
		full.addRectangle(MLToJuceRect(fullRect));
		g.setColour(fullColor);
		g.fillPath(full);	
				
		g.setColour(outlineColor);
		g.strokePath(empty, PathStrokeType (outlineThickness));
	}
}
Beispiel #2
0
void MLPageView::resized()
{
	int w = getWidth();
	int h = getHeight();
	Rectangle<int> myBounds(0, 0, w, h);
	MLLookAndFeel* myLookAndFeel = (&(getRootViewResources(this).mLookAndFeel));
	int u = myLookAndFeel->getGridUnitSize(); 
	int margin = u;

	int numPages = getNumPages();
	for(int i=0; i<numPages; ++i)
	{
		mPages[i]->setVisible(i == mCurrPage);
		mPages[i]->setBounds(myBounds.translated((w + margin)*(i - mCurrPage), 0));
		mPages[i]->repaint();
	}
}
Beispiel #3
0
void MLEnvelope::paint (Graphics& g)
{	
	float mDelay = getFloatProperty("delay");
	float mAttack = getFloatProperty("attack");
	float mSustain = getFloatProperty("sustain");
	float mDecay = getFloatProperty("decay");
	float mRelease = getFloatProperty("release");
	float r = getFloatProperty("repeat");
	float mRepeat = (r > 0.f) ? (1.f / (r + 0.0001f)) : 0.f;

	MLLookAndFeel* myLookAndFeel = (&(getRootViewResources(this).mLookAndFeel));
	if (isOpaque()) 
		myLookAndFeel->drawBackground(g, this);	
	
	float margin = myLookAndFeel->getSmallMargin() * myLookAndFeel->getGridUnitSize();
	int w = getWidth()-1;
	int h = getHeight()-1;
	
	float totalTime;
	float startX, delX, attX, decX, susX, relX, repX, endX;
	float attTime, decTime, relTime, susTime;
	float leadIn = 0.01;
	float leadOut = 0.01;
	float susHeight;
	float epsilon = 0.0005;
	float susLevel = mDARMode ? 1.0f : mSustain;
	attTime = mAttack + kMinAttack;
	decTime = mDecay * (1.f - susLevel) + kMinDecay;
	relTime = mRelease * susLevel + kMinDecay;
			
	// get times
	if (mDARMode)
	{
		susTime = (mSustain > 0.5) ? 1.f : 0.f; // is hold on?
		decTime = 0.;
		totalTime = leadIn + mDelay + attTime + susTime + relTime + leadIn + leadOut;
	}
	else
	{
		susTime = 1.f;
		totalTime = leadIn + attTime + decTime + susTime + relTime + leadIn + leadOut;
	}
	
	if (mRepeat > epsilon)
	{
		totalTime = ml::max(totalTime, (float)(leadIn + mDelay + mRepeat + leadOut));
	}
	
	totalTime = ml::max(totalTime, 0.01f);
	
	// get dims
	MLRange vRange(UnityRange);
	MLRange wRange(0.f, totalTime);
	vRange.convertTo(MLRange(h - margin, margin));
	wRange.convertTo(MLRange(margin, w - margin*2));
	float t = 0.;
	startX = wRange(0.);

	delX = wRange(t += mDelay);
	attX = wRange(t += attTime);
	decX = wRange(t += decTime);
	susX = wRange(t += susTime);
	relX = wRange(t += relTime);
	endX = wRange(totalTime);
	repX = wRange(leadIn + mDelay + mRepeat);
	susHeight = vRange(susLevel);
		
	// draw env shape
	Path envPath;
	envPath.startNewSubPath(startX,  floor(h - margin) + 0.5);
	envPath.lineTo(delX,  floor(h - margin) + 0.5);
	envPath.quadraticTo(delX,  floor(margin) + 0.5, attX, floor(margin) + 0.5); // up
	envPath.quadraticTo(attX,  floor(susHeight) + 0.5, decX,  floor(susHeight) + 0.5);  // down
	envPath.quadraticTo(decX,  floor(susHeight) + 0.5, susX,  floor(susHeight) + 0.5); // across
	envPath.quadraticTo(susX,  floor(h - margin) + 0.5, relX,  floor(h - margin) + 0.5); // down
	envPath.quadraticTo(relX,  floor(h - margin) + 0.5, endX,  floor(h - margin) + 0.5); // across
	g.setColour(findColour(MLLookAndFeel::outlineColor));
	g.strokePath(envPath, PathStrokeType (mOutlineThickness));	
	g.setColour(findColour(MLLookAndFeel::outlineColor).withAlpha(0.125f));
	g.fillPath(envPath);
	// lines down
	envPath.clear();
	envPath.startNewSubPath(attX,  floor(margin) + 0.5);
	envPath.lineTo(attX,  floor(h - margin) + 0.5);
	envPath.startNewSubPath(decX,  floor(susHeight) + 0.5);
	envPath.lineTo(decX,  floor(h - margin) + 0.5);
	envPath.startNewSubPath(susX,  floor(susHeight) + 0.5);
	envPath.lineTo(susX,   floor(h - margin) + 0.5);
	g.setColour(findColour(MLLookAndFeel::outlineColor));
	g.strokePath(envPath, PathStrokeType (mOutlineThickness / 2));	

	// draw repeat bracket
	if (mRepeat > epsilon)
	{		
		float thick = margin / 2;
		float high = margin * 1.5;
		envPath.clear();
		envPath.startNewSubPath(floor(delX - thick/2) , floor(h - margin - high));
		envPath.lineTo(floor(delX - thick/2) , floor(h - margin));
		envPath.lineTo(floor( repX + thick/2) , floor(h - margin));
		envPath.lineTo(floor( repX + thick/2) , floor(h - margin - high));
		g.strokePath(envPath, PathStrokeType (mOutlineThickness * 4));	

	}

//debug() << "DEL " << mDelay << " ATT " << attTime << " DEC " << decTime << " SUS " << susTime << " REL " << relTime << " REP " << mRepeat << "\n";
//debug() << "repeatX: " << repX << " delayX: " << delX << "\n";

	/*
	// TEST
	Path tbounds;
	const Rectangle<int> & boundsRect ( getLocalBounds());	
	tbounds.addRectangle(boundsRect);
	g.setColour(Colours::red);	
	g.strokePath(tbounds, PathStrokeType(0.5f));
	*/
}
Beispiel #4
0
void MLPageView::goToPage (int destPage, bool animate, Component* prevButton, Component* nextButton)
{
	int duration = 500;
	float targetAlpha;
	
	//with this on, animations fail sometimes. with this off, they fail in a different way,always.
	bool proxy = true;
	
	int w = getWidth();
	int h = getHeight();
	Rectangle<int> localBounds(0, 0, w, h);
	
    int pages = mPages.size();
	if(!pages) return;
    if(mCurrPage == destPage) return;

	MLLookAndFeel* myLookAndFeel = (&(getRootViewResources(this).mLookAndFeel));
	int u = myLookAndFeel->getGridUnitSize(); 
	
	// margin between pages prevents invisible components from overlapping
	// those onscreen
	int margin = u;
	int newPage = ml::clamp(destPage, 0, (int)mPages.size() - 1);

	animate = true;
	if ((animate) && (newPage != mCurrPage) && (mCurrPage >= 0))
	{
		// line up all pages from new through current offscreen
		// and make visible all in line up
		
		int start = ml::min(mCurrPage, newPage);
		int end = ml::max(mCurrPage, newPage);
		for(int i=start; i <= end; ++i)
		{
			mPages[i]->setBounds(localBounds.translated((w + margin)*(i - mCurrPage), 0));
			mPages[i]->setVisible(true);
		}
				
		// scroll past all to new page
		for(int i=start; i <= end; ++i)
		{
			if (i == newPage)
			{
				targetAlpha = 1.f;
			}
			else if (i == mCurrPage)
			{
				targetAlpha = 0.f;
			}
			else 
			{
				// allow intermediate pages to show? we don't really do these
				// transitions anyway.  
				targetAlpha = 1.f;
			}
            
            // NOTE: this can cause a problem stopping a running thread in CachedImage::stop if called at just the wrong time-- TODO investigate!
			
			
			mAnimator.animateComponent (mPages[i], localBounds.translated((w + margin)*(i - newPage), 0),
				targetAlpha, duration, proxy, 4.0, 0.25);
		}
		
		// animate buttons 
		if (prevButton)
		{
			targetAlpha = (newPage > 0) ? 1.f : 0.f;
			mAnimator.animateComponent (prevButton, prevButton->getBounds(), 
				targetAlpha, duration, proxy, 1.0, 1.0);
//	//debug() << "prev alpha: " << targetAlpha << "\n";
		}

		// animate buttons 
		if (nextButton)
		{
			int last = mPages.size() - 1;
			targetAlpha = (newPage < last) ? 1.f : 0.f;
			mAnimator.animateComponent (nextButton, nextButton->getBounds(),
				targetAlpha, duration, proxy, 1.0, 1.0);
				
//	//debug() << "next alpha: " << targetAlpha << "\n";
		}
	}
    else
    {
        for(int p=0; p<pages; ++p)
        {
            if(p == newPage)
            {
                mPages[p]->setBounds(localBounds);
                mPages[p]->setVisible(true);
            }
            else
            {
                mPages[p]->setBounds(localBounds.translated((w + margin), 0));
                mPages[p]->setVisible(false);
            }
        }
    }

	mCurrPage = newPage;
}
Beispiel #5
0
void MLDrawing::paint(Graphics& g)
{
	MLLookAndFeel* myLookAndFeel = (&(getRootViewResources(this).mLookAndFeel));
	float fu = myLookAndFeel->getGridUnitSize();

	if (isOpaque())
		myLookAndFeel->drawBackground(g, this);
	
	// defaults
	float ft = 1.0f * fu / 64.;
	float arrowScale = fu / 48.;
	float dotRadius = fu / 24.;
	mLineColor = mDarkColor;
	g.setColour(mLineColor);
//	int w = getWidth();
//	int h = getHeight();
	
	/*
	// TEST TODO auto border / background?
	Path tbounds;
	const MLRect boundsRect ( getLocalBounds());	
	tbounds.addRectangle(boundsRect);
	g.setColour(Colours::blue.withAlpha(0.5f));	
	g.fillPath(tbounds);
	g.setColour(Colours::red);	
	g.strokePath(tbounds, PathStrokeType(1.0f));
	*/
	
//debug() << "painting MLDrawing " << getWidgetName() << "\n";
//int c = 0;	

	for(auto op : mOperations)
	{
		Path p;
		Vec2 p1, p2;
		//const MLDrawing::Operation& op = *it;

//debug() << "    painting op " << c++ << "\n";	
		for(int i=0; i<4; ++i)
		{
			assert(ml::within((int)op.args[i], 0, (int)mTransformedPoints.size()));
		}
		
		switch(op.type)
		{
			case drawLine:				
				p1 = mTransformedPoints[(int)op.args[0]];
				p2 = mTransformedPoints[(int)op.args[1]];				
				p.startNewSubPath(MLToJucePoint(correctPoint(p1)));
				p.lineTo(MLToJucePoint(correctPoint(p2)));
				g.strokePath(p, PathStrokeType(ft));
				break;
			case drawLineArrowStart:
			case drawLineArrowEnd:
				p1 = mTransformedPoints[(int)op.args[0]];
				p2 = mTransformedPoints[(int)op.args[1]];				
				p.startNewSubPath(MLToJucePoint(correctPoint(p1)));
				p.lineTo(MLToJucePoint(correctPoint(p2)));
				g.strokePath(p, PathStrokeType(ft));
				drawArrowhead(g, p1, p2, arrowScale);
				break;
			case drawDot:
				p1 = mTransformedPoints[(int)op.args[0]];
				
				// p.startNewSubPath(MLToJucePoint(correctPoint(p1)));
				{
					juce::Point<float> pc = MLToJucePoint(correctPoint(p1));
					juce::Point<float> pr1 = pc + juce::Point<float>(dotRadius, 0);
					p.startNewSubPath(pr1);
					int s = 10;
					for(int i=0; i<s; ++i)
					{
						float omega = i*kMLTwoPi/(s - 1);
						juce::Point<float> pr = pc + juce::Point<float>(cos(omega)*dotRadius, sin(omega)*dotRadius);
						p.lineTo(pr);
					}
					p.lineTo(pr1);
					g.fillPath(p);
				}
				

				break;
			case drawLineArrowBoth:
			break;
			case setLineThickness:
				mLineThickness = op.args[0];
				ft = mLineThickness * fu / 64.;
			break;
			case setLightColor:
				g.setColour(mLightColor);
			break;
			case setDarkColor:
				g.setColour(mDarkColor);
			break;
		}
	}
}