added key navigation for palette panel
This commit is contained in:
parent
b732a3f81a
commit
1b73eed0ae
24 changed files with 493 additions and 665 deletions
|
@ -158,7 +158,11 @@ DockPage {
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: keynavComp
|
id: keynavComp
|
||||||
KeyNavExample{}
|
KeyNavExample {
|
||||||
|
onActiveFocusRequested: {
|
||||||
|
devtoolsCentral.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ Rectangle {
|
||||||
|
|
||||||
property string lastClickedInfo: ""
|
property string lastClickedInfo: ""
|
||||||
|
|
||||||
|
signal activeFocusRequested()
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: infoPanel
|
id: infoPanel
|
||||||
|
|
||||||
|
@ -36,6 +38,13 @@ Rectangle {
|
||||||
sectionName: "mainMenu"
|
sectionName: "mainMenu"
|
||||||
sectionOrder: 101
|
sectionOrder: 101
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
root.activeFocusRequested()
|
||||||
|
root.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
|
@ -9,6 +9,7 @@ Rectangle {
|
||||||
property alias keynavSection: keynavsec
|
property alias keynavSection: keynavsec
|
||||||
property alias sectionName: keynavsec.name
|
property alias sectionName: keynavsec.name
|
||||||
property alias sectionOrder: keynavsec.order
|
property alias sectionOrder: keynavsec.order
|
||||||
|
property alias active: keynavsec.active
|
||||||
|
|
||||||
default property alias content: contentItem.data
|
default property alias content: contentItem.data
|
||||||
|
|
||||||
|
@ -20,14 +21,8 @@ Rectangle {
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
console.debug("KeyNavSection.qml active: " + keynavsec.active)
|
console.debug("KeyNavSection.qml active: " + keynavsec.active)
|
||||||
if (keynavsec.active) {
|
if (keynavsec.active) {
|
||||||
|
root.forceActiveFocus()
|
||||||
|
|
||||||
var p = root.parent
|
|
||||||
while (p) {
|
|
||||||
p.focus = true
|
|
||||||
p = p.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
root.focus = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,12 +133,20 @@ DockPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
property KeyNavigationControl keynavTab: KeyNavigationControl {
|
property KeyNavigationControl keynavTab: KeyNavigationControl {
|
||||||
name: "PanelTab"
|
name: "PaletteTab"
|
||||||
order: 1 //! TODO Needs order from DockPanel
|
order: 1 //! TODO Needs order from DockPanel
|
||||||
subsection: notationPage.keynavPanelTabSubSec(palettePanel.area)
|
subsection: notationPage.keynavPanelTabSubSec(palettePanel.area)
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
palettePanel.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PalettesWidget {}
|
PalettesWidget {
|
||||||
|
anchors.fill: parent
|
||||||
|
keynavSection: notationPage.keynavPanelSec(palettePanel.area)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DockPanel {
|
DockPanel {
|
||||||
|
@ -167,11 +175,17 @@ DockPage {
|
||||||
name: "InstrumentsTab"
|
name: "InstrumentsTab"
|
||||||
order: 2 //! TODO Needs order from DockPanel
|
order: 2 //! TODO Needs order from DockPanel
|
||||||
subsection: notationPage.keynavPanelTabSubSec(instrumentsPanel.area)
|
subsection: notationPage.keynavPanelTabSubSec(instrumentsPanel.area)
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
instrumentsPanel.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InstrumentsPanel {
|
InstrumentsPanel {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
keynavSection: notationPage.keynavPanelSec(instrumentsPanel.area)
|
keynavSection: notationPage.keynavPanelSec(instrumentsPanel.area)
|
||||||
|
visible: instrumentsPanel.isShown
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -201,6 +215,11 @@ DockPage {
|
||||||
name: "InspectorTab"
|
name: "InspectorTab"
|
||||||
order: 3 //! TODO Needs order from DockPanel
|
order: 3 //! TODO Needs order from DockPanel
|
||||||
subsection: notationPage.keynavPanelTabSubSec(inspectorPanel.area)
|
subsection: notationPage.keynavPanelTabSubSec(inspectorPanel.area)
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
inspectorPanel.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InspectorForm {
|
InspectorForm {
|
||||||
|
|
|
@ -81,6 +81,7 @@ DockWindow {
|
||||||
|
|
||||||
toolbars: [
|
toolbars: [
|
||||||
DockToolBar {
|
DockToolBar {
|
||||||
|
id: mainToolBar
|
||||||
objectName: "mainToolBar"
|
objectName: "mainToolBar"
|
||||||
minimumWidth: 296
|
minimumWidth: 296
|
||||||
minimumHeight: dockWindow.toolbarHeight
|
minimumHeight: dockWindow.toolbarHeight
|
||||||
|
@ -96,6 +97,12 @@ DockWindow {
|
||||||
keynav.order: 1
|
keynav.order: 1
|
||||||
currentUri: dockWindow.currentPageUri
|
currentUri: dockWindow.currentPageUri
|
||||||
|
|
||||||
|
keynav.onActiveChanged: {
|
||||||
|
if (keynav.active) {
|
||||||
|
mainToolBar.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onSelected: {
|
onSelected: {
|
||||||
api.launcher.open(uri)
|
api.launcher.open(uri)
|
||||||
}
|
}
|
||||||
|
@ -120,6 +127,11 @@ DockWindow {
|
||||||
keynav.section: topToolKeyNavSec
|
keynav.section: topToolKeyNavSec
|
||||||
keynav.order: 2
|
keynav.order: 2
|
||||||
keynav.enabled: notationToolBar.visible
|
keynav.enabled: notationToolBar.visible
|
||||||
|
onActiveFocusRequested: {
|
||||||
|
if (keynav.active) {
|
||||||
|
notationToolBar.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: notationToolBar
|
target: notationToolBar
|
||||||
|
|
|
@ -37,7 +37,15 @@ DockPanel::DockPanel(QQuickItem* parent)
|
||||||
connect(this, &DockPanel::visibleEdited, this, [this](bool visible) {
|
connect(this, &DockPanel::visibleEdited, this, [this](bool visible) {
|
||||||
if (m_dock.panel->isVisible() != visible) {
|
if (m_dock.panel->isVisible() != visible) {
|
||||||
m_dock.panel->setVisible(visible);
|
m_dock.panel->setVisible(visible);
|
||||||
|
if (!visible) {
|
||||||
|
m_isShown = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_dock.panel, &QDockWidget::visibilityChanged, this, [this](bool vsbl) {
|
||||||
|
m_isShown = vsbl;
|
||||||
|
emit isShownChanged(vsbl);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_eventsWatcher = new EventsWatcher(this);
|
m_eventsWatcher = new EventsWatcher(this);
|
||||||
|
@ -58,6 +66,7 @@ void DockPanel::onComponentCompleted()
|
||||||
updateStyle();
|
updateStyle();
|
||||||
|
|
||||||
m_preferedWidth = width();
|
m_preferedWidth = width();
|
||||||
|
m_isShown = panel()->isVisible();
|
||||||
|
|
||||||
if (minimumWidth() == 0) {
|
if (minimumWidth() == 0) {
|
||||||
panel()->setMinimumWidth(width());
|
panel()->setMinimumWidth(width());
|
||||||
|
@ -161,6 +170,11 @@ bool DockPanel::closable() const
|
||||||
return featureEnabled(QDockWidget::DockWidgetClosable);
|
return featureEnabled(QDockWidget::DockWidgetClosable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockPanel::isShown() const
|
||||||
|
{
|
||||||
|
return m_isShown;
|
||||||
|
}
|
||||||
|
|
||||||
bool DockPanel::visible() const
|
bool DockPanel::visible() const
|
||||||
{
|
{
|
||||||
return m_dock.panel ? m_dock.panel->isVisible() : false;
|
return m_dock.panel ? m_dock.panel->isVisible() : false;
|
||||||
|
|
|
@ -36,6 +36,8 @@ class DockPanel : public DockView
|
||||||
Q_PROPERTY(bool floatable READ floatable WRITE setFloatable NOTIFY floatableChanged)
|
Q_PROPERTY(bool floatable READ floatable WRITE setFloatable NOTIFY floatableChanged)
|
||||||
Q_PROPERTY(bool closable READ closable WRITE setClosable NOTIFY closableChanged)
|
Q_PROPERTY(bool closable READ closable WRITE setClosable NOTIFY closableChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(bool isShown READ isShown NOTIFY isShownChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DockPanel(QQuickItem* parent = nullptr);
|
explicit DockPanel(QQuickItem* parent = nullptr);
|
||||||
~DockPanel() override;
|
~DockPanel() override;
|
||||||
|
@ -49,6 +51,7 @@ public:
|
||||||
|
|
||||||
bool floatable() const;
|
bool floatable() const;
|
||||||
bool closable() const;
|
bool closable() const;
|
||||||
|
bool isShown() const;
|
||||||
bool visible() const override;
|
bool visible() const override;
|
||||||
|
|
||||||
struct Widget {
|
struct Widget {
|
||||||
|
@ -78,6 +81,7 @@ signals:
|
||||||
void floatableChanged(bool floatable);
|
void floatableChanged(bool floatable);
|
||||||
void closableChanged(bool closable);
|
void closableChanged(bool closable);
|
||||||
void closed();
|
void closed();
|
||||||
|
void isShownChanged(bool isShown);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onComponentCompleted() override;
|
void onComponentCompleted() override;
|
||||||
|
@ -94,6 +98,7 @@ private:
|
||||||
EventsWatcher* m_eventsWatcher = nullptr;
|
EventsWatcher* m_eventsWatcher = nullptr;
|
||||||
|
|
||||||
int m_preferedWidth = 0;
|
int m_preferedWidth = 0;
|
||||||
|
bool m_isShown = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,13 +42,29 @@
|
||||||
<seq>Down</seq>
|
<seq>Down</seq>
|
||||||
</SC>
|
</SC>
|
||||||
<SC>
|
<SC>
|
||||||
<key>nav-trigger</key>
|
<key>nav-trigger-control</key>
|
||||||
<seq>Return</seq>
|
<seq>Return</seq>
|
||||||
</SC>
|
</SC>
|
||||||
<SC>
|
<SC>
|
||||||
<key>nav-trigger</key>
|
<key>nav-trigger-control</key>
|
||||||
<seq>Space</seq>
|
<seq>Space</seq>
|
||||||
</SC>
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-first-control</key>
|
||||||
|
<seq>Home</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-last-control</key>
|
||||||
|
<seq>End</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-nextrow-control</key>
|
||||||
|
<seq>PgDown</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-prevrow-control</key>
|
||||||
|
<seq>PgUp</seq>
|
||||||
|
</SC>
|
||||||
<!-- end Keyboard navigation -->
|
<!-- end Keyboard navigation -->
|
||||||
|
|
||||||
<SC>
|
<SC>
|
||||||
|
|
|
@ -42,13 +42,30 @@
|
||||||
<seq>Down</seq>
|
<seq>Down</seq>
|
||||||
</SC>
|
</SC>
|
||||||
<SC>
|
<SC>
|
||||||
<key>nav-trigger</key>
|
<key>nav-trigger-control</key>
|
||||||
<seq>Return</seq>
|
<seq>Return</seq>
|
||||||
</SC>
|
</SC>
|
||||||
<SC>
|
<SC>
|
||||||
<key>nav-trigger</key>
|
<key>nav-trigger-control</key>
|
||||||
<seq>Space</seq>
|
<seq>Space</seq>
|
||||||
</SC>
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-first-control</key>
|
||||||
|
<seq>Home</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-last-control</key>
|
||||||
|
<seq>End</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-nextrow-control</key>
|
||||||
|
<seq>PgDown</seq>
|
||||||
|
</SC>
|
||||||
|
<SC>
|
||||||
|
<key>nav-prevrow-control</key>
|
||||||
|
<seq>PgUp</seq>
|
||||||
|
</SC>
|
||||||
|
|
||||||
<!-- end Keyboard navigation -->
|
<!-- end Keyboard navigation -->
|
||||||
|
|
||||||
<SC>
|
<SC>
|
||||||
|
|
|
@ -28,60 +28,6 @@ using namespace mu::ui;
|
||||||
using MoveDirection = KeyNavigationController::MoveDirection;
|
using MoveDirection = KeyNavigationController::MoveDirection;
|
||||||
|
|
||||||
// algorithms
|
// algorithms
|
||||||
template<class T>
|
|
||||||
static IKeyNavigation::Index determinateExtremeIndex(const QSet<T*>& set, MoveDirection direction)
|
|
||||||
{
|
|
||||||
IKeyNavigation::Index index;
|
|
||||||
switch (direction) {
|
|
||||||
case MoveDirection::Right: {
|
|
||||||
index.column = -1;
|
|
||||||
|
|
||||||
// find min row
|
|
||||||
index.row = std::numeric_limits<int>::max();
|
|
||||||
for (T* v : set) {
|
|
||||||
if (v->index().row < index.row) {
|
|
||||||
index.row = v->index().row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MoveDirection::Left: {
|
|
||||||
index.column = std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
// find max row
|
|
||||||
index.row = -1;
|
|
||||||
for (T* v : set) {
|
|
||||||
if (v->index().row > index.row) {
|
|
||||||
index.row = v->index().row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MoveDirection::Down: {
|
|
||||||
index.row = -1;
|
|
||||||
|
|
||||||
// find min column
|
|
||||||
index.column = std::numeric_limits<int>::max();
|
|
||||||
for (T* v : set) {
|
|
||||||
if (v->index().column < index.column) {
|
|
||||||
index.column = v->index().column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MoveDirection::Up: {
|
|
||||||
index.row = std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
// find max row
|
|
||||||
index.column = -1;
|
|
||||||
for (T* v : set) {
|
|
||||||
if (v->index().column > index.column) {
|
|
||||||
index.column = v->index().row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static T* findNearestEnabled(const QSet<T*>& set, const IKeyNavigation::Index& currentIndex, MoveDirection direction)
|
static T* findNearestEnabled(const QSet<T*>& set, const IKeyNavigation::Index& currentIndex, MoveDirection direction)
|
||||||
{
|
{
|
||||||
|
@ -92,6 +38,32 @@ static T* findNearestEnabled(const QSet<T*>& set, const IKeyNavigation::Index& c
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
|
case MoveDirection::First: {
|
||||||
|
if (!ret) {
|
||||||
|
ret = v;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->index().row <= ret->index().row) {
|
||||||
|
if (v->index().column <= ret->index().column) {
|
||||||
|
ret = v;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case MoveDirection::Last: {
|
||||||
|
if (!ret) {
|
||||||
|
ret = v;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->index().row >= ret->index().row) {
|
||||||
|
if (v->index().column >= ret->index().column) {
|
||||||
|
ret = v;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case MoveDirection::Right: {
|
case MoveDirection::Right: {
|
||||||
if (v->index().row != currentIndex.row) {
|
if (v->index().row != currentIndex.row) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -163,9 +135,7 @@ static T* findNearestEnabled(const QSet<T*>& set, const IKeyNavigation::Index& c
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static T* firstEnabled(const QSet<T*>& set,
|
static T* firstEnabled(const QSet<T*>& set, const IKeyNavigation::Index& currentIndex, MoveDirection direction)
|
||||||
const IKeyNavigation::Index& currentIndex = IKeyNavigation::Index(),
|
|
||||||
MoveDirection direction = MoveDirection::Right)
|
|
||||||
{
|
{
|
||||||
if (set.empty()) {
|
if (set.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -175,31 +145,41 @@ static T* firstEnabled(const QSet<T*>& set,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentIndex.column < 0 && currentIndex.row < 0) {
|
return findNearestEnabled<T>(set, currentIndex, direction);
|
||||||
return findNearestEnabled<T>(set, determinateExtremeIndex(set, direction), direction);
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static T* firstEnabled(const QSet<T*>& set)
|
||||||
|
{
|
||||||
|
if (set.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return findNearestEnabled<T>(set, IKeyNavigation::Index(), MoveDirection::First);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static T* lastEnabled(const QSet<T*>& set, const IKeyNavigation::Index& currentIndex, MoveDirection direction)
|
||||||
|
{
|
||||||
|
if (set.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_ASSERT_FAILED(direction == MoveDirection::Left || (direction == MoveDirection::Up)) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return findNearestEnabled<T>(set, currentIndex, direction);
|
return findNearestEnabled<T>(set, currentIndex, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static T* lastEnabled(const QSet<T*>& set,
|
static T* lastEnabled(const QSet<T*>& set)
|
||||||
const IKeyNavigation::Index& currentIndex = IKeyNavigation::Index(),
|
|
||||||
MoveDirection direction = MoveDirection::Left)
|
|
||||||
{
|
{
|
||||||
if (set.empty()) {
|
if (set.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_ASSERT_FAILED(direction == MoveDirection::Left || direction == MoveDirection::Up) {
|
return findNearestEnabled<T>(set, IKeyNavigation::Index(), MoveDirection::Last);
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentIndex.column < 0 && currentIndex.row < 0) {
|
|
||||||
return findNearestEnabled<T>(set, determinateExtremeIndex(set, direction), direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
return findNearestEnabled<T>(set, currentIndex, direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -250,11 +230,18 @@ void KeyNavigationController::init()
|
||||||
dispatcher()->reg(this, "nav-prev-section", this, &KeyNavigationController::goToPrevSection);
|
dispatcher()->reg(this, "nav-prev-section", this, &KeyNavigationController::goToPrevSection);
|
||||||
dispatcher()->reg(this, "nav-next-subsection", this, &KeyNavigationController::goToNextSubSection);
|
dispatcher()->reg(this, "nav-next-subsection", this, &KeyNavigationController::goToNextSubSection);
|
||||||
dispatcher()->reg(this, "nav-prev-subsection", this, &KeyNavigationController::goToPrevSubSection);
|
dispatcher()->reg(this, "nav-prev-subsection", this, &KeyNavigationController::goToPrevSubSection);
|
||||||
|
|
||||||
|
dispatcher()->reg(this, "nav-trigger-control", this, &KeyNavigationController::doTriggerControl);
|
||||||
|
|
||||||
dispatcher()->reg(this, "nav-right", this, &KeyNavigationController::onRight);
|
dispatcher()->reg(this, "nav-right", this, &KeyNavigationController::onRight);
|
||||||
dispatcher()->reg(this, "nav-left", this, &KeyNavigationController::onLeft);
|
dispatcher()->reg(this, "nav-left", this, &KeyNavigationController::onLeft);
|
||||||
dispatcher()->reg(this, "nav-up", this, &KeyNavigationController::onUp);
|
dispatcher()->reg(this, "nav-up", this, &KeyNavigationController::onUp);
|
||||||
dispatcher()->reg(this, "nav-down", this, &KeyNavigationController::onDown);
|
dispatcher()->reg(this, "nav-down", this, &KeyNavigationController::onDown);
|
||||||
dispatcher()->reg(this, "nav-trigger", this, &KeyNavigationController::doTriggerControl);
|
|
||||||
|
dispatcher()->reg(this, "nav-first-control", this, &KeyNavigationController::goToFirstControl); // typically Home key
|
||||||
|
dispatcher()->reg(this, "nav-last-control", this, &KeyNavigationController::goToLastControl); // typically End key
|
||||||
|
dispatcher()->reg(this, "nav-nextrow-control", this, &KeyNavigationController::goToNextRowControl); // typically PageDown key
|
||||||
|
dispatcher()->reg(this, "nav-prevrow-control", this, &KeyNavigationController::goToPrevRowControl); // typically PageUp key
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyNavigationController::reg(IKeyNavigationSection* s)
|
void KeyNavigationController::reg(IKeyNavigationSection* s)
|
||||||
|
@ -594,6 +581,80 @@ void KeyNavigationController::onUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyNavigationController::goToFirstControl()
|
||||||
|
{
|
||||||
|
LOGI() << "====";
|
||||||
|
goToControl(MoveDirection::First);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyNavigationController::goToLastControl()
|
||||||
|
{
|
||||||
|
LOGI() << "====";
|
||||||
|
goToControl(MoveDirection::Last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyNavigationController::goToNextRowControl()
|
||||||
|
{
|
||||||
|
LOGI() << "====";
|
||||||
|
|
||||||
|
IKeyNavigationSubSection* activeSubSec = activeSubSection();
|
||||||
|
if (!activeSubSec) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IKeyNavigationControl* activeControl = findActive(activeSubSec->controls());
|
||||||
|
if (activeControl) {
|
||||||
|
doDeactivateControl(activeControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
IKeyNavigationControl* toControl = nullptr;
|
||||||
|
if (activeControl) {
|
||||||
|
IKeyNavigation::Index index = activeControl->index();
|
||||||
|
index.column = 0;
|
||||||
|
toControl = nextEnabled(activeSubSec->controls(), index, MoveDirection::Down);
|
||||||
|
if (!toControl) { // last row
|
||||||
|
toControl = firstEnabled(activeSubSec->controls());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toControl = firstEnabled(activeSubSec->controls());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toControl) {
|
||||||
|
doActivateControl(toControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyNavigationController::goToPrevRowControl()
|
||||||
|
{
|
||||||
|
LOGI() << "====";
|
||||||
|
|
||||||
|
IKeyNavigationSubSection* activeSubSec = activeSubSection();
|
||||||
|
if (!activeSubSec) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IKeyNavigationControl* activeControl = findActive(activeSubSec->controls());
|
||||||
|
if (activeControl) {
|
||||||
|
doDeactivateControl(activeControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
IKeyNavigationControl* toControl = nullptr;
|
||||||
|
if (activeControl) {
|
||||||
|
IKeyNavigation::Index index = activeControl->index();
|
||||||
|
index.column = 0;
|
||||||
|
toControl = prevEnabled(activeSubSec->controls(), index, MoveDirection::Up);
|
||||||
|
if (!toControl) { // first row
|
||||||
|
toControl = lastEnabled(activeSubSec->controls());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toControl = lastEnabled(activeSubSec->controls());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toControl) {
|
||||||
|
doActivateControl(toControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KeyNavigationController::goToControl(MoveDirection direction, IKeyNavigationSubSection* activeSubSec)
|
void KeyNavigationController::goToControl(MoveDirection direction, IKeyNavigationSubSection* activeSubSec)
|
||||||
{
|
{
|
||||||
LOGI() << "direction: " << direction;
|
LOGI() << "direction: " << direction;
|
||||||
|
@ -614,6 +675,12 @@ void KeyNavigationController::goToControl(MoveDirection direction, IKeyNavigatio
|
||||||
IKeyNavigationControl* toControl = nullptr;
|
IKeyNavigationControl* toControl = nullptr;
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
|
case MoveDirection::First: {
|
||||||
|
toControl = firstEnabled(activeSubSec->controls());
|
||||||
|
} break;
|
||||||
|
case MoveDirection::Last: {
|
||||||
|
toControl = lastEnabled(activeSubSec->controls());
|
||||||
|
} break;
|
||||||
case MoveDirection::Right: {
|
case MoveDirection::Right: {
|
||||||
if (!activeControl) { // no any active
|
if (!activeControl) { // no any active
|
||||||
toControl = firstEnabled(activeSubSec->controls(), IKeyNavigation::Index(), direction);
|
toControl = firstEnabled(activeSubSec->controls(), IKeyNavigation::Index(), direction);
|
||||||
|
|
|
@ -35,7 +35,9 @@ public:
|
||||||
KeyNavigationController() = default;
|
KeyNavigationController() = default;
|
||||||
|
|
||||||
enum MoveDirection {
|
enum MoveDirection {
|
||||||
Right = 0,
|
First = 0,
|
||||||
|
Last,
|
||||||
|
Right,
|
||||||
Left,
|
Left,
|
||||||
Up,
|
Up,
|
||||||
Down
|
Down
|
||||||
|
@ -52,7 +54,12 @@ private:
|
||||||
void goToNextSubSection();
|
void goToNextSubSection();
|
||||||
void goToPrevSubSection();
|
void goToPrevSubSection();
|
||||||
|
|
||||||
void goToControl(MoveDirection direction, IKeyNavigationSubSection* activeSubSec);
|
void goToFirstControl();
|
||||||
|
void goToLastControl();
|
||||||
|
void goToNextRowControl();
|
||||||
|
void goToPrevRowControl();
|
||||||
|
|
||||||
|
void goToControl(MoveDirection direction, IKeyNavigationSubSection* activeSubSec = nullptr);
|
||||||
|
|
||||||
void onLeft();
|
void onLeft();
|
||||||
void onRight();
|
void onRight();
|
||||||
|
|
|
@ -48,7 +48,19 @@ const UiActionList KeyNavigationUiActions::m_actions = {
|
||||||
UiAction("nav-down",
|
UiAction("nav-down",
|
||||||
mu::context::UiCtxAny
|
mu::context::UiCtxAny
|
||||||
),
|
),
|
||||||
UiAction("nav-trigger",
|
UiAction("nav-trigger-control",
|
||||||
|
mu::context::UiCtxAny
|
||||||
|
),
|
||||||
|
UiAction("nav-first-control",
|
||||||
|
mu::context::UiCtxAny
|
||||||
|
),
|
||||||
|
UiAction("nav-last-control",
|
||||||
|
mu::context::UiCtxAny
|
||||||
|
),
|
||||||
|
UiAction("nav-nextrow-control",
|
||||||
|
mu::context::UiCtxAny
|
||||||
|
),
|
||||||
|
UiAction("nav-prevrow-control",
|
||||||
mu::context::UiCtxAny
|
mu::context::UiCtxAny
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,17 +33,8 @@ FocusableControl {
|
||||||
|
|
||||||
opacity: root.enabled ? 1.0 : ui.theme.itemOpacityDisabled
|
opacity: root.enabled ? 1.0 : ui.theme.itemOpacityDisabled
|
||||||
|
|
||||||
onInternalClicked: {
|
mouseArea.onClicked: root.clicked()
|
||||||
root.clicked()
|
mouseArea.onPressAndHold: root.pressAndHold()
|
||||||
}
|
|
||||||
|
|
||||||
onInternalPressAndHold: {
|
|
||||||
root.pressAndHold()
|
|
||||||
}
|
|
||||||
|
|
||||||
onInternalTriggered: {
|
|
||||||
root.clicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseArea.hoverEnabled: true
|
mouseArea.hoverEnabled: true
|
||||||
mouseArea.onContainsMouseChanged: {
|
mouseArea.onContainsMouseChanged: {
|
||||||
|
@ -58,6 +49,8 @@ FocusableControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keynav.onTriggered: root.clicked()
|
||||||
|
|
||||||
background.color: normalStateColor
|
background.color: normalStateColor
|
||||||
background.opacity: ui.theme.buttonOpacityNormal
|
background.opacity: ui.theme.buttonOpacityNormal
|
||||||
background.radius: 3
|
background.radius: 3
|
||||||
|
|
|
@ -12,13 +12,6 @@ FocusScope {
|
||||||
|
|
||||||
property alias keynav: keynavItem
|
property alias keynav: keynavItem
|
||||||
|
|
||||||
signal internalPressed()
|
|
||||||
signal internalReleased()
|
|
||||||
signal internalClicked()
|
|
||||||
signal internalPressAndHold()
|
|
||||||
|
|
||||||
signal internalTriggered()
|
|
||||||
|
|
||||||
function insureActiveFocus() {
|
function insureActiveFocus() {
|
||||||
if (!root.activeFocus) {
|
if (!root.activeFocus) {
|
||||||
root.forceActiveFocus()
|
root.forceActiveFocus()
|
||||||
|
@ -39,10 +32,6 @@ FocusScope {
|
||||||
root.insureActiveFocus()
|
root.insureActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onTriggered: {
|
|
||||||
root.internalTriggered()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -64,19 +53,6 @@ FocusScope {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.insureActiveFocus()
|
root.insureActiveFocus()
|
||||||
root.internalClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onPressAndHold: {
|
|
||||||
root.internalPressAndHold()
|
|
||||||
}
|
|
||||||
|
|
||||||
onPressed: {
|
|
||||||
root.internalPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
onReleased: {
|
|
||||||
root.internalReleased()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,13 @@ import QtQuick 2.15
|
||||||
|
|
||||||
import MuseScore.Ui 1.0
|
import MuseScore.Ui 1.0
|
||||||
|
|
||||||
Item {
|
FocusableControl {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string hint
|
property string hint
|
||||||
|
|
||||||
property bool isSelected: false
|
property bool isSelected: false
|
||||||
property alias radius: background.radius
|
property alias radius: root.background.radius
|
||||||
|
|
||||||
property color normalStateColor: "transparent"
|
property color normalStateColor: "transparent"
|
||||||
property color hoveredStateColor: privateProperties.defaultColor
|
property color hoveredStateColor: privateProperties.defaultColor
|
||||||
|
@ -24,20 +24,31 @@ Item {
|
||||||
Accessible.selectable: true
|
Accessible.selectable: true
|
||||||
Accessible.selected: isSelected
|
Accessible.selected: isSelected
|
||||||
|
|
||||||
|
mouseArea.hoverEnabled: root.visible
|
||||||
|
mouseArea.onHoveredChanged: root.hovered(mouseArea.containsMouse, mouseArea.mouseX, mouseArea.mouseY)
|
||||||
|
|
||||||
|
mouseArea.onClicked: root.clicked()
|
||||||
|
mouseArea.onDoubleClicked: root.doubleClicked()
|
||||||
|
|
||||||
|
mouseArea.onContainsMouseChanged: {
|
||||||
|
if (!Boolean(root.hint)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseArea.containsMouse) {
|
||||||
|
ui.tooltip.show(this, root.hint)
|
||||||
|
} else {
|
||||||
|
ui.tooltip.hide(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: privateProperties
|
id: privateProperties
|
||||||
|
|
||||||
property color defaultColor: ui.theme.buttonColor
|
property color defaultColor: ui.theme.buttonColor
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
background.opacity: root.enabled ? 1 : ui.theme.itemOpacityDisabled
|
||||||
id: background
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
color: normalStateColor
|
|
||||||
opacity: root.enabled ? 1 : ui.theme.itemOpacityDisabled
|
|
||||||
}
|
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
|
@ -45,7 +56,7 @@ Item {
|
||||||
when: mouseArea.containsMouse && !mouseArea.pressed && !root.isSelected
|
when: mouseArea.containsMouse && !mouseArea.pressed && !root.isSelected
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: background
|
target: root.background
|
||||||
opacity: ui.theme.buttonOpacityHover
|
opacity: ui.theme.buttonOpacityHover
|
||||||
color: hoveredStateColor
|
color: hoveredStateColor
|
||||||
}
|
}
|
||||||
|
@ -56,7 +67,7 @@ Item {
|
||||||
when: mouseArea.pressed && !root.isSelected
|
when: mouseArea.pressed && !root.isSelected
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: background
|
target: root.background
|
||||||
opacity: ui.theme.buttonOpacityHit
|
opacity: ui.theme.buttonOpacityHit
|
||||||
color: pressedStateColor
|
color: pressedStateColor
|
||||||
}
|
}
|
||||||
|
@ -67,42 +78,10 @@ Item {
|
||||||
when: root.isSelected
|
when: root.isSelected
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: background
|
target: root.background
|
||||||
opacity: ui.theme.accentOpacityHit
|
opacity: ui.theme.accentOpacityHit
|
||||||
color: ui.theme.accentColor
|
color: ui.theme.accentColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
hoverEnabled: root.visible
|
|
||||||
|
|
||||||
onHoveredChanged: {
|
|
||||||
root.hovered(mouseArea.containsMouse, mouseX, mouseY)
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
root.clicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onDoubleClicked: {
|
|
||||||
root.doubleClicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
onContainsMouseChanged: {
|
|
||||||
if (!Boolean(root.hint)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (containsMouse) {
|
|
||||||
ui.tooltip.show(this, root.hint)
|
|
||||||
} else {
|
|
||||||
ui.tooltip.hide(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import MuseScore.Instruments 1.0
|
||||||
import "internal"
|
import "internal"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property KeyNavigationSection keynavSection: null
|
property KeyNavigationSection keynavSection: null
|
||||||
|
@ -37,6 +38,7 @@ Item {
|
||||||
name: "InstrumentsTree"
|
name: "InstrumentsTree"
|
||||||
section: root.keynavSection
|
section: root.keynavSection
|
||||||
direction: KeyNavigationSubSection.Both
|
direction: KeyNavigationSubSection.Both
|
||||||
|
enabled: root.visible
|
||||||
order: 3
|
order: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +59,7 @@ Item {
|
||||||
Layout.rightMargin: contentColumn.sideMargin
|
Layout.rightMargin: contentColumn.sideMargin
|
||||||
|
|
||||||
keynav.section: root.keynavSection
|
keynav.section: root.keynavSection
|
||||||
|
keynav.enabled: root.visible
|
||||||
keynav.order: 2
|
keynav.order: 2
|
||||||
|
|
||||||
isMovingUpAvailable: instrumentTreeModel.isMovingUpAvailable
|
isMovingUpAvailable: instrumentTreeModel.isMovingUpAvailable
|
||||||
|
|
|
@ -31,7 +31,7 @@ RowLayout {
|
||||||
|
|
||||||
KeyNavigationSubSection {
|
KeyNavigationSubSection {
|
||||||
id: keynavSub
|
id: keynavSub
|
||||||
name: "InstrumentsControlPanel"
|
name: "InstrumentsHeader"
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatButton {
|
FlatButton {
|
||||||
|
|
|
@ -262,7 +262,6 @@ bool InstrumentPanelTreeModel::moveRows(const QModelIndex& sourceParent, int sou
|
||||||
|
|
||||||
bool InstrumentPanelTreeModel::isSelected(const QModelIndex& rowIndex) const
|
bool InstrumentPanelTreeModel::isSelected(const QModelIndex& rowIndex) const
|
||||||
{
|
{
|
||||||
TRACEFUNC;
|
|
||||||
if (m_selectionModel->selectedIndexes().isEmpty()) {
|
if (m_selectionModel->selectedIndexes().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -346,7 +345,6 @@ int InstrumentPanelTreeModel::columnCount(const QModelIndex&) const
|
||||||
|
|
||||||
QVariant InstrumentPanelTreeModel::data(const QModelIndex& index, int role) const
|
QVariant InstrumentPanelTreeModel::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
TRACEFUNC;
|
|
||||||
if (!index.isValid() && role != ItemRole) {
|
if (!index.isValid() && role != ItemRole) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ Rectangle {
|
||||||
|
|
||||||
property alias keynav: keynavSub
|
property alias keynav: keynavSub
|
||||||
|
|
||||||
|
signal activeFocusRequested()
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
toolbarModel.load()
|
toolbarModel.load()
|
||||||
}
|
}
|
||||||
|
@ -15,6 +17,12 @@ Rectangle {
|
||||||
KeyNavigationSubSection {
|
KeyNavigationSubSection {
|
||||||
id: keynavSub
|
id: keynavSub
|
||||||
name: "NotationToolBar"
|
name: "NotationToolBar"
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
root.activeFocusRequested()
|
||||||
|
root.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NotationToolBarModel {
|
NotationToolBarModel {
|
||||||
|
|
|
@ -17,23 +17,22 @@
|
||||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
import QtQuick 2.8
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.1
|
import QtQuick.Controls 2.1
|
||||||
import QtQuick.Window 2.2
|
import QtQuick.Window 2.2
|
||||||
|
import MuseScore.Ui 1.0
|
||||||
import MuseScore.UiComponents 1.0
|
import MuseScore.UiComponents 1.0
|
||||||
import MuseScore.Palette 1.0
|
import MuseScore.Palette 1.0
|
||||||
|
|
||||||
// TODO: make some properties 'property alias`?
|
|
||||||
// and `readonly property`?
|
|
||||||
|
|
||||||
import "internal"
|
import "internal"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
||||||
id: palettesWidget
|
id: palettesWidget
|
||||||
|
|
||||||
readonly property PaletteWorkspace paletteWorkspace: paletteRootModel.paletteWorkspace
|
property KeyNavigationSection keynavSection: null
|
||||||
|
|
||||||
readonly property bool hasFocus: Window.activeFocusItem
|
readonly property PaletteWorkspace paletteWorkspace: paletteRootModel.paletteWorkspace
|
||||||
|
|
||||||
implicitHeight: 4 * palettesWidgetHeader.implicitHeight
|
implicitHeight: 4 * palettesWidgetHeader.implicitHeight
|
||||||
implicitWidth: paletteTree.implicitWidth
|
implicitWidth: paletteTree.implicitWidth
|
||||||
|
@ -46,14 +45,6 @@ Rectangle {
|
||||||
|
|
||||||
color: ui.theme.backgroundPrimaryColor
|
color: ui.theme.backgroundPrimaryColor
|
||||||
|
|
||||||
FocusableItem {
|
|
||||||
id: focusBreaker
|
|
||||||
|
|
||||||
onActiveFocusChanged: {
|
|
||||||
parent.focus = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PaletteRootModel {
|
PaletteRootModel {
|
||||||
id: paletteRootModel
|
id: paletteRootModel
|
||||||
|
|
||||||
|
@ -77,6 +68,9 @@ Rectangle {
|
||||||
rightMargin: 12
|
rightMargin: 12
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keynav.section: palettesWidget.keynavSection
|
||||||
|
keynav.order: 2
|
||||||
|
|
||||||
onAddCustomPaletteRequested: paletteTree.insertCustomPalette(0, paletteName);
|
onAddCustomPaletteRequested: paletteTree.insertCustomPalette(0, paletteName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +90,11 @@ Rectangle {
|
||||||
id: paletteTree
|
id: paletteTree
|
||||||
clip: true
|
clip: true
|
||||||
paletteWorkspace: palettesWidget.paletteWorkspace
|
paletteWorkspace: palettesWidget.paletteWorkspace
|
||||||
|
backgroundColor: palettesWidget.color
|
||||||
|
|
||||||
|
keynav.section: palettesWidget.keynavSection
|
||||||
|
keynav.order: 3
|
||||||
|
keynav.enabled: paletteTree.visible
|
||||||
|
|
||||||
filter: palettesWidgetHeader.searchText
|
filter: palettesWidgetHeader.searchText
|
||||||
enableAnimations: !palettesWidgetHeader.searching
|
enableAnimations: !palettesWidgetHeader.searching
|
||||||
|
|
|
@ -50,6 +50,10 @@ GridView {
|
||||||
|
|
||||||
property bool enableAnimations: true
|
property bool enableAnimations: true
|
||||||
|
|
||||||
|
property KeyNavigationSubSection keynavSubSection: null
|
||||||
|
property int keynavRow: 0
|
||||||
|
property int keynavCol: 1
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "default"
|
name: "default"
|
||||||
|
@ -97,7 +101,8 @@ GridView {
|
||||||
cellWidth: stretchWidth ? Math.floor(Utils.stretched(cellDefaultWidth, width)) : cellDefaultWidth
|
cellWidth: stretchWidth ? Math.floor(Utils.stretched(cellDefaultWidth, width)) : cellDefaultWidth
|
||||||
cellHeight: cellSize.height
|
cellHeight: cellSize.height
|
||||||
|
|
||||||
readonly property real ncolumns: Math.floor(width / cellWidth);
|
readonly property int nrows: Math.max(0, Math.floor(height / cellHeight))
|
||||||
|
readonly property int ncolumns: Math.max(0, Math.floor(width / cellWidth))
|
||||||
readonly property real lastColumnCellWidth : cellWidth + (width % cellWidth) // width of last cell in a row: might be stretched to avoid a gap at row end
|
readonly property real lastColumnCellWidth : cellWidth + (width % cellWidth) // width of last cell in a row: might be stretched to avoid a gap at row end
|
||||||
|
|
||||||
signal moreButtonClicked()
|
signal moreButtonClicked()
|
||||||
|
@ -164,7 +169,12 @@ GridView {
|
||||||
id: moreButton
|
id: moreButton
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
activeFocusOnTab: this === paletteTree.currentTreeItem
|
|
||||||
|
keynav.subsection: paletteView.keynavSubSection
|
||||||
|
//! NOTE Just Up/Down navigation now
|
||||||
|
keynav.row: paletteView.ncells + paletteView.keynavRow
|
||||||
|
keynav.column: 1
|
||||||
|
keynav.enabled: paletteView.visible
|
||||||
|
|
||||||
onActiveFocusChanged: {
|
onActiveFocusChanged: {
|
||||||
if (activeFocus) {
|
if (activeFocus) {
|
||||||
|
@ -183,42 +193,6 @@ GridView {
|
||||||
pressedStateColor: ui.theme.accentColor
|
pressedStateColor: ui.theme.accentColor
|
||||||
|
|
||||||
onClicked: paletteView.moreButtonClicked()
|
onClicked: paletteView.moreButtonClicked()
|
||||||
|
|
||||||
Keys.onShortcutOverride: {
|
|
||||||
// Intercept all keys that we want to use with Keys.onPressed
|
|
||||||
// in case they are assigned as shortcuts in Preferences.
|
|
||||||
event.accepted = true; // intercept everything
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Up:
|
|
||||||
case Qt.Key_Down:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.accepted = false; // allow key to function as shortcut (don't intercept)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
|
||||||
// NOTE: All keys must be intercepted with Keys.onShortcutOverride.
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Up:
|
|
||||||
focusPreviousItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Down:
|
|
||||||
paletteTree.focusNextItem(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return; // don't accept event
|
|
||||||
}
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusPreviousItem() {
|
|
||||||
if (paletteView.count == 0) {
|
|
||||||
paletteTree.currentItem.forceActiveFocus();
|
|
||||||
} else {
|
|
||||||
paletteView.currentIndex = paletteView.count - 1
|
|
||||||
paletteView.currentItem.forceActiveFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,34 +382,6 @@ GridView {
|
||||||
Utils.removeSelectedItems(paletteController, selectionModel, paletteRootIndex);
|
Utils.removeSelectedItems(paletteController, selectionModel, paletteRootIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusNextItem(flags) {
|
|
||||||
if (flags === undefined) {
|
|
||||||
flags = ItemSelectionModel.ClearAndSelect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentIndex == count - 1) {
|
|
||||||
if (moreButton.visible) {
|
|
||||||
moreButton.forceActiveFocus();
|
|
||||||
} else {
|
|
||||||
paletteTree.focusNextItem(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentIndex++; // next grid item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusPreviousItem(flags) {
|
|
||||||
if (flags === undefined) {
|
|
||||||
flags = ItemSelectionModel.ClearAndSelect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentIndex == 0) {
|
|
||||||
paletteTree.currentItem.forceActiveFocus();
|
|
||||||
} else {
|
|
||||||
currentIndex--; // previous grid item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusFirstItem() {
|
function focusFirstItem() {
|
||||||
if (count == 0 && moreButton.visible) {
|
if (count == 0 && moreButton.visible) {
|
||||||
moreButton.forceActiveFocus();
|
moreButton.forceActiveFocus();
|
||||||
|
@ -504,48 +450,6 @@ GridView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onShortcutOverride: {
|
|
||||||
// Intercept all keys that we want to use with Keys.onPressed
|
|
||||||
// in case they are assigned as shortcuts in Preferences.
|
|
||||||
event.accepted = true; // intercept everything
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Up:
|
|
||||||
case Qt.Key_Down:
|
|
||||||
case Qt.Key_Left:
|
|
||||||
case Qt.Key_Right:
|
|
||||||
case Qt.Key_Backspace:
|
|
||||||
case Qt.Key_Delete:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.accepted = false; // allow key to function as shortcut (don't intercept)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
|
||||||
// NOTE: All keys must be intercepted with Keys.onShortcutOverride.
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Up:
|
|
||||||
focusPreviousItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Down:
|
|
||||||
focusNextItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Left:
|
|
||||||
paletteTree.currentItem.forceActiveFocus();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Right:
|
|
||||||
if (moreButton.visible)
|
|
||||||
moreButton.forceActiveFocus();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Backspace:
|
|
||||||
case Qt.Key_Delete:
|
|
||||||
removeSelectedCells();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return; // don't accept event
|
|
||||||
}
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: draggedIcon
|
id: draggedIcon
|
||||||
|
|
||||||
|
@ -576,6 +480,10 @@ GridView {
|
||||||
property var modelIndex: paletteView.model.modelIndex(index)
|
property var modelIndex: paletteView.model.modelIndex(index)
|
||||||
property var parentModelIndex: paletteView.paletteRootIndex
|
property var parentModelIndex: paletteView.paletteRootIndex
|
||||||
|
|
||||||
|
//! NOTE Please, don't remove (igor.korsukov@gmail.com)
|
||||||
|
//property int cellRow: paletteView.ncolumns == 0 ? 0 : Math.floor(model.index / paletteView.ncolumns)
|
||||||
|
//property int cellCol: model.index - (cellRow * paletteView.ncolumns)
|
||||||
|
|
||||||
onActiveFocusChanged: {
|
onActiveFocusChanged: {
|
||||||
if (activeFocus) {
|
if (activeFocus) {
|
||||||
paletteTree.currentTreeItem = this;
|
paletteTree.currentTreeItem = this;
|
||||||
|
@ -593,7 +501,17 @@ GridView {
|
||||||
width: paletteView.cellWidth
|
width: paletteView.cellWidth
|
||||||
height: paletteView.cellHeight
|
height: paletteView.cellHeight
|
||||||
|
|
||||||
activeFocusOnTab: this === paletteTree.currentTreeItem
|
keynav.subsection: paletteView.keynavSubSection
|
||||||
|
|
||||||
|
//! NOTE Please, don't remove (igor.korsukov@gmail.com)
|
||||||
|
//keynav.row: paletteCell.cellRow + paletteView.keynavRow
|
||||||
|
//keynav.column: paletteCell.cellCol + paletteView.keynavCol
|
||||||
|
|
||||||
|
//! NOTE Just Up/Down navigation now
|
||||||
|
keynav.row: model.index + paletteView.keynavRow
|
||||||
|
keynav.column: 1
|
||||||
|
keynav.enabled: paletteView.visible
|
||||||
|
keynav.onTriggered: paletteCell.doClicked()
|
||||||
|
|
||||||
IconView {
|
IconView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -605,108 +523,37 @@ GridView {
|
||||||
|
|
||||||
Accessible.name: model.accessibleText;
|
Accessible.name: model.accessibleText;
|
||||||
|
|
||||||
Keys.onShortcutOverride: {
|
// leftClickArea
|
||||||
// Intercept all keys that we want to use with Keys.onPressed
|
mouseArea.drag.target: this
|
||||||
// in case they are assigned as shortcuts in Preferences.
|
mouseArea.onPressed: {
|
||||||
event.accepted = true; // intercept everything
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Space:
|
|
||||||
case Qt.Key_Enter:
|
|
||||||
case Qt.Key_Return:
|
|
||||||
case Qt.Key_Menu:
|
|
||||||
case Qt.Key_Asterisk:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === Qt.Key_F10 && event.modifiers & Qt.ShiftModifier) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.text.match(/[^\x00-\x20\x7F]+$/) !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.accepted = false; // allow key to function as shortcut (don't intercept)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
|
||||||
// NOTE: All keys must be intercepted with Keys.onShortcutOverride.
|
|
||||||
const shiftHeld = event.modifiers & Qt.ShiftModifier;
|
|
||||||
const ctrlHeld = event.modifiers & Qt.ControlModifier;
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Space:
|
|
||||||
if (paletteTree.typeAheadStr.length) {
|
|
||||||
paletteView.typeAheadFind(' ');
|
|
||||||
} else {
|
|
||||||
paletteView.updateSelection(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Qt.Key_Enter:
|
|
||||||
case Qt.Key_Return:
|
|
||||||
paletteView.selectionModel.setCurrentIndex(modelIndex, ItemSelectionModel.ClearAndSelect);
|
|
||||||
paletteView.paletteController.applyPaletteElement(modelIndex, ui.keyboardModifiers());
|
|
||||||
break;
|
|
||||||
case Qt.Key_F10:
|
|
||||||
if (!shiftHeld) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// fallthrough
|
|
||||||
case Qt.Key_Menu:
|
|
||||||
showCellMenu();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Asterisk:
|
|
||||||
if (paletteTree.typeAheadStr.length) {
|
|
||||||
paletteView.typeAheadFind('*');
|
|
||||||
} else if (!paletteTree.expandCollapseAll(null)) {
|
|
||||||
paletteTree.currentItem.forceActiveFocus();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (event.text.match(/[^\x00-\x20\x7F]+$/) !== null) {
|
|
||||||
// Pressed non-control character(s) (e.g. "D") so go
|
|
||||||
// to matching item (e.g. "D Major" in keysig palette)
|
|
||||||
paletteView.typeAheadFind(event.text);
|
|
||||||
} else {
|
|
||||||
return; // don't accept event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: leftClickArea
|
|
||||||
anchors.fill: parent
|
|
||||||
drag.target: this
|
|
||||||
|
|
||||||
onPressed: {
|
|
||||||
paletteView.currentIndex = paletteCell.rowIndex;
|
paletteView.currentIndex = paletteCell.rowIndex;
|
||||||
paletteCell.forceActiveFocus();
|
paletteCell.forceActiveFocus();
|
||||||
paletteView.updateSelection(true);
|
paletteView.updateSelection(true);
|
||||||
paletteCell.beginDrag();
|
paletteCell.beginDrag();
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
function doClicked() {
|
||||||
if (paletteView.paletteController.applyPaletteElement(paletteCell.modelIndex, ui.keyboardModifiers())) {
|
if (paletteView.paletteController.applyPaletteElement(paletteCell.modelIndex, ui.keyboardModifiers())) {
|
||||||
paletteView.selectionModel.setCurrentIndex(paletteCell.modelIndex, ItemSelectionModel.Current);
|
paletteView.selectionModel.setCurrentIndex(paletteCell.modelIndex, ItemSelectionModel.Current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClicked: paletteCell.doClicked()
|
||||||
|
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
const index = paletteCell.modelIndex;
|
const index = paletteCell.modelIndex;
|
||||||
paletteView.selectionModel.setCurrentIndex(index, ItemSelectionModel.Current);
|
paletteView.selectionModel.setCurrentIndex(index, ItemSelectionModel.Current);
|
||||||
paletteView.paletteController.applyPaletteElement(index, mouse.modifiers);
|
paletteView.paletteController.applyPaletteElement(index, mouseArea.mouse.modifiers);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: rightClickArea
|
id: rightClickArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
|
|
||||||
onClicked: showCellMenu(true)
|
onClicked: showCellMenu(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
Drag.active: leftClickArea.drag.active
|
Drag.active: mouseArea.drag.active
|
||||||
Drag.dragType: Drag.Automatic
|
Drag.dragType: Drag.Automatic
|
||||||
Drag.supportedActions: Qt.CopyAction | (model.editable ? Qt.MoveAction : 0)
|
Drag.supportedActions: Qt.CopyAction | (model.editable ? Qt.MoveAction : 0)
|
||||||
Drag.mimeData: Drag.active ? mimeData : {}
|
Drag.mimeData: Drag.active ? mimeData : {}
|
||||||
|
|
|
@ -29,25 +29,44 @@ import "utils.js" as Utils
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: paletteTree
|
id: paletteTree
|
||||||
Accessible.name: qsTrc("palette", "Palettes Tree, contains %n palette(s)", "", count)
|
|
||||||
|
|
||||||
activeFocusOnTab: true // allow focus even when empty
|
|
||||||
|
|
||||||
property PaletteWorkspace paletteWorkspace
|
property PaletteWorkspace paletteWorkspace
|
||||||
property var paletteModel: Boolean(paletteWorkspace) ? paletteWorkspace.mainPaletteModel : null
|
property var paletteModel: Boolean(paletteWorkspace) ? paletteWorkspace.mainPaletteModel : null
|
||||||
property PaletteController paletteController: paletteWorkspace ? paletteWorkspace.mainPaletteController : null
|
property PaletteController paletteController: paletteWorkspace ? paletteWorkspace.mainPaletteController : null
|
||||||
|
|
||||||
|
property alias keynav: keynavTree
|
||||||
|
|
||||||
// Scroll palettes list when dragging a palette close to the list's border
|
// Scroll palettes list when dragging a palette close to the list's border
|
||||||
property bool itemDragged: false
|
property bool itemDragged: false
|
||||||
preferredHighlightBegin: Math.min(48, Math.floor(0.1 * height))
|
|
||||||
preferredHighlightEnd: Math.ceil(height - preferredHighlightBegin)
|
|
||||||
highlightRangeMode: itemDragged ? ListView.ApplyRange : ListView.NoHighlightRange
|
|
||||||
|
|
||||||
property Item currentTreeItem: currentItem // most recently focused item at any level of the tree
|
property Item currentTreeItem: currentItem // most recently focused item at any level of the tree
|
||||||
|
|
||||||
property string filter: ""
|
property string filter: ""
|
||||||
property bool searchOpened: false
|
property bool searchOpened: false
|
||||||
|
|
||||||
|
property bool enableAnimations: true
|
||||||
|
property int expandDuration: enableAnimations ? 150 : 0 // duration of expand / collapse animations
|
||||||
|
|
||||||
|
property string backgroundColor: "#ffffff"
|
||||||
|
|
||||||
|
preferredHighlightBegin: Math.min(48, Math.floor(0.1 * height))
|
||||||
|
preferredHighlightEnd: Math.ceil(height - preferredHighlightBegin)
|
||||||
|
highlightRangeMode: itemDragged ? ListView.ApplyRange : ListView.NoHighlightRange
|
||||||
|
|
||||||
|
Accessible.name: qsTrc("palette", "Palettes Tree, contains %n palette(s)", "", count)
|
||||||
|
|
||||||
|
|
||||||
|
KeyNavigationSubSection {
|
||||||
|
id: keynavTree
|
||||||
|
name: "PalettesTree"
|
||||||
|
direction: KeyNavigationSubSection.Both
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
paletteTree.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onSearchOpenedChanged: {
|
onSearchOpenedChanged: {
|
||||||
if (paletteWorkspace) {
|
if (paletteWorkspace) {
|
||||||
paletteWorkspace.setSearching(searchOpened)
|
paletteWorkspace.setSearching(searchOpened)
|
||||||
|
@ -65,9 +84,6 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool enableAnimations: true
|
|
||||||
property int expandDuration: enableAnimations ? 150 : 0 // duration of expand / collapse animations
|
|
||||||
|
|
||||||
function insertCustomPalette(idx, paletteName) {
|
function insertCustomPalette(idx, paletteName) {
|
||||||
if (paletteTree.paletteController.insertNewItem(paletteTreeDelegateModel.rootIndex, idx, paletteName)) {
|
if (paletteTree.paletteController.insertNewItem(paletteTreeDelegateModel.rootIndex, idx, paletteName)) {
|
||||||
positionViewAtIndex(idx, ListView.Contain)
|
positionViewAtIndex(idx, ListView.Contain)
|
||||||
|
@ -132,56 +148,6 @@ ListView {
|
||||||
Utils.removeSelectedItems(paletteController, paletteSelectionModel, parentIndex);
|
Utils.removeSelectedItems(paletteController, paletteSelectionModel, parentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onShortcutOverride: {
|
|
||||||
// Intercept all keys that we want to use with Keys.onPressed
|
|
||||||
// in case they are assigned as shortcuts in Preferences.
|
|
||||||
event.accepted = true; // intercept everything
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Down:
|
|
||||||
case Qt.Key_Up:
|
|
||||||
case Qt.Key_Home:
|
|
||||||
case Qt.Key_End:
|
|
||||||
case Qt.Key_PageUp:
|
|
||||||
case Qt.Key_PageDown:
|
|
||||||
case Qt.Key_Backspace:
|
|
||||||
case Qt.Key_Delete:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.accepted = false; // allow key to function as shortcut (don't intercept)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
|
||||||
// NOTE: All keys must be intercepted with Keys.onShortcutOverride.
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Down:
|
|
||||||
focusNextItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Up:
|
|
||||||
focusPreviousItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Home:
|
|
||||||
focusFirstItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_End:
|
|
||||||
focusLastItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_PageUp:
|
|
||||||
focusPreviousPageItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_PageDown:
|
|
||||||
focusNextPageItem();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Backspace:
|
|
||||||
case Qt.Key_Delete:
|
|
||||||
expandedPopupIndex = null;
|
|
||||||
removeSelectedItems();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return; // don't accept event
|
|
||||||
}
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
displaced: Transition {
|
displaced: Transition {
|
||||||
enabled: paletteTree.enableAnimations
|
enabled: paletteTree.enableAnimations
|
||||||
NumberAnimation { property: "y"; duration: 150 }
|
NumberAnimation { property: "y"; duration: 150 }
|
||||||
|
@ -200,103 +166,6 @@ ListView {
|
||||||
return { display: "", gridSize: Qt.size(1, 1), drawGrid: false, custom: false, editable: false, expanded: false };
|
return { display: "", gridSize: Qt.size(1, 1), drawGrid: false, custom: false, editable: false, expanded: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusNextItem(includeChildren) {
|
|
||||||
if (includeChildren === undefined) { // https://stackoverflow.com/a/44128406
|
|
||||||
includeChildren = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeChildren && currentItem.expanded) {
|
|
||||||
currentItem.focusFirstItem();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentIndex == count - 1) {
|
|
||||||
return; // no next item
|
|
||||||
}
|
|
||||||
|
|
||||||
incrementCurrentIndex();
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusPreviousItem(includeChildren) {
|
|
||||||
if (includeChildren === undefined) { // https://stackoverflow.com/a/44128406
|
|
||||||
includeChildren = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentIndex == 0) {
|
|
||||||
return; // no previous item
|
|
||||||
}
|
|
||||||
|
|
||||||
decrementCurrentIndex();
|
|
||||||
|
|
||||||
if (includeChildren && currentItem.expanded) {
|
|
||||||
currentItem.focusLastItem();
|
|
||||||
} else {
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusNextPageItem() {
|
|
||||||
if (currentIndex < count - 1) {
|
|
||||||
currentIndex++; // move by at least one item
|
|
||||||
// try to keep going, but new item must stay entirely in view
|
|
||||||
var distance = currentItem.height;
|
|
||||||
|
|
||||||
while (currentIndex < count - 1) {
|
|
||||||
currentIndex++; // try another
|
|
||||||
distance += currentItem.height;
|
|
||||||
if (distance > height) {
|
|
||||||
currentIndex--; // too far, go back one
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusPreviousPageItem() {
|
|
||||||
if (currentIndex > 0) {
|
|
||||||
currentIndex--; // move by at least one item
|
|
||||||
// try to keep going, but new item must stay entirely in view
|
|
||||||
var distance = currentItem.height;
|
|
||||||
|
|
||||||
while (currentIndex > 0) {
|
|
||||||
currentIndex--; // try another
|
|
||||||
distance += currentItem.height;
|
|
||||||
if (distance > height) {
|
|
||||||
currentIndex++; // too far, go back one
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusFirstItem() {
|
|
||||||
currentIndex = 0;
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusLastItem() {
|
|
||||||
currentIndex = count - 1;
|
|
||||||
|
|
||||||
if (currentItem.expanded) {
|
|
||||||
currentItem.focusLastItem();
|
|
||||||
} else {
|
|
||||||
currentItem.forceActiveFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
positionViewAtIndex(currentIndex, ListView.Contain);
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusNextMatchingItem(str, startIndex) {
|
function focusNextMatchingItem(str, startIndex) {
|
||||||
const modelIndex = paletteModel.index(startIndex, 0);
|
const modelIndex = paletteModel.index(startIndex, 0);
|
||||||
const matchedIndexList = paletteModel.match(modelIndex, Qt.ToolTipRole, str);
|
const matchedIndexList = paletteModel.match(modelIndex, Qt.ToolTipRole, str);
|
||||||
|
@ -373,6 +242,7 @@ ListView {
|
||||||
topPadding: 0
|
topPadding: 0
|
||||||
bottomPadding: expanded ? 4 : 0
|
bottomPadding: expanded ? 4 : 0
|
||||||
property int rowIndex: index
|
property int rowIndex: index
|
||||||
|
property int keynavRow: (index + 1) * 10000 // to make unique
|
||||||
property var modelIndex: paletteTree.model.modelIndex(index, 0)
|
property var modelIndex: paletteTree.model.modelIndex(index, 0)
|
||||||
|
|
||||||
onActiveFocusChanged: {
|
onActiveFocusChanged: {
|
||||||
|
@ -386,14 +256,6 @@ ListView {
|
||||||
paletteTree.implicitWidth = Math.max(paletteTree.implicitWidth, w);
|
paletteTree.implicitWidth = Math.max(paletteTree.implicitWidth, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusFirstItem() {
|
|
||||||
mainPalette.focusFirstItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusLastItem() {
|
|
||||||
mainPalette.focusLastItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
property bool expanded: filter.length || model.expanded
|
property bool expanded: filter.length || model.expanded
|
||||||
|
|
||||||
function toggleExpand() {
|
function toggleExpand() {
|
||||||
|
@ -418,13 +280,17 @@ ListView {
|
||||||
|
|
||||||
property bool selected: paletteSelectionModel.hasSelection ? paletteSelectionModel.isSelected(modelIndex) : false
|
property bool selected: paletteSelectionModel.hasSelection ? paletteSelectionModel.isSelected(modelIndex) : false
|
||||||
|
|
||||||
onClicked: {
|
function doItemClicked() {
|
||||||
forceActiveFocus();
|
forceActiveFocus();
|
||||||
const cmd = selected ? ItemSelectionModel.Toggle : ItemSelectionModel.ClearAndSelect;
|
const cmd = selected ? ItemSelectionModel.Toggle : ItemSelectionModel.ClearAndSelect;
|
||||||
paletteSelectionModel.setCurrentIndex(modelIndex, cmd);
|
paletteSelectionModel.setCurrentIndex(modelIndex, cmd);
|
||||||
paletteTree.currentIndex = index;
|
paletteTree.currentIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
control.doItemClicked()
|
||||||
|
}
|
||||||
|
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
forceActiveFocus();
|
forceActiveFocus();
|
||||||
paletteSelectionModel.setCurrentIndex(modelIndex, ItemSelectionModel.Deselect);
|
paletteSelectionModel.setCurrentIndex(modelIndex, ItemSelectionModel.Deselect);
|
||||||
|
@ -432,9 +298,21 @@ ListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
background: ListItemBlank {
|
background: ListItemBlank {
|
||||||
|
background.color: paletteTree.backgroundColor
|
||||||
visible: !control.Drag.active
|
visible: !control.Drag.active
|
||||||
|
|
||||||
isSelected: control.selected
|
isSelected: control.selected
|
||||||
|
|
||||||
|
keynav.name: "PaletteTreeItemDelegate"
|
||||||
|
keynav.subsection: keynavTree
|
||||||
|
keynav.row: control.keynavRow
|
||||||
|
keynav.column: 0
|
||||||
|
enabled: control.visible
|
||||||
|
keynav.onActiveChanged: {
|
||||||
|
if (keynav.active && !control.selected) {
|
||||||
|
control.doItemClicked()
|
||||||
|
}
|
||||||
|
paletteTree.positionViewAtIndex(control.rowIndex, ListView.Contain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
highlighted: (activeFocus && !selected) || DelegateModel.isUnresolved
|
highlighted: (activeFocus && !selected) || DelegateModel.isUnresolved
|
||||||
|
@ -449,94 +327,11 @@ ListView {
|
||||||
property size cellSize: model.gridSize
|
property size cellSize: model.gridSize
|
||||||
property bool drawGrid: model.drawGrid
|
property bool drawGrid: model.drawGrid
|
||||||
|
|
||||||
activeFocusOnTab: this === paletteTree.currentTreeItem
|
|
||||||
|
|
||||||
function hidePalette() {
|
function hidePalette() {
|
||||||
paletteTree.expandedPopupIndex = null;
|
paletteTree.expandedPopupIndex = null;
|
||||||
paletteTree.paletteController.remove(modelIndex);
|
paletteTree.paletteController.remove(modelIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onShortcutOverride: {
|
|
||||||
// Intercept all keys that we want to use with Keys.onPressed
|
|
||||||
// in case they are assigned as shortcuts in Preferences.
|
|
||||||
event.accepted = true; // intercept everything
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Right:
|
|
||||||
case Qt.Key_Plus:
|
|
||||||
case Qt.Key_Left:
|
|
||||||
case Qt.Key_Minus:
|
|
||||||
case Qt.Key_Space:
|
|
||||||
case Qt.Key_Enter:
|
|
||||||
case Qt.Key_Return:
|
|
||||||
case Qt.Key_Menu:
|
|
||||||
case Qt.Key_Asterisk:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key === Qt.Key_F10 && event.modifiers & Qt.ShiftModifier) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.text.match(/[^\x00-\x20\x7F]+$/) !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.accepted = false; // allow key to function as shortcut (don't intercept)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
|
||||||
// NOTE: All keys must be intercepted with Keys.onShortcutOverride.
|
|
||||||
switch (event.key) {
|
|
||||||
case Qt.Key_Right:
|
|
||||||
case Qt.Key_Plus:
|
|
||||||
if (!expanded) {
|
|
||||||
toggleExpand();
|
|
||||||
} else if (event.key === Qt.Key_Right) {
|
|
||||||
focusFirstItem();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Qt.Key_Left:
|
|
||||||
case Qt.Key_Minus:
|
|
||||||
if (expanded)
|
|
||||||
toggleExpand();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Space:
|
|
||||||
if (paletteTree.typeAheadStr.length) {
|
|
||||||
paletteTree.typeAheadFind(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// fallthrough
|
|
||||||
case Qt.Key_Enter:
|
|
||||||
case Qt.Key_Return:
|
|
||||||
toggleExpand();
|
|
||||||
break;
|
|
||||||
case Qt.Key_F10:
|
|
||||||
if (!(event.modifiers & Qt.ShiftModifier)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// fallthrough
|
|
||||||
case Qt.Key_Menu:
|
|
||||||
paletteHeader.showPaletteMenu();
|
|
||||||
break;
|
|
||||||
case Qt.Key_Asterisk:
|
|
||||||
if (paletteTree.typeAheadStr.length) {
|
|
||||||
paletteTree.typeAheadFind('*');
|
|
||||||
} else {
|
|
||||||
paletteTree.expandCollapseAll(null);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (event.text.match(/[^\x00-\x20\x7F]+$/) !== null) {
|
|
||||||
// Pressed non-control character(s) (e.g. "L")
|
|
||||||
// so go to matching palette (e.g. "Lines")
|
|
||||||
paletteTree.typeAheadFind(event.text);
|
|
||||||
} else {
|
|
||||||
return; // don't accept event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
text: filter.length ? qsTrc("palette", "%1, contains %n matching element(s)", "palette", mainPalette.count).arg(model.accessibleText)
|
text: filter.length ? qsTrc("palette", "%1, contains %n matching element(s)", "palette", mainPalette.count).arg(model.accessibleText)
|
||||||
: model.expanded ? qsTrc("palette", "%1 expanded", "tree item not collapsed").arg(model.accessibleText)
|
: model.expanded ? qsTrc("palette", "%1 expanded", "tree item not collapsed").arg(model.accessibleText)
|
||||||
: model.accessibleText
|
: model.accessibleText
|
||||||
|
@ -647,6 +442,9 @@ ListView {
|
||||||
hovered: control.hovered
|
hovered: control.hovered
|
||||||
text: model.display
|
text: model.display
|
||||||
|
|
||||||
|
keynavSubsection: keynavTree
|
||||||
|
keynavRow: control.keynavRow
|
||||||
|
|
||||||
hidePaletteElementVisible: {
|
hidePaletteElementVisible: {
|
||||||
return !control.selected && control.expanded
|
return !control.selected && control.expanded
|
||||||
&& paletteSelectionModel.hasSelection && paletteSelectionModel.columnIntersectsSelection(0, control.modelIndex)
|
&& paletteSelectionModel.hasSelection && paletteSelectionModel.columnIntersectsSelection(0, control.modelIndex)
|
||||||
|
@ -706,6 +504,9 @@ ListView {
|
||||||
id: mainPalette
|
id: mainPalette
|
||||||
anchors { fill: parent; margins: parent.padding }
|
anchors { fill: parent; margins: parent.padding }
|
||||||
|
|
||||||
|
keynavSubSection: keynavTree
|
||||||
|
keynavRow: control.keynavRow + 1
|
||||||
|
|
||||||
cellSize: control.cellSize
|
cellSize: control.cellSize
|
||||||
drawGrid: control.drawGrid
|
drawGrid: control.drawGrid
|
||||||
|
|
||||||
|
@ -811,14 +612,4 @@ ListView {
|
||||||
|
|
||||||
// placeholder footer item to reserve a space for "More" popup to expand
|
// placeholder footer item to reserve a space for "More" popup to expand
|
||||||
footer: Item { height: 0 }
|
footer: Item { height: 0 }
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: palettesWidget
|
|
||||||
function onHasFocusChanged() {
|
|
||||||
if (!palettesWidget.hasFocus) {
|
|
||||||
paletteSelectionModel.clearSelection();
|
|
||||||
expandedPopupIndex = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
import QtQuick 2.8
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.1
|
import QtQuick.Controls 2.1
|
||||||
|
|
||||||
import MuseScore.Palette 1.0
|
|
||||||
import MuseScore.UiComponents 1.0
|
|
||||||
import MuseScore.Ui 1.0
|
import MuseScore.Ui 1.0
|
||||||
|
import MuseScore.UiComponents 1.0
|
||||||
|
import MuseScore.Palette 1.0
|
||||||
|
|
||||||
import "utils.js" as Utils
|
import "utils.js" as Utils
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ Item {
|
||||||
|
|
||||||
property alias popupMaxHeight: palettePopup.maxHeight
|
property alias popupMaxHeight: palettePopup.maxHeight
|
||||||
|
|
||||||
|
property alias keynav: keynavSub
|
||||||
|
|
||||||
signal addCustomPaletteRequested(var paletteName)
|
signal addCustomPaletteRequested(var paletteName)
|
||||||
|
|
||||||
implicitHeight: childrenRect.height
|
implicitHeight: childrenRect.height
|
||||||
|
@ -55,20 +57,39 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigationSubSection {
|
||||||
|
id: keynavSub
|
||||||
|
name: "PalettesHeader"
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
header.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlatButton {
|
FlatButton {
|
||||||
id: morePalettesButton
|
id: morePalettesButton
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: searchTextButton.left
|
anchors.right: searchTextButton.left
|
||||||
anchors.rightMargin: 8
|
anchors.rightMargin: 8
|
||||||
|
objectName: "AddPalettesBtn"
|
||||||
|
keynav.subsection: keynavSub
|
||||||
|
keynav.order: 1
|
||||||
|
enabled: !searchTextInput.visible
|
||||||
text: qsTrc("palette", "Add Palettes")
|
text: qsTrc("palette", "Add Palettes")
|
||||||
onClicked: palettePopup.visible = !palettePopup.visible
|
onClicked: {
|
||||||
|
palettePopup.visible = !palettePopup.visible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatButton {
|
FlatButton {
|
||||||
id: searchTextButton
|
id: searchTextButton
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
objectName: "SearchPalettesBtn"
|
||||||
|
keynav.subsection: keynavSub
|
||||||
|
keynav.order: 2
|
||||||
|
enabled: !searchTextInput.visible
|
||||||
icon: IconCode.SEARCH
|
icon: IconCode.SEARCH
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
toggleSearch()
|
toggleSearch()
|
||||||
}
|
}
|
||||||
|
@ -78,12 +99,47 @@ Item {
|
||||||
id: searchTextInput
|
id: searchTextInput
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
|
//! TODO Move to SearchField inside
|
||||||
|
KeyNavigationControl {
|
||||||
|
id: keynavSearchField
|
||||||
|
name: "SearchPalettesField"
|
||||||
|
subsection: keynavSub
|
||||||
|
order: 3
|
||||||
|
enabled: searchTextInput.visible
|
||||||
|
onActiveChanged: {
|
||||||
|
if (keynavSearchField.active) {
|
||||||
|
searchTextInput.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyNavigationControl {
|
||||||
|
id: keynavSearchFieldClose
|
||||||
|
name: "SearchPalettesFieldClose"
|
||||||
|
subsection: keynavSub
|
||||||
|
order: 4
|
||||||
|
enabled: searchTextInput.visible && searchTextInput.clearTextButtonVisible
|
||||||
|
onTriggered: toggleSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!searchTextInput.visible) {
|
||||||
|
morePalettesButton.keynav.forceActive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! ----------
|
||||||
|
|
||||||
visible: false
|
visible: false
|
||||||
|
|
||||||
onSearchTextChanged: resultsTimer.restart()
|
onSearchTextChanged: resultsTimer.restart()
|
||||||
onActiveFocusChanged: {
|
onActiveFocusChanged: {
|
||||||
resultsTimer.stop();
|
resultsTimer.stop();
|
||||||
Accessible.name = qsTrc("palette", "Palette Search")
|
Accessible.name = qsTrc("palette", "Palette Search")
|
||||||
|
|
||||||
|
if (searchTextInput.activeFocus) {
|
||||||
|
keynavSearchField.forceActive()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
|
@ -94,10 +150,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyNavigation.tab: paletteTree.currentTreeItem
|
|
||||||
|
|
||||||
Keys.onDownPressed: paletteTree.focusFirstItem();
|
|
||||||
Keys.onUpPressed: paletteTree.focusLastItem();
|
|
||||||
Keys.onEscapePressed: toggleSearch()
|
Keys.onEscapePressed: toggleSearch()
|
||||||
|
|
||||||
clearTextButtonVisible: true
|
clearTextButtonVisible: true
|
||||||
|
@ -137,12 +189,4 @@ Item {
|
||||||
createCustomPalettePopup.open()
|
createCustomPalettePopup.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: palettesWidget
|
|
||||||
function onHasFocusChanged() {
|
|
||||||
if (!palettesWidget.hasFocus && !palettePopup.inMenuAction)
|
|
||||||
palettePopup.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,9 @@ Item {
|
||||||
property PaletteWorkspace paletteWorkspace
|
property PaletteWorkspace paletteWorkspace
|
||||||
property var modelIndex: null
|
property var modelIndex: null
|
||||||
|
|
||||||
|
property KeyNavigationSubSection keynavSubsection: null
|
||||||
|
property int keynavRow: 0
|
||||||
|
|
||||||
signal toggleExpandRequested()
|
signal toggleExpandRequested()
|
||||||
signal enableEditingToggled(bool val)
|
signal enableEditingToggled(bool val)
|
||||||
signal hideSelectedElementsRequested()
|
signal hideSelectedElementsRequested()
|
||||||
|
@ -66,6 +69,11 @@ Item {
|
||||||
icon: paletteHeader.expanded ? IconCode.SMALL_ARROW_DOWN : IconCode.SMALL_ARROW_RIGHT
|
icon: paletteHeader.expanded ? IconCode.SMALL_ARROW_DOWN : IconCode.SMALL_ARROW_RIGHT
|
||||||
normalStateColor: "transparent"
|
normalStateColor: "transparent"
|
||||||
|
|
||||||
|
enabled: paletteExpandArrow.visible
|
||||||
|
keynav.subsection: paletteHeader.keynavSubsection
|
||||||
|
keynav.row: paletteHeader.keynavRow
|
||||||
|
keynav.column: 1
|
||||||
|
|
||||||
onClicked: paletteHeader.toggleExpandRequested()
|
onClicked: paletteHeader.toggleExpandRequested()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +107,10 @@ Item {
|
||||||
activeFocusOnTab: mainPalette.currentItem === paletteTree.currentTreeItem
|
activeFocusOnTab: mainPalette.currentItem === paletteTree.currentTreeItem
|
||||||
normalStateColor: "transparent"
|
normalStateColor: "transparent"
|
||||||
|
|
||||||
KeyNavigation.backtab: mainPalette.currentItem
|
enabled: deleteButton.visible
|
||||||
KeyNavigation.tab: focusBreaker
|
keynav.subsection: paletteHeader.keynavSubsection
|
||||||
|
keynav.row: paletteHeader.keynavRow
|
||||||
|
keynav.column: 2
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
hideSelectedElementsRequested()
|
hideSelectedElementsRequested()
|
||||||
|
@ -115,7 +125,10 @@ Item {
|
||||||
|
|
||||||
visible: paletteHeader.expanded || paletteHeader.hovered || paletteHeaderMenu.visible
|
visible: paletteHeader.expanded || paletteHeader.hovered || paletteHeaderMenu.visible
|
||||||
|
|
||||||
activeFocusOnTab: parent.parent.parent === paletteTree.currentTreeItem
|
enabled: paletteHeaderMenuButton.visible
|
||||||
|
keynav.subsection: paletteHeader.keynavSubsection
|
||||||
|
keynav.row: paletteHeader.keynavRow
|
||||||
|
keynav.column: 3
|
||||||
|
|
||||||
icon: IconCode.MENU_THREE_DOTS
|
icon: IconCode.MENU_THREE_DOTS
|
||||||
normalStateColor: "transparent"
|
normalStateColor: "transparent"
|
||||||
|
|
Loading…
Reference in a new issue