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