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