1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15 
16 #pragma once
17 #include "vstcontrols.h"
18 #include "Parameter.h"
19 #include <iostream>
20 #include "SkinSupport.h"
21 #include "SkinColors.h"
22 #include "RuntimeFont.h"
23 
24 class CParameterTooltip : public VSTGUI::CControl, public Surge::UI::SkinConsumingComponent
25 {
26   public:
CParameterTooltip(const VSTGUI::CRect & size)27     CParameterTooltip(const VSTGUI::CRect &size) : VSTGUI::CControl(size, 0, 0, 0)
28     {
29         label[0][0] = 0;
30         label[1][0] = 0;
31         visible = false;
32         last_tag = -1;
33     }
34 
35     void setLabel(const char *txt1, const char *txt2, const char *txt2left = nullptr)
36     {
37         if (txt1)
38             strncpy(label[0], txt1, 256);
39         else
40             label[0][0] = 0;
41         if (txt2)
42             strncpy(label[1], txt2, 256);
43         else
44             label[1][0] = 0;
45         if (txt2left)
46             strncpy(label2left, txt2left, 256);
47         else
48             label2left[0] = 0;
49 
50         setDirty(true);
51     }
52 
getMaxLabelLen()53     int getMaxLabelLen()
54     {
55         auto l0len = strlen(label[0]);
56         auto l1len = strlen(label[1]) + strlen(label2left);
57         return std::max(l0len, l1len);
58     }
59 
Show()60     void Show()
61     {
62         visible = true;
63         invalid();
64         setDirty(true);
65     }
Hide()66     void Hide()
67     {
68         visible = false;
69 #if TARGET_JUCE_UI
70         this->setViewSize(VSTGUI::CRect(VSTGUI::CPoint(0, 0), VSTGUI::CPoint(1, 1)));
71 #endif
72         invalid();
73         setDirty(true);
74     }
isNewTag(long tag)75     bool isNewTag(long tag)
76     {
77         bool b = (last_tag != tag);
78         last_tag = tag;
79         return b;
80     }
isVisible()81     bool isVisible() { return visible; }
82 
draw(VSTGUI::CDrawContext * dc)83     virtual void draw(VSTGUI::CDrawContext *dc) override
84     {
85         if (visible)
86         {
87             dc->setFont(Surge::GUI::getLatoAtSize(10));
88 
89             auto frameCol = skin->getColor(Colors::InfoWindow::Border);
90             auto bgCol = skin->getColor(Colors::InfoWindow::Background);
91 
92             auto txtCol = skin->getColor(Colors::InfoWindow::Text);
93             auto mpCol = skin->getColor(Colors::InfoWindow::Modulation::Positive);
94             auto mnCol = skin->getColor(Colors::InfoWindow::Modulation::Negative);
95             auto mpValCol = skin->getColor(Colors::InfoWindow::Modulation::ValuePositive);
96             auto mnValCol = skin->getColor(Colors::InfoWindow::Modulation::ValueNegative);
97 
98             auto size = getViewSize();
99             size = size.inset(0.75, 0.75);
100             dc->setFrameColor(frameCol);
101             dc->drawRect(size);
102             VSTGUI::CRect sizem1(size);
103             sizem1.inset(1, 1);
104             dc->setFillColor(bgCol);
105             dc->drawRect(sizem1, VSTGUI::kDrawFilled);
106             dc->setFontColor(txtCol);
107             VSTGUI::CRect trect(size);
108             trect.inset(4, 1);
109             VSTGUI::CRect tupper(trect), tlower(trect);
110             tupper.bottom = tupper.top + 13;
111             tlower.top = tlower.bottom - 15;
112 
113             if (hasiwstrings)
114             {
115                 VSTGUI::CRect tmid(trect);
116                 tmid.bottom = trect.bottom - 18;
117                 tmid.top = trect.top + 15;
118                 if (!extendedwsstrings)
119                 {
120                     tmid = tlower;
121                 }
122                 if (label[0][0])
123                 {
124                     dc->drawString(label[0], tupper, VSTGUI::kLeftText, true);
125                 }
126 
127                 if (!extendedwsstrings)
128                 {
129                     dc->drawString(iwstrings.val.c_str(), tmid, VSTGUI::kLeftText, true);
130                     dc->setFontColor(mpCol);
131                     dc->drawString(iwstrings.dvalplus.c_str(), tmid, VSTGUI::kRightText, true);
132                     dc->setFontColor(txtCol);
133                 }
134                 else
135                 {
136                     auto valalign = VSTGUI::kCenterText;
137                     if (iwstrings.dvalminus.size() == 0 && iwstrings.valminus.size() == 0)
138                         valalign = VSTGUI::kLeftText;
139 
140                     dc->drawString(iwstrings.val.c_str(), tmid, valalign, true);
141                     dc->setFontColor(mpCol);
142                     dc->drawString(iwstrings.dvalplus.c_str(), tmid, VSTGUI::kRightText, true);
143                     dc->setFontColor(mnCol);
144                     dc->drawString(iwstrings.dvalminus.c_str(), tmid, VSTGUI::kLeftText, true);
145 
146                     dc->setFontColor(mpValCol);
147                     dc->drawString(iwstrings.valplus.c_str(), tlower, VSTGUI::kRightText, true);
148                     dc->setFontColor(mnValCol);
149                     dc->drawString(iwstrings.valminus.c_str(), tlower, VSTGUI::kLeftText, true);
150                     dc->setFontColor(txtCol);
151                 }
152             }
153             else
154             {
155                 if (label[0][0])
156                 {
157                     dc->drawString(label[0], tupper, VSTGUI::kLeftText, true);
158                 }
159                 // dc->drawString(label[1],tlower,false,label[0][0]?kRightText:kCenterText);
160                 dc->drawString(label[1], tlower, VSTGUI::kRightText, true);
161 
162                 if (label2left[0])
163                 {
164                     dc->drawString(label2left, tlower, VSTGUI::kLeftText, true);
165                 }
166             }
167         }
168         else
169         {
170 #if 0
171             auto size = getViewSize();
172             size = size.inset(0.75, 0.75);
173             dc->setFrameColor(VSTGUI::kRedCColor);
174             dc->setFrameColor(VSTGUI::kBlueCColor);
175             dc->drawRect(size, VSTGUI::kDrawFilledAndStroked);
176 #endif
177         }
178         setDirty(false);
179     }
180 
setMDIWS(const ModulationDisplayInfoWindowStrings & i)181     void setMDIWS(const ModulationDisplayInfoWindowStrings &i)
182     {
183         iwstrings = i;
184         hasiwstrings = true;
185     }
186 
setExtendedMDIWS(bool b)187     void setExtendedMDIWS(bool b) { extendedwsstrings = b; }
188 
clearMDIWS()189     void clearMDIWS() { hasiwstrings = false; }
hasMDIWS()190     bool hasMDIWS() { return hasiwstrings; }
191 
192   protected:
193     char label[2][256], label2left[256];
194     bool visible;
195     int last_tag;
196 
197     ModulationDisplayInfoWindowStrings iwstrings;
198     bool hasiwstrings = false;
199     bool extendedwsstrings = false;
200 
201     CLASS_METHODS(CParameterTooltip, VSTGUI::CControl)
202 };
203