Skip to content

Commit cf454c3

Browse files
* Updated menu system
- Support mouse clicks - Generate key labels automatically - Eliminated menu mode enumeration
1 parent 8c5c8b0 commit cf454c3

35 files changed

+185
-107
lines changed

DisplayFilterFrequency.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ void DisplayFilterFrequency::Update(HANDLE hOut, int const v)
3232
float const flt_key_freq = NoteFrequency(voice_note[v], flt_config.key_follow);
3333

3434
// get attributes to use
35-
COORD const pos = { Menu::menu_flt.pos.X + 8, Menu::menu_flt.pos.Y };
36-
bool const selected = (Menu::active_page == Menu::PAGE_MAIN && Menu::active_menu == Menu::MAIN_FLT);
35+
COORD const pos = { Menu::menu_flt.rect.Right - 10, Menu::menu_flt.rect.Top };
36+
bool const selected = (Menu::page_info[Menu::active_page].menu[Menu::active_menu] == &Menu::menu_flt);
3737
bool const title_selected = selected && Menu::menu_flt.item == 0;
3838
WORD const title_attrib = Menu::title_attrib[true][selected + title_selected];
39-
WORD const num_attrib = (title_attrib & 0xF8) | (FOREGROUND_GREEN);
40-
WORD const unit_attrib = (title_attrib & 0xF8) | (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
39+
WORD const back_attrib = title_attrib & 0xF8;
40+
WORD const num_attrib = back_attrib | (FOREGROUND_GREEN);
41+
WORD const unit_attrib = back_attrib | (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
4142

4243
// current frequency in Hz
4344
float const freq = flt_key_freq * flt_config.GetCutoff(lfo, flt_env_amplitude, key_vel);

DisplayKeyVolumeEnvelope.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Per-Key Volume Envelope Display
1515
#include "Amplifier.h"
1616

1717
static COORD const key_pos = { 12, SPECTRUM_HEIGHT };
18-
static COORD const voice_pos = { 73 - VOICES, 49 };
18+
static COORD const voice_pos = { WINDOW_WIDTH - 7 - VOICES, WINDOW_HEIGHT - 1 };
1919

2020
// attribute associated with each envelope state
2121
static WORD const env_attrib[EnvelopeState::COUNT] =

DisplayLowFrequencyOscillator.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,21 @@ static WORD const plot[2] = { 221, 222 };
2424
void DisplayLowFrequencyOscillator::Update(HANDLE hOut)
2525
{
2626
// initialize buffer
27-
CHAR_INFO buf[18];
28-
for (int x = 0; x < 9; x++)
27+
CHAR_INFO *buf = static_cast<CHAR_INFO *>(_alloca(size.X * sizeof(CHAR_INFO)));
28+
for (int x = 0; x < size.X / 2; x++)
2929
buf[x] = negative;
30-
for (int x = 9; x < 18; ++x)
30+
for (int x = size.X / 2; x < size.X; ++x)
3131
buf[x] = positive;
3232

3333
// plot low-frequency oscillator value
3434
float const lfo = lfo_state.Update(lfo_config, 0.0f);
35-
int const grid_x = Clamp(FloorInt(18.0f * lfo + 18.0f), 0, 35);
35+
int const grid_x = Clamp(FloorInt(size.X * lfo + size.X), 0, size.X * 2 - 1);
3636
buf[grid_x / 2].Char.UnicodeChar = plot[grid_x & 1];
3737

3838
// draw the gauge
3939
SMALL_RECT region = {
40-
Menu::menu_lfo.pos.X, Menu::menu_lfo.pos.Y + 4,
41-
Menu::menu_lfo.pos.X + 19, Menu::menu_lfo.pos.Y + 4
40+
Menu::menu_lfo.rect.Left, Menu::menu_lfo.rect.Bottom,
41+
Menu::menu_lfo.rect.Right + 1, Menu::menu_lfo.rect.Bottom
4242
};
4343
WriteConsoleOutput(hOut, &buf[0], size, pos, &region);
4444
}

DisplayOscillatorFrequency.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ void DisplayOscillatorFrequency::Update(HANDLE hOut, int const v, int const o)
2121
float const osc_key_freq = NoteFrequency(voice_note[v], osc_config[o].key_follow);
2222

2323
// get attributes to use
24-
COORD const pos = { Menu::menu_osc[o].pos.X + 8, Menu::menu_osc[o].pos.Y };
25-
bool const selected = (Menu::active_page == Menu::PAGE_MAIN && Menu::active_menu == Menu::MAIN_OSC1 + o);
24+
COORD const pos = { Menu::menu_osc[o].rect.Right - 10, Menu::menu_osc[o].rect.Top };
25+
bool const selected = (Menu::page_info[Menu::active_page].menu[Menu::active_menu] == &Menu::menu_osc[o]);
2626
bool const title_selected = selected && Menu::menu_osc[o].item == 0;
2727
WORD const title_attrib = Menu::title_attrib[true][selected + title_selected];
28-
WORD const num_attrib = (title_attrib & 0xF8) | (FOREGROUND_GREEN);
29-
WORD const unit_attrib = (title_attrib & 0xF8) | (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
28+
WORD const back_attrib = title_attrib & 0xF8;
29+
WORD const num_attrib = back_attrib | (FOREGROUND_GREEN);
30+
WORD const unit_attrib = back_attrib | (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
3031

3132
// current frequency in Hz
3233
float const freq = osc_key_freq * osc_config[o].frequency;

DisplayOscillatorWaveform.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Oscillator Waveform Display
1717
#include "Voice.h"
1818
#include "Control.h"
1919

20-
#define WAVEFORM_WIDTH 80
20+
#define WAVEFORM_WIDTH WINDOW_WIDTH
2121
#define WAVEFORM_HEIGHT 20
2222
#define WAVEFORM_MIDLINE 10
2323

@@ -76,7 +76,7 @@ float DisplayOscillatorWaveform::UpdateWaveformStep(int oversample, NoteOscillat
7676
void DisplayOscillatorWaveform::Update(HANDLE hOut, BASS_INFO const &info, int const v)
7777
{
7878
// display region
79-
SMALL_RECT region = { 0, 49 - WAVEFORM_HEIGHT, WAVEFORM_WIDTH - 1, 48 };
79+
SMALL_RECT region = { 0, WINDOW_HEIGHT - 1 - WAVEFORM_HEIGHT, WAVEFORM_WIDTH - 1, WINDOW_HEIGHT - 2 };
8080

8181
// waveform buffer
8282
CHAR_INFO buf[WAVEFORM_HEIGHT][WAVEFORM_WIDTH] = { 0 };

DisplaySpectrumAnalyzer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ void DisplaySpectrumAnalyzer::Update(HANDLE hOut, DWORD stream, BASS_INFO const
154154
// plot log-log spectrum
155155
// each grid cell is one semitone wide and 6 dB high
156156
CHAR_INFO buf[SPECTRUM_HEIGHT][SPECTRUM_WIDTH];
157-
SMALL_RECT region = { 0, 0, 79, 49 };
157+
SMALL_RECT region = { 0, 0, SPECTRUM_WIDTH - 1, SPECTRUM_HEIGHT - 1 };
158158
float threshold = 1.0f;
159159
for (int y = 0; y < SPECTRUM_HEIGHT; ++y)
160160
{

DisplaySpectrumAnalyzer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Copyright 2014 Kenneth D. Miller III
66
Spectrum Analyzer Display
77
*/
88

9-
#define SPECTRUM_WIDTH 80
9+
#define SPECTRUM_WIDTH WINDOW_WIDTH
1010
#define SPECTRUM_HEIGHT 10
1111

1212
// fast fourier transform properties

Menu.cpp

+68-26
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,15 @@ namespace Menu
2828
static Menu * const menu_main[] =
2929
{
3030
&menu_osc[0],
31+
#if NUM_OSCILLATORS >= 2
3132
&menu_osc[1],
33+
#if NUM_OSCILLATORS >= 3
34+
&menu_osc[2],
35+
#if NUM_OSCILLATORS >= 4
36+
&menu_osc[3],
37+
#endif
38+
#endif
39+
#endif
3240
&menu_lfo,
3341
&menu_flt,
3442
&menu_amp,
@@ -57,7 +65,7 @@ namespace Menu
5765
Page active_page = PAGE_MAIN;
5866

5967
// active menu
60-
int active_menu = MAIN_OSC1;
68+
int active_menu = 0;
6169
int save_menu[PAGE_COUNT];
6270

6371
// menu attributes
@@ -120,11 +128,23 @@ namespace Menu
120128
// update a linear time property
121129
float const time_step[] = { 1, 10, 100, 1000 };
122130

131+
// initialize the menu system
132+
void Init()
133+
{
134+
for (int page = 0; page < ARRAY_SIZE(page_info); ++page)
135+
{
136+
for (int i = 0; i < page_info[page].count; ++i)
137+
{
138+
page_info[page].menu[i]->menu = i;
139+
}
140+
}
141+
}
142+
123143
// set the active page
124144
void SetActivePage(HANDLE hOut, Page page)
125145
{
126146
// clear the area
127-
static DWORD const size = (49 - page_pos.Y) * 80;
147+
static DWORD const size = (WINDOW_HEIGHT - 1 - page_pos.Y) * WINDOW_WIDTH;
128148
DWORD written;
129149
FillConsoleOutputCharacter(hOut, 0, size, page_pos, &written);
130150
FillConsoleOutputAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, size, page_pos, &written);
@@ -164,24 +184,36 @@ namespace Menu
164184
SetActiveMenu(hOut, active_menu > 0 ? active_menu - 1 : page_info[active_page].count - 1);
165185
}
166186

167-
// menu input handler
187+
// menu key press handler
168188
void Handler(HANDLE hOut, WORD key, DWORD modifiers)
169189
{
170190
page_info[active_page].menu[active_menu]->Handler(hOut, key, modifiers);
171191
}
172192

193+
// menu mouse click handler
194+
void Click(HANDLE hOut, COORD pos)
195+
{
196+
// try dispatching to menus
197+
for (int menu = 0; menu < page_info[active_page].count; ++menu)
198+
{
199+
if (page_info[active_page].menu[menu]->Click(hOut, pos))
200+
break;
201+
}
202+
}
203+
204+
173205
// print menu title bar
174206
void Menu::PrintTitle(HANDLE hOut, bool enable, DWORD flags, char const *on_text, char const *off_text)
175207
{
176208
// print menu name
177209
WORD const attrib = title_attrib[enable][flags];
178-
PrintConsoleWithAttribute(hOut, pos, attrib, "%-15s", name);
210+
PrintConsoleWithAttribute(hOut, { rect.Left, rect.Top }, attrib, "F%d %-*s", menu + 1, rect.Right - rect.Left - 3, name);
179211

180212
// print component enabled
181213
if (char const *text = enable ? on_text : off_text)
182214
{
183215
WORD const enable_attrib = (attrib & 0xF8) | (enable ? FOREGROUND_GREEN : (flags ? FOREGROUND_RED : 0));
184-
PrintConsoleWithAttribute(hOut, { pos.X + 15, pos.Y }, enable_attrib, text);
216+
PrintConsoleWithAttribute(hOut, { rect.Right - 3, rect.Top }, enable_attrib, text);
185217
}
186218
}
187219

@@ -196,26 +228,26 @@ namespace Menu
196228
WORD const attrib = item_attrib[flags];
197229
PrintConsoleWithAttribute(hOut, pos, attrib, format, value);
198230
}
199-
void PrintItemBool(HANDLE hOut, COORD pos, DWORD flags, char const *format, bool value)
231+
void PrintItemBool(HANDLE hOut, COORD pos, SHORT width, DWORD flags, char const *format, bool value)
200232
{
201233
WORD const attrib = item_attrib[flags];
202234
PrintConsoleWithAttribute(hOut, pos, attrib, format);
203235
WORD const value_attrib = (attrib & 0xF8) | (value ? FOREGROUND_GREEN : FOREGROUND_RED);
204236
char const *value_text = value ? " ON" : "OFF";
205-
PrintConsoleWithAttribute(hOut, { pos.X + 15, pos.Y }, value_attrib, value_text);
237+
PrintConsoleWithAttribute(hOut, { pos.X + width - 3, pos.Y }, value_attrib, value_text);
206238
}
207239

208240
// print marker
209-
static void PrintMarker(HANDLE hOut, COORD pos, CHAR_INFO left, CHAR_INFO right)
241+
void Menu::PrintMarker(HANDLE hOut, int index, CHAR_INFO left, CHAR_INFO right)
210242
{
211243
static COORD const zero = { 0, 0 };
212244
static COORD const size = { 1, 1 };
213245
SMALL_RECT region;
214246

215-
region.Left = region.Right = pos.X - 1;
216-
region.Top = region.Bottom = pos.Y;
247+
region.Left = region.Right = rect.Left - 1;
248+
region.Top = region.Bottom = rect.Top + SHORT(index);
217249
WriteConsoleOutput(hOut, &left, size, zero, &region);
218-
region.Left = region.Right = pos.X + 18;
250+
region.Left = region.Right = rect.Right;
219251
WriteConsoleOutput(hOut, &right, size, zero, &region);
220252
}
221253

@@ -225,60 +257,56 @@ namespace Menu
225257
static CHAR_INFO const marker_blank = { 0, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE };
226258

227259
// show selection marker on an item
228-
static inline void ShowMarker(HANDLE hOut, COORD pos)
260+
inline void Menu::ShowMarker(HANDLE hOut, int index)
229261
{
230-
PrintMarker(hOut, pos, marker_left, marker_right);
262+
PrintMarker(hOut, index, marker_left, marker_right);
231263
}
232264

233265
// hide selection marker on an item
234-
static inline void HideMarker(HANDLE hOut, COORD pos)
266+
inline void Menu::HideMarker(HANDLE hOut, int index)
235267
{
236-
PrintMarker(hOut, pos, marker_blank, marker_blank);
268+
PrintMarker(hOut, index, marker_blank, marker_blank);
237269
}
238270

239271
// print the whole menu
240272
void Menu::Print(HANDLE hOut)
241273
{
242-
COORD p = pos;
243-
p.Y += SHORT(item);
244-
245274
int flags[2];
246275
if (active_menu >= 0 && this == page_info[active_page].menu[active_menu])
247276
{
248-
ShowMarker(hOut, p);
277+
ShowMarker(hOut, item);
249278
flags[0] = 1; flags[1] = 2;
250279
}
251280
else
252281
{
253-
HideMarker(hOut, p);
282+
HideMarker(hOut, item);
254283
flags[0] = 0; flags[1] = 0;
255284
}
256285

257-
p.Y = pos.Y;
258286
for (int i = 0; i < count; ++i)
259287
{
260-
Print(i, hOut, p, flags[item == i]);
261-
++p.Y;
288+
Print(i, hOut, { rect.Left, rect.Top + SHORT(i) }, flags[item == i]);
262289
}
263290
}
264291

265-
// general menu handler
292+
// general key press handler
266293
void Menu::Handler(HANDLE hOut, WORD key, DWORD modifiers)
267294
{
268295
int sign;
296+
COORD pos = { rect.Left, rect.Top };
269297
COORD p = pos;
270298
switch (key)
271299
{
272300
case VK_UP:
273301
case VK_DOWN:
274302
sign = key == VK_DOWN ? 1 : -1;
275303
p.Y = pos.Y + SHORT(item);
276-
HideMarker(hOut, p);
304+
HideMarker(hOut, item);
277305
Print(item, hOut, p, 1);
278306
item = (item + count + sign) % count;
279307
p.Y = pos.Y + SHORT(item);
280308
Print(item, hOut, p, 2);
281-
ShowMarker(hOut, p);
309+
ShowMarker(hOut, item);
282310
break;
283311

284312
case VK_LEFT:
@@ -290,4 +318,18 @@ namespace Menu
290318
break;
291319
}
292320
}
321+
322+
// general mouse click handler
323+
bool Menu::Click(HANDLE hOut, COORD pos)
324+
{
325+
if (!Inside(pos))
326+
return false;
327+
SetActiveMenu(hOut, menu);
328+
HideMarker(hOut, item);
329+
Print(item, hOut, { rect.Left, rect.Top + SHORT(item) }, 1);
330+
item = Clamp(pos.Y - rect.Top, 0, count - 1);
331+
Print(item, hOut, { rect.Left, rect.Top + SHORT(item) }, 2);
332+
ShowMarker(hOut, item);
333+
return true;
334+
}
293335
}

0 commit comments

Comments
 (0)