]> git.saurik.com Git - wxWidgets.git/blob - samples/access/accesstest.cpp
Implement NSMenuValidation protocol for the wxNSMenuItemTarget
[wxWidgets.git] / samples / access / accesstest.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: accesstest.cpp
3 // Purpose: wxWindows accessibility sample
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2002-02-12
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWindows headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #include "wx/access.h"
34 #include "wx/splitter.h"
35 #include "wx/cshelp.h"
36
37 #ifdef __WXMSW__
38 #include "windows.h"
39 #include <ole2.h>
40 #include <oleauto.h>
41 #include <oleacc.h>
42 #include "wx/msw/ole/oleutils.h"
43 #include "wx/msw/winundef.h"
44
45 #ifndef OBJID_CLIENT
46 #define OBJID_CLIENT 0xFFFFFFFC
47 #endif
48
49 #endif
50
51 // ----------------------------------------------------------------------------
52 // resources
53 // ----------------------------------------------------------------------------
54
55 // the application icon (under Windows and OS/2 it is in resources)
56 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
57 #include "mondrian.xpm"
58 #endif
59
60 // ----------------------------------------------------------------------------
61 // private classes
62 // ----------------------------------------------------------------------------
63
64 // Define a new application type, each program should derive a class from wxApp
65 class MyApp : public wxApp
66 {
67 public:
68 // override base class virtuals
69 // ----------------------------
70
71 // this one is called on application startup and is a good place for the app
72 // initialization (doing it here and not in the ctor allows to have an error
73 // return: if OnInit() returns false, the application terminates)
74 virtual bool OnInit();
75
76 };
77
78 // Define a new frame type: this is going to be our main frame
79 class MyFrame : public wxFrame
80 {
81 public:
82 // ctor(s)
83 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
84 long style = wxDEFAULT_FRAME_STYLE);
85
86 // event handlers (these functions should _not_ be virtual)
87 void OnQuit(wxCommandEvent& event);
88 void OnQuery(wxCommandEvent& event);
89 void OnAbout(wxCommandEvent& event);
90
91 // Log messages to the text control
92 void Log(const wxString& text);
93
94 // Recursively give information about an object
95 void LogObject(int indent, IAccessible* obj);
96
97 // Get info for a child (id > 0) or object (id == 0)
98 void GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role);
99 private:
100 wxTextCtrl* m_textCtrl;
101
102 // any class wishing to process wxWindows events must use this macro
103 DECLARE_EVENT_TABLE()
104 };
105
106 // ----------------------------------------------------------------------------
107 // constants
108 // ----------------------------------------------------------------------------
109
110 // IDs for the controls and the menu commands
111 enum
112 {
113 // menu items
114 AccessTest_Quit = 1,
115
116 // query the hierarchy
117 AccessTest_Query,
118
119 // it is important for the id corresponding to the "About" command to have
120 // this standard value as otherwise it won't be handled properly under Mac
121 // (where it is special and put into the "Apple" menu)
122 AccessTest_About = wxID_ABOUT
123 };
124
125 // ----------------------------------------------------------------------------
126 // event tables and other macros for wxWindows
127 // ----------------------------------------------------------------------------
128
129 // the event tables connect the wxWindows events with the functions (event
130 // handlers) which process them. It can be also done at run-time, but for the
131 // simple menu events like this the static method is much simpler.
132 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
133 EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
134 EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
135 EVT_MENU(AccessTest_About, MyFrame::OnAbout)
136 END_EVENT_TABLE()
137
138 // Create a new application object: this macro will allow wxWindows to create
139 // the application object during program execution (it's better than using a
140 // static object for many reasons) and also declares the accessor function
141 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
142 // not wxApp)
143 IMPLEMENT_APP(MyApp)
144
145 // ============================================================================
146 // implementation
147 // ============================================================================
148
149 // ----------------------------------------------------------------------------
150 // the application class
151 // ----------------------------------------------------------------------------
152
153 // 'Main program' equivalent: the program execution "starts" here
154 bool MyApp::OnInit()
155 {
156 // Note: JAWS for Windows will only speak the context-sensitive
157 // help if you use this help provider:
158 // wxHelpProvider::Set(new wxHelpControllerHelpProvider(m_helpController)).
159 // JAWS does not seem to be getting the help text from
160 // the wxAccessible object.
161 wxHelpProvider::Set(new wxSimpleHelpProvider());
162
163 // create the main application window
164 MyFrame *frame = new MyFrame(_T("AccessTest wxWindows App"),
165 wxPoint(50, 50), wxSize(450, 340));
166
167 // and show it (the frames, unlike simple controls, are not shown when
168 // created initially)
169 frame->Show(TRUE);
170
171 // success: wxApp::OnRun() will be called which will enter the main message
172 // loop and the application will run. If we returned FALSE here, the
173 // application would exit immediately.
174 return TRUE;
175 }
176
177 class FrameAccessible: public wxWindowAccessible
178 {
179 public:
180 FrameAccessible(wxWindow* win): wxWindowAccessible(win) {}
181
182 // Gets the name of the specified object.
183 virtual wxAccStatus GetName(int childId, wxString* name)
184 {
185 if (childId == wxACC_SELF)
186 {
187 * name = wxT("Julian's Frame");
188 return wxACC_OK;
189 }
190 else
191 return wxACC_NOT_IMPLEMENTED;
192 }
193 };
194
195 class ScrolledWindowAccessible: public wxWindowAccessible
196 {
197 public:
198 ScrolledWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
199
200 // Gets the name of the specified object.
201 virtual wxAccStatus GetName(int childId, wxString* name)
202 {
203 if (childId == wxACC_SELF)
204 {
205 * name = wxT("My scrolled window");
206 return wxACC_OK;
207 }
208 else
209 return wxACC_NOT_IMPLEMENTED;
210 }
211 };
212
213 class SplitterWindowAccessible: public wxWindowAccessible
214 {
215 public:
216 SplitterWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
217
218 // Gets the name of the specified object.
219 virtual wxAccStatus GetName(int childId, wxString* name);
220
221 // Can return either a child object, or an integer
222 // representing the child element, starting from 1.
223 virtual wxAccStatus HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject);
224
225 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
226 virtual wxAccStatus GetLocation(wxRect& rect, int elementId);
227
228 // Navigates from fromId to toId/toObject.
229 virtual wxAccStatus Navigate(wxNavDir navDir, int fromId,
230 int* toId, wxAccessible** toObject);
231
232 // Gets the number of children.
233 virtual wxAccStatus GetChildCount(int* childCount);
234
235 // Gets the specified child (starting from 1).
236 // If *child is NULL and return value is wxACC_OK,
237 // this means that the child is a simple element and
238 // not an accessible object.
239 virtual wxAccStatus GetChild(int childId, wxAccessible** child);
240
241 // Gets the parent, or NULL.
242 virtual wxAccStatus GetParent(wxAccessible** parent);
243
244 // Performs the default action. childId is 0 (the action for this object)
245 // or > 0 (the action for a child).
246 // Return wxACC_NOT_SUPPORTED if there is no default action for this
247 // window (e.g. an edit control).
248 virtual wxAccStatus DoDefaultAction(int childId);
249
250 // Gets the default action for this object (0) or > 0 (the action for a child).
251 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
252 // string if there is no action.
253 // The retrieved string describes the action that is performed on an object,
254 // not what the object does as a result. For example, a toolbar button that prints
255 // a document has a default action of "Press" rather than "Prints the current document."
256 virtual wxAccStatus GetDefaultAction(int childId, wxString* actionName);
257
258 // Returns the description for this object or a child.
259 virtual wxAccStatus GetDescription(int childId, wxString* description);
260
261 // Returns help text for this object or a child, similar to tooltip text.
262 virtual wxAccStatus GetHelpText(int childId, wxString* helpText);
263
264 // Returns the keyboard shortcut for this object or child.
265 // Return e.g. ALT+K
266 virtual wxAccStatus GetKeyboardShortcut(int childId, wxString* shortcut);
267
268 // Returns a role constant.
269 virtual wxAccStatus GetRole(int childId, wxAccRole* role);
270
271 // Returns a state constant.
272 virtual wxAccStatus GetState(int childId, long* state);
273
274 // Returns a localized string representing the value for the object
275 // or child.
276 virtual wxAccStatus GetValue(int childId, wxString* strValue);
277
278 // Selects the object or child.
279 virtual wxAccStatus Select(int childId, wxAccSelectionFlags selectFlags);
280
281 // Gets the window with the keyboard focus.
282 // If childId is 0 and child is NULL, no object in
283 // this subhierarchy has the focus.
284 // If this object has the focus, child should be 'this'.
285 virtual wxAccStatus GetFocus(int* childId, wxAccessible** child);
286
287 // Gets a variant representing the selected children
288 // of this object.
289 // Acceptable values:
290 // - a null variant (IsNull() returns TRUE)
291 // - a list variant (GetType() == wxT("list"))
292 // - an integer representing the selected child element,
293 // or 0 if this object is selected (GetType() == wxT("long"))
294 // - a "void*" pointer to a wxAccessible child object
295 virtual wxAccStatus GetSelections(wxVariant* selections);
296
297 };
298
299 // ----------------------------------------------------------------------------
300 // main frame
301 // ----------------------------------------------------------------------------
302
303 // frame constructor
304 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
305 : wxFrame(NULL, -1, title, pos, size, style)
306 {
307 m_textCtrl = NULL;
308
309 SetAccessible(new FrameAccessible(this));
310
311 // set the frame icon
312 SetIcon(wxICON(mondrian));
313
314 #if wxUSE_MENUS
315 // create a menu bar
316 wxMenu *menuFile = new wxMenu;
317
318 // the "About" item should be in the help menu
319 wxMenu *helpMenu = new wxMenu;
320 helpMenu->Append(AccessTest_About, _T("&About..."), _T("Show about dialog"));
321
322 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
323 menuFile->AppendSeparator();
324 menuFile->Append(AccessTest_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
325
326 // now append the freshly created menu to the menu bar...
327 wxMenuBar *menuBar = new wxMenuBar();
328 menuBar->Append(menuFile, _T("&File"));
329 menuBar->Append(helpMenu, _T("&Help"));
330
331 // ... and attach this menu bar to the frame
332 SetMenuBar(menuBar);
333 #endif // wxUSE_MENUS
334
335 #if 0 // wxUSE_STATUSBAR
336 // create a status bar just for fun (by default with 1 pane only)
337 CreateStatusBar(2);
338 SetStatusText(_T("Welcome to wxWindows!"));
339 #endif // wxUSE_STATUSBAR
340
341
342 wxSplitterWindow* splitter = new wxSplitterWindow(this, -1);
343 splitter->SetAccessible(new SplitterWindowAccessible(splitter));
344
345 wxListBox* listBox = new wxListBox(splitter, -1);
346 listBox->Append(wxT("Cabbages"));
347 listBox->Append(wxT("Kings"));
348 listBox->Append(wxT("Sealing wax"));
349 listBox->Append(wxT("Strings"));
350 listBox->CreateAccessible();
351 listBox->SetHelpText(wxT("This is a sample wxWindows listbox, with a number of items in it."));
352
353 m_textCtrl = new wxTextCtrl(splitter, -1, wxT(""), wxDefaultPosition,
354 wxDefaultSize, wxTE_MULTILINE);
355 m_textCtrl->CreateAccessible();
356 m_textCtrl->SetHelpText(wxT("This is a sample wxWindows multiline text control."));
357
358 splitter->SplitHorizontally(listBox, m_textCtrl, 150);
359
360 #if 0
361 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
362 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
363 #endif
364 }
365
366
367 // event handlers
368
369 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
370 {
371 // TRUE is to force the frame to close
372 Close(TRUE);
373 }
374
375 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
376 {
377 wxString msg;
378 msg.Printf( _T("This is the About dialog of the AccessTest sample.\n")
379 _T("Welcome to %s"), wxVERSION_STRING);
380
381 wxMessageBox(msg, _T("About AccessTest"), wxOK | wxICON_INFORMATION, this);
382 }
383
384 void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event))
385 {
386 m_textCtrl->Clear();
387 IAccessible* accessibleFrame = NULL;
388 if (S_OK != AccessibleObjectFromWindow((HWND) GetHWND(), OBJID_CLIENT,
389 IID_IAccessible, (void**) & accessibleFrame))
390 {
391 Log(wxT("Could not get object."));
392 return;
393 }
394 if (accessibleFrame)
395 {
396 //Log(wxT("Got an IAccessible for the frame."));
397 LogObject(0, accessibleFrame);
398 Log(wxT("Checking children using AccessibleChildren()..."));
399
400 // Now check the AccessibleChildren function works OK
401 long childCount = 0;
402 if (S_OK != accessibleFrame->get_accChildCount(& childCount))
403 {
404 Log(wxT("Could not get number of children."));
405 accessibleFrame->Release();
406 return;
407 }
408 else if (childCount == 0)
409 {
410 Log(wxT("No children."));
411 accessibleFrame->Release();
412 return;
413 }
414
415
416 long obtained = 0;
417 VARIANT *var = new VARIANT[childCount];
418 int i;
419 for (i = 0; i < childCount; i++)
420 {
421 VariantInit(& (var[i]));
422 var[i].vt = VT_DISPATCH;
423 }
424
425 if (S_OK == AccessibleChildren(accessibleFrame, 0, childCount, var, &obtained))
426 {
427 for (i = 0; i < childCount; i++)
428 {
429 IAccessible* childAccessible = NULL;
430 if (var[i].pdispVal)
431 {
432 if (var[i].pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
433 {
434 var[i].pdispVal->Release();
435
436 wxString name, role;
437 GetInfo(childAccessible, 0, name, role);
438 wxString str;
439 str.Printf(wxT("Found child %s/%s"), name.c_str(), role.c_str());
440 Log(str);
441 childAccessible->Release();
442 }
443 else
444 {
445 var[i].pdispVal->Release();
446 }
447 }
448 }
449 }
450 else
451 {
452 Log(wxT("AccessibleChildren failed."));
453 }
454 delete[] var;
455
456
457 accessibleFrame->Release();
458 }
459 }
460
461 // Log messages to the text control
462 void MyFrame::Log(const wxString& text)
463 {
464 if (m_textCtrl)
465 {
466 wxString text2(text);
467 text2.Replace(wxT("\n"), wxT(" "));
468 text2.Replace(wxT("\r"), wxT(" "));
469 m_textCtrl->SetInsertionPointEnd();
470 m_textCtrl->WriteText(text2 + wxT("\n"));
471 }
472 }
473
474 // Recursively give information about an object
475 void MyFrame::LogObject(int indent, IAccessible* obj)
476 {
477 wxString name, role;
478 if (indent == 0)
479 {
480 GetInfo(obj, 0, name, role);
481
482 wxString str;
483 str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str());
484 str.Pad(indent, wxT(' '), FALSE);
485 Log(str);
486 }
487
488 long childCount = 0;
489 if (S_OK == obj->get_accChildCount(& childCount))
490 {
491 wxString str;
492 str.Printf(wxT("There are %d children."), (int) childCount);
493 str.Pad(indent, wxT(' '), FALSE);
494 Log(str);
495 Log(wxT(""));
496 }
497
498 int i;
499 for (i = 1; i <= childCount; i++)
500 {
501 GetInfo(obj, i, name, role);
502
503 wxString str;
504 str.Printf(wxT("%d) Name = %s; Role = %s"), i, name.c_str(), role.c_str());
505 str.Pad(indent, wxT(' '), FALSE);
506 Log(str);
507
508 VARIANT var;
509 VariantInit(& var);
510 var.vt = VT_I4;
511 var.lVal = i;
512 IDispatch* pDisp = NULL;
513 IAccessible* childObject = NULL;
514
515 if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
516 {
517 wxString str;
518 str.Printf(wxT("This is a real object."));
519 str.Pad(indent+4, wxT(' '), FALSE);
520 Log(str);
521
522 if (pDisp->QueryInterface(IID_IAccessible, (LPVOID*) & childObject) == S_OK)
523 {
524 LogObject(indent + 4, childObject);
525 childObject->Release();
526 }
527 pDisp->Release();
528 }
529 else
530 {
531 wxString str;
532 str.Printf(wxT("This is an element."));
533 str.Pad(indent+4, wxT(' '), FALSE);
534 Log(str);
535 }
536 // Log(wxT(""));
537 }
538
539 }
540
541 // Get info for a child (id > 0) or object (id == 0)
542 void MyFrame::GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role)
543 {
544 VARIANT var;
545 VariantInit(& var);
546 var.vt = VT_I4;
547 var.lVal = id;
548
549 BSTR bStrName = 0;
550 HRESULT hResult = accessible->get_accName(var, & bStrName);
551
552 if (hResult == S_OK)
553 {
554 name = wxConvertStringFromOle(bStrName);
555 SysFreeString(bStrName);
556 }
557 else
558 {
559 name = wxT("NO NAME");
560 }
561
562 VARIANT varRole;
563 VariantInit(& varRole);
564
565 hResult = accessible->get_accRole(var, & varRole);
566
567 if (hResult == S_OK && varRole.vt == VT_I4)
568 {
569 wxChar buf[256];
570 GetRoleText(varRole.lVal, buf, 256);
571
572 role = buf;
573 }
574 else
575 {
576 role = wxT("NO ROLE");
577 }
578 }
579
580 /*
581 * SplitterWindowAccessible implementation
582 */
583
584 // Gets the name of the specified object.
585 wxAccStatus SplitterWindowAccessible::GetName(int childId, wxString* name)
586 {
587 if (childId == wxACC_SELF)
588 {
589 * name = wxT("Splitter window");
590 return wxACC_OK;
591 }
592 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
593 if (splitter)
594 {
595 if (splitter->IsSplit())
596 {
597 // Two windows, and the sash.
598 if (childId == 1 || childId == 3)
599 return wxACC_NOT_IMPLEMENTED;
600 else if (childId == 2)
601 {
602 *name = wxT("Sash");
603 return wxACC_OK;
604 }
605 }
606 }
607 // Let the framework handle the other cases.
608 return wxACC_NOT_IMPLEMENTED;
609 }
610
611 // Can return either a child object, or an integer
612 // representing the child element, starting from 1.
613 wxAccStatus SplitterWindowAccessible::HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject)
614 {
615 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
616 if (splitter)
617 {
618 if (splitter->IsSplit())
619 {
620 wxPoint clientPt = splitter->ScreenToClient(pt);
621 if (splitter->SashHitTest(clientPt.x, clientPt.y, 1))
622 {
623 // We're over the sash
624 *childId = 2;
625 return wxACC_OK;
626 }
627 }
628 }
629 // Let the framework handle the other cases.
630 return wxACC_NOT_IMPLEMENTED;
631 }
632
633 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
634 wxAccStatus SplitterWindowAccessible::GetLocation(wxRect& rect, int elementId)
635 {
636 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
637 if (splitter && elementId == 2 && splitter->IsSplit())
638 {
639 wxSize clientSize = splitter->GetClientSize();
640 if (splitter->GetSplitMode() == wxSPLIT_VERTICAL)
641 {
642 rect.x = splitter->GetSashPosition();
643 rect.y = 0;
644 rect.SetPosition(splitter->ClientToScreen(rect.GetPosition()));
645 rect.width = splitter->GetSashSize();
646 rect.height = clientSize.y;
647 }
648 else
649 {
650 rect.x = 0;
651 rect.y = splitter->GetSashPosition();
652 rect.SetPosition(splitter->ClientToScreen(rect.GetPosition()));
653 rect.width = clientSize.x;
654 rect.height = splitter->GetSashSize();
655 }
656 return wxACC_OK;
657 }
658 // Let the framework handle the other cases.
659 return wxACC_NOT_IMPLEMENTED;
660 }
661
662 // Navigates from fromId to toId/toObject.
663 wxAccStatus SplitterWindowAccessible::Navigate(wxNavDir navDir, int fromId,
664 int* toId, wxAccessible** toObject)
665 {
666 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
667 if (splitter && splitter->IsSplit())
668 {
669 switch (navDir)
670 {
671 case wxNAVDIR_DOWN:
672 {
673 if (splitter->GetSplitMode() == wxSPLIT_VERTICAL)
674 {
675 // Can't go down spatially if split vertically.
676 return wxACC_FALSE;
677 }
678 else
679 {
680 if (fromId == 1)
681 {
682 *toId = 2;
683 *toObject = NULL;
684 return wxACC_OK;
685 }
686 else if (fromId == 2)
687 {
688 *toId = 3;
689 *toObject = splitter->GetWindow2()->GetAccessible();
690 return wxACC_OK;
691 }
692 else
693 return wxACC_FALSE;
694 }
695
696 break;
697 }
698 case wxNAVDIR_FIRSTCHILD:
699 {
700 if (fromId == 2)
701 return wxACC_FALSE;
702 }
703 break;
704
705 case wxNAVDIR_LASTCHILD:
706 {
707 if (fromId == 2)
708 return wxACC_FALSE;
709 }
710 break;
711
712 case wxNAVDIR_LEFT:
713 {
714 if (splitter->GetSplitMode() == wxSPLIT_HORIZONTAL)
715 {
716 // Can't go left spatially if split horizontally.
717 return wxACC_FALSE;
718 }
719 else
720 {
721 if (fromId == 3)
722 {
723 *toId = 2;
724 *toObject = NULL;
725 return wxACC_OK;
726 }
727 else if (fromId == 2)
728 {
729 *toId = 1;
730 *toObject = splitter->GetWindow1()->GetAccessible();
731 return wxACC_OK;
732 }
733 else
734 return wxACC_FALSE;
735 }
736 }
737 break;
738
739 case wxNAVDIR_NEXT:
740 {
741 if (fromId == 1)
742 {
743 *toId = 2;
744 *toObject = NULL;
745 return wxACC_OK;
746 }
747 else if (fromId == 2)
748 {
749 *toId = 3;
750 *toObject = splitter->GetWindow2()->GetAccessible();
751 return wxACC_OK;
752 }
753 else
754 return wxACC_FALSE;
755 }
756 break;
757
758 case wxNAVDIR_PREVIOUS:
759 {
760 if (fromId == 3)
761 {
762 *toId = 2;
763 *toObject = NULL;
764 return wxACC_OK;
765 }
766 else if (fromId == 2)
767 {
768 *toId = 1;
769 *toObject = splitter->GetWindow1()->GetAccessible();
770 return wxACC_OK;
771 }
772 else
773 return wxACC_FALSE;
774 }
775 break;
776
777 case wxNAVDIR_RIGHT:
778 {
779 if (splitter->GetSplitMode() == wxSPLIT_HORIZONTAL)
780 {
781 // Can't go right spatially if split horizontally.
782 return wxACC_FALSE;
783 }
784 else
785 {
786 if (fromId == 1)
787 {
788 *toId = 2;
789 *toObject = NULL;
790 return wxACC_OK;
791 }
792 else if (fromId == 2)
793 {
794 *toId = 3;
795 *toObject = splitter->GetWindow2()->GetAccessible();
796 return wxACC_OK;
797 }
798 else
799 return wxACC_FALSE;
800 }
801 }
802 break;
803
804 case wxNAVDIR_UP:
805 {
806 if (splitter->GetSplitMode() == wxSPLIT_VERTICAL)
807 {
808 // Can't go up spatially if split vertically.
809 return wxACC_FALSE;
810 }
811 else
812 {
813 if (fromId == 3)
814 {
815 *toId = 2;
816 return wxACC_OK;
817 }
818 else if (fromId == 2)
819 {
820 *toId = 1;
821 *toObject = splitter->GetWindow1()->GetAccessible();
822 return wxACC_OK;
823 }
824 else
825 return wxACC_FALSE;
826 }
827
828 break;
829 }
830 }
831
832 }
833 // Let the framework handle the other cases.
834 return wxACC_NOT_IMPLEMENTED;
835 }
836
837 // Gets the number of children.
838 wxAccStatus SplitterWindowAccessible::GetChildCount(int* childCount)
839 {
840 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
841 if (splitter)
842 {
843 if (splitter->IsSplit())
844 {
845 // Two windows, and the sash.
846 *childCount = 3;
847 return wxACC_OK;
848 }
849 else
850 {
851 // No sash -- 1 or 0 windows.
852 if (splitter->GetWindow1() || splitter->GetWindow2())
853 {
854 *childCount = 1;
855 return wxACC_OK;
856 }
857 else
858 {
859 *childCount = 0;
860 return wxACC_OK;
861 }
862 }
863 }
864 // Let the framework handle the other cases.
865 return wxACC_NOT_IMPLEMENTED;
866 }
867
868 // Gets the specified child (starting from 1).
869 // If *child is NULL and return value is wxACC_OK,
870 // this means that the child is a simple element and
871 // not an accessible object.
872 wxAccStatus SplitterWindowAccessible::GetChild(int childId, wxAccessible** child)
873 {
874 if (childId == wxACC_SELF)
875 {
876 *child = this;
877 return wxACC_OK;
878 }
879
880 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
881 if (splitter)
882 {
883 if (splitter->IsSplit())
884 {
885 // Two windows, and the sash.
886 if (childId == 1)
887 {
888 *child = splitter->GetWindow1()->GetAccessible();
889 }
890 else if (childId == 2)
891 {
892 *child = NULL; // Sash
893 }
894 else if (childId == 3)
895 {
896 *child = splitter->GetWindow2()->GetAccessible();
897 }
898 else
899 {
900 return wxACC_FAIL;
901 }
902 return wxACC_OK;
903 }
904 else
905 {
906 // No sash -- 1 or 0 windows.
907 if (childId == 1)
908 {
909 if (splitter->GetWindow1())
910 {
911 *child = splitter->GetWindow1()->GetAccessible();
912 return wxACC_OK;
913 }
914 else if (splitter->GetWindow2())
915 {
916 *child = splitter->GetWindow2()->GetAccessible();
917 return wxACC_OK;
918 }
919 else
920 {
921 return wxACC_FAIL;
922 }
923 }
924 else
925 return wxACC_FAIL;
926 }
927 }
928 // Let the framework handle the other cases.
929 return wxACC_NOT_IMPLEMENTED;
930 }
931
932 // Gets the parent, or NULL.
933 wxAccStatus SplitterWindowAccessible::GetParent(wxAccessible** parent)
934 {
935 return wxACC_NOT_IMPLEMENTED;
936 }
937
938 // Performs the default action. childId is 0 (the action for this object)
939 // or > 0 (the action for a child).
940 // Return wxACC_NOT_SUPPORTED if there is no default action for this
941 // window (e.g. an edit control).
942 wxAccStatus SplitterWindowAccessible::DoDefaultAction(int childId)
943 {
944 return wxACC_NOT_IMPLEMENTED;
945 }
946
947 // Gets the default action for this object (0) or > 0 (the action for a child).
948 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
949 // string if there is no action.
950 // The retrieved string describes the action that is performed on an object,
951 // not what the object does as a result. For example, a toolbar button that prints
952 // a document has a default action of "Press" rather than "Prints the current document."
953 wxAccStatus SplitterWindowAccessible::GetDefaultAction(int childId, wxString* actionName)
954 {
955 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
956 if (splitter && splitter->IsSplit() && childId == 2)
957 {
958 // No default action for the splitter.
959 return wxACC_FALSE;
960 }
961 // Let the framework handle the other cases.
962 return wxACC_NOT_IMPLEMENTED;
963 }
964
965 // Returns the description for this object or a child.
966 wxAccStatus SplitterWindowAccessible::GetDescription(int childId, wxString* description)
967 {
968 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
969 if (splitter)
970 {
971 if (splitter->IsSplit())
972 {
973 if (childId == 2)
974 {
975 * description = _("The splitter window sash.");
976 return wxACC_OK;
977 }
978 }
979 }
980 // Let the framework handle the other cases.
981 return wxACC_NOT_IMPLEMENTED;
982 }
983
984 // Returns help text for this object or a child, similar to tooltip text.
985 wxAccStatus SplitterWindowAccessible::GetHelpText(int childId, wxString* helpText)
986 {
987 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
988 if (splitter)
989 {
990 if (splitter->IsSplit())
991 {
992 if (childId == 2)
993 {
994 * helpText = _("The splitter window sash.");
995 return wxACC_OK;
996 }
997 }
998 }
999 // Let the framework handle the other cases.
1000 return wxACC_NOT_IMPLEMENTED;
1001 }
1002
1003 // Returns the keyboard shortcut for this object or child.
1004 // Return e.g. ALT+K
1005 wxAccStatus SplitterWindowAccessible::GetKeyboardShortcut(int childId, wxString* shortcut)
1006 {
1007 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
1008 if (splitter && splitter->IsSplit() && childId == 2)
1009 {
1010 // No keyboard shortcut for the splitter.
1011 return wxACC_FALSE;
1012 }
1013 // Let the framework handle the other cases.
1014 return wxACC_NOT_IMPLEMENTED;
1015 }
1016
1017 // Returns a role constant.
1018 wxAccStatus SplitterWindowAccessible::GetRole(int childId, wxAccRole* role)
1019 {
1020 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
1021 if (splitter)
1022 {
1023 if (splitter->IsSplit())
1024 {
1025 if (childId == 2)
1026 {
1027 * role = wxROLE_SYSTEM_GRIP;
1028 return wxACC_OK;
1029 }
1030 }
1031 }
1032 // Let the framework handle the other cases.
1033 return wxACC_NOT_IMPLEMENTED;
1034 }
1035
1036 // Returns a state constant.
1037 wxAccStatus SplitterWindowAccessible::GetState(int childId, long* state)
1038 {
1039 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
1040 if (splitter && splitter->IsSplit() && childId == 2)
1041 {
1042 // No particular state. Not sure what would be appropriate here.
1043 *state = wxACC_STATE_SYSTEM_UNAVAILABLE;
1044 return wxACC_OK;
1045 }
1046 // Let the framework handle the other cases.
1047 return wxACC_NOT_IMPLEMENTED;
1048 }
1049
1050 // Returns a localized string representing the value for the object
1051 // or child.
1052 wxAccStatus SplitterWindowAccessible::GetValue(int childId, wxString* strValue)
1053 {
1054 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
1055 if (splitter && splitter->IsSplit() && childId == 2)
1056 {
1057 // The sash position is the value.
1058 wxString pos;
1059 pos << splitter->GetSashPosition();
1060 *strValue = pos;
1061
1062 return wxACC_OK;
1063 }
1064 // Let the framework handle the other cases.
1065 return wxACC_NOT_IMPLEMENTED;
1066 }
1067
1068 // Selects the object or child.
1069 wxAccStatus SplitterWindowAccessible::Select(int childId, wxAccSelectionFlags selectFlags)
1070 {
1071 wxSplitterWindow* splitter = wxDynamicCast(GetWindow(), wxSplitterWindow);
1072 if (splitter && splitter->IsSplit() && childId == 2)
1073 {
1074 // Can't select the sash.
1075 return wxACC_FALSE;
1076 }
1077 // Let the framework handle the other cases.
1078 return wxACC_NOT_IMPLEMENTED;
1079 }
1080
1081 // Gets the window with the keyboard focus.
1082 // If childId is 0 and child is NULL, no object in
1083 // this subhierarchy has the focus.
1084 // If this object has the focus, child should be 'this'.
1085 wxAccStatus SplitterWindowAccessible::GetFocus(int* childId, wxAccessible** child)
1086 {
1087 return wxACC_NOT_IMPLEMENTED;
1088 }
1089
1090 // Gets a variant representing the selected children
1091 // of this object.
1092 // Acceptable values:
1093 // - a null variant (IsNull() returns TRUE)
1094 // - a list variant (GetType() == wxT("list"))
1095 // - an integer representing the selected child element,
1096 // or 0 if this object is selected (GetType() == wxT("long"))
1097 // - a "void*" pointer to a wxAccessible child object
1098 wxAccStatus SplitterWindowAccessible::GetSelections(wxVariant* selections)
1099 {
1100 return wxACC_NOT_IMPLEMENTED;
1101 }
1102