1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-21 14:50:06 +02:00

Okay, let's try this again. Now there's only a type of external index...none of

this "use aline index here and a node index here" stupidity.
This commit is contained in:
lllucius 2013-10-02 08:17:16 +00:00
parent 0beec63b1e
commit 856c51e6a6
5 changed files with 433 additions and 214 deletions

View File

@ -1202,7 +1202,15 @@ wxString CommandManager::GetPrefixedLabelFromName(wxString name)
if (!entry) if (!entry)
return wxT(""); return wxT("");
#if defined(EXPERIMENTAL_KEY_VIEW)
wxString prefix;
if (!entry->labelPrefix.IsEmpty()) {
prefix = entry->labelPrefix + wxT(" - ");
}
return wxMenuItem::GetLabelFromText(prefix + entry->label);
#else
return wxString(entry->labelPrefix + wxT(" ") + entry->label).Trim(false).Trim(true); return wxString(entry->labelPrefix + wxT(" ") + entry->label).Trim(false).Trim(true);
#endif
} }
wxString CommandManager::GetCategoryFromName(wxString name) wxString CommandManager::GetCategoryFromName(wxString name)

View File

@ -135,6 +135,12 @@ void KeyConfigPrefs::Populate()
PopulateOrExchange(S); PopulateOrExchange(S);
mCommandSelected = wxNOT_FOUND;
mManager = project->GetCommandManager();
RefreshBindings();
if (mViewByTree->GetValue()) { if (mViewByTree->GetValue()) {
mView->SetView(ViewByTree); mView->SetView(ViewByTree);
} }
@ -144,12 +150,6 @@ void KeyConfigPrefs::Populate()
else if (mViewByKey->GetValue()) { else if (mViewByKey->GetValue()) {
mView->SetView(ViewByKey); mView->SetView(ViewByKey);
} }
mCommandSelected = -1;
mManager = project->GetCommandManager();
RefreshBindings();
} }
/// Normally in classes derived from PrefsPanel this function /// Normally in classes derived from PrefsPanel this function
@ -257,8 +257,8 @@ void KeyConfigPrefs::PopulateOrExchange(ShuttleGui & S)
S.AddWindow(mKey); S.AddWindow(mKey);
/* i18n-hint: (verb)*/ /* i18n-hint: (verb)*/
S.Id(SetButtonID).AddButton(_("&Set")); mSet = S.Id(SetButtonID).AddButton(_("&Set"));
S.Id(ClearButtonID).AddButton(_("Cl&ear")); mClear = S.Id(ClearButtonID).AddButton(_("Cl&ear"));
} }
S.EndThreeColumn(); S.EndThreeColumn();
@ -288,6 +288,8 @@ void KeyConfigPrefs::RefreshBindings()
wxArrayString Prefixes; wxArrayString Prefixes;
mNames.Clear(); mNames.Clear();
mKeys.Clear();
mDefaultKeys.Clear();
mManager->GetAllCommandData( mManager->GetAllCommandData(
mNames, mNames,
mKeys, mKeys,
@ -429,7 +431,7 @@ void KeyConfigPrefs::OnHotkeyKillFocus(wxFocusEvent & e)
e.Skip(); e.Skip();
} }
void KeyConfigPrefs::OnFilterTimer(wxTimerEvent & e) void KeyConfigPrefs::OnFilterTimer(wxTimerEvent & WXUNUSED(e))
{ {
// The filter timer has expired, so set the filter // The filter timer has expired, so set the filter
if (mFilterPending) if (mFilterPending)
@ -493,45 +495,69 @@ void KeyConfigPrefs::OnFilterChar(wxKeyEvent & e)
// corresponding command, or the empty string if none is found. // corresponding command, or the empty string if none is found.
wxString KeyConfigPrefs::NameFromKey(const wxString & key) wxString KeyConfigPrefs::NameFromKey(const wxString & key)
{ {
int i = mNewKeys.Index(key); return mView->GetNameByKey(key);
if (i == wxNOT_FOUND) {
return wxEmptyString;
}
return mNames[i];
} }
// Sets the selected command to have this key // Sets the selected command to have this key
// This is not yet a committed change, which will happen on a save. // This is not yet a committed change, which will happen on a save.
void KeyConfigPrefs::SetKeyForSelected(const wxString & key) void KeyConfigPrefs::SetKeyForSelected(const wxString & key)
{ {
int index = mView->GetIndex(mCommandSelected); wxString name = mView->GetName(mCommandSelected);
if (!mView->CanSetKey(mCommandSelected))
{
wxMessageBox(_("You may not assign a key to this entry"),
_("Error"), wxICON_ERROR | wxCENTRE, this);
return;
}
mView->SetKey(mCommandSelected, key); mView->SetKey(mCommandSelected, key);
mManager->SetKeyFromIndex(index, key); mManager->SetKeyFromName(name, key);
mNewKeys[index] = key; mNewKeys[mNames.Index(name)] = key;
} }
void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event)) void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event))
{ {
wxString newKey = mKey->GetValue(); if (mCommandSelected == wxNOT_FOUND) {
wxMessageBox(_("You must select a binding before assigning a shortcut"),
wxString alreadyAssignedName = NameFromKey(newKey); _("Error"), wxICON_WARNING | wxCENTRE, this);
// Prevent same hotkey combination being used twice.
if (!alreadyAssignedName.IsEmpty()) {
wxMessageBox(
wxString::Format(
_("The keyboard shortcut '%s' is already assigned to:\n\n'%s'"),
newKey.c_str(),
alreadyAssignedName.c_str()),
_("Error"), wxICON_STOP | wxCENTRE, this);
return; return;
} }
SetKeyForSelected(newKey); wxString key = mKey->GetValue();
wxString oldname = mView->GetNameByKey(key);
wxString newname = mView->GetName(mCommandSelected);
// Just ignore it if they are the same
if (oldname == newname) {
return;
}
// Prevent same hotkey combination being used twice.
if (!oldname.IsEmpty()) {
wxString oldlabel = mManager->GetCategoryFromName(oldname) + wxT(" - ") +
mManager->GetPrefixedLabelFromName(oldname);
wxString newlabel = mManager->GetCategoryFromName(newname) + wxT(" - ") +
mManager->GetPrefixedLabelFromName(newname);
if (wxMessageBox(
wxString::Format(
_("The keyboard shortcut '%s' is already assigned to:\n\n\t'%s'\n\nClick OK to assign the shortcut to\n\n\t'%s'\n\ninstead. Otherwise, click Cancel."),
key.c_str(),
oldlabel.c_str(),
newlabel.c_str()),
_("Error"), wxOK | wxCANCEL | wxICON_STOP | wxCENTRE, this) == wxCANCEL)
{
return;
}
mView->SetKeyByName(oldname, wxEmptyString);
mManager->SetKeyFromName(oldname, wxEmptyString);
mNewKeys[mNames.Index(oldname)].Empty();
}
SetKeyForSelected(key);
} }
void KeyConfigPrefs::OnClear(wxCommandEvent& WXUNUSED(event)) void KeyConfigPrefs::OnClear(wxCommandEvent& WXUNUSED(event))
@ -543,10 +569,17 @@ void KeyConfigPrefs::OnClear(wxCommandEvent& WXUNUSED(event))
void KeyConfigPrefs::OnSelected(wxCommandEvent & e) void KeyConfigPrefs::OnSelected(wxCommandEvent & e)
{ {
mCommandSelected = e.GetInt(); mCommandSelected = mView->GetSelected();
mKey->Clear(); mKey->Clear();
bool canset = mView->CanSetKey(mCommandSelected);
if (canset) {
mKey->AppendText(mView->GetKey(mCommandSelected)); mKey->AppendText(mView->GetKey(mCommandSelected));
}
mKey->Enable(canset);
mSet->Enable(canset);
mClear->Enable(canset);
} }
void KeyConfigPrefs::OnViewBy(wxCommandEvent & e) void KeyConfigPrefs::OnViewBy(wxCommandEvent & e)

View File

@ -62,6 +62,8 @@ private:
KeyView *mView; KeyView *mView;
wxTextCtrl *mKey; wxTextCtrl *mKey;
wxButton *mSet;
wxButton *mClear;
wxTextCtrl *mFilter; wxTextCtrl *mFilter;
wxStaticText *mFilterLabel; wxStaticText *mFilterLabel;

View File

@ -113,107 +113,232 @@ KeyView::~KeyView()
} }
// //
// Returns the label for the given line // Returns the index of the selected node
//
int
KeyView::GetSelected() const
{
return LineToIndex(GetSelection());
}
//
// Returns the name of the control
// //
wxString wxString
KeyView::GetLabel(int line) KeyView::GetName() const
{ {
// Make sure line is valid // Just forward request
if (line < 0 || line >= (int) mLines.GetCount()) return wxVListBox::GetName();
}
//
// Returns the label for the given index
//
wxString
KeyView::GetLabel(int index) const
{
// Make sure index is valid
if (index < 0 || index >= (int) mNodes.GetCount())
{ {
wxASSERT(false); wxASSERT(false);
return wxEmptyString; return wxEmptyString;
} }
return mLines[line]->label; return mNodes[index].label;
} }
// //
// Returns the prefix (if available) prepended to the label for the given line // Returns the prefix (if available) prepended to the label for the given index
// //
wxString wxString
KeyView::GetFullLabel(int line) KeyView::GetFullLabel(int index) const
{ {
// Make sure line is valid // Make sure index is valid
if (line < 0 || line >= (int) mLines.GetCount()) if (index < 0 || index >= (int) mNodes.GetCount())
{ {
wxASSERT(false); wxASSERT(false);
return wxEmptyString; return wxEmptyString;
} }
// Cache the node and label // Cache the node and label
KeyNode *node = mLines[line]; KeyNode & node = mNodes[index];
wxString label = node->label; wxString label = node.label;
// Prepend the prefix if available // Prepend the prefix if available
if (!node->prefix.IsEmpty()) if (!node.prefix.IsEmpty())
{ {
label = node->prefix + wxT(" - ") + label; label = node.prefix + wxT(" - ") + label;
} }
return label; return label;
} }
// //
// Returns the key for the given line // Returns the index for the given name
//
int
KeyView::GetIndexByName(const wxString & name) const
{
int cnt = (int) mNodes.GetCount();
// Search the nodes for the key
for (int i = 0; i < cnt; i++)
{
if (name.CmpNoCase(mNodes[i].name) == 0)
{
return mNodes[i].index;
}
}
return wxNOT_FOUND;
}
//
// Returns the command manager name for the given index
// //
wxString wxString
KeyView::GetKey(int line) KeyView::GetName(int index) const
{ {
// Make sure line is valid // Make sure index is valid
if (line < 0 || line >= (int) mLines.GetCount()) if (index < 0 || index >= (int) mNodes.GetCount())
{ {
wxASSERT(false); wxASSERT(false);
return wxEmptyString; return wxEmptyString;
} }
return mLines[line]->key; return mNodes[index].name;
} }
// //
// Returns the command manager index for the given line // Returns the command manager index for the given key combination
//
wxString
KeyView::GetNameByKey(const wxString & key) const
{
int cnt = (int) mNodes.GetCount();
// Search the nodes for the key
for (int i = 0; i < cnt; i++)
{
if (key.CmpNoCase(mNodes[i].key) == 0)
{
return mNodes[i].name;
}
}
return wxEmptyString;
}
//
// Returns the index for the given key
// //
int int
KeyView::GetIndex(int line) KeyView::GetIndexByKey(const wxString & key) const
{ {
// Make sure line is valid int cnt = (int) mNodes.GetCount();
if (line < 0 || line >= (int) mLines.GetCount())
// Search the nodes for the key
for (int i = 0; i < cnt; i++)
{ {
wxASSERT(false); if (key.CmpNoCase(mNodes[i].key) == 0)
return wxNOT_FOUND; {
return mNodes[i].index;
}
} }
return mLines[line]->index; return wxNOT_FOUND;
} }
// //
// Sets the key for the given line // Returns the key for the given index
// //
void wxString
KeyView::SetKey(int line, const wxString & key) KeyView::GetKey(int index) const
{ {
// Make sure line is valid // Make sure index is valid
if (line < 0 || line >= (int) mLines.GetCount()) if (index < 0 || index >= (int) mNodes.GetCount())
{ {
return; wxASSERT(false);
return wxEmptyString;
} }
// Cache the node and set the new key return mNodes[index].key;
KeyNode *node = mLines[line]; }
node->key = key;
//
// Use to determine if a key can be assigned to the given index
//
bool
KeyView::CanSetKey(int index) const
{
// Make sure index is valid
if (index < 0 || index >= (int) mNodes.GetCount())
{
wxASSERT(false);
return false;
}
// Parents can't be assigned keys
return !mNodes[index].isparent;
}
//
// Sets the key for the given index
//
bool
KeyView::SetKey(int index, const wxString & key)
{
// Make sure index is valid
if (index < 0 || index >= (int) mNodes.GetCount())
{
wxASSERT(false);
return false;
}
// Cache the node
KeyNode & node = mNodes[index];
// Do not allow setting keys on branches
if (node.isparent)
{
return false;
}
// Set the new key
node.key = key;
// Check to see if the key column needs to be expanded // Check to see if the key column needs to be expanded
int x, y; int x, y;
GetTextExtent(node->key, &x, &y); GetTextExtent(node.key, &x, &y);
if (x > mKeyWidth || y > mLineHeight) if (x > mKeyWidth || y > mLineHeight)
{ {
// New key is wider than column to recalc extents (will refresh view) // New key is wider than column to recalc extents (will refresh view)
RecalcExtents(); RecalcExtents();
return; return true;
} }
// Refresh the view lines // Refresh the view lines
RefreshLine(line); RefreshAll();
return true;
}
//
// Sets the key for the given name
//
bool
KeyView::SetKeyByName(const wxString & name, const wxString & key)
{
int index = GetIndexByName(name);
// Bail is the name wasn't found
if (index == wxNOT_FOUND)
{
return false;
}
// Go set the key
return SetKey(index, key);
} }
// //
@ -222,24 +347,23 @@ KeyView::SetKey(int line, const wxString & key)
void void
KeyView::SetView(ViewByType type) KeyView::SetView(ViewByType type)
{ {
int line = GetSelection(); int index = LineToIndex(GetSelection());
KeyNode *node = NULL;
// Handle an existing selection // Handle an existing selection
if (line != wxNOT_FOUND) if (index != wxNOT_FOUND)
{ {
// Cache the currently selected node // Cache the currently selected node
node = mLines[line]; KeyNode & node = mNodes[index];
// Expand branches if switching to Tree view and a line // Expand branches if switching to Tree view and a line
// is currently selected // is currently selected
if (type == ViewByTree) if (type == ViewByTree)
{ {
// Cache the node's depth // Cache the node's depth
int depth = node->depth; int depth = node.depth;
// Search for its parents, setting each one as open // Search for its parents, setting each one as open
for (int i = node->node - 1; i >= 0 && depth > 1; i--) for (int i = node.index - 1; i >= 0 && depth > 1; i--)
{ {
if (mNodes[i].depth < depth) if (mNodes[i].depth < depth)
{ {
@ -250,26 +374,19 @@ KeyView::SetView(ViewByType type)
} }
} }
// Unselect any currently selected line...do even if none selected
SelectNode(-1);
// Save new type // Save new type
mViewType = type; mViewType = type;
// Refresh the view lines // Refresh the view lines
RefreshLineCount(); RefreshLines();
// Unselect any currently selected line...do even if none selected // Reselect old node
SelectLine(-1); if (index != wxNOT_FOUND)
// Locate the previously selected node and reselect
if (node)
{ {
for (size_t i = 0; i < mLines.GetCount(); i++) SelectNode(index);
{
if (mLines[i]->node == node->node)
{
SelectLine(i);
break;
}
}
} }
return; return;
@ -283,7 +400,7 @@ KeyView::SetFilter(const wxString & filter)
{ {
// Save it and refresh to filter the view // Save it and refresh to filter the view
mFilter = filter.Lower(); mFilter = filter.Lower();
RefreshLineCount(); RefreshLines();
} }
// //
@ -292,7 +409,7 @@ KeyView::SetFilter(const wxString & filter)
void void
KeyView::ExpandAll() KeyView::ExpandAll()
{ {
size_t cnt = mNodes.GetCount(); int cnt = (int) mNodes.GetCount();
// Set all parent nodes to open // Set all parent nodes to open
for (int i = 0; i < cnt; i++) for (int i = 0; i < cnt; i++)
@ -305,7 +422,7 @@ KeyView::ExpandAll()
} }
} }
RefreshLineCount(); RefreshLines();
} }
// //
@ -314,7 +431,7 @@ KeyView::ExpandAll()
void void
KeyView::CollapseAll() KeyView::CollapseAll()
{ {
size_t cnt = mNodes.GetCount(); int cnt = (int) mNodes.GetCount();
// Set all parent nodes to closed // Set all parent nodes to closed
for (int i = 0; i < cnt; i++) for (int i = 0; i < cnt; i++)
@ -327,7 +444,7 @@ KeyView::CollapseAll()
} }
} }
RefreshLineCount(); RefreshLines();
} }
// //
@ -342,7 +459,8 @@ KeyView::RecalcExtents()
mKeyWidth = 0; mKeyWidth = 0;
// Examine all nodes // Examine all nodes
for (size_t i = 0; i < mNodes.GetCount(); i++) int cnt = (int) mNodes.GetCount();
for (int i = 0; i < cnt; i++)
{ {
KeyNode & node = mNodes[i]; KeyNode & node = mNodes[i];
int x, y; int x, y;
@ -444,8 +562,10 @@ KeyView::RefreshBindings(const wxArrayString & names,
bool inpfx = false; bool inpfx = false;
// Examine all names...all arrays passed have the same indexes // Examine all names...all arrays passed have the same indexes
for (size_t i = 0; i < names.GetCount(); i++) int cnt = (int) names.GetCount();
for (int i = 0; i < cnt; i++)
{ {
wxString name = names[i];
int x, y; int x, y;
// Remove any menu code from the category and prefix // Remove any menu code from the category and prefix
@ -487,18 +607,17 @@ KeyView::RefreshBindings(const wxArrayString & names,
KeyNode node; KeyNode node;
// Fill in the node info // Fill in the node info
node.name = wxEmptyString; // don't associate branches with a command
node.category = cat; node.category = cat;
node.prefix = pfx; node.prefix = pfx;
node.label = cat; node.label = cat;
node.node = ++nodecnt; node.index = nodecnt++;
node.index = i;
node.iscat = true; node.iscat = true;
node.isparent = true; node.isparent = true;
node.depth = depth; node.depth = depth++;
// Add it to the tree // Add it to the tree
mNodes.Add(node); mNodes.Add(node);
depth++;
incat = true; incat = true;
// Measure category // Measure category
@ -527,18 +646,17 @@ KeyView::RefreshBindings(const wxArrayString & names,
KeyNode node; KeyNode node;
// Fill in the node info // Fill in the node info
node.name = wxEmptyString; // don't associate branches with a command
node.category = cat; node.category = cat;
node.prefix = pfx; node.prefix = pfx;
node.label = pfx; node.label = pfx;
node.node = ++nodecnt; node.index = nodecnt++;
node.index = i;
node.ispfx = true; node.ispfx = true;
node.isparent = true; node.isparent = true;
node.depth = depth; node.depth = depth++;
// Add it to the tree // Add it to the tree
mNodes.Add(node); mNodes.Add(node);
depth++;
inpfx = true; inpfx = true;
// Measure prefix // Measure prefix
@ -556,11 +674,11 @@ KeyView::RefreshBindings(const wxArrayString & names,
// Labels for undo and redo change according to the last command // Labels for undo and redo change according to the last command
// which can be undone/redone, so give them a special check in order // which can be undone/redone, so give them a special check in order
// not to confuse users // not to confuse users
if (names[i] == wxT("Undo")) if (name == wxT("Undo"))
{ {
node.label = _("Undo"); node.label = _("Undo");
} }
else if (names[i] == wxT("Redo")) else if (name == wxT("Redo"))
{ {
node.label = _("Redo"); node.label = _("Redo");
} }
@ -571,9 +689,9 @@ KeyView::RefreshBindings(const wxArrayString & names,
} }
// Fill in remaining info // Fill in remaining info
node.name = name;
node.key = KeyStringDisplay(keys[i]); node.key = KeyStringDisplay(keys[i]);
node.node = ++nodecnt; node.index = nodecnt++;
node.index = i;
node.depth = depth; node.depth = depth;
// Add it to the tree // Add it to the tree
@ -595,7 +713,6 @@ KeyView::RefreshBindings(const wxArrayString & names,
GetTextExtent(label, &x, &y); GetTextExtent(label, &x, &y);
mLineHeight = wxMax(mLineHeight, y); mLineHeight = wxMax(mLineHeight, y);
mCommandWidth = wxMax(mCommandWidth, x); mCommandWidth = wxMax(mCommandWidth, x);
} }
#if 0 #if 0
@ -603,15 +720,15 @@ KeyView::RefreshBindings(const wxArrayString & names,
for (int j = 0; j < mNodes.GetCount(); j++) for (int j = 0; j < mNodes.GetCount(); j++)
{ {
KeyNode & node = mNodes[j]; KeyNode & node = mNodes[j];
wxLogDebug(wxT("NODE line %4d node %4d index %4d depth %1d open %1d parent %1d cat %1d pfx %1d STR %s | %s | %s"), wxLogDebug(wxT("NODE line %4d index %4d depth %1d open %1d parent %1d cat %1d pfx %1d name %s STR %s | %s | %s"),
node.line, node.line,
node.node,
node.index, node.index,
node.depth, node.depth,
node.isopen, node.isopen,
node.isparent, node.isparent,
node.iscat, node.iscat,
node.ispfx, node.ispfx,
node.name.c_str(),
node.category.c_str(), node.category.c_str(),
node.prefix.c_str(), node.prefix.c_str(),
node.label.c_str()); node.label.c_str());
@ -622,24 +739,24 @@ KeyView::RefreshBindings(const wxArrayString & names,
UpdateHScroll(); UpdateHScroll();
// Refresh the view lines // Refresh the view lines
RefreshLineCount(); RefreshLines();
} }
// //
// Refresh the list of lines within the current view // Refresh the list of lines within the current view
// //
void void
KeyView::RefreshLineCount() KeyView::RefreshLines()
{ {
size_t cnt = mNodes.GetCount(); int cnt = (int) mNodes.GetCount();
int numlines = 0; int linecnt = 0;
mLines.Empty(); mLines.Empty();
// Process a filter if one is set // Process a filter if one is set
if (!mFilter.IsEmpty()) if (!mFilter.IsEmpty())
{ {
// Examine all nodes // Examine all nodes
for (size_t i = 0; i < cnt; i++) for (int i = 0; i < cnt; i++)
{ {
KeyNode & node = mNodes[i]; KeyNode & node = mNodes[i];
@ -677,7 +794,7 @@ KeyView::RefreshLineCount()
} }
// Examine siblings until a parent is found. // Examine siblings until a parent is found.
for (int j = node.node - 1; j >= 0 && depth > 0; j--) for (int j = node.index - 1; j >= 0 && depth > 0; j--)
{ {
// Found a parent // Found a parent
if (mNodes[j].depth < depth) if (mNodes[j].depth < depth)
@ -685,11 +802,11 @@ KeyView::RefreshLineCount()
// Examine all previously added nodes to see if this nodes // Examine all previously added nodes to see if this nodes
// ancestors need to be added prior to adding this node. // ancestors need to be added prior to adding this node.
bool found = false; bool found = false;
for (int k = mLines.GetCount() - 1; k >= 0; k--) for (int k = (int) mLines.GetCount() - 1; k >= 0; k--)
{ {
// The node indexes match, so we've found the child nodes // The node indexes match, so we've found the parent of the
// parent. // child node.
if (mLines[k]->node == mNodes[j].node) if (mLines[k]->index == mNodes[j].index)
{ {
found = true; found = true;
break; break;
@ -711,37 +828,37 @@ KeyView::RefreshLineCount()
// Add any queues nodes to list. This will all be // Add any queues nodes to list. This will all be
// parent nodes, so mark them as open. // parent nodes, so mark them as open.
for (int j = queue.GetCount() - 1; j >= 0; j--) for (int j = (int) queue.GetCount() - 1; j >= 0; j--)
{ {
queue[j]->isopen = true; queue[j]->isopen = true;
queue[j]->line = numlines++; queue[j]->line = linecnt++;
mLines.Add(queue[j]); mLines.Add(queue[j]);
} }
} }
// Finally add the child node // Finally add the child node
node.line = numlines++; node.line = linecnt++;
mLines.Add(&node); mLines.Add(&node);
} }
} }
else else
{ {
// Examine all nodes - non-filtered // Examine all nodes - non-filtered
for (size_t i = 0; i < cnt; i++) for (int i = 0; i < cnt; i++)
{ {
KeyNode & node = mNodes[i]; KeyNode & node = mNodes[i];
// Node is either a category or prefix // Node is either a category or prefix
if (node.isparent) if (node.isparent)
{ {
// Only need to do this for non-tree views // Only need to do this for tree views
if (mViewType != ViewByTree) if (mViewType != ViewByTree)
{ {
continue; continue;
} }
// Add the node // Add the node
node.line = numlines++; node.line = linecnt++;
mLines.Add(&node); mLines.Add(&node);
// If this node is not open, then skip all of it's decendants // If this node is not open, then skip all of it's decendants
@ -774,31 +891,11 @@ KeyView::RefreshLineCount()
} }
// Add child node to list // Add child node to list
node.line = numlines++; node.line = linecnt++;
mLines.Add(&node); mLines.Add(&node);
} }
} }
#if 0
// For debugging
for (int j = 0; j < mLines.GetCount() ; j++)
{
KeyNode & node = *mLines[j];
wxLogDebug(wxT("LINE line %4d node %4d index %4d depth %1d open %1d parent %1d cat %1d pfx %1d STR %s | %s | %s"),
node.line,
node.node,
node.index,
node.depth,
node.isopen,
node.isparent,
node.iscat,
node.ispfx,
node.category.c_str(),
node.prefix.c_str(),
node.label.c_str());
}
#endif
// Sort list based on type // Sort list based on type
switch (mViewType) switch (mViewType)
{ {
@ -815,6 +912,32 @@ KeyView::RefreshLineCount()
break; break;
} }
// Now, reassign the line numbers
for (int i = 0; i < mLines.GetCount(); i++)
{
mLines[i]->line = i;
}
#if 0
// For debugging
for (int j = 0; j < mLines.GetCount(); j++)
{
KeyNode & node = *mLines[j];
wxLogDebug(wxT("LINE line %4d index %4d depth %1d open %1d parent %1d cat %1d pfx %1d name %s STR %s | %s | %s"),
node.line,
node.index,
node.depth,
node.isopen,
node.isparent,
node.iscat,
node.ispfx,
node.name.c_str(),
node.category.c_str(),
node.prefix.c_str(),
node.label.c_str());
}
#endif
// Tell listbox the new count and refresh the entire view // Tell listbox the new count and refresh the entire view
SetItemCount(mLines.GetCount()); SetItemCount(mLines.GetCount());
RefreshAll(); RefreshAll();
@ -826,29 +949,57 @@ KeyView::RefreshLineCount()
} }
// //
// Select a line // Select a node
// //
// Parameter can be wxNOT_FOUND to clear selection // Parameter can be wxNOT_FOUND to clear selection
// //
void void
KeyView::SelectLine(int line) KeyView::SelectNode(int index)
{ {
// Tell the listbox to select the line // Tell the listbox to select the line
SetSelection(line); SetSelection(IndexToLine(index));
#if wxUSE_ACCESSIBILITY #if wxUSE_ACCESSIBILITY
// And accessibility // And accessibility
mAx->SetCurrentLine(line); mAx->SetCurrentLine(IndexToLine(index));
#endif #endif
// If not clearing, then send a selected event as it is not // If not clearing, then send a selected event as it is not
// automatically done. // automatically done.
if (line != wxNOT_FOUND) if (index != wxNOT_FOUND)
{ {
SendSelectedEvent(); SendSelectedEvent();
} }
} }
//
// Converts a line index to a node index
//
int
KeyView::LineToIndex(int line) const
{
if (line < 0 || line >= (int) mLines.GetCount())
{
return wxNOT_FOUND;
}
return mLines[line]->index;
}
//
// Converts a node index to a line index
//
int
KeyView::IndexToLine(int index) const
{
if (index < 0 || index >= (int) mNodes.GetCount())
{
return wxNOT_FOUND;
}
return mNodes[index].line;
}
// //
// Draw the background for a given line // Draw the background for a given line
// //
@ -1052,7 +1203,7 @@ KeyView::OnKillFocus(wxFocusEvent & event)
// Handle the wxEVT_SIZE event // Handle the wxEVT_SIZE event
// //
void void
KeyView::OnSize(wxSizeEvent & event) KeyView::OnSize(wxSizeEvent & WXUNUSED(event))
{ {
// Update horizontal scrollbar // Update horizontal scrollbar
UpdateHScroll(); UpdateHScroll();
@ -1086,7 +1237,7 @@ KeyView::OnScroll(wxScrollWinEvent & event)
void void
KeyView::OnKeyDown(wxKeyEvent & event) KeyView::OnKeyDown(wxKeyEvent & event)
{ {
size_t line = GetSelection(); int line = GetSelection();
int keycode = event.GetKeyCode(); int keycode = event.GetKeyCode();
switch (keycode) switch (keycode)
@ -1096,7 +1247,7 @@ KeyView::OnKeyDown(wxKeyEvent & event)
case WXK_LEFT: case WXK_LEFT:
{ {
// Nothing selected...nothing to do // Nothing selected...nothing to do
if (line == (size_t) wxNOT_FOUND) if (line == wxNOT_FOUND)
{ {
// Allow further processing // Allow further processing
event.Skip(); event.Skip();
@ -1116,13 +1267,13 @@ KeyView::OnKeyDown(wxKeyEvent & event)
size_t topline = GetVisibleBegin(); size_t topline = GetVisibleBegin();
// Refresh the view now that the number of lines have changed // Refresh the view now that the number of lines have changed
RefreshLineCount(); RefreshLines();
// Reset the original top line // Reset the original top line
ScrollToLine(topline); ScrollToLine(topline);
// And make sure current line is still selected // And make sure current line is still selected
SelectLine(line); SelectNode(LineToIndex(line));
} }
else else
{ {
@ -1133,13 +1284,13 @@ KeyView::OnKeyDown(wxKeyEvent & event)
if (mLines[i]->depth < node->depth) if (mLines[i]->depth < node->depth)
{ {
// So select it // So select it
SelectLine(i); SelectNode(LineToIndex(i));
break; break;
} }
} }
} }
// Further processing of the event is not allowed // Further processing of the event is not wanted
// (we didn't call event.Skip() // (we didn't call event.Skip()
} }
break; break;
@ -1149,7 +1300,7 @@ KeyView::OnKeyDown(wxKeyEvent & event)
case WXK_RIGHT: case WXK_RIGHT:
{ {
// Nothing selected...nothing to do // Nothing selected...nothing to do
if (line == (size_t) wxNOT_FOUND) if (line == wxNOT_FOUND)
{ {
// Allow further processing // Allow further processing
event.Skip(); event.Skip();
@ -1165,9 +1316,9 @@ KeyView::OnKeyDown(wxKeyEvent & event)
if (node->isopen) if (node->isopen)
{ {
// But only if there is one // But only if there is one
if (line < mLines.GetCount() - 1) if (line < (int) mLines.GetCount() - 1)
{ {
SelectLine(line + 1); SelectNode(LineToIndex(line + 1));
} }
} }
else else
@ -1180,17 +1331,17 @@ KeyView::OnKeyDown(wxKeyEvent & event)
size_t topline = GetVisibleBegin(); size_t topline = GetVisibleBegin();
// Refresh the view now that the number of lines have changed // Refresh the view now that the number of lines have changed
RefreshLineCount(); RefreshLines();
// Reset the original top line // Reset the original top line
ScrollToLine(topline); ScrollToLine(topline);
// And make sure current line is still selected // And make sure current line is still selected
SelectLine(line); SelectNode(LineToIndex(line));
} }
} }
// Further processing of the event is not allowed // Further processing of the event is not wanted
// (we didn't call event.Skip() // (we didn't call event.Skip()
} }
break; break;
@ -1199,11 +1350,11 @@ KeyView::OnKeyDown(wxKeyEvent & event)
// the keycode // the keycode
default: default:
{ {
int cnt = mLines.GetCount(); int cnt = (int) mLines.GetCount();
bool found = false; bool found = false;
// Search the entire list if not is currently selected // Search the entire list if not is currently selected
if (line == (size_t) wxNOT_FOUND) if (line == wxNOT_FOUND)
{ {
line = cnt; line = cnt;
} }
@ -1217,16 +1368,16 @@ KeyView::OnKeyDown(wxKeyEvent & event)
// Get the string to search based on view type // Get the string to search based on view type
if (mViewType == ViewByKey) if (mViewType == ViewByKey)
{ {
label = GetKey(i); label = GetKey(LineToIndex(i));
} }
else else
{ {
label = GetFullLabel(i); label = GetFullLabel(LineToIndex(i));
} }
// Move selection if they match // Move selection if they match
if (label.Left(1).IsSameAs(keycode, false)) { if (label.Left(1).IsSameAs(keycode, false)) {
SelectLine(i); SelectNode(LineToIndex(i));
found = true; found = true;
@ -1239,23 +1390,23 @@ KeyView::OnKeyDown(wxKeyEvent & event)
if (!found) if (!found)
{ {
// So scan from the start of the list to the current node // So scan from the start of the list to the current node
for (int i = 0; i < (int) line; i++) for (int i = 0; i < line; i++)
{ {
wxString label; wxString label;
// Get the string to search based on view type // Get the string to search based on view type
if (mViewType == ViewByKey) if (mViewType == ViewByKey)
{ {
label = GetKey(i); label = GetKey(LineToIndex(i));
} }
else else
{ {
label = GetFullLabel(i); label = GetFullLabel(LineToIndex(i));
} }
// Move selection if they match // Move selection if they match
if (label.Left(1).IsSameAs(keycode, false)) { if (label.Left(1).IsSameAs(keycode, false)) {
SelectLine(i); SelectNode(LineToIndex(i));
found = true; found = true;
@ -1269,7 +1420,7 @@ KeyView::OnKeyDown(wxKeyEvent & event)
event.Skip(); event.Skip();
} }
// Otherwise, further processing of the event is not allowed // Otherwise, further processing of the event is not wanted
// (we didn't call event.Skip() // (we didn't call event.Skip()
} }
} }
@ -1294,17 +1445,15 @@ KeyView::OnLeftDown(wxMouseEvent & event)
wxPoint pos = event.GetPosition(); wxPoint pos = event.GetPosition();
// And see if it was on a line within the view // And see if it was on a line within the view
size_t line = HitTest(pos); int line = HitTest(pos);
// It was on a line // It was on a line
if ((int) line != wxNOT_FOUND) if (line != wxNOT_FOUND)
{ {
KeyNode *node = mLines[line]; KeyNode *node = mLines[line];
wxCoord indent = KV_LEFT_MARGIN + node->depth * KV_BITMAP_SIZE;
// Toggle the open state if this is a parent node and the click // Toggle the open state if this is a parent node
// happened to the left of the text (I know...lazy ;-)) if (node->isparent)
if (node->isparent && pos.x < indent)
{ {
// Toggle state // Toggle state
node->isopen = !node->isopen; node->isopen = !node->isopen;
@ -1314,13 +1463,13 @@ KeyView::OnLeftDown(wxMouseEvent & event)
size_t topline = GetVisibleBegin(); size_t topline = GetVisibleBegin();
// Refresh the view now that the number of lines have changed // Refresh the view now that the number of lines have changed
RefreshLineCount(); RefreshLines();
// Reset the original top line // Reset the original top line
ScrollToLine(topline); ScrollToLine(topline);
// And make sure current line is still selected // And make sure current line is still selected
SelectLine(line); SelectNode(LineToIndex(line));
} }
} }
@ -1562,8 +1711,8 @@ KeyView::GetValue(int line)
} }
// Get the label and key values // Get the label and key values
wxString value = GetLabel(line); wxString value = GetLabel(LineToIndex(line));
wxString key = GetKey(line); wxString key = GetKey(LineToIndex(line));
// Add the key if it isn't empty // Add the key if it isn't empty
if (!key.IsEmpty()) if (!key.IsEmpty())
@ -1621,7 +1770,7 @@ KeyViewAx::SetCurrentLine(int line)
if (line != wxNOT_FOUND) if (line != wxNOT_FOUND)
{ {
// Convert line number to childId // Convert line number to childId
mLastId = line + 1; LineToId(line + 1, mLastId);
// Send notifications that the line has focus // Send notifications that the line has focus
NotifyEvent(wxACC_EVENT_OBJECT_FOCUS, NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
@ -1642,7 +1791,7 @@ KeyViewAx::SetCurrentLine(int line)
// represents a child or TRUE if it a line // represents a child or TRUE if it a line
// //
bool bool
KeyViewAx::GetLine(int childId, int & line) KeyViewAx::IdToLine(int childId, int & line)
{ {
if (childId == wxACC_SELF) if (childId == wxACC_SELF)
{ {
@ -1655,6 +1804,18 @@ KeyViewAx::GetLine(int childId, int & line)
return true; return true;
} }
//
// Convert the line number to a childId.
//
bool
KeyViewAx::LineToId(int line, int & childId)
{
// Convert to line
childId = line - 1;
return true;
}
// Retrieves the address of an IDispatch interface for the specified child. // Retrieves the address of an IDispatch interface for the specified child.
// All objects must support this property. // All objects must support this property.
wxAccStatus wxAccStatus
@ -1676,7 +1837,7 @@ KeyViewAx::GetChild(int childId, wxAccessible** child)
wxAccStatus wxAccStatus
KeyViewAx::GetChildCount(int *childCount) KeyViewAx::GetChildCount(int *childCount)
{ {
*childCount = mView->GetLineCount(); *childCount = (int) mView->GetLineCount();
return wxACC_OK; return wxACC_OK;
} }
@ -1730,7 +1891,7 @@ KeyViewAx::GetLocation(wxRect & rect, int elementId)
{ {
int line; int line;
if (GetLine(elementId, line)) if (IdToLine(elementId, line))
{ {
wxRect rectLine; wxRect rectLine;
@ -1772,7 +1933,7 @@ KeyViewAx::GetName(int childId, wxString *name)
} }
else else
{ {
if (GetLine(childId, line)) if (IdToLine(childId, line))
{ {
*name = mView->GetValue(line); *name = mView->GetValue(line);
} }
@ -1835,7 +1996,7 @@ KeyViewAx::GetState(int childId, long *state)
wxACC_STATE_SYSTEM_SELECTABLE; wxACC_STATE_SYSTEM_SELECTABLE;
int line; int line;
if (!GetLine(childId, line)) if (!IdToLine(childId, line))
{ {
*state = 0; *state = 0;
return wxACC_FAIL; return wxACC_FAIL;

View File

@ -26,10 +26,9 @@ class KeyNode
public: public:
KeyNode() KeyNode()
{ {
node = -1;
index = -1; index = -1;
depth = -1;
line = -1; line = -1;
depth = -1;
iscat = false; iscat = false;
ispfx = false; ispfx = false;
isparent = false; isparent = false;
@ -37,14 +36,14 @@ public:
} }
public: public:
wxString name;
wxString category; wxString category;
wxString prefix; wxString prefix;
wxString label; wxString label;
wxString key; wxString key;
int node;
int index; int index;
int depth;
int line; int line;
int depth;
bool iscat; bool iscat;
bool ispfx; bool ispfx;
bool isparent; bool isparent;
@ -79,6 +78,7 @@ public:
const wxPoint & pos = wxDefaultPosition, const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize); const wxSize & size = wxDefaultSize);
virtual ~KeyView(); virtual ~KeyView();
wxString GetName() const; // Gets the control name from the base class
void RefreshBindings(const wxArrayString & names, void RefreshBindings(const wxArrayString & names,
const wxArrayString & categories, const wxArrayString & categories,
@ -86,35 +86,49 @@ public:
const wxArrayString & labels, const wxArrayString & labels,
const wxArrayString & keys); const wxArrayString & keys);
wxString GetLabel(int line); int GetSelected() const;
wxString GetFullLabel(int line);
wxString GetKey(int line); wxString GetLabel(int index) const;
int GetIndex(int line); wxString GetFullLabel(int index) const;
int GetIndexByName(const wxString & name) const;
wxString GetName(int index) const;
wxString GetNameByKey(const wxString & key) const;
int GetIndexByKey(const wxString & key) const;
wxString GetKey(int index) const;
bool CanSetKey(int index) const;
bool SetKey(int index, const wxString & key);
bool SetKeyByName(const wxString & name, const wxString & key);
void SetKey(int line, const wxString & key);
void SetView(ViewByType type); void SetView(ViewByType type);
void SetFilter(const wxString & filter); void SetFilter(const wxString & filter);
void ExpandAll(); void ExpandAll();
void CollapseAll(); void CollapseAll();
private: private:
void OnDrawItem(wxDC & dc, const wxRect & rect, size_t line) const; void RecalcExtents();
void UpdateHScroll();
void RefreshLines();
void SelectNode(int index);
int LineToIndex(int line) const;
int IndexToLine(int index) const;
void OnDrawBackground(wxDC & dc, const wxRect & rect, size_t line) const; void OnDrawBackground(wxDC & dc, const wxRect & rect, size_t line) const;
void OnDrawItem(wxDC & dc, const wxRect & rect, size_t line) const;
wxCoord OnMeasureItem(size_t line) const; wxCoord OnMeasureItem(size_t line) const;
void OnLeftDown(wxMouseEvent & event);
void OnKeyDown(wxKeyEvent & event);
void OnSelected(wxCommandEvent & event); void OnSelected(wxCommandEvent & event);
void OnSetFocus(wxFocusEvent & event); void OnSetFocus(wxFocusEvent & event);
void OnKillFocus(wxFocusEvent & event); void OnKillFocus(wxFocusEvent & event);
void OnScroll(wxScrollWinEvent & event);
void OnSize(wxSizeEvent & event); void OnSize(wxSizeEvent & event);
void OnScroll(wxScrollWinEvent & event);
void RecalcExtents(); void OnKeyDown(wxKeyEvent & event);
void RefreshLineCount(); void OnLeftDown(wxMouseEvent & event);
void UpdateHScroll();
void SelectLine(int line);
static int CmpKeyNodeByTree(KeyNode ***n1, KeyNode ***n2); static int CmpKeyNodeByTree(KeyNode ***n1, KeyNode ***n2);
static int CmpKeyNodeByName(KeyNode ***n1, KeyNode ***n2); static int CmpKeyNodeByName(KeyNode ***n1, KeyNode ***n2);
@ -172,7 +186,8 @@ public:
void SetCurrentLine(int row); void SetCurrentLine(int row);
void ListUpdated(); void ListUpdated();
bool GetLine(int childId, int & line); bool LineToId(int line, int & childId);
bool IdToLine(int childId, int & line);
// Retrieves the address of an IDispatch interface for the specified child. // Retrieves the address of an IDispatch interface for the specified child.
// All objects must support this property. // All objects must support this property.