Skip to content

Commit

Permalink
Accessibility Set 2 (#41)
Browse files Browse the repository at this point in the history
- Edit gestures
- Better spoken names and invalidation
- Actually not that bad!
  • Loading branch information
baconpaul authored Apr 26, 2024
1 parent 572d51b commit dac810a
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 65 deletions.
182 changes: 119 additions & 63 deletions src-juce/AWConsolidatedEditor.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <algorithm>

#include <juce_gui_basics/juce_gui_basics.h>

Expand Down Expand Up @@ -42,9 +43,8 @@ struct Picker : public juce::Component
{
setAccessible(true);
}
void paintButton (juce:: Graphics& g,
bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override
void paintButton(juce::Graphics &g, bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override
{
auto p = juce::Path();
auto jd = getLocalBounds().reduced(3, 5);
Expand Down Expand Up @@ -82,17 +82,27 @@ struct Picker : public juce::Component

void mouseDown(const juce::MouseEvent &) override { picker->doJog(dir); }
void mouseUp(const juce::MouseEvent &) override { picker->stopJogHold(); }

bool keyPressed(const juce::KeyPress &p) override
{
if (p.getKeyCode() == juce::KeyPress::returnKey)
{
// dojog does long hold stuff so go direct
picker->editor->jog(dir);
return true;
}
return false;
}
};
std::unique_ptr<Jog> up, down;

struct Hamburger : juce::Button
{
Picker *picker;
Hamburger(Picker *p) : juce::Button("Menu"), picker(p) { setAccessible(true); }
Hamburger(Picker *p) : juce::Button("Main Menu"), picker(p) { setAccessible(true); }

void paintButton (juce:: Graphics& g,
bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override
void paintButton(juce::Graphics &g, bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override
{
auto r = getLocalBounds().withHeight(getHeight() / 5);
for (int i = 0; i < 3; ++i)
Expand Down Expand Up @@ -122,6 +132,18 @@ struct Picker : public juce::Component
repaint();
}
void mouseDown(const juce::MouseEvent &) override { picker->editor->showMenu(); }

bool keyPressed(const juce::KeyPress &p) override
{
if (p.getKeyCode() == juce::KeyPress::returnKey ||
(p.getKeyCode() == juce::KeyPress::F10Key && p.getModifiers().isShiftDown()))
{
// dojog does long hold stuff so go direct
picker->editor->showMenu();
return true;
}
return false;
}
};
std::unique_ptr<Hamburger> hamburger;

Expand Down Expand Up @@ -236,51 +258,26 @@ struct Picker : public juce::Component
});
}

AWConsolidatedAudioProcessorEditor *editor{nullptr};
#if 0
struct AH : public juce::AccessibilityHandler
void rebuild()
{
struct AHV : public juce::AccessibilityValueInterface
{
explicit AHV(Picker *s) : comp(s) {}

Picker *comp;

bool isReadOnly() const override { return true; }
double getCurrentValue() const override { return 0.; }

void setValue(double) override {}
void setValueAsString(const juce::String &newValue) override {}
AccessibleValueRange getRange() const override { return {{0, 1}, 1}; }
juce::String getCurrentValueAsString() const override
{
return fx_type_names[comp->editor->processor.getEffectType()];
}

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AHV);
};

explicit AH(Picker *s)
: comp(s),
juce::AccessibilityHandler(*s, juce::AccessibilityRole::button,
juce::AccessibilityActions()
.addAction(juce::AccessibilityActionType::press,
[this]() { comp->editor->showMenu(); })
.addAction(juce::AccessibilityActionType::showMenu,
[this]() { comp->editor->showMenu(); }),
AccessibilityHandler::Interfaces{std::make_unique<AHV>(s)})
{
}

Picker *comp;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AH);
};
int idx = editor->processor.curentProcessorIndex;
auto &rg = AirwinRegistry::registry[idx];

std::unique_ptr<juce::AccessibilityHandler> createAccessibilityHandler() override
{
return std::make_unique<AH>(this);
setTitle(rg.name + " (" + rg.category + ")");
if (getAccessibilityHandler())
getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::titleChanged);

up->setTitle("Select Previous from " + rg.name);
if (up->getAccessibilityHandler())
up->getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::titleChanged);
down->setTitle("Select Next from " + rg.name);
if (down->getAccessibilityHandler())
down->getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::titleChanged);
}
#endif
AWConsolidatedAudioProcessorEditor *editor{nullptr};
};

struct AWLink : public juce::Component
Expand Down Expand Up @@ -318,7 +315,8 @@ struct AWLink : public juce::Component
struct DocPanel : juce::Component
{
AWConsolidatedAudioProcessorEditor *editor{nullptr};
DocPanel(AWConsolidatedAudioProcessorEditor *ed) : editor(ed) {
DocPanel(AWConsolidatedAudioProcessorEditor *ed) : editor(ed)
{
setAccessible(true);
setWantsKeyboardFocus(true);
}
Expand All @@ -343,19 +341,23 @@ struct DocPanel : juce::Component

setSize(r.getWidth(), r.getHeight());

setTitle(AirwinRegistry::registry[editor->processor.curentProcessorIndex].name + " Documentation. Control R to read");
setTitle(AirwinRegistry::registry[editor->processor.curentProcessorIndex].name +
" Documentation. Control R to read");
if (getAccessibilityHandler())
getAccessibilityHandler()->notifyAccessibilityEvent(juce::AccessibilityEvent::titleChanged);
getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::titleChanged);
}

float targetWidth{10};

bool keyPressed(const juce::KeyPress &key) override {
if ((key.getKeyCode() == 'r' ||
key.getKeyCode() == 'R') && (key.getModifiers().isCommandDown() || key.getModifiers().isCtrlDown()))
bool keyPressed(const juce::KeyPress &key) override
{
if ((key.getKeyCode() == 'r' || key.getKeyCode() == 'R') &&
(key.getModifiers().isCommandDown() || key.getModifiers().isCtrlDown()))
{
getAccessibilityHandler()->postAnnouncement(editor->docHeader.substring(2) + "." + editor->docString,
juce::AccessibilityHandler::AnnouncementPriority::medium);
getAccessibilityHandler()->postAnnouncement(
editor->docHeader.substring(2) + "." + editor->docString,
juce::AccessibilityHandler::AnnouncementPriority::medium);
return true;
}
return false;
Expand Down Expand Up @@ -404,13 +406,23 @@ struct ParamKnob : juce::Component
setWantsKeyboardFocus(active);
if (active && weakParam)
setTitle(weakParam->getName(64));
if (getAccessibilityHandler())
{
getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::valueChanged);
getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::textChanged);
}
}

float getValue() const { return weakParam ? weakParam->get() : 0.f; }
void setValue(float to)
{
if (weakParam)
weakParam->setValueNotifyingHost(to);
if (getAccessibilityHandler())
getAccessibilityHandler()->notifyAccessibilityEvent(
juce::AccessibilityEvent::valueChanged);
}

void paint(juce::Graphics &g) override
Expand Down Expand Up @@ -507,26 +519,62 @@ struct ParamKnob : juce::Component
{
if (slider->weakParam)
{
return slider->weakParam->getCurrentValueAsText();
auto res = slider->weakParam->getCurrentValueAsText();
return res;
}
return "";
}
void setValueAsString(const juce::String &) {}
void setValueAsString(const juce::String &) override {}

AccessibleValueRange getRange() const override { return {{0, 1}, 0.01}; }

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AHValue);
};
struct AH : juce::AccessibilityHandler
{
ParamKnob *slider{nullptr};
AH(ParamKnob *c)
: juce::AccessibilityHandler(
*c, juce::AccessibilityRole::slider, juce::AccessibilityActions(),
AccessibilityHandler::Interfaces{std::make_unique<AHValue>(c)})
AccessibilityHandler::Interfaces{std::make_unique<AHValue>(c)}),
slider(c)
{
}

juce::String getTitle() const override { return slider->weakParam->getName(64); }
};

bool keyPressed(const juce::KeyPress &key) override
{
float amt = 0.05;
if (key.getModifiers().isShiftDown())
amt = 0.01;
if (key.getKeyCode() == juce::KeyPress::upKey)
{
setValue(std::clamp((double)getValue() + amt, 0., 1.));
return true;
}

if (key.getKeyCode() == juce::KeyPress::downKey)
{
setValue(std::clamp((double)getValue() - amt, 0., 1.));
return true;
}

if (key.getKeyCode() == juce::KeyPress::homeKey)
{
setValue(1.);
return true;
}

if (key.getKeyCode() == juce::KeyPress::endKey)
{
setValue(0.);
return true;
}
return false;
}

std::unique_ptr<juce::AccessibilityHandler> createAccessibilityHandler() override
{
return std::make_unique<AH>(this);
Expand Down Expand Up @@ -697,7 +745,7 @@ AWConsolidatedAudioProcessorEditor::~AWConsolidatedAudioProcessorEditor()

void AWConsolidatedAudioProcessorEditor::idle()
{
if (processor.refreshUI.exchange(false))
if (processor.rebuildUI.exchange(false))
{
docString = AirwinRegistry::documentationStringFor(processor.curentProcessorIndex);
docHeader = docString.upToFirstOccurrenceOf("\n", false, false);
Expand All @@ -708,6 +756,12 @@ void AWConsolidatedAudioProcessorEditor::idle()
for (auto &k : knobs)
k->refreshModel();

menuPicker->rebuild();
repaint();
}

if (processor.refreshUI.exchange(false))
{
repaint();
}
}
Expand Down Expand Up @@ -834,7 +888,8 @@ struct FxFocusTrav : public juce::ComponentTraverser
{
auto res = iter;

while (res != editor->accessibleOrderWeakRefs.cbegin() && !(*std::prev(res))->isAccessible())
while (res != editor->accessibleOrderWeakRefs.cbegin() &&
!(*std::prev(res))->isAccessible())
{
res = std::prev(res);
}
Expand All @@ -860,7 +915,8 @@ struct FxFocusTrav : public juce::ComponentTraverser
AWConsolidatedAudioProcessorEditor *editor{nullptr};
};

std::unique_ptr<juce::ComponentTraverser> AWConsolidatedAudioProcessorEditor::createKeyboardFocusTraverser()
std::unique_ptr<juce::ComponentTraverser>
AWConsolidatedAudioProcessorEditor::createKeyboardFocusTraverser()
{
return std::make_unique<FxFocusTrav>(this);
}
2 changes: 1 addition & 1 deletion src-juce/AWConsolidatedProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void AWConsolidatedAudioProcessor::setAWProcessorTo(int registryIndex, bool init
}

updateHostDisplay(juce::AudioProcessor::ChangeDetails().withParameterInfoChanged(true));
refreshUI = true;
rebuildUI = true;
}
//==============================================================================
void AWConsolidatedAudioProcessor::getStateInformation(juce::MemoryBlock &destData)
Expand Down
3 changes: 2 additions & 1 deletion src-juce/AWConsolidatedProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class AWConsolidatedAudioProcessor : public juce::AudioProcessor,
setAWProcessorTo(index, false);
}
}
std::atomic<bool> refreshUI{false};
std::atomic<bool> refreshUI{false},
rebuildUI{false}; // repaint vs re-setup everything. Value vs type

struct AWParam : public juce::AudioParameterFloat
{
Expand Down

0 comments on commit dac810a

Please sign in to comment.