1 module soundtab.ui.pitchwidget; 2 3 import dlangui.widgets.widget; 4 import soundtab.ui.noteutil; 5 6 class PitchWidget : Widget { 7 8 double _currentPitch = 478; 9 10 this() { 11 super("pitch"); 12 styleId = "EDIT_LINE"; 13 margins = Rect(5,5,5,5).pointsToPixels; 14 } 15 16 /** 17 Measure widget according to desired width and height constraints. (Step 1 of two phase layout). 18 */ 19 override void measure(int parentWidth, int parentHeight) { 20 int h = font.height * 150 / 100; 21 measuredContent(parentWidth, parentHeight, parentWidth / 5, h); 22 } 23 24 /// Draw widget at its position to buffer 25 override void onDraw(DrawBuf buf) { 26 if (visibility != Visibility.Visible) 27 return; 28 Rect rc = _pos; 29 applyMargins(rc); 30 auto saver = ClipRectSaver(buf, rc, alpha); 31 DrawableRef bg = backgroundDrawable; 32 if (!bg.isNull) { 33 bg.drawTo(buf, rc, state); 34 } 35 applyPadding(rc); 36 _needDraw = false; 37 38 buf.fillRect(Rect(rc.middlex, rc.top, rc.middlex + 1, rc.top + rc.height / 3), 0x00C000); 39 buf.fillRect(Rect(rc.middlex, rc.bottom - rc.height / 3, rc.middlex + 1, rc.bottom), 0x00C000); 40 41 if (_currentPitch < 8 || _currentPitch > 20000) 42 return; // no note 43 double currentNote = toLogScale(_currentPitch); 44 int intNote = getNearestNote(currentNote); 45 double noteDiff = currentNote - intNote; 46 dstring noteName = noteToFullName(currentNote); 47 FontRef fnt = font; 48 Point sz = fnt.textSize(noteName); 49 fnt.drawText(buf, rc.middlex - sz.x / 2, rc.middley - sz.y/2, noteName, 0x8090A0); 50 51 int x = cast(int)(rc.left + rc.width * (noteDiff + 0.5)); 52 buf.fillRect(Rect(x, rc.top, x+1, rc.bottom), 0x40FF0000); 53 54 // draw frequency 55 import std..string : format; 56 import std.utf : toUTF32; 57 dstring freq = "%.2fHz".format(_currentPitch).toUTF32; 58 fnt.drawText(buf, rc.left, rc.middley - sz.y/2, freq, 0x808080); 59 } 60 61 void setPitch(double freq) { 62 _currentPitch = freq; 63 invalidate(); 64 } 65 66 67 } 68