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 NumericFormatId &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 
135 {
136  return mFormat;
137 }
138 
140 {
141  return mRate;
142 }
143 
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,
400  NumericConverter::SecondsFormat(), 44100.0 });
401 
402  RegisterDataType(GRID_VALUE_FREQUENCY,
406  NumericConverter::HertzFormat(), 44100.0 });
407 
408  RegisterDataType(GRID_VALUE_CHOICE,
409  safenew wxGridCellStringRenderer,
411 }
412 
414 {
415 #if wxUSE_ACCESSIBILITY
416  int cnt = mChildren.size();
417  while (cnt--) {
418  // PRL: I found this loop destroying right-to-left.
419  // Is the sequence of destruction important?
420  mChildren.pop_back();
421  }
422 #endif
423 }
424 
425 void Grid::OnSetFocus(wxFocusEvent &event)
426 {
427  event.Skip();
428 
429 #if wxUSE_ACCESSIBILITY
430  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
431 #endif
432 }
433 
434 void Grid::OnSelectCell(wxGridEvent &event)
435 {
436  event.Skip();
437 
438 #if wxUSE_ACCESSIBILITY
439  mAx->SetCurrentCell(event.GetRow(), event.GetCol());
440 #endif
441 }
442 
443 void Grid::OnKeyDown(wxKeyEvent &event)
444 {
445  switch (event.GetKeyCode())
446  {
447  case WXK_LEFT:
448  case WXK_RIGHT:
449  {
450  int rows = GetNumberRows();
451  int cols = GetNumberCols();
452  int crow = GetGridCursorRow();
453  int ccol = GetGridCursorCol();
454 
455  if (event.GetKeyCode() == WXK_LEFT) {
456  if (crow == 0 && ccol == 0) {
457  // do nothing
458  }
459  else if (ccol == 0) {
460  SetGridCursor(crow - 1, cols - 1);
461  }
462  else {
463  SetGridCursor(crow, ccol - 1);
464  }
465  }
466  else {
467  if (crow == rows - 1 && ccol == cols - 1) {
468  // do nothing
469  }
470  else if (ccol == cols - 1) {
471  SetGridCursor(crow + 1, 0);
472  }
473  else {
474  SetGridCursor(crow, ccol + 1);
475  }
476  }
477 
478 #if wxUSE_ACCESSIBILITY
479  // Make sure the NEW cell is made available to the screen reader
480  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
481 #endif
482  }
483  break;
484 
485  case WXK_TAB:
486  {
487  int rows = GetNumberRows();
488  int cols = GetNumberCols();
489  int crow = GetGridCursorRow();
490  int ccol = GetGridCursorCol();
491 
492  if (event.ControlDown()) {
493  int flags = wxNavigationKeyEvent::FromTab |
494  ( event.ShiftDown() ?
495  wxNavigationKeyEvent::IsBackward :
496  wxNavigationKeyEvent::IsForward );
497  Navigate(flags);
498  return;
499  }
500  else if (event.ShiftDown()) {
501  if (crow == 0 && ccol == 0) {
502  Navigate(wxNavigationKeyEvent::FromTab | wxNavigationKeyEvent::IsBackward);
503  return;
504  }
505  else if (ccol == 0) {
506  SetGridCursor(crow - 1, cols - 1);
507  }
508  else {
509  SetGridCursor(crow, ccol - 1);
510  }
511  }
512  else {
513  if (crow == rows - 1 && ccol == cols - 1) {
514  Navigate(wxNavigationKeyEvent::FromTab | wxNavigationKeyEvent::IsForward);
515  return;
516  }
517  else if (ccol == cols - 1) {
518  SetGridCursor(crow + 1, 0);
519  }
520  else {
521  SetGridCursor(crow, ccol + 1);
522  }
523  }
524  MakeCellVisible(GetGridCursorRow(), GetGridCursorCol());
525 
526 #if wxUSE_ACCESSIBILITY
527  // Make sure the NEW cell is made available to the screen reader
528  mAx->SetCurrentCell(GetGridCursorRow(), GetGridCursorCol());
529 #endif
530  }
531  break;
532 
533  case WXK_RETURN:
534  case WXK_NUMPAD_ENTER:
535  {
536  if (!IsCellEditControlShown()) {
537  wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
538  wxWindow *def = tlw->GetDefaultItem();
539  if (def && def->IsEnabled()) {
540  wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED,
541  def->GetId());
542  GetParent()->GetEventHandler()->ProcessEvent(cevent);
543  }
544  }
545  else {
546  wxGrid::OnKeyDown(event);
547 
548  // This looks strange, but what it does is selects the cell when
549  // enter is pressed after editing. Without it, Jaws and Window-Eyes
550  // do not speak the NEW cell contents (the one below the edited one).
551  SetGridCursor(GetGridCursorRow(), GetGridCursorCol());
552  }
553  break;
554  }
555 
556  default:
557  wxGrid::OnKeyDown(event);
558  break;
559  }
560 }
561 
562 #if wxUSE_ACCESSIBILITY
563 void Grid::ClearGrid()
564 {
565  wxGrid::ClearGrid();
566 
567  mAx->TableUpdated();
568 
569  return;
570 }
571 
572 bool Grid::InsertRows(int pos, int numRows, bool updateLabels)
573 {
574  bool res = wxGrid::InsertRows(pos, numRows, updateLabels);
575 
576  mAx->TableUpdated();
577 
578  return res;
579 }
580 
581 bool Grid::AppendRows(int numRows, bool updateLabels)
582 {
583  bool res = wxGrid::AppendRows(numRows, updateLabels);
584 
585  mAx->TableUpdated();
586 
587  return res;
588 }
589 
590 bool Grid::DeleteRows(int pos, int numRows, bool updateLabels)
591 {
592  bool res = wxGrid::DeleteRows(pos, numRows, updateLabels);
593 
594  mAx->TableUpdated();
595 
596  return res;
597 }
598 
599 bool Grid::InsertCols(int pos, int numCols, bool updateLabels)
600 {
601  bool res = wxGrid::InsertCols(pos, numCols, updateLabels);
602 
603  mAx->TableUpdated();
604 
605  return res;
606 }
607 
608 bool Grid::AppendCols(int numCols, bool updateLabels)
609 {
610  bool res = wxGrid::AppendCols(numCols, updateLabels);
611 
612  mAx->TableUpdated();
613 
614  return res;
615 }
616 
617 bool Grid::DeleteCols(int pos, int numCols, bool updateLabels)
618 {
619  bool res = wxGrid::DeleteCols(pos, numCols, updateLabels);
620 
621  mAx->TableUpdated();
622 
623  return res;
624 }
625 
626 GridAx::GridAx(Grid *grid)
627 : WindowAccessible(grid->GetGridWindow())
628 {
629  mGrid = grid;
630  mLastId = -1;
631 }
632 
633 void GridAx::TableUpdated()
634 {
635  NotifyEvent(wxACC_EVENT_OBJECT_REORDER,
636  mGrid->GetGridWindow(),
637  wxOBJID_CLIENT,
638  0);
639 }
640 
641 void GridAx::SetCurrentCell(int row, int col)
642 {
643  int id = (((row * mGrid->GetNumberCols()) + col) + 1);
644 
645  if (mLastId != -1) {
646  NotifyEvent(wxACC_EVENT_OBJECT_SELECTIONREMOVE,
647  mGrid->GetGridWindow(),
648  wxOBJID_CLIENT,
649  mLastId);
650  }
651 
652  NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
653  mGrid->GetGridWindow(),
654  wxOBJID_CLIENT,
655  id);
656 
657  NotifyEvent(wxACC_EVENT_OBJECT_SELECTION,
658  mGrid->GetGridWindow(),
659  wxOBJID_CLIENT,
660  id);
661 
662  mLastId = id;
663 }
664 
665 bool GridAx::GetRowCol(int childId, int & row, int & col)
666 {
667  if (childId == wxACC_SELF) {
668  return false;
669  }
670 
671  int cols = mGrid->GetNumberCols();
672  int id = childId - 1;
673 
674  row = id / cols;
675  col = id % cols;
676 
677  return true;
678 }
679 
680 // Retrieves the address of an IDispatch interface for the specified child.
681 // All objects must support this property.
682 wxAccStatus GridAx::GetChild(int childId, wxAccessible** child)
683 {
684  if (childId == wxACC_SELF) {
685  *child = this;
686  }
687  else {
688  *child = NULL;
689  }
690 
691  return wxACC_OK;
692 }
693 
694 // Gets the number of children.
695 wxAccStatus GridAx::GetChildCount(int *childCount)
696 {
697  *childCount = mGrid->GetNumberRows() * mGrid->GetNumberCols();
698 
699  return wxACC_OK;
700 }
701 
702 // Gets the default action for this object (0) or > 0 (the action for a child).
703 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
704 // string if there is no action.
705 // The retrieved string describes the action that is performed on an object,
706 // not what the object does as a result. For example, a toolbar button that prints
707 // a document has a default action of "Press" rather than "Prints the current document."
708 wxAccStatus GridAx::GetDefaultAction(int WXUNUSED(childId), wxString *actionName)
709 {
710  actionName->Clear();
711 
712  return wxACC_OK;
713 }
714 
715 // Returns the description for this object or a child.
716 wxAccStatus GridAx::GetDescription(int WXUNUSED(childId), wxString *description)
717 {
718  description->Clear();
719 
720  return wxACC_OK;
721 }
722 
723 // Returns help text for this object or a child, similar to tooltip text.
724 wxAccStatus GridAx::GetHelpText(int WXUNUSED(childId), wxString *helpText)
725 {
726  helpText->Clear();
727 
728  return wxACC_OK;
729 }
730 
731 // Returns the keyboard shortcut for this object or child.
732 // Return e.g. ALT+K
733 wxAccStatus GridAx::GetKeyboardShortcut(int WXUNUSED(childId), wxString *shortcut)
734 {
735  shortcut->Clear();
736 
737  return wxACC_OK;
738 }
739 
740 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
741 // rect is in screen coordinates.
742 wxAccStatus GridAx::GetLocation(wxRect & rect, int elementId)
743 {
744  wxRect r;
745  int row;
746  int col;
747 
748  if (GetRowCol(elementId, row, col)) {
749  rect = mGrid->CellToRect(row, col);
750  rect.SetPosition(mGrid->GetGridWindow()->ClientToScreen(rect.GetPosition()));
751  }
752  else {
753  rect = mGrid->GetRect();
754  rect.SetPosition(mGrid->GetParent()->ClientToScreen(rect.GetPosition()));
755  }
756 
757  return wxACC_OK;
758 }
759 
760 // Gets the name of the specified object.
761 wxAccStatus GridAx::GetName(int childId, wxString *name)
762 {
763  int row;
764  int col;
765 
766  if (GetRowCol(childId, row, col)) {
767  wxString n = mGrid->GetColLabelValue(col);
768  wxString v = mGrid->GetCellValue(row, col);
769  if (v.IsEmpty()) {
770  v = _("Empty");
771  }
772 
773  // Hack to provide a more intelligible response
774  NumericEditor *dt =
775  static_cast<NumericEditor *>(mGrid->GetDefaultEditorForType(GRID_VALUE_TIME));
776  NumericEditor *df =
777  static_cast<NumericEditor *>(mGrid->GetDefaultEditorForType(GRID_VALUE_FREQUENCY));
778  NumericEditor *c =
779  static_cast<NumericEditor *>(mGrid->GetCellEditor(row, col));
780 
781  if (c && dt && df && ( c == dt || c == df)) {
782  double value;
783  v.ToDouble(&value);
785  c->GetFormat(),
786  value,
787  c->GetRate() );
788 
789  v = converter.GetString();
790  }
791 
792  if (c)
793  c->DecRef();
794  if (dt)
795  dt->DecRef();
796  if (df)
797  df->DecRef();
798 
799  *name = n + wxT(" ") + v;
800  }
801 
802  return wxACC_OK;
803 }
804 
805 wxAccStatus GridAx::GetParent(wxAccessible ** WXUNUSED(parent))
806 {
807  return wxACC_NOT_IMPLEMENTED;
808 }
809 
810 // Returns a role constant.
811 wxAccStatus GridAx::GetRole(int childId, wxAccRole *role)
812 {
813  if (childId == wxACC_SELF) {
814 #if defined(__WXMSW__)
815  *role = wxROLE_SYSTEM_TABLE;
816 #endif
817 
818 #if defined(__WXMAC__)
819  *role = wxROLE_SYSTEM_GROUPING;
820 #endif
821  }
822  else {
823  *role = wxROLE_SYSTEM_TEXT;
824  }
825 
826  return wxACC_OK;
827 }
828 
829 // Gets a variant representing the selected children
830 // of this object.
831 // Acceptable values:
832 // - a null variant (IsNull() returns TRUE)
833 // - a list variant (GetType() == wxT("list"))
834 // - an integer representing the selected child element,
835 // or 0 if this object is selected (GetType() == wxT("long"))
836 // - a "void*" pointer to a wxAccessible child object
837 wxAccStatus GridAx::GetSelections(wxVariant * WXUNUSED(selections))
838 {
839  return wxACC_NOT_IMPLEMENTED;
840 }
841 
842 // Returns a state constant.
843 wxAccStatus GridAx::GetState(int childId, long *state)
844 {
845  int flag = wxACC_STATE_SYSTEM_FOCUSABLE |
846  wxACC_STATE_SYSTEM_SELECTABLE;
847  int col;
848  int row;
849 
850  if (!GetRowCol(childId, row, col)) {
851  *state = 0;
852  return wxACC_FAIL;
853  }
854 
855 #if defined(__WXMSW__)
856  flag |= wxACC_STATE_SYSTEM_FOCUSED |
857  wxACC_STATE_SYSTEM_SELECTED;
858 
859  if (mGrid->IsReadOnly(row, col)) {
860  flag = wxACC_STATE_SYSTEM_UNAVAILABLE;
861  }
862 #endif
863 
864 #if defined(__WXMAC__)
865  if (mGrid->IsInSelection(row, col)) {
866  flag |= wxACC_STATE_SYSTEM_SELECTED;
867  }
868 
869  if (mGrid->GetGridCursorRow() == row && mGrid->GetGridCursorCol() == col) {
870  flag |= wxACC_STATE_SYSTEM_FOCUSED;
871  }
872 
873  if (mGrid->IsReadOnly(row, col)) {
874  flag |= wxACC_STATE_SYSTEM_UNAVAILABLE;
875  }
876 #endif
877 
878  *state = flag;
879 
880  return wxACC_OK;
881 }
882 
883 // Returns a localized string representing the value for the object
884 // or child.
885 #if defined(__WXMAC__)
886 wxAccStatus GridAx::GetValue(int childId, wxString *strValue)
887 #else
888 wxAccStatus GridAx::GetValue(int WXUNUSED(childId), wxString *strValue)
889 #endif
890 {
891  strValue->Clear();
892 
893 #if defined(__WXMSW__)
894  return wxACC_OK;
895 #endif
896 
897 #if defined(__WXMAC__)
898  return GetName(childId, strValue);
899 #endif
900 }
901 
902 #if defined(__WXMAC__)
903 // Selects the object or child.
904 wxAccStatus GridAx::Select(int childId, wxAccSelectionFlags selectFlags)
905 {
906  int row;
907  int col;
908 
909  if (GetRowCol(childId, row, col)) {
910 
911  if (selectFlags & wxACC_SEL_TAKESELECTION) {
912  mGrid->SetGridCursor(row, col);
913  }
914 
915  mGrid->SelectBlock(row, col, row, col, selectFlags & wxACC_SEL_ADDSELECTION);
916  }
917 
918  return wxACC_OK;
919 }
920 #endif
921 
922 // Gets the window with the keyboard focus.
923 // If childId is 0 and child is NULL, no object in
924 // this subhierarchy has the focus.
925 // If this object has the focus, child should be 'this'.
926 wxAccStatus GridAx::GetFocus(int * WXUNUSED(childId), wxAccessible **child)
927 {
928  *child = this;
929 
930  return wxACC_OK;
931 }
932 
933 #endif // wxUSE_ACCESSIBILITY
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
NumericFormatId GetFormat() const
Definition: Grid.cpp:134
~Grid()
Definition: Grid.cpp:413
#define GRID_VALUE_TIME
Definition: Grid.h:41
Options & InvalidValue(bool has, double v=-1.0)
void OnSetFocus(wxFocusEvent &event)
Definition: Grid.cpp:425
#define GRID_VALUE_CHOICE
Definition: Grid.h:126
void ApplyEdit(int row, int col, wxGrid *grid) override
Definition: Grid.cpp:352
void DisconnectEvent(wxWindow *w)
Definition: Grid.h:172
ChoiceEditor::FocusHandler mHandler
~NumericRenderer() override
Definition: Grid.cpp:154
wxString GetValue() const override
Definition: Grid.cpp:367
wxArrayString mChoices
Definition: Grid.h:182
wxChoice * Choice() const
Definition: Grid.h:158
wxString mOldString
Definition: Grid.h:85
NumericEditor(NumericConverter::Type type, const NumericFormatId &format, double rate)
Definition: Grid.cpp:32
void OnKeyDown(wxKeyEvent &event)
Definition: Grid.cpp:443
Options & AutoPos(bool enable)
double mOld
Definition: Grid.h:84
#define safenew
Definition: Audacity.h:230
void Reset() override
Definition: Grid.cpp:357
~ChoiceEditor()
Definition: Grid.cpp:270
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
#define GRID_VALUE_FREQUENCY
Definition: Grid.h:42
bool EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval) override
Definition: Grid.cpp:89
double mRate
Definition: Grid.h:82
int format
Definition: ExportPCM.cpp:56
static NumericFormatId SecondsFormat()
void SetFormat(const NumericFormatId &format)
Definition: Grid.cpp:144
NumericConverter provides the advanced formatting control used in the selection bar of Audacity...
void BeginEdit(int row, int col, wxGrid *grid) override
Definition: Grid.cpp:305
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:166
void SetChoices(const wxArrayString &choices)
Definition: Grid.cpp:362
wxString mValueAsString
Definition: Grid.h:86
IdentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
void SetSize(const wxRect &rect) override
Definition: Grid.cpp:294
void SetValue(double newValue)
NumericConverter::Type mType
Definition: Grid.h:83
NumericConverter::Type mType
Definition: Grid.h:118
void ApplyEdit(int row, int col, wxGrid *grid) override
Definition: Grid.cpp:102
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, const wxRect &rect, int row, int col, bool isSelected) override
Definition: Grid.cpp:158
void OnSelectCell(wxGridEvent &event)
Definition: Grid.cpp:434
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
NumericFormatId mFormat
Definition: Grid.h:81
wxSize GetBestSize(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, int row, int col) override
Definition: Grid.cpp:220
~NumericEditor()
Definition: Grid.cpp:40
wxString mValueAsString
Definition: Grid.h:184
NumericTextCtrl * GetNumericTextControl() const
Definition: Grid.h:76
wxGridCellEditor * Clone() const override
Definition: Grid.cpp:277
END_EVENT_TABLE()
Supplies an accessible grid based on wxGrid.
Definition: Grid.h:193
void Reset() override
Definition: Grid.cpp:107
void SetRate(double rate)
Definition: Grid.cpp:149
static const int UndefinedFrequency
static NumericFormatId HertzFormat()
wxString GetValue() const override
Definition: Grid.cpp:129
wxString mOld
Definition: Grid.h:183
void SetSize(const wxRect &rect) override
Definition: Grid.cpp:63