void MLMenuButton::paint(Graphics& g) { MLLookAndFeel* myLookAndFeel = MLLookAndFeel::getInstance(); const Colour c (findColour (MLTextButton::buttonColourId)); const Colour t (findColour (MLTextButton::textColourId)); myLookAndFeel->drawBackground(g, this); if(mStyle != kTextOnlyStyle) { myLookAndFeel->drawButtonBackground(g, *this, c, mOver, mToggleState, mLineThickness); } switch(mStyle) { case kPlainStyle: myLookAndFeel->drawButtonText(g, *this, t, mOver, mDown); break; case kRightArrowStyle: myLookAndFeel->drawMenuButtonText(g, *this, t); break; case kTextOnlyStyle: myLookAndFeel->drawButtonText(g, *this, t, mOver, mDown); break; } }
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)); } }
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)); */ }
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; } } }