n2xLcd.cpp (3166B)
1 #include "n2xLcd.h" 2 3 #include "n2xController.h" 4 #include "n2xEditor.h" 5 6 namespace n2xJucePlugin 7 { 8 constexpr char space = 0x21; // unit separator, i.e. full width space 9 10 constexpr uint32_t g_animDelayStart = 1000; 11 constexpr uint32_t g_animDelayScroll = 500; 12 constexpr uint32_t g_animDelayEnd = 1000; 13 14 Lcd::Lcd(Editor& _editor) : m_editor(_editor) 15 { 16 m_label = _editor.findComponentT<juce::Label>("PatchName"); 17 setText("---"); 18 19 m_onProgramChanged.set(_editor.getN2xController().onProgramChanged, [this] 20 { 21 onProgramChanged(); 22 }); 23 24 m_onPartChanged.set(_editor.getN2xController().onCurrentPartChanged, [this](const uint8_t&) 25 { 26 onProgramChanged(); 27 }); 28 } 29 30 void Lcd::setText(const std::string& _text) 31 { 32 if(m_text == _text) 33 return; 34 m_text = _text; 35 36 if(m_overrideText.empty()) 37 onTextChanged(); 38 } 39 40 void Lcd::timerCallback() 41 { 42 stopTimer(); 43 44 switch(m_animState) 45 { 46 case AnimState::Start: 47 if(updateClippedText(getCurrentText(), ++m_currentOffset)) 48 { 49 m_animState = AnimState::Scroll; 50 startTimer(g_animDelayScroll); 51 } 52 break; 53 case AnimState::Scroll: 54 if(!updateClippedText(getCurrentText(), ++m_currentOffset)) 55 { 56 m_animState = AnimState::End; 57 startTimer(g_animDelayEnd); 58 } 59 else 60 { 61 startTimer(g_animDelayScroll); 62 } 63 break; 64 case AnimState::End: 65 m_animState = AnimState::Start; 66 m_currentOffset = 0; 67 updateClippedText(getCurrentText(), m_currentOffset); 68 startTimer(g_animDelayStart); 69 break; 70 } 71 } 72 73 void Lcd::updatePatchName() 74 { 75 onProgramChanged(); 76 } 77 78 void Lcd::setOverrideText(const std::string& _text) 79 { 80 std::string t = _text; 81 if(!t.empty()) 82 { 83 while(t.size() < 3) 84 t = ' ' + t; 85 } 86 87 if(t == m_overrideText) 88 return; 89 m_overrideText = t; 90 onTextChanged(); 91 } 92 93 void Lcd::setClippedText(const std::string& _text) 94 { 95 if(m_clippedText == _text) 96 return; 97 m_clippedText = _text; 98 99 auto t = _text; 100 101 for (char& c : t) 102 { 103 if(c == ' ') 104 c = space; 105 } 106 107 m_label->setText(t, juce::dontSendNotification); 108 } 109 110 std::string Lcd::substring(const std::string& _text, uint32_t _offset, uint32_t _len) 111 { 112 auto findIndex = [&_text](const uint32_t _off) 113 { 114 uint32_t o = _off; 115 116 for(uint32_t i=0; i<_text.size(); ++i) 117 { 118 if(_text[i] == '.' && i < o) 119 ++o; 120 } 121 return o; 122 }; 123 124 const auto start = findIndex(_offset); 125 const auto end = findIndex(_offset + _len); 126 127 return _text.substr(start, end - start); 128 } 129 130 bool Lcd::updateClippedText(const std::string& _text, const uint32_t _offset) 131 { 132 const auto str = substring(_text, _offset, 3); 133 if(str.size() < 3) 134 return false; 135 setClippedText(str); 136 return true; 137 } 138 139 void Lcd::startAnim() 140 { 141 m_currentOffset = 0; 142 m_animState = AnimState::Start; 143 startTimer(g_animDelayStart); 144 } 145 146 void Lcd::onTextChanged() 147 { 148 updateClippedText(getCurrentText(), 0); 149 150 if(m_clippedText != getCurrentText()) 151 { 152 startAnim(); 153 } 154 else 155 { 156 stopTimer(); 157 } 158 } 159 160 void Lcd::onProgramChanged() 161 { 162 setText(m_editor.getCurrentPatchName()); 163 } 164 165 const std::string& Lcd::getCurrentText() const 166 { 167 if(m_overrideText.empty()) 168 return m_text; 169 return m_overrideText; 170 } 171 }