From 7d817d74ee7a0e9e01fc2904af4d7bce093afb78 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 09:35:39 +0100 Subject: [PATCH 01/11] updates play indicators to use graphic icons instead of '>', '-' and '_' --- sources/Application/Player/Player.cpp | 7 ++++--- sources/Application/Views/ChainView.cpp | 5 +++-- sources/Application/Views/GrooveView.cpp | 3 ++- sources/Application/Views/PhraseView.cpp | 5 +++-- sources/Application/Views/SongView.cpp | 5 +++-- sources/Application/Views/TableView.cpp | 3 ++- sources/Foundation/Constants/SpecialCharacters.h | 2 +- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sources/Application/Player/Player.cpp b/sources/Application/Player/Player.cpp index 2ba10e87f..2b7b17e93 100644 --- a/sources/Application/Player/Player.cpp +++ b/sources/Application/Player/Player.cpp @@ -15,6 +15,7 @@ #include "Application/Player/TablePlayback.h" #include "Application/Utils/char.h" #include "Application/Views/BaseClasses/ViewEvent.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "PlayerMixer.h" #include "Services/Midi/MidiService.h" #include "System/Console/n_assert.h" @@ -277,14 +278,14 @@ const char *Player::GetLiveIndicator(int channel) { case QM_PHRASESTART: case QM_TICKSTART: if (!IsChannelMuted(channel)) { - return (">"); + return (char_indicator_position_s); } else { - return ("-"); + return (char_indicator_positionMuted_s); } break; case QM_CHAINSTOP: case QM_PHRASESTOP: - return "_"; + return char_playback_pause_s; break; case QM_NONE: break; diff --git a/sources/Application/Views/ChainView.cpp b/sources/Application/Views/ChainView.cpp index fff39142a..612ddcf26 100644 --- a/sources/Application/Views/ChainView.cpp +++ b/sources/Application/Views/ChainView.cpp @@ -10,6 +10,7 @@ #include "ChainView.h" #include "Application/Utils/char.h" #include "Application/Views/SampleEditorView.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "ScreenView.h" #include "System/Console/Trace.h" #include "UIController.h" @@ -814,10 +815,10 @@ void ChainView::AnimationUpdate() { pos._y = anchor._y + viewData_->chainPlayPos_[i]; if (!player->IsChannelMuted(i)) { SetColor(CD_ACCENT); - DrawString(pos._x, pos._y, ">", props); + DrawString(pos._x, pos._y, char_indicator_position_s, props); } else { SetColor(CD_ACCENTALT); - DrawString(pos._x, pos._y, "-", props); + DrawString(pos._x, pos._y, char_indicator_positionMuted_s, props); } lastPlayingPos_ = viewData_->chainPlayPos_[i]; break; diff --git a/sources/Application/Views/GrooveView.cpp b/sources/Application/Views/GrooveView.cpp index 63072f165..13ab94c1c 100644 --- a/sources/Application/Views/GrooveView.cpp +++ b/sources/Application/Views/GrooveView.cpp @@ -11,6 +11,7 @@ #include "Application/Model/Groove.h" #include "Application/Utils/char.h" #include "Application/Views/SampleEditorView.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "ViewData.h" #include #include @@ -229,7 +230,7 @@ void GrooveView::OnPlayerUpdate(PlayerEventType, unsigned int tick) { pos._x = anchor._x - 1; pos._y = anchor._y + lastPosition_; SetColor(CD_ACCENT); - DrawString(pos._x, pos._y, ">", props); + DrawString(pos._x, pos._y, char_indicator_position_s, props); SetColor(CD_NORMAL); }; diff --git a/sources/Application/Views/PhraseView.cpp b/sources/Application/Views/PhraseView.cpp index bbe48f889..1ecc52295 100644 --- a/sources/Application/Views/PhraseView.cpp +++ b/sources/Application/Views/PhraseView.cpp @@ -16,6 +16,7 @@ #include "Application/Utils/char.h" #include "Application/Views/ModalDialogs/MessageBox.h" #include "Application/Views/SampleEditorView.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "System/Console/Trace.h" #include "UIController.h" #include "ViewData.h" @@ -1469,10 +1470,10 @@ void PhraseView::AnimationUpdate() { pos._y = anchor._y + viewData_->phrasePlayPos_[i]; if (!player->IsChannelMuted(i)) { SetColor(CD_ACCENT); - DrawString(pos._x, pos._y, ">", props); + DrawString(pos._x, pos._y, char_indicator_position_s, props); } else { SetColor(CD_ACCENTALT); - DrawString(pos._x, pos._y, "-", props); + DrawString(pos._x, pos._y, char_indicator_positionMuted_s, props); } SetColor(CD_CURSOR); lastPlayingPos_ = viewData_->phrasePlayPos_[i]; diff --git a/sources/Application/Views/SongView.cpp b/sources/Application/Views/SongView.cpp index 457a1d66d..e5e319c6e 100644 --- a/sources/Application/Views/SongView.cpp +++ b/sources/Application/Views/SongView.cpp @@ -11,6 +11,7 @@ #include "Application/Player/Player.h" #include "Application/Utils/char.h" #include "Application/Views/SampleEditorView.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "System/Console/Trace.h" #include "System/System/System.h" #include "UIController.h" @@ -1028,10 +1029,10 @@ void SongView::AnimationUpdate() { pos._y = anchor._y + y; if (!player->IsChannelMuted(i)) { SetColor(CD_ACCENT); - DrawString(pos._x, pos._y, ">", props); + DrawString(pos._x, pos._y, char_indicator_position_s, props); } else { SetColor(CD_ACCENTALT); - DrawString(pos._x, pos._y, "-", props); + DrawString(pos._x, pos._y, char_indicator_positionMuted_s, props); } SetColor(CD_CURSOR); lastPlayedPosition_[i] = viewData_->songPlayPos_[i]; diff --git a/sources/Application/Views/TableView.cpp b/sources/Application/Views/TableView.cpp index 1237ddf1f..72ae8d9e8 100644 --- a/sources/Application/Views/TableView.cpp +++ b/sources/Application/Views/TableView.cpp @@ -13,6 +13,7 @@ #include "Application/Utils/HelpLegend.h" #include "Application/Utils/char.h" #include "Application/Views/SampleEditorView.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "ViewData.h" #include @@ -992,7 +993,7 @@ void TableView::AnimationUpdate() { if (yPos >= 0 && yPos < 16) { // Only draw if position is valid pos._x = anchor._x - 1 + (i * 9); pos._y = anchor._y + yPos; - DrawString(pos._x, pos._y, ">", props); + DrawString(pos._x, pos._y, char_indicator_position_s, props); } } } diff --git a/sources/Foundation/Constants/SpecialCharacters.h b/sources/Foundation/Constants/SpecialCharacters.h index 2571cfdb8..9ae235b6b 100644 --- a/sources/Foundation/Constants/SpecialCharacters.h +++ b/sources/Foundation/Constants/SpecialCharacters.h @@ -30,7 +30,7 @@ #define char_symbol_indicatorFull_s "\214" #define char_symbol_indicatorFull char_symbol_indicatorFull_s[0] -#define char_playback_pause_s "\214" +#define char_playback_pause_s "\215" #define char_playback_pause char_playback_pause_s[0] #define char_playback_play_s "\220" #define char_playback_play char_playback_play_s[0] From 2dd16110fdb162f060401f4a0d443157be232071 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 12:14:57 +0100 Subject: [PATCH 02/11] drawing a double border for modal views --- sources/Application/Utils/CMakeLists.txt | 3 +- sources/Application/Utils/DrawTools.cpp | 42 +++++++++++++++++++ sources/Application/Utils/DrawTools.h | 16 +++++++ .../Views/BaseClasses/ModalView.cpp | 17 ++------ .../Foundation/Constants/SpecialCharacters.h | 10 +++++ 5 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 sources/Application/Utils/DrawTools.cpp create mode 100644 sources/Application/Utils/DrawTools.h diff --git a/sources/Application/Utils/CMakeLists.txt b/sources/Application/Utils/CMakeLists.txt index c7d11033d..5c91dcde9 100644 --- a/sources/Application/Utils/CMakeLists.txt +++ b/sources/Application/Utils/CMakeLists.txt @@ -2,7 +2,8 @@ add_library(application_utils HexBuffers.cpp char.cpp fixed.cpp - stringutils.cpp + stringutils.cpp + DrawTools.cpp ) target_link_libraries(application_utils PUBLIC diff --git a/sources/Application/Utils/DrawTools.cpp b/sources/Application/Utils/DrawTools.cpp new file mode 100644 index 000000000..f07ea148b --- /dev/null +++ b/sources/Application/Utils/DrawTools.cpp @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2026 xiphonics, inc. + * + * This file is part of the picoTracker firmware + */ + +#include "DrawTools.h" +#include "Application/AppWindow.h" +#include "Foundation/Constants/SpecialCharacters.h" + +void DrawBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props, const char *charset) { + char line[SCREEN_WIDTH + 1]; + memset(line, charset[4], width); + line[width] = 0; + + line[0] = charset[0]; // top left + line[width - 1] = charset[1]; // top right + view.DrawString(x, y, line, props); + + line[0] = charset[2]; // bottom left + line[width - 1] = charset[3]; // bottom right + view.DrawString(x, y + height - 1, line, props); + + char vline[2] = {charset[5], 0}; // vertical line + for (int i = 1; i < height - 1; i++) { + view.DrawString(x, y + i, vline, props); + view.DrawString(x + width - 1, y + i, vline, props); + } +} + +void DrawDoubleBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props) { + DrawBorder(view, x, y, width, height, props, char_border_double_charset); +} + +void DrawSingleBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props) { + DrawBorder(view, x, y, width, height, props, char_border_single_charset); +} \ No newline at end of file diff --git a/sources/Application/Utils/DrawTools.h b/sources/Application/Utils/DrawTools.h new file mode 100644 index 000000000..e057fd3d3 --- /dev/null +++ b/sources/Application/Utils/DrawTools.h @@ -0,0 +1,16 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2026 xiphonics, inc. + * + * This file is part of the picoTracker firmware + */ + +#include "Application/Views/BaseClasses/View.h" + +void DrawBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props, const char *charset); +void DrawDoubleBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props); +void DrawSingleBorder(View &view, int x, int y, int width, int height, + const GUITextProperties &props); \ No newline at end of file diff --git a/sources/Application/Views/BaseClasses/ModalView.cpp b/sources/Application/Views/BaseClasses/ModalView.cpp index 063d3944c..5a6e9af0c 100644 --- a/sources/Application/Views/BaseClasses/ModalView.cpp +++ b/sources/Application/Views/BaseClasses/ModalView.cpp @@ -9,6 +9,8 @@ #include "ModalView.h" #include "Application/AppWindow.h" +#include "Application/Utils/DrawTools.h" +#include "Foundation/Constants/SpecialCharacters.h" ModalView::ModalView(View &v) : View(v.w_, v.viewData_), finished_(false), returnCode_(0){}; @@ -63,16 +65,5 @@ void ModalView::SetWindow(int width, int height) { SetColor(CD_ACCENT); GUITextProperties props; - props.invert_ = true; - char line[SCREEN_WIDTH + 1]; - memset(line, ' ', SCREEN_WIDTH); - line[SCREEN_WIDTH] = '\0'; - line[width + 4] = 0; - DrawString(-2, -2, line, props); - DrawString(-2, height + 1, line, props); - line[1] = 0; - for (int i = 0; i < height + 2; i++) { - DrawString(-2, i - 1, line, props); - DrawString(width + 1, i - 1, line, props); - } -}; + DrawDoubleBorder(*this, -2, -2, width + 4, height + 4, props); +} diff --git a/sources/Foundation/Constants/SpecialCharacters.h b/sources/Foundation/Constants/SpecialCharacters.h index 9ae235b6b..94b83cb8f 100644 --- a/sources/Foundation/Constants/SpecialCharacters.h +++ b/sources/Foundation/Constants/SpecialCharacters.h @@ -254,6 +254,16 @@ #define char_border_double_cross_s "\316" #define char_border_double_cross char_border_double_cross_s[0] +#define char_border_double_charset \ + char_border_double_topLeft_s char_border_double_topRight_s \ + char_border_double_bottomLeft_s char_border_double_bottomRight_s \ + char_border_double_horizontal_s char_border_double_vertical_s + +#define char_border_single_charset \ + char_border_single_topLeft_s char_border_single_topRight_s \ + char_border_single_bottomLeft_s char_border_single_bottomRight_s \ + char_border_single_horizontal_s char_border_single_vertical_s + #define char_logo_x_s "\320" #define char_logo_x char_logo_x_s[0] #define char_logo_xiponics_0_s "\321" From b80d92d2c5f66e4066e9c6f36f90760788254237 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 13:38:54 +0100 Subject: [PATCH 03/11] adjusts messages to fit within the screen --- sources/Application/Views/ImportView.cpp | 14 ++++++-------- sources/Application/Views/ThemeView.cpp | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index 3102b9e9d..3c52eb63e 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -495,7 +495,7 @@ void ImportView::import() { // stop playing before trying to import if (Player::GetInstance()->IsPlaying()) { MessageBox *mb = - MessageBox::Create(*this, "Can't import while previewing", MBBF_OK); + MessageBox::Create(*this, "Can't import while", "previewing", MBBF_OK); DoModal(mb); return; } @@ -524,11 +524,10 @@ void ImportView::import() { if (currentCount >= MAX_SAMPLES) { // Show error dialog to inform the user char message[SCREEN_WIDTH]; - npf_snprintf(message, sizeof(message), "Maximum of %d samples reached", + npf_snprintf(message, sizeof(message), "Limit of %d sample reached", MAX_SAMPLES); - // pad with trailing spaces as dialog size based on title - MessageBox *mb = MessageBox::Create(*this, "Cannot Import Sample ", - message, MBBF_OK); + MessageBox *mb = + MessageBox::Create(*this, "Cannot Import Sample", message, MBBF_OK); DoModal(mb); return; } @@ -547,9 +546,8 @@ void ImportView::import() { uint32_t availBytes = availableFlash; npf_snprintf(message, sizeof(message), "Only %d bytes free", availBytes); - // pad with trailing spaces as dialog width based on title length MessageBox *mb = - MessageBox::Create(*this, "Sample Too Large ", message, MBBF_OK); + MessageBox::Create(*this, "Sample Too Large", message, MBBF_OK); DoModal(mb); return; } @@ -714,7 +712,7 @@ void ImportView::removeProjectSample(uint8_t fileIndex, FileSystem *fs) { // add spacing for basic way to size dialog wider to give Ok/cancel // buttons between space - MessageBox *mb = MessageBox::Create(*this, " Remove sample? ", filename, + MessageBox *mb = MessageBox::Create(*this, "Remove sample?", filename, MBBF_OK | MBBF_CANCEL); DoModal(mb, [this, fs, filename, fileIndex](View &v, ModalView &dialog) { if (dialog.GetReturnCode() == MBL_OK) { diff --git a/sources/Application/Views/ThemeView.cpp b/sources/Application/Views/ThemeView.cpp index eaea4ea4f..ca016f46d 100644 --- a/sources/Application/Views/ThemeView.cpp +++ b/sources/Application/Views/ThemeView.cpp @@ -408,8 +408,8 @@ void ThemeView::handleThemeExport() { auto fs = FileSystem::GetInstance(); if (fs->exists(pathBuffer)) { // Theme exists, ask for confirmation - MessageBox *mb = MessageBox::Create( - *this, "Theme already exists. Overwrite?", MBBF_YES | MBBF_NO); + MessageBox *mb = MessageBox::Create(*this, "Theme already exists.", + "Overwrite?", MBBF_YES | MBBF_NO); // Use a lambda for the callback to avoid the static function DoModal(mb, [this](View &v, ModalView &dialog) { From 9877ce54d9ff4f05b3dae792c69fb6f1f7744d88 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 14:03:46 +0100 Subject: [PATCH 04/11] adds button ends to message box buttons, applies some DRY, fixes max width for buttons --- .../Views/ModalDialogs/MessageBox.cpp | 49 ++++++++++--------- .../Views/ModalDialogs/MessageBox.h | 2 + 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/sources/Application/Views/ModalDialogs/MessageBox.cpp b/sources/Application/Views/ModalDialogs/MessageBox.cpp index de6ae709f..b5c33fb75 100644 --- a/sources/Application/Views/ModalDialogs/MessageBox.cpp +++ b/sources/Application/Views/ModalDialogs/MessageBox.cpp @@ -8,6 +8,7 @@ */ #include "MessageBox.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "System/Console/n_assert.h" #include #include @@ -41,36 +42,35 @@ MessageBox *MessageBox::Create(View &view, const char *message, MessageBox::MessageBox(View &view, const char *message, int btnFlags) : ModalView(view), line1_(message) { - - buttonCount_ = 0; - for (int i = 0; i < MBL_LAST; i++) { - if (btnFlags & (1 << (i))) { - button_[buttonCount_] = i; - buttonCount_++; - } - } - selected_ = buttonCount_ - 1; - NAssert(buttonCount_ != 0); + InitButtons(btnFlags); }; // Constructor for 2 line message MessageBox::MessageBox(View &view, const char *messageLine1, const char *messageLine2, int btnFlags) : ModalView(view), line1_(messageLine1), line2_(messageLine2) { + InitButtons(btnFlags); +} +MessageBox::~MessageBox(){}; + +void MessageBox::InitButtons(int btnFlags) { buttonCount_ = 0; + buttonWidth_ = 0; + for (int i = 0; i < MBL_LAST; i++) { if (btnFlags & (1 << (i))) { button_[buttonCount_] = i; buttonCount_++; + + int len = strlen(buttonText[button_[i]]); + buttonWidth_ = std::max(buttonWidth_, len); } } selected_ = buttonCount_ - 1; NAssert(buttonCount_ != 0); } -MessageBox::~MessageBox(){}; - void MessageBox::Destroy() { this->~MessageBox(); inUse_ = false; @@ -78,15 +78,11 @@ void MessageBox::Destroy() { void MessageBox::DrawView() { // message size - int size1 = line1_.size(); - int size2 = line2_.size(); - int size = (size1 > size2) ? size1 : size2; + int size = std::max(line1_.size(), line2_.size()); // compute space needed for buttons // and set window size - - int btnSize = 5; - int width = buttonCount_ * (btnSize + 1) + 1; + int width = buttonCount_ * (buttonWidth_ + 1) + 1; width = (size > width) ? size : width; SetWindow(width, line2_.size() > 0 ? 4 : 3); @@ -105,16 +101,21 @@ void MessageBox::DrawView() { int offset = width / (buttonCount_ + 1); for (int i = 0; i < buttonCount_; i++) { + bool selected = (i == selected_); + const char *text = buttonText[button_[i]]; x = offset * (i + 1) - strlen(text) / 2; - if (i == selected_) { - SetColor(CD_HILITE2); - props.invert_ = true; - } else { - SetColor(CD_HILITE1); + SetColor(selected ? CD_HILITE2 : CD_HILITE1); + props.invert_ = selected; + + DrawString(x, y, text, props); + + // button ends + if (selected) { props.invert_ = false; + DrawString(x - 1, y, char_button_border_left_s, props); + DrawString(x + strlen(text), y, char_button_border_right_s, props); } - DrawString(x, y, text, props); } }; diff --git a/sources/Application/Views/ModalDialogs/MessageBox.h b/sources/Application/Views/ModalDialogs/MessageBox.h index 746555811..3dadb2ef1 100644 --- a/sources/Application/Views/ModalDialogs/MessageBox.h +++ b/sources/Application/Views/ModalDialogs/MessageBox.h @@ -46,10 +46,12 @@ class MessageBox : public ModalView { MessageBox(View &view, const char *message, int btnFlags = MBBF_OK); MessageBox(View &view, const char *message, const char *message2, int btnFlags = MBBF_OK); + void InitButtons(int btnFlags); etl::string line1_ = ""; etl::string line2_ = ""; int button_[4]; int buttonCount_; + int buttonWidth_; int selected_; private: From cb3f812261945280322649aa40cdb3e669844611 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 14:35:30 +0100 Subject: [PATCH 05/11] moves scrollbar implementation to DrawTools, adds scrollbar to the ImportView --- sources/Application/Utils/DrawTools.cpp | 31 ++++++++++++++++- sources/Application/Utils/DrawTools.h | 3 +- sources/Application/Views/ImportView.cpp | 3 ++ .../Application/Views/SelectProjectView.cpp | 33 ++----------------- sources/Application/Views/SelectProjectView.h | 1 - 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/sources/Application/Utils/DrawTools.cpp b/sources/Application/Utils/DrawTools.cpp index f07ea148b..aee1b0e8d 100644 --- a/sources/Application/Utils/DrawTools.cpp +++ b/sources/Application/Utils/DrawTools.cpp @@ -39,4 +39,33 @@ void DrawDoubleBorder(View &view, int x, int y, int width, int height, void DrawSingleBorder(View &view, int x, int y, int width, int height, const GUITextProperties &props) { DrawBorder(view, x, y, width, height, props, char_border_single_charset); -} \ No newline at end of file +} + +void DrawScrollBar(View &view, int topIndex, int totalItems, int pageSize) { + if (totalItems <= pageSize) { + return; // no scrollbar needed + } + + GUITextProperties props; + GUITextProperties inv; + inv.invert_ = true; + view.SetColor(CD_NORMAL); + + // Thumb size represents the ratio of visible items to total items + int thumbSize = std::max(1, (pageSize * pageSize) / totalItems); + + // Thumb position: map topIndex (0 to maxScroll) onto available scrollbar + // space + int maxScroll = totalItems - pageSize; + int availableSpace = pageSize - thumbSize; + int thumbPos = (topIndex * availableSpace) / maxScroll; + + Trace::Error("%d total, %d thumb size, %d maxScroll, %d thumbPos", totalItems, + thumbSize, maxScroll, thumbPos); + for (int y = 0; y < pageSize; y++) { + bool thumb = y >= thumbPos && y < thumbPos + thumbSize; + view.DrawString(SCREEN_WIDTH - 1, 2 + y, + thumb ? char_block_full_s : char_border_single_vertical_s, + props); + } +} diff --git a/sources/Application/Utils/DrawTools.h b/sources/Application/Utils/DrawTools.h index e057fd3d3..c0a738ba7 100644 --- a/sources/Application/Utils/DrawTools.h +++ b/sources/Application/Utils/DrawTools.h @@ -13,4 +13,5 @@ void DrawBorder(View &view, int x, int y, int width, int height, void DrawDoubleBorder(View &view, int x, int y, int width, int height, const GUITextProperties &props); void DrawSingleBorder(View &view, int x, int y, int width, int height, - const GUITextProperties &props); \ No newline at end of file + const GUITextProperties &props); +void DrawScrollBar(View &view, int topIndex, int totalItems, int pageSize); \ No newline at end of file diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index 3c52eb63e..cc24f5d2e 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -11,6 +11,7 @@ #include "Application/Audio/AudioFileStreamer.h" #include "Application/Instruments/SampleInstrument.h" #include "Application/Instruments/SamplePool.h" +#include "Application/Utils/DrawTools.h" #include "Application/Views/SampleEditorView.h" #include "Externals/etl/include/etl/string.h" #include "Externals/etl/include/etl/to_string.h" @@ -382,6 +383,8 @@ void ImportView::DrawView() { y = 23; // bottom line DrawString(x, y, tempBuffer, props); + DrawScrollBar(*this, topIndex_, fileIndexList_.size(), LIST_PAGE_SIZE); + SetColor(CD_NORMAL); }; diff --git a/sources/Application/Views/SelectProjectView.cpp b/sources/Application/Views/SelectProjectView.cpp index 139c847f9..724cc0c12 100644 --- a/sources/Application/Views/SelectProjectView.cpp +++ b/sources/Application/Views/SelectProjectView.cpp @@ -10,6 +10,7 @@ #include "SelectProjectView.h" #include "Application/AppWindow.h" #include "Application/Persistency/PersistencyService.h" +#include "Application/Utils/DrawTools.h" #include "Application/Views/ModalDialogs/MessageBox.h" #include "BaseClasses/ViewEvent.h" #include "Foundation/Constants/SpecialCharacters.h" @@ -131,39 +132,9 @@ void SelectProjectView::DrawView() { } // scroll bar - DrawScrollBar(); + DrawScrollBar(*this, topIndex_, fileIndexList_.size(), LIST_PAGE_SIZE); }; -void SelectProjectView::DrawScrollBar() { - int totalItems = fileIndexList_.size(); - if (totalItems <= LIST_PAGE_SIZE) { - return; // no scrollbar needed - } - - GUITextProperties props; - GUITextProperties inv; - inv.invert_ = true; - SetColor(CD_NORMAL); - - // Thumb size represents the ratio of visible items to total items - int thumbSize = std::max(1, (LIST_PAGE_SIZE * LIST_PAGE_SIZE) / totalItems); - - // Thumb position: map topIndex (0 to maxScroll) onto available scrollbar - // space - int maxScroll = totalItems - LIST_PAGE_SIZE; - int availableSpace = LIST_PAGE_SIZE - thumbSize; - int thumbPos = (topIndex_ * availableSpace) / maxScroll; - - Trace::Error("%d total, %d thumb size, %d maxScroll, %d thumbPos", totalItems, - thumbSize, maxScroll, thumbPos); - for (int y = 0; y < LIST_PAGE_SIZE; y++) { - bool thumb = y >= thumbPos && y < thumbPos + thumbSize; - DrawString(SCREEN_WIDTH - 1, 2 + y, - thumb ? char_block_full_s : char_border_single_vertical_s, - props); - } -} - void SelectProjectView::OnPlayerUpdate(PlayerEventType, unsigned int currentTick){}; diff --git a/sources/Application/Views/SelectProjectView.h b/sources/Application/Views/SelectProjectView.h index bf075d080..8c7c954de 100644 --- a/sources/Application/Views/SelectProjectView.h +++ b/sources/Application/Views/SelectProjectView.h @@ -43,7 +43,6 @@ class SelectProjectView : public ScreenView { etl::vector fileIndexList_; int selectedButton_ = 0; - void DrawScrollBar(); void AttemptDeletingSelectedProject(); void AttemptLoadingProject(); bool SelectionIsCurrentProject(); From 53a7c0891c4b5d86c9331de2919bd33a2a4f6237 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 14:46:06 +0100 Subject: [PATCH 06/11] removes superflouos spaces from the tempo display --- sources/Application/Views/ProjectView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Views/ProjectView.cpp b/sources/Application/Views/ProjectView.cpp index 6c13fd617..d819e95fb 100644 --- a/sources/Application/Views/ProjectView.cpp +++ b/sources/Application/Views/ProjectView.cpp @@ -107,7 +107,7 @@ ProjectView::ProjectView(GUIWindow &w, ViewData *data) : FieldView(w, data) { Variable *v = project_->FindVariable(FourCC::VarTempo); tempoField_.emplace_back(FourCC::ActionTempoChanged, position, *v, - "tempo: %d [%2.2x] ", MIN_TEMPO, MAX_TEMPO, 1, 10); + "tempo: %d [%2.2x]", MIN_TEMPO, MAX_TEMPO, 1, 10); fieldList_.insert(fieldList_.end(), &(*tempoField_.rbegin())); (*tempoField_.rbegin()).AddObserver(*this); From 080f0f6b533f56626bc59123ace7a1789e2e9b77 Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 14:47:39 +0100 Subject: [PATCH 07/11] matches case for Off in Device view --- sources/Application/Model/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Model/Config.cpp b/sources/Application/Model/Config.cpp index 51f109a7c..f07814535 100644 --- a/sources/Application/Model/Config.cpp +++ b/sources/Application/Model/Config.cpp @@ -28,7 +28,7 @@ #define MIDI_DEVICE_LEN 4 static const char *lineOutOptions[3] = {"HP Low", "HP High", "Line Level"}; -static const char *midiDeviceList[MIDI_DEVICE_LEN] = {"OFF", "TRS", "USB", +static const char *midiDeviceList[MIDI_DEVICE_LEN] = {"Off", "TRS", "USB", "TRS+USB"}; static const char *midiSendSync[2] = {"Off", "Send"}; static const char *midiClockSyncOptions[2] = {"Internal", "External"}; From 4c9fcd2114d71dba0a000dd58d7d0608411843cb Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 6 Feb 2026 14:57:09 +0100 Subject: [PATCH 08/11] adds button ends to UIActionField --- sources/Application/Views/BaseClasses/UIActionField.cpp | 6 ++++++ sources/UIFramework/BasicDatas/GUIPoint.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/sources/Application/Views/BaseClasses/UIActionField.cpp b/sources/Application/Views/BaseClasses/UIActionField.cpp index 462600892..ee553b166 100644 --- a/sources/Application/Views/BaseClasses/UIActionField.cpp +++ b/sources/Application/Views/BaseClasses/UIActionField.cpp @@ -9,6 +9,7 @@ #include "UIActionField.h" #include "Application/AppWindow.h" +#include "Foundation/Constants/SpecialCharacters.h" #include "ViewUtils.h" #include @@ -31,6 +32,11 @@ void UIActionField::Draw(GUIWindow &w, int offset) { ((AppWindow &)w).SetColor(CD_HILITE2); props.invert_ = true; w.DrawString(name_, position, props); + props.invert_ = false; + w.DrawString(char_button_border_left_s, position - GUIPoint(1, 0), props); + w.DrawString(char_button_border_right_s, + position + GUIPoint(strlen(name_), 0), props); + } else { // enforce max field length char buffer[MAX_FIELD_WIDTH + 1]; diff --git a/sources/UIFramework/BasicDatas/GUIPoint.h b/sources/UIFramework/BasicDatas/GUIPoint.h index 0bcd1e755..07e6e25ec 100644 --- a/sources/UIFramework/BasicDatas/GUIPoint.h +++ b/sources/UIFramework/BasicDatas/GUIPoint.h @@ -28,6 +28,12 @@ class GUIPoint { }; bool operator==(const GUIPoint &p) const { return _x == p._x && _y == p._y; }; bool operator!=(const GUIPoint &p) const { return _x != p._x || _y != p._y; }; + GUIPoint operator+(const GUIPoint &p) const { + return GUIPoint(_x + p._x, _y + p._y); + }; + GUIPoint operator-(const GUIPoint &p) const { + return GUIPoint(_x - p._x, _y - p._y); + }; long _x, _y; }; From f9edb9574eb07b8e1a45e0f06f3c04c201ca8dae Mon Sep 17 00:00:00 2001 From: nILS Date: Mon, 9 Feb 2026 09:14:16 +0100 Subject: [PATCH 09/11] invert selection in map and and cleaned up drawing code --- .../Application/Views/BaseClasses/View.cpp | 55 +++++-------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/sources/Application/Views/BaseClasses/View.cpp b/sources/Application/Views/BaseClasses/View.cpp index 577d7c3aa..53309b205 100644 --- a/sources/Application/Views/BaseClasses/View.cpp +++ b/sources/Application/Views/BaseClasses/View.cpp @@ -92,72 +92,47 @@ void View::drawMap() { // draw entire map SetColor(CD_NORMAL); - char buffer[5]; + props.invert_ = false; - // row1 - strcpy(buffer, "D "); - DrawString(pos._x, pos._y, buffer, props); - pos._y++; - // row2 - strcpy(buffer, "P G "); - DrawString(pos._x, pos._y, buffer, props); - pos._y++; - // row3 - strcpy(buffer, "SCPI"); - DrawString(pos._x, pos._y, buffer, props); - pos._y++; - // row4 - strcpy(buffer, "M TT"); - DrawString(pos._x, pos._y, buffer, props); + const char *map[] = {"D ", "P G ", "SCPI", "M TT"}; + for (int i = 0; i < 4; i++) { + DrawString(pos._x, pos._y + i, map[i], props); + } // draw current screen on map SetColor(CD_HILITE2); + props.invert_ = true; pos._y = anchor._y + View::songRowCount_ + 1; switch (viewType_) { case VT_CHAIN: - pos._x += 1; - pos._y += 2; - DrawString(pos._x, pos._y, "C", props); + DrawString(pos._x + 1, pos._y + 2, "C", props); break; case VT_PHRASE: - pos._x += 2; - pos._y += 2; - DrawString(pos._x, pos._y, "P", props); + DrawString(pos._x + 2, pos._y + 2, "P", props); break; case VT_DEVICE: DrawString(pos._x, pos._y, "D", props); break; case VT_PROJECT: - pos._y += 1; - DrawString(pos._x, pos._y, "P", props); + DrawString(pos._x, pos._y + 1, "P", props); break; case VT_INSTRUMENT: - pos._x += 3; - pos._y += 2; - DrawString(pos._x, pos._y, "I", props); + DrawString(pos._x + 3, pos._y + 2, "I", props); break; case VT_TABLE: // under phrase - pos._x += 2; - pos._y += 3; - DrawString(pos._x, pos._y, "T", props); + DrawString(pos._x + 2, pos._y + 3, "T", props); break; case VT_TABLE2: // under instrument - pos._x += 3; - pos._y += 3; - DrawString(pos._x, pos._y, "T", props); + DrawString(pos._x + 3, pos._y + 3, "T", props); break; case VT_GROOVE: - pos._x += 2; - pos._y += 1; - DrawString(pos._x, pos._y, "G", props); + DrawString(pos._x + 2, pos._y + 1, "G", props); break; case VT_MIXER: - pos._y += 3; - DrawString(pos._x, pos._y, "M", props); + DrawString(pos._x, pos._y + 3, "M", props); break; default: // VT_SONG - pos._y += 2; - DrawString(pos._x, pos._y, "S", props); + DrawString(pos._x, pos._y + 2, "S", props); } } From d0f6eb23377e7231597bfdd0b2eb97bd71d0cd59 Mon Sep 17 00:00:00 2001 From: nILS Date: Mon, 9 Feb 2026 11:30:08 +0100 Subject: [PATCH 10/11] cleaned up DrawView to move things out of loops --- sources/Application/Views/PhraseView.cpp | 91 ++++++++++++------------ sources/Application/Views/PhraseView.h | 2 +- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/sources/Application/Views/PhraseView.cpp b/sources/Application/Views/PhraseView.cpp index 1ecc52295..8591ffa0e 100644 --- a/sources/Application/Views/PhraseView.cpp +++ b/sources/Application/Views/PhraseView.cpp @@ -1220,8 +1220,7 @@ void PhraseView::DrawView() { for (int j = 0; j < 16; j++) { ((j / ALT_ROW_NUMBER) % 2) ? SetColor(CD_ACCENT) : SetColor(CD_ACCENTALT); hex2char(j, buffer); - DrawString(pos._x, pos._y, buffer, props); - pos._y++; + DrawString(pos._x, pos._y + j, buffer, props); } SetColor(CD_NORMAL); @@ -1229,6 +1228,7 @@ void PhraseView::DrawView() { pos = anchor; // Display notes + unsigned char *data = phrase_->note_ + (16 * viewData_->currentPhrase_); unsigned char *instrData = phrase_->instr_ + (16 * viewData_->currentPhrase_); unsigned char lastInstr = 0xFF; @@ -1284,6 +1284,7 @@ void PhraseView::DrawView() { } // Draw instruments + pos = anchor; pos._x += 4; @@ -1295,24 +1296,12 @@ void PhraseView::DrawView() { unsigned char d = *data++; setTextProps(props, 1, j, false); if (d == 0xFF) { - DrawString(pos._x, pos._y, "I--", props); + DrawString(pos._x, pos._y + j, "I--", props); } else { hex2char(d, buffer + 1); - DrawString(pos._x, pos._y, buffer, props); - if (j == row_) { - npf_snprintf(buffer, sizeof(buffer), "I%2.2x:", d); - etl::string<32 - BATTERY_GAUGE_WIDTH> instrLine = buffer; - setTextProps(props, 1, j, true); - GUIPoint location = GetTitlePosition(); - location._x += 10; // make space for "Phrase %2.2x" - InstrumentBank *bank = viewData_->project_->GetInstrumentBank(); - I_Instrument *instr = bank->GetInstrument(d); - instrLine += instr->GetDisplayName(); - DrawString(location._x, location._y, instrLine.c_str(), props); - } + DrawString(pos._x, pos._y + j, buffer, props); } setTextProps(props, 1, j, true); - pos._y++; } // Draw command 1 @@ -1325,12 +1314,8 @@ void PhraseView::DrawView() { for (int j = 0; j < 16; j++) { FourCC command = *f++; setTextProps(props, 2, j, false); - DrawString(pos._x, pos._y, command.c_str(), props); + DrawString(pos._x, pos._y + j, command.c_str(), props); setTextProps(props, 2, j, true); - pos._y++; - if (j == row_ && (col_ == 2 || col_ == 3)) { - printHelpLegend(command, props); - } } // Draw commands params 1 @@ -1344,16 +1329,9 @@ void PhraseView::DrawView() { for (int j = 0; j < 16; j++) { ushort p = *param++; setTextProps(props, 3, j, false); - /* if (p==0xFFFF) { - DrawString(pos._x,pos._y,"----",props) ; - } else { - */ hexshort2char(p, buffer); - DrawString(pos._x, pos._y, buffer, props); - /* } - */ + DrawString(pos._x, pos._y + j, buffer, props); setTextProps(props, 3, j, true); - pos._y++; } // Draw commands 2 @@ -1366,12 +1344,8 @@ void PhraseView::DrawView() { for (int j = 0; j < 16; j++) { FourCC command = *f++; setTextProps(props, 4, j, false); - DrawString(pos._x, pos._y, command.c_str(), props); + DrawString(pos._x, pos._y + j, command.c_str(), props); setTextProps(props, 4, j, true); - pos._y++; - if (j == row_ && (col_ == 4 || col_ == 5)) { - printHelpLegend(command, props); - } } // Draw commands params @@ -1385,23 +1359,34 @@ void PhraseView::DrawView() { for (int j = 0; j < 16; j++) { ushort p = *param++; setTextProps(props, 5, j, false); - /* if (p==0xFFFF) { - DrawString(pos._x,pos._y,"----",props) ; - } else { - */ hexshort2char(p, buffer); - DrawString(pos._x, pos._y, buffer, props); - /* } - */ + DrawString(pos._x, pos._y + j, buffer, props); setTextProps(props, 5, j, true); - pos._y++; + } + + // Draw instrument Name + + if (col_ == 1) { + unsigned char *data = + phrase_->instr_ + (16 * viewData_->currentPhrase_ + row_); + if (*data != 0xFF) { + GUIPoint location = GetTitlePosition(); + InstrumentBank *bank = viewData_->project_->GetInstrumentBank(); + I_Instrument *instr = bank->GetInstrument(*data); + npf_snprintf(buffer, sizeof(buffer), "I%2.2x:", *data); + etl::string<32 - BATTERY_GAUGE_WIDTH> instrLine = buffer; + instrLine += instr->GetDisplayName(); + setTextProps(props, 1, row_, true); + DrawString(location._x + 10, location._y, instrLine.c_str(), props); + } + } else { + drawHelpLegend(); } drawMap(); drawNotes(); - Player *player = Player::GetInstance(); - if (player->IsRunning()) { + if (Player::GetInstance()->IsRunning()) { OnPlayerUpdate(PET_UPDATE); }; @@ -1516,13 +1501,25 @@ void PhraseView::AnimationUpdate() { // Flush the window to ensure changes are displayed w_.Flush(); } -void PhraseView::printHelpLegend(FourCC command, GUITextProperties props) { - if (command == FourCC::InstrumentCommandNone) { + +void PhraseView::drawHelpLegend() { + GUITextProperties props; + FourCC *command = nullptr; + + if (col_ == 2 || col_ == 3) { + command = phrase_->cmd1_; + } else if (col_ == 4 || col_ == 5) { + command = phrase_->cmd2_; + } + + command += (16 * viewData_->currentPhrase_ + row_); + + if (!command || *command == FourCC::InstrumentCommandNone) { // no command -> no help text return; } - char **helpLegend = getHelpLegend(command); + char **helpLegend = getHelpLegend(*command); char line[32]; //-1 for 1char space start of line // first clear top line upto battery gauge DrawString(0, 0, " ", props); diff --git a/sources/Application/Views/PhraseView.h b/sources/Application/Views/PhraseView.h index 42b6be16b..421a288ed 100644 --- a/sources/Application/Views/PhraseView.h +++ b/sources/Application/Views/PhraseView.h @@ -68,7 +68,7 @@ class PhraseView : public ScreenView { Variable cmdEdit_; GUIPoint cmdEditPos_; UIBigHexVarField cmdEditField_; - void printHelpLegend(FourCC command, GUITextProperties props); + void drawHelpLegend(); struct clipboard { bool active_; From 669022d68ba7458df4790b4e5dd30922eb13f4ff Mon Sep 17 00:00:00 2001 From: nILS Date: Mon, 9 Feb 2026 17:04:36 +0100 Subject: [PATCH 11/11] enhances command help and adds abbreviation highlighting --- sources/Application/Utils/HelpLegend.h | 99 +++++++++++++----------- sources/Application/Views/PhraseView.cpp | 16 ++++ sources/Application/Views/TableView.cpp | 16 ++++ 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/sources/Application/Utils/HelpLegend.h b/sources/Application/Utils/HelpLegend.h index e91458999..99e04155a 100644 --- a/sources/Application/Utils/HelpLegend.h +++ b/sources/Application/Utils/HelpLegend.h @@ -15,104 +15,115 @@ // chars static char **getHelpLegend(FourCC command) { static char *result[2]; - result[1] = (char *)("bb at speed aa"); + + result[1] = (char *)""; + switch (command) { case FourCC::InstrumentCommandKill: - result[0] = (char *)("KILl:--bb, stop playing"); - result[1] = (char *)("after bb ticks"); + result[0] = (char *)"KILl: --bb, stop playing"; + result[1] = (char *)"after bb ticks"; break; case FourCC::InstrumentCommandLoopOfset: - result[0] = (char *)("Loop OFset: Shift loop"); - result[1] = (char *)("start & end values aaaa"); + result[0] = (char *)"Loop OFset: aaaa shift"; + result[1] = (char *)"loop start & end by aaaa"; break; case FourCC::InstrumentCommandArpeggiator: - result[0] = (char *)("ARPeggio: Cycle through"); - result[1] = (char *)("relative pitches"); + result[0] = (char *)"ARPeggio: abcd, cycle"; + result[1] = (char *)"rel. pitches +a,+b,+c,+d"; break; case FourCC::InstrumentCommandVolume: - result[0] = (char *)("VOLume:aabb, reach volume"); + result[0] = (char *)"VOLume: aabb, approach"; + result[1] = (char *)"volume bb at speed aa"; break; case FourCC::InstrumentCommandVelocity: - result[0] = (char *)("VELocity:--bb,"); - result[1] = (char *)("MIDI velocity"); + result[0] = (char *)"VELocity: --bb, send MIDI"; + result[1] = (char *)"velocity bb"; break; case FourCC::InstrumentCommandPitchSlide: - result[0] = (char *)("Pitch SLide:aabb, to pitch"); + result[0] = (char *)"Pitch SLide: aabb, slide"; + result[1] = (char *)"to pitch bb at speed aa"; break; case FourCC::InstrumentCommandHop: - result[0] = (char *)("Hop:aabb, hop to bb"); - result[1] = (char *)("aa times"); + result[0] = (char *)"HOP: aabb, hop to bb"; + result[1] = (char *)"aa times"; break; case FourCC::InstrumentCommandLegato: - result[0] = (char *)("Legato:aabb, slide"); - result[1] = (char *)("to pitch bb at speed aa"); + result[0] = (char *)"LEGato: aabb, slide"; + result[1] = (char *)"to pitch bb at speed aa"; break; case FourCC::InstrumentCommandRetrigger: - result[0] = (char *)("Retrigger:aabb retrigger"); - result[1] = (char *)("loop bb ticks at speed aa"); + result[0] = (char *)"ReTriGger: aabb retrigger"; + result[1] = (char *)"loop bb ticks at speed aa"; break; case FourCC::InstrumentCommandTempo: - result[0] = (char *)("Tempo:--bb, set tempo to"); - result[1] = (char *)("hex value bb"); + result[0] = (char *)"TemPO: --bb, set tempo to"; + result[1] = (char *)"hex value bb"; break; case FourCC::InstrumentCommandMidiCC: - result[0] = (char *)("MIDI CC:aabb, "); - result[1] = (char *)("CC message aa value bb"); + result[0] = (char *)"Midi CC: aabb, send"; + result[1] = (char *)"CC message aa value bb"; break; case FourCC::InstrumentCommandMidiPC: - result[0] = (char *)("MIDI Program Change:aabb,"); - result[1] = (char *)("send program change bb"); + result[0] = (char *)"Midi Program Change: --bb"; + result[1] = (char *)"send program change bb"; break; case FourCC::InstrumentCommandPlayOfset: - result[0] = (char *)("Play OFfset:aabb, jump abs"); - result[1] = (char *)("to aa or move rel bb chunks"); + result[0] = (char *)"Play OFfset: aabb, go abs"; + result[1] = (char *)"to aa or move rel bb chunks"; break; case FourCC::InstrumentCommandFilterResonance: - result[0] = (char *)("FiLTer&Res:aabb, cutoff aa"); - result[1] = (char *)("resonance bb"); + result[0] = (char *)"Filter ReS: aabb, set"; + result[1] = (char *)"resonance bb at speed aa"; break; case FourCC::InstrumentCommandLowPassFilter: - result[0] = (char *)("FiLTeR:aabb, resonance to"); + result[0] = (char *)"FiLTer: aabb, set cutoff"; + result[1] = (char *)"aa & resonance bb"; break; case FourCC::InstrumentCommandTable: - result[0] = (char *)("TaBLe:--bb, run table bb"); + result[0] = (char *)"TaBLe: --bb, run table bb"; break; case FourCC::InstrumentCommandCrush: - result[0] = (char *)("drive&CruSH:aa-b,"); - result[1] = (char *)("drive aa crush -b"); + result[0] = (char *)"drive & CruSH: aa-b, set"; + result[1] = (char *)"drive aa & crush b"; break; case FourCC::InstrumentCommandFilterCut: - result[0] = (char *)("FilterCuToff:aabb, cutoff"); + result[0] = (char *)"FilterCuToff: aabb, set"; + result[1] = (char *)"cutoff bb at speed aa"; break; case FourCC::InstrumentCommandPan: - result[0] = (char *)("PAN:aabb, pan to value"); + result[0] = (char *)"PAN: aabb, pan to value,"; + result[1] = (char *)"00 is left, FF is right"; break; case FourCC::InstrumentCommandGroove: - result[0] = (char *)("GRooVe:aabb, set groove bb"); - result[1] = (char *)("if aa > 0, set all tracks"); + result[0] = (char *)"GRooVe: aabb, set groove"; + result[1] = (char *)"bb, if aa>0 set all tracks"; break; case FourCC::InstrumentCommandInstrumentRetrigger: - result[0] = (char *)("InstrumentReTrig:aabb,"); - result[1] = (char *)("trig&transpose aa speed bb"); + result[0] = (char *)"InstrumentReTrig: aabb,"; + result[1] = (char *)"trig & transp. aa speed bb"; break; case FourCC::InstrumentCommandPitchFineTune: - result[0] = (char *)("PitchFineTune:aabb, tune"); + result[0] = (char *)"PitchFineTune: aabb, tune"; + result[1] = (char *)"offset bb at speed bb"; break; case FourCC::InstrumentCommandDelay: - result[0] = (char *)("Delay:--bb, delay bb tics"); + result[0] = (char *)"DeLaY: --bb, delay by bb"; + result[1] = (char *)"tics"; break; case FourCC::InstrumentCommandStop: - result[0] = (char *)("Stop playing song now"); + result[0] = (char *)"SToP: Stop playing the"; + result[1] = (char *)"song now"; break; case FourCC::InstrumentCommandGateOff: - result[0] = (char *)("GateOff (Synth only)"); + result[0] = (char *)"Gate OFf: Set the gate"; + result[1] = (char *)"off for synths only"; break; case FourCC::InstrumentCommandMidiChord: - result[0] = (char *)("MIDI Chord:abcd"); - result[1] = (char *)("send rel notes:+a,+b,+c,+d"); + result[0] = (char *)"Midi CHord: abcd"; + result[1] = (char *)"Send rel notes: +a,+b,+c,+d"; break; default: - result[0] = result[1] = (char *)(""); + result[0] = result[1] = (char *)""; break; } return result; diff --git a/sources/Application/Views/PhraseView.cpp b/sources/Application/Views/PhraseView.cpp index 8591ffa0e..b5b1b7de0 100644 --- a/sources/Application/Views/PhraseView.cpp +++ b/sources/Application/Views/PhraseView.cpp @@ -1533,4 +1533,20 @@ void PhraseView::drawHelpLegend() { strcpy(line, helpLegend[1]); DrawString(0, 1, line, props); } + + // highlight the upper case letters before the ':' + const char *line0 = helpLegend[0]; + const char *colonPos = strchr(line0, ':'); + + if (colonPos) { + SetColor(CD_ACCENT); + char str[2] = {0, 0}; + for (const char *p = line0; p < colonPos; ++p) { + if ((*p >= 'A') && (*p <= 'Z')) { + str[0] = *p; + DrawString(static_cast(p - line0), 0, str, props); + } + } + SetColor(CD_NORMAL); + } } diff --git a/sources/Application/Views/TableView.cpp b/sources/Application/Views/TableView.cpp index 72ae8d9e8..2627b5559 100644 --- a/sources/Application/Views/TableView.cpp +++ b/sources/Application/Views/TableView.cpp @@ -1021,4 +1021,20 @@ void TableView::printHelpLegend(FourCC command, GUITextProperties props) { strcpy(line, helpLegend[1]); DrawString(0, 1, line, props); } + + // highlight the upper case letters before the ':' + const char *line0 = helpLegend[0]; + const char *colonPos = strchr(line0, ':'); + + if (colonPos) { + SetColor(CD_ACCENT); + char str[2] = {0, 0}; + for (const char *p = line0; p < colonPos; ++p) { + if ((*p >= 'A') && (*p <= 'Z')) { + str[0] = *p; + DrawString(static_cast(p - line0), 0, str, props); + } + } + SetColor(CD_NORMAL); + } }