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