Audacity  2.2.2
Grid.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Grid.cpp
6 
7  Leland Lucius
8 
9 *******************************************************************//*******************************************************************/
15 
16 #include "../Audacity.h"
17 
18 #include <wx/defs.h>
19 #include <wx/choice.h>
20 #include <wx/dc.h>
21 #include <wx/grid.h>
22 #include <wx/intl.h>
23 #include <wx/settings.h>
24 #include <wx/toplevel.h>
25 
26 #include "Grid.h"
27 #include "NumericTextCtrl.h"
28 #include "../SelectedRegion.h"
29 #include "../Internat.h"
30 
32  (NumericConverter::Type type, const wxString &format, double rate)
33 {
34  mType = type;
35  mFormat = format;
36  mRate = rate;
37  mOld = 0.0;
38 }
39 
41 {
42 }
43 
44 void NumericEditor::Create(wxWindow *parent, wxWindowID id, wxEvtHandler *handler)
45 {
46  wxASSERT(parent); // to justify safenew
47  auto control = safenew NumericTextCtrl(
48  parent, wxID_ANY,
49  mType,
50  mFormat,
51  mOld,
52  mRate,
54  .AutoPos(true)
57  );
58  m_control = control;
59 
60  wxGridCellEditor::Create(parent, id, handler);
61 }
62 
63 void NumericEditor::SetSize(const wxRect &rect)
64 {
65  wxSize size = m_control->GetSize();
66 
67  // Always center...looks bad otherwise
68  int x = rect.x + ((rect.width / 2) - (size.x / 2)) + 1;
69  int y = rect.y + ((rect.height / 2) - (size.y / 2)) + 1;
70 
71  m_control->Move(x, y);
72 }
73 
74 void NumericEditor::BeginEdit(int row, int col, wxGrid *grid)
75 {
76  wxGridTableBase *table = grid->GetTable();
77 
78  mOldString = table->GetValue(row, col);
79  mOldString.ToDouble(&mOld);
80 
81  auto control = GetNumericTextControl();
82  control->SetValue(mOld);
83  control->EnableMenu();
84 
85  control->SetFocus();
86 }
87 
88 
89 bool NumericEditor::EndEdit(int WXUNUSED(row), int WXUNUSED(col), const wxGrid *WXUNUSED(grid), const wxString &WXUNUSED(oldval), wxString *newval)
90 {
91  double newtime = GetNumericTextControl()->GetValue();
92  bool changed = newtime != mOld;
93 
94  if (changed) {
95  mValueAsString = wxString::Format(wxT("%g"), newtime);
96  *newval = mValueAsString;
97  }
98 
99  return changed;
100 }
101 
102 void NumericEditor::ApplyEdit(int row, int col, wxGrid *grid)
103 {
104  grid->GetTable()->SetValue(row, col, mValueAsString);
105 }
106 
108 {
110 }
111 
112 bool NumericEditor::IsAcceptedKey(wxKeyEvent &event)
113 {
114  if (wxGridCellEditor::IsAcceptedKey(event)) {
115  if (event.GetKeyCode() == WXK_RETURN) {
116  return true;
117  }
118  }
119 
120  return false;
121 }
122 
123 // Clone is required by wxwidgets; implemented via copy constructor
124 wxGridCellEditor *NumericEditor::Clone() const
125 {
127 }
128 
129 wxString NumericEditor::GetValue() const
130 {
131  return wxString::Format(wxT("%g"), GetNumericTextControl()->GetValue());
132 }
133 
134 wxString NumericEditor::GetFormat() const
135 {
136  return mFormat;
137 }
138 
140 {
141  return mRate;
142 }
143 
144 void NumericEditor::SetFormat(const wxString &format)
145 {
146  mFormat = format;
147 }
148 
149 void NumericEditor::SetRate(double rate)
150 {
151  mRate = rate;
152 }
153 
155 {
156 }
157 
158 void NumericRenderer::Draw(wxGrid &grid,
159  wxGridCellAttr &attr,
160  wxDC &dc,
161  const wxRect &rect,
162  int row,
163  int col,
164  bool isSelected)
165 {
166  wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
167 
168  wxGridTableBase *table = grid.GetTable();
169  NumericEditor *ne =
170  static_cast<NumericEditor *>(grid.GetCellEditor(row, col));
171  wxString tstr;
172 
173  if (ne) {
174  double value;
175 
176  table->GetValue(row, col).ToDouble(&value);
177 
178  NumericTextCtrl tt(&grid, wxID_ANY,
179  mType,
180  ne->GetFormat(),
181  value,
182  ne->GetRate(),
184  wxPoint(10000, 10000)); // create offscreen
185  tstr = tt.GetString();
186 
187  ne->DecRef();
188  }
189 
190  dc.SetBackgroundMode(wxTRANSPARENT);
191 
192  if (grid.IsEnabled())
193  {
194  if (isSelected)
195  {
196  dc.SetTextBackground(grid.GetSelectionBackground());
197  dc.SetTextForeground(grid.GetSelectionForeground());
198  }
199  else
200  {
201  dc.SetTextBackground(attr.GetBackgroundColour());
202  dc.SetTextForeground(attr.GetTextColour());
203  }
204  }
205  else
206  {
207  dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
208  dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
209  }
210 
211  dc.SetFont(attr.GetFont());
212 
213  int hAlign, vAlign;
214 
215  attr.GetAlignment(&hAlign, &vAlign);
216 
217  grid.DrawTextRectangle(dc, tstr, rect, hAlign, vAlign);
218 }
219 
220 wxSize NumericRenderer::GetBestSize(wxGrid &grid,
221  wxGridCellAttr & WXUNUSED(attr),
222  wxDC & WXUNUSED(dc),
223  int row,
224  int col)
225 {
226  wxGridTableBase *table = grid.GetTable();
227  NumericEditor *ne =
228  static_cast<NumericEditor *>(grid.GetCellEditor(row, col));
229  wxSize sz;
230 
231  if (ne) {
232  double value;
233  table->GetValue(row, col).ToDouble(&value);
234  NumericTextCtrl tt(&grid, wxID_ANY,
235  mType,
236  ne->GetFormat(),
237  value,
238  ne->GetRate(),
240  wxPoint(10000, 10000)); // create offscreen
241  sz = tt.GetSize();
242 
243  ne->DecRef();
244  }
245 
246  return sz;
247 }
248 
249 // Clone is required by wxwidgets; implemented via copy constructor
250 wxGridCellRenderer *NumericRenderer::Clone() const
251 {
252  return safenew NumericRenderer{ mType };
253 }
254 
255 ChoiceEditor::ChoiceEditor(size_t count, const wxString choices[])
256 {
257  if (count) {
258  mChoices.Alloc(count);
259  for (size_t n = 0; n < count; n++) {
260  mChoices.Add(choices[n]);
261  }
262  }
263 }
264 
265 ChoiceEditor::ChoiceEditor(const wxArrayString &choices)
266 {
267  mChoices = choices;
268 }
269 
271 {
272  if (m_control)
273  mHandler.DisconnectEvent(m_control);
274 }
275 
276 // Clone is required by wxwidgets; implemented via copy constructor
277 wxGridCellEditor *ChoiceEditor::Clone() const
278 {
279  return safenew ChoiceEditor(mChoices);
280 }
281 
282 void ChoiceEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler)
283 {
284  m_control = safenew wxChoice(parent,
285  id,
286  wxDefaultPosition,
287  wxDefaultSize,
288  mChoices);
289 
290  wxGridCellEditor::Create(parent, id, evtHandler);
291  mHandler.ConnectEvent(m_control);
292 }
293 
294 void ChoiceEditor::SetSize(const wxRect &rect)
295 {
296  wxSize size = m_control->GetSize();
297 
298  // Always center...looks bad otherwise
299  int x = rect.x + ((rect.width / 2) - (size.x / 2)) + 1;
300  int y = rect.y + ((rect.height / 2) - (size.y / 2)) + 1;
301 
302  m_control->Move(x, y);
303 }
304 
305 void ChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
306 {
307  if (!m_control)
308  return;
309 
310  mOld = grid->GetTable()->GetValue(row, col);
311 
312  Choice()->Clear();
313  Choice()->Append(mChoices);
314  Choice()->SetSelection(mChoices.Index(mOld));
315  Choice()->SetFocus();
316 }
317 
318 bool ChoiceEditor::EndEdit(int row, int col, wxGrid *grid)
319 {
320  wxString newvalue;
321  bool changed = EndEdit(row, col, grid, mOld, &newvalue);
322  if (changed) {
323  ApplyEdit(row, col, grid);
324  }
325  return changed;
326 }
327 
328 bool ChoiceEditor::EndEdit(int WXUNUSED(row), int WXUNUSED(col),
329  const wxGrid* WXUNUSED(grid),
330  const wxString &WXUNUSED(oldval), wxString *newval)
331 {
332  int sel = Choice()->GetSelection();
333 
334  // This can happen if the wxChoice control is displayed and the list of choices get changed
335  if ((sel < 0) || (sel >= (int)(mChoices.GetCount())))
336  {
337  return false;
338  }
339 
340  wxString val = mChoices[sel];
341  bool changed = val != mOld;
342 
343  if (changed)
344  {
345  mValueAsString = val;
346  *newval = val;
347  }
348 
349  return changed;
350 }
351 
352 void ChoiceEditor::ApplyEdit(int row, int col, wxGrid *grid)
353 {
354  grid->GetTable()->SetValue(row, col, mValueAsString);
355 }
356 
358 {
359  Choice()->SetSelection(mChoices.Index(mOld));
360 }
361 
362 void ChoiceEditor::SetChoices(const wxArrayString &choices)
363 {
364  mChoices = choices;
365 }
366 
367 wxString ChoiceEditor::GetValue() const
368 {
369  return mChoices[Choice()->GetSelection()];
370 }
371 
375 
376 BEGIN_EVENT_TABLE(Grid, wxGrid)
377  EVT_SET_FOCUS(Grid::OnSetFocus)
378  EVT_KEY_DOWN(Grid::OnKeyDown)
379  EVT_GRID_SELECT_CELL(Grid::OnSelectCell)
381 
382 Grid::Grid(wxWindow *parent,
383  wxWindowID id,
384  const wxPoint& pos,
385  const wxSize& size,
386  long style,
387  const wxString& name)
388 : wxGrid(parent, id, pos, size, style | wxWANTS_CHARS, name)
389 {
390 #if wxUSE_ACCESSIBILITY
391  GetGridWindow()->SetAccessible(mAx = safenew GridAx(this));
392 #endif
393 
394  // RegisterDataType takes ownership of renderer and editor
395 
396  RegisterDataType(GRID_VALUE_TIME,
399  { NumericTextCtrl::TIME, wxT("seconds"), 44100.0 });
400 
401  RegisterDataType(GRID_VALUE_FREQUENCY,
404  { NumericTextCtrl::FREQUENCY, wxT("Hz"), 44100.0 });
405 
406  RegisterDataType(GRID_VALUE_CHOICE,
407  safenew wxGridCellStringRenderer,
409 }
410 
412 {
413 #if wxUSE_ACCESSIBILITY
414  int cnt = mChildren.size();
415  while (cnt--) {
416  // PRL: I found this loop destroying right-to-left.
417  // Is the sequence of destruction important?
418  mChildren.pop_back();
419  }
420 #endif
421 }
422 
423 void Grid::OnSetFocus(wxFocusEvent &event)
424 {
425  event.Skip();
426 
427 #if wxUSE_ACCESSIBILITY
428  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
429 #endif
430 }
431 
432 void Grid::OnSelectCell(wxGridEvent &event)
433 {
434  event.Skip();
435 
436 #if wxUSE_ACCESSIBILITY
437  mAx->SetCurrentCell(event.GetRow(), event.GetCol());
438 #endif
439 }
440 
441 void Grid::OnKeyDown(wxKeyEvent &event)
442 {
443  switch (event.GetKeyCode())
444  {
445  case WXK_LEFT:
446  case WXK_RIGHT:
447  {
448  int rows = GetNumberRows();
449  int cols = GetNumberCols();
450  int crow = GetGridCursorRow();
451  int ccol = GetGridCursorCol();
452 
453  if (event.GetKeyCode() == WXK_LEFT) {
454  if (crow == 0 && ccol == 0) {
455  // do nothing
456  }
457  else if (ccol == 0) {
458  SetGridCursor(crow - 1, cols - 1);
459  }
460  else {
461  SetGridCursor(crow, ccol - 1);
462  }
463  }
464  else {
465  if (crow == rows - 1 && ccol == cols - 1) {
466  // do nothing
467  }
468  else if (ccol == cols - 1) {
469  SetGridCursor(crow + 1, 0);
470  }
471  else {
472  SetGridCursor(crow, ccol + 1);
473  }
474  }
475 
476 #if wxUSE_ACCESSIBILITY
477  // Make sure the NEW cell is made available to the screen reader
478  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
479 #endif
480  }
481  break;
482 
483  case WXK_TAB:
484  {
485  int rows = GetNumberRows();
486  int cols = GetNumberCols();
487  int crow = GetGridCursorRow();
488  int ccol = GetGridCursorCol();
489 
490  if (event.ControlDown()) {
491  int flags = wxNavigationKeyEvent::FromTab |
492  ( event.ShiftDown() ?
493  wxNavigationKeyEvent::IsBackward :
494  wxNavigationKeyEvent::IsForward );
495  Navigate(flags);
496  return;
497  }
498  else if (event.ShiftDown()) {
499  if (crow == 0 && ccol == 0) {
500  Navigate(wxNavigationKeyEvent::FromTab | wxNavigationKeyEvent::IsBackward);
501  return;
502  }
503  else if (ccol == 0) {
504  SetGridCursor(crow - 1, cols - 1);
505  }
506  else {
507  SetGridCursor(crow, ccol - 1);
508  }
509  }
510  else {
511  if (crow == rows - 1 && ccol == cols - 1) {
512  Navigate(wxNavigationKeyEvent::FromTab | wxNavigationKeyEvent::IsForward);
513  return;
514  }
515  else if (ccol == cols - 1) {
516  SetGridCursor(crow + 1, 0);
517  }
518  else {
519  SetGridCursor(crow, ccol + 1);
520  }
521  }
522  MakeCellVisible(GetGridCursorRow(), GetGridCursorCol());
523 
524 #if wxUSE_ACCESSIBILITY
525  // Make sure the NEW cell is made available to the screen reader
526  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
527 #endif
528  }
529  break;
530 
531  case WXK_RETURN:
532  case WXK_NUMPAD_ENTER:
533  {
534  if (!IsCellEditControlShown()) {
535  wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
536  wxWindow *def = tlw->GetDefaultItem();
537  if (def && def->IsEnabled()) {
538  wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED,
539  def->GetId());
540  GetParent()->GetEventHandler()->ProcessEvent(cevent);
541  }
542  }
543  else {
544  wxGrid::OnKeyDown(event);
545 
546  // This looks strange, but what it does is selects the cell when
547  // enter is pressed after editing. Without it, Jaws and Window-Eyes
548  // do not speak the NEW cell contents (the one below the edited one).
549  SetGridCursor(GetGridCursorRow(), GetGridCursorCol());
550  }
551  break;
552  }
553 
554  default:
555  wxGrid::OnKeyDown(event);
556  break;
557  }
558 }
559 
560 #if wxUSE_ACCESSIBILITY
561 void Grid::ClearGrid()
562 {
563  wxGrid::ClearGrid();
564 
565  mAx->TableUpdated();
566 
567  return;
568 }
569 
570 bool Grid::InsertRows(int pos, int numRows, bool updateLabels)
571 {
572  bool res = wxGrid::InsertRows(pos, numRows, updateLabels);
573 
574  mAx->TableUpdated();
575 
576  return res;
577 }
578 
579 bool Grid::AppendRows(int numRows, bool updateLabels)
580 {
581  bool res = wxGrid::AppendRows(numRows, updateLabels);
582 
583  mAx->TableUpdated();
584 
585  return res;
586 }
587 
588 bool Grid::DeleteRows(int pos, int numRows, bool updateLabels)
589 {
590  bool res = wxGrid::DeleteRows(pos, numRows, updateLabels);
591 
592  mAx->TableUpdated();
593 
594  return res;
595 }
596 
597 bool Grid::InsertCols(int pos, int numCols, bool updateLabels)
598 {
599  bool res = wxGrid::InsertCols(pos, numCols, updateLabels);
600 
601  mAx->TableUpdated();
602 
603  return res;
604 }
605 
606 bool Grid::AppendCols(int numCols, bool updateLabels)
607 {
608  bool res = wxGrid::AppendCols(numCols, updateLabels);
609 
610  mAx->TableUpdated();
611 
612  return res;
613 }
614 
615 bool Grid::DeleteCols(int pos, int numCols, bool updateLabels)
616 {
617  bool res = wxGrid::DeleteCols(pos, numCols, updateLabels);
618 
619  mAx->TableUpdated();
620 
621  return res;
622 }
623 
624 GridAx::GridAx(Grid *grid)
625 : wxWindowAccessible(grid->GetGridWindow())
626 {
627  mGrid = grid;
628  mLastId = -1;
629 }
630 
631 void GridAx::TableUpdated()
632 {
633  NotifyEvent(wxACC_EVENT_OBJECT_REORDER,
634  mGrid->GetGridWindow(),
635  wxOBJID_CLIENT,
636  0);
637 }
638 
639 void GridAx::SetCurrentCell(int row, int col)
640 {
641  int id = (((row * mGrid->GetNumberCols()) + col) + 1);
642 
643  if (mLastId != -1) {
644  NotifyEvent(wxACC_EVENT_OBJECT_SELECTIONREMOVE,
645  mGrid->GetGridWindow(),
646  wxOBJID_CLIENT,
647  mLastId);
648  }
649 
650  NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
651  mGrid->GetGridWindow(),
652  wxOBJID_CLIENT,
653  id);
654 
655  NotifyEvent(wxACC_EVENT_OBJECT_SELECTION,
656  mGrid->GetGridWindow(),
657  wxOBJID_CLIENT,
658  id);
659 
660  mLastId = id;
661 }
662 
663 bool GridAx::GetRowCol(int childId, int & row, int & col)
664 {
665  if (childId == wxACC_SELF) {
666  return false;
667  }
668 
669  int cols = mGrid->GetNumberCols();
670  int id = childId - 1;
671 
672  row = id / cols;
673  col = id % cols;
674 
675  return true;
676 }
677 
678 // Retrieves the address of an IDispatch interface for the specified child.
679 // All objects must support this property.
680 wxAccStatus GridAx::GetChild(int childId, wxAccessible** child)
681 {
682  if (childId == wxACC_SELF) {
683  *child = this;
684  }
685  else {
686  *child = NULL;
687  }
688 
689  return wxACC_OK;
690 }
691 
692 // Gets the number of children.
693 wxAccStatus GridAx::GetChildCount(int *childCount)
694 {
695  *childCount = mGrid->GetNumberRows() * mGrid->GetNumberCols();
696 
697  return wxACC_OK;
698 }
699 
700 // Gets the default action for this object (0) or > 0 (the action for a child).
701 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
702 // string if there is no action.
703 // The retrieved string describes the action that is performed on an object,
704 // not what the object does as a result. For example, a toolbar button that prints
705 // a document has a default action of "Press" rather than "Prints the current document."
706 wxAccStatus GridAx::GetDefaultAction(int WXUNUSED(childId), wxString *actionName)
707 {
708  actionName->Clear();
709 
710  return wxACC_OK;
711 }
712 
713 // Returns the description for this object or a child.
714 wxAccStatus GridAx::GetDescription(int WXUNUSED(childId), wxString *description)
715 {
716  description->Clear();
717 
718  return wxACC_OK;
719 }
720 
721 // Returns help text for this object or a child, similar to tooltip text.
722 wxAccStatus GridAx::GetHelpText(int WXUNUSED(childId), wxString *helpText)
723 {
724  helpText->Clear();
725 
726  return wxACC_OK;
727 }
728 
729 // Returns the keyboard shortcut for this object or child.
730 // Return e.g. ALT+K
731 wxAccStatus GridAx::GetKeyboardShortcut(int WXUNUSED(childId), wxString *shortcut)
732 {
733  shortcut->Clear();
734 
735  return wxACC_OK;
736 }
737 
738 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
739 // rect is in screen coordinates.
740 wxAccStatus GridAx::GetLocation(wxRect & rect, int elementId)
741 {
742  wxRect r;
743  int row;
744  int col;
745 
746  if (GetRowCol(elementId, row, col)) {
747  rect = mGrid->CellToRect(row, col);
748  rect.SetPosition(mGrid->GetGridWindow()->ClientToScreen(rect.GetPosition()));
749  }
750  else {
751  rect = mGrid->GetRect();
752  rect.SetPosition(mGrid->GetParent()->ClientToScreen(rect.GetPosition()));
753  }
754 
755  return wxACC_OK;
756 }
757 
758 // Gets the name of the specified object.
759 wxAccStatus GridAx::GetName(int childId, wxString *name)
760 {
761  int row;
762  int col;
763 
764  if (GetRowCol(childId, row, col)) {
765  wxString n = mGrid->GetColLabelValue(col);
766  wxString v = mGrid->GetCellValue(row, col);
767  if (v.IsEmpty()) {
768  v = _("Empty");
769  }
770 
771  // Hack to provide a more intelligible response
772  NumericEditor *dt =
773  static_cast<NumericEditor *>(mGrid->GetDefaultEditorForType(GRID_VALUE_TIME));
774  NumericEditor *df =
775  static_cast<NumericEditor *>(mGrid->GetDefaultEditorForType(GRID_VALUE_FREQUENCY));
776  NumericEditor *c =
777  static_cast<NumericEditor *>(mGrid->GetCellEditor(row, col));
778 
779  if (c && dt && df && ( c == dt || c == df)) {
780  double value;
781  v.ToDouble(&value);
783  c->GetFormat(),
784  value,
785  c->GetRate() );
786 
787  v = converter.GetString();
788  }
789 
790  if (c)
791  c->DecRef();
792  if (dt)
793  dt->DecRef();
794  if (df)
795  df->DecRef();
796 
797  *name = n + wxT(" ") + v;
798  }
799 
800  return wxACC_OK;
801 }
802 
803 wxAccStatus GridAx::GetParent(wxAccessible ** WXUNUSED(parent))
804 {
805  return wxACC_NOT_IMPLEMENTED;
806 }
807 
808 // Returns a role constant.
809 wxAccStatus GridAx::GetRole(int childId, wxAccRole *role)
810 {
811  if (childId == wxACC_SELF) {
812 #if defined(__WXMSW__)
813  *role = wxROLE_SYSTEM_TABLE;
814 #endif
815 
816 #if defined(__WXMAC__)
817  *role = wxROLE_SYSTEM_GROUPING;
818 #endif
819  }
820  else {
821  *role = wxROLE_SYSTEM_TEXT;
822  }
823 
824  return wxACC_OK;
825 }
826 
827 // Gets a variant representing the selected children
828 // of this object.
829 // Acceptable values:
830 // - a null variant (IsNull() returns TRUE)
831 // - a list variant (GetType() == wxT("list"))
832 // - an integer representing the selected child element,
833 // or 0 if this object is selected (GetType() == wxT("long"))
834 // - a "void*" pointer to a wxAccessible child object
835 wxAccStatus GridAx::GetSelections(wxVariant * WXUNUSED(selections))
836 {
837  return wxACC_NOT_IMPLEMENTED;
838 }
839 
840 // Returns a state constant.
841 wxAccStatus GridAx::GetState(int childId, long *state)
842 {
843  int flag = wxACC_STATE_SYSTEM_FOCUSABLE |
844  wxACC_STATE_SYSTEM_SELECTABLE;
845  int col;
846  int row;
847 
848  if (!GetRowCol(childId, row, col)) {
849  *state = 0;
850  return wxACC_FAIL;
851  }
852 
853 #if defined(__WXMSW__)
854  flag |= wxACC_STATE_SYSTEM_FOCUSED |
855  wxACC_STATE_SYSTEM_SELECTED;
856 
857  if (mGrid->IsReadOnly(row, col)) {
858  flag = wxACC_STATE_SYSTEM_UNAVAILABLE;
859  }
860 #endif
861 
862 #if defined(__WXMAC__)
863  if (mGrid->IsInSelection(row, col)) {
864  flag |= wxACC_STATE_SYSTEM_SELECTED;
865  }
866 
867  if (mGrid->GetGridCursorRow() == row && mGrid->GetGridCursorCol() == col) {
868  flag |= wxACC_STATE_SYSTEM_FOCUSED;
869  }
870 
871  if (mGrid->IsReadOnly(row, col)) {
872  flag |= wxACC_STATE_SYSTEM_UNAVAILABLE;
873  }
874 #endif
875 
876  *state = flag;
877 
878  return wxACC_OK;
879 }
880 
881 // Returns a localized string representing the value for the object
882 // or child.
883 #if defined(__WXMAC__)
884 wxAccStatus GridAx::GetValue(int childId, wxString *strValue)
885 #else
886 wxAccStatus GridAx::GetValue(int WXUNUSED(childId), wxString *strValue)
887 #endif
888 {
889  strValue->Clear();
890 
891 #if defined(__WXMSW__)
892  return wxACC_OK;
893 #endif
894 
895 #if defined(__WXMAC__)
896  return GetName(childId, strValue);
897 #endif
898 }
899 
900 #if defined(__WXMAC__)
901 // Selects the object or child.
902 wxAccStatus GridAx::Select(int childId, wxAccSelectionFlags selectFlags)
903 {
904  int row;
905  int col;
906 
907  if (GetRowCol(childId, row, col)) {
908 
909  if (selectFlags & wxACC_SEL_TAKESELECTION) {
910  mGrid->SetGridCursor(row, col);
911  }
912 
913  mGrid->SelectBlock(row, col, row, col, selectFlags & wxACC_SEL_ADDSELECTION);
914  }
915 
916  return wxACC_OK;
917 }
918 #endif
919 
920 // Gets the window with the keyboard focus.
921 // If childId is 0 and child is NULL, no object in
922 // this subhierarchy has the focus.
923 // If this object has the focus, child should be 'this'.
924 wxAccStatus GridAx::GetFocus(int * WXUNUSED(childId), wxAccessible **child)
925 {
926  *child = this;
927 
928  return wxACC_OK;
929 }
930 
931 #endif // wxUSE_ACCESSIBILITY
void ApplyEdit(int row, int col, wxGrid *grid)
Definition: Grid.cpp:352
void Create(wxWindow *parent, wxWindowID id, wxEvtHandler *handler) override
Definition: Grid.cpp:44
bool EndEdit(int row, int col, wxGrid *grid)
Definition: Grid.cpp:318
Options & InvalidValue(bool has, double value=-1.0)
~Grid()
Definition: Grid.cpp:411
void SetSize(const wxRect &rect)
Definition: Grid.cpp:294
#define GRID_VALUE_TIME
Definition: Grid.h:38
void OnSetFocus(wxFocusEvent &event)
Definition: Grid.cpp:423
#define GRID_VALUE_CHOICE
Definition: Grid.h:123
void DisconnectEvent(wxWindow *w)
Definition: Grid.h:173
ChoiceEditor::FocusHandler mHandler
~NumericRenderer() override
Definition: Grid.cpp:154
void BeginEdit(int row, int col, wxGrid *grid)
Definition: Grid.cpp:305
wxArrayString mChoices
Definition: Grid.h:183
wxChoice * Choice() const
Definition: Grid.h:159
wxString mOldString
Definition: Grid.h:82
void OnKeyDown(wxKeyEvent &event)
Definition: Grid.cpp:441
double mOld
Definition: Grid.h:81
#define safenew
Definition: Audacity.h:223
~ChoiceEditor()
Definition: Grid.cpp:270
#define GRID_VALUE_FREQUENCY
Definition: Grid.h:39
NumericEditor(NumericConverter::Type type, const wxString &format, double rate)
Definition: Grid.cpp:32
bool EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval) override
Definition: Grid.cpp:89
double mRate
Definition: Grid.h:79
int format
Definition: ExportPCM.cpp:56
NumericConverter provides the advanced formatting control used in the selection bar of Audacity...
wxString mFormat
Definition: Grid.h:78
wxString GetFormat() const
Definition: Grid.cpp:134
void BeginEdit(int row, int col, wxGrid *grid) override
Definition: Grid.cpp:74
void Create(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler) override
Definition: Grid.cpp:282
double GetRate() const
Definition: Grid.cpp:139
void ConnectEvent(wxWindow *w)
Definition: Grid.h:167
void SetChoices(const wxArrayString &choices)
Definition: Grid.cpp:362
wxString mValueAsString
Definition: Grid.h:83
void SetFormat(const wxString &format)
Definition: Grid.cpp:144
void SetValue(double newValue)
NumericConverter::Type mType
Definition: Grid.h:80
NumericConverter::Type mType
Definition: Grid.h:115
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
void ApplyEdit(int row, int col, wxGrid *grid) override
Definition: Grid.cpp:102
void Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, const wxRect &rect, int row, int col, bool isSelected) override
Definition: Grid.cpp:158
void Reset()
Definition: Grid.cpp:357
void OnSelectCell(wxGridEvent &event)
Definition: Grid.cpp:432
const wxChar * name
Definition: Distortion.cpp:94
ChoiceEditor(size_t count=0, const wxString choices[]=NULL)
Definition: Grid.cpp:255
wxGridCellRenderer * Clone() const override
Definition: Grid.cpp:250
wxGridCellEditor * Clone() const override
Definition: Grid.cpp:124
bool IsAcceptedKey(wxKeyEvent &event) override
Definition: Grid.cpp:112
wxSize GetBestSize(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, int row, int col) override
Definition: Grid.cpp:220
~NumericEditor()
Definition: Grid.cpp:40
Options & AutoPos(bool value)
wxString mValueAsString
Definition: Grid.h:185
NumericTextCtrl * GetNumericTextControl() const
Definition: Grid.h:73
wxGridCellEditor * Clone() const override
Definition: Grid.cpp:277
END_EVENT_TABLE()
Supplies an accessible grid based on wxGrid.
Definition: Grid.h:194
void Reset() override
Definition: Grid.cpp:107
void SetRate(double rate)
Definition: Grid.cpp:149
static const int UndefinedFrequency
wxString GetValue() const override
Definition: Grid.cpp:129
wxString mOld
Definition: Grid.h:184
wxString GetValue() const
Definition: Grid.cpp:367
void SetSize(const wxRect &rect) override
Definition: Grid.cpp:63