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