]> git.saurik.com Git - wxWidgets.git/blame - samples/access/accesstest.cpp
Scrolling improvements
[wxWidgets.git] / samples / access / accesstest.cpp
CommitLineData
ae23a52a
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: accesstest.cpp
be5a51fb 3// Purpose: wxWidgets accessibility sample
ae23a52a
JS
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
be5a51fb 28// need because it includes almost all "standard" wxWidgets headers)
ae23a52a
JS
29#ifndef WX_PRECOMP
30 #include "wx/wx.h"
31#endif
32
7d418908
JS
33#if wxUSE_ACCESSIBILITY
34 #include "wx/access.h"
35#endif // wxUSE_ACCESSIBILITY
36
8586126c 37#include "wx/splitter.h"
a37e4a07 38#include "wx/cshelp.h"
8586126c
JS
39
40#ifdef __WXMSW__
7d418908
JS
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"
8586126c 51
7d418908
JS
52 #ifndef OBJID_CLIENT
53 #define OBJID_CLIENT 0xFFFFFFFC
54 #endif
8586126c 55#endif
ae23a52a
JS
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
71class MyApp : public wxApp
72{
73public:
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();
8586126c 81
ae23a52a
JS
82};
83
7d418908
JS
84#if wxUSE_ACCESSIBILITY
85
ae23a52a
JS
86// Define a new frame type: this is going to be our main frame
87class MyFrame : public wxFrame
88{
89public:
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);
8586126c 96 void OnQuery(wxCommandEvent& event);
ae23a52a
JS
97 void OnAbout(wxCommandEvent& event);
98
8586126c
JS
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
2aefc528
JS
105 // Get info for a child (id > 0) or object (id == 0)
106 void GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role);
ae23a52a 107private:
8586126c
JS
108 wxTextCtrl* m_textCtrl;
109
be5a51fb 110 // any class wishing to process wxWidgets events must use this macro
ae23a52a
JS
111 DECLARE_EVENT_TABLE()
112};
113
114// ----------------------------------------------------------------------------
115// constants
116// ----------------------------------------------------------------------------
117
118// IDs for the controls and the menu commands
119enum
120{
121 // menu items
122 AccessTest_Quit = 1,
123
8586126c
JS
124 // query the hierarchy
125 AccessTest_Query,
126
ae23a52a
JS
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// ----------------------------------------------------------------------------
be5a51fb 134// event tables and other macros for wxWidgets
ae23a52a
JS
135// ----------------------------------------------------------------------------
136
be5a51fb 137// the event tables connect the wxWidgets events with the functions (event
ae23a52a
JS
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.
140BEGIN_EVENT_TABLE(MyFrame, wxFrame)
141 EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
8586126c 142 EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
ae23a52a
JS
143 EVT_MENU(AccessTest_About, MyFrame::OnAbout)
144END_EVENT_TABLE()
145
7d418908
JS
146#endif // wxUSE_ACCESSIBILITY
147
be5a51fb 148// Create a new application object: this macro will allow wxWidgets to create
ae23a52a
JS
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)
153IMPLEMENT_APP(MyApp)
154
155// ============================================================================
156// implementation
157// ============================================================================
158
159// ----------------------------------------------------------------------------
160// the application class
161// ----------------------------------------------------------------------------
162
163// 'Main program' equivalent: the program execution "starts" here
164bool MyApp::OnInit()
165{
7d418908 166#if wxUSE_ACCESSIBILITY
a37e4a07
JS
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
ae23a52a 174 // create the main application window
be5a51fb 175 MyFrame *frame = new MyFrame(_T("AccessTest wxWidgets App"),
ae23a52a
JS
176 wxPoint(50, 50), wxSize(450, 340));
177
178 // and show it (the frames, unlike simple controls, are not shown when
179 // created initially)
5014bb3a 180 frame->Show(true);
ae23a52a
JS
181
182 // success: wxApp::OnRun() will be called which will enter the main message
5014bb3a 183 // loop and the application will run. If we returned false here, the
ae23a52a 184 // application would exit immediately.
5014bb3a 185 return true;
7d418908
JS
186#else
187 wxMessageBox( _T("This sample has to be compiled with wxUSE_ACCESSIBILITY"), _T("Building error"), wxOK);
5014bb3a 188 return false;
7d418908 189#endif // wxUSE_ACCESSIBILITY
ae23a52a
JS
190}
191
7d418908
JS
192#if wxUSE_ACCESSIBILITY
193
ae23a52a
JS
194class FrameAccessible: public wxWindowAccessible
195{
196public:
197 FrameAccessible(wxWindow* win): wxWindowAccessible(win) {}
198
199 // Gets the name of the specified object.
200 virtual wxAccStatus GetName(int childId, wxString* name)
201 {
ae23a52a
JS
202 if (childId == wxACC_SELF)
203 {
204 * name = wxT("Julian's Frame");
205 return wxACC_OK;
206 }
207 else
ae23a52a
JS
208 return wxACC_NOT_IMPLEMENTED;
209 }
210};
211
212class ScrolledWindowAccessible: public wxWindowAccessible
213{
214public:
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
84969af7
JS
230class SplitterWindowAccessible: public wxWindowAccessible
231{
232public:
233 SplitterWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
234
235 // Gets the name of the specified object.
a37e4a07 236 virtual wxAccStatus GetName(int childId, wxString* name);
84969af7
JS
237
238 // Can return either a child object, or an integer
239 // representing the child element, starting from 1.
a37e4a07 240 virtual wxAccStatus HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject);
84969af7
JS
241
242 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
a37e4a07 243 virtual wxAccStatus GetLocation(wxRect& rect, int elementId);
84969af7
JS
244
245 // Navigates from fromId to toId/toObject.
a37e4a07
JS
246 virtual wxAccStatus Navigate(wxNavDir navDir, int fromId,
247 int* toId, wxAccessible** toObject);
84969af7
JS
248
249 // Gets the number of children.
a37e4a07 250 virtual wxAccStatus GetChildCount(int* childCount);
84969af7
JS
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.
a37e4a07 256 virtual wxAccStatus GetChild(int childId, wxAccessible** child);
84969af7
JS
257
258 // Gets the parent, or NULL.
a37e4a07 259 virtual wxAccStatus GetParent(wxAccessible** parent);
84969af7
JS
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).
a37e4a07 265 virtual wxAccStatus DoDefaultAction(int childId);
84969af7
JS
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."
a37e4a07 273 virtual wxAccStatus GetDefaultAction(int childId, wxString* actionName);
84969af7
JS
274
275 // Returns the description for this object or a child.
a37e4a07 276 virtual wxAccStatus GetDescription(int childId, wxString* description);
84969af7
JS
277
278 // Returns help text for this object or a child, similar to tooltip text.
a37e4a07 279 virtual wxAccStatus GetHelpText(int childId, wxString* helpText);
84969af7
JS
280
281 // Returns the keyboard shortcut for this object or child.
282 // Return e.g. ALT+K
a37e4a07 283 virtual wxAccStatus GetKeyboardShortcut(int childId, wxString* shortcut);
84969af7
JS
284
285 // Returns a role constant.
a37e4a07 286 virtual wxAccStatus GetRole(int childId, wxAccRole* role);
84969af7
JS
287
288 // Returns a state constant.
a37e4a07 289 virtual wxAccStatus GetState(int childId, long* state);
84969af7
JS
290
291 // Returns a localized string representing the value for the object
292 // or child.
a37e4a07 293 virtual wxAccStatus GetValue(int childId, wxString* strValue);
84969af7
JS
294
295 // Selects the object or child.
a37e4a07 296 virtual wxAccStatus Select(int childId, wxAccSelectionFlags selectFlags);
84969af7
JS
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'.
a37e4a07 302 virtual wxAccStatus GetFocus(int* childId, wxAccessible** child);
84969af7
JS
303
304 // Gets a variant representing the selected children
305 // of this object.
306 // Acceptable values:
5014bb3a 307 // - a null variant (IsNull() returns true)
84969af7
JS
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
a37e4a07 312 virtual wxAccStatus GetSelections(wxVariant* selections);
84969af7
JS
313
314};
315
ae23a52a
JS
316// ----------------------------------------------------------------------------
317// main frame
318// ----------------------------------------------------------------------------
319
320// frame constructor
321MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
5014bb3a 322 : wxFrame(NULL, wxID_ANY, title, pos, size, style)
ae23a52a 323{
8586126c
JS
324 m_textCtrl = NULL;
325
a37e4a07 326 SetAccessible(new FrameAccessible(this));
ae23a52a
JS
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;
a37e4a07 337 helpMenu->Append(AccessTest_About, _T("&About..."), _T("Show about dialog"));
ae23a52a 338
8586126c
JS
339 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
340 menuFile->AppendSeparator();
ae23a52a
JS
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
2aefc528 352#if 0 // wxUSE_STATUSBAR
ae23a52a
JS
353 // create a status bar just for fun (by default with 1 pane only)
354 CreateStatusBar(2);
be5a51fb 355 SetStatusText(_T("Welcome to wxWidgets!"));
ae23a52a
JS
356#endif // wxUSE_STATUSBAR
357
a37e4a07 358
5014bb3a 359 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY);
a37e4a07 360 splitter->SetAccessible(new SplitterWindowAccessible(splitter));
8586126c 361
5014bb3a 362 wxListBox* listBox = new wxListBox(splitter, wxID_ANY);
a37e4a07
JS
363 listBox->Append(wxT("Cabbages"));
364 listBox->Append(wxT("Kings"));
365 listBox->Append(wxT("Sealing wax"));
366 listBox->Append(wxT("Strings"));
8586126c 367 listBox->CreateAccessible();
be5a51fb 368 listBox->SetHelpText(wxT("This is a sample wxWidgets listbox, with a number of items in it."));
8586126c 369
5014bb3a 370 m_textCtrl = new wxTextCtrl(splitter, wxID_ANY, wxT(""), wxDefaultPosition,
8586126c
JS
371 wxDefaultSize, wxTE_MULTILINE);
372 m_textCtrl->CreateAccessible();
be5a51fb 373 m_textCtrl->SetHelpText(wxT("This is a sample wxWidgets multiline text control."));
8586126c
JS
374
375 splitter->SplitHorizontally(listBox, m_textCtrl, 150);
376
377#if 0
5014bb3a 378 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, wxID_ANY);
ae23a52a
JS
379 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
380#endif
381}
382
383
384// event handlers
385
386void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
387{
5014bb3a
WS
388 // true is to force the frame to close
389 Close(true);
ae23a52a
JS
390}
391
392void 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}
8586126c
JS
400
401void 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 {
2aefc528 413 //Log(wxT("Got an IAccessible for the frame."));
8586126c 414 LogObject(0, accessibleFrame);
2aefc528
JS
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
8586126c
JS
474 accessibleFrame->Release();
475 }
476}
477
478// Log messages to the text control
479void 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
492void MyFrame::LogObject(int indent, IAccessible* obj)
493{
2aefc528
JS
494 wxString name, role;
495 if (indent == 0)
8586126c 496 {
2aefc528
JS
497 GetInfo(obj, 0, name, role);
498
8586126c 499 wxString str;
2aefc528 500 str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str());
5014bb3a 501 str.Pad(indent, wxT(' '), false);
8586126c
JS
502 Log(str);
503 }
8586126c
JS
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);
5014bb3a 510 str.Pad(indent, wxT(' '), false);
8586126c 511 Log(str);
2aefc528 512 Log(wxT(""));
8586126c
JS
513 }
514
515 int i;
516 for (i = 1; i <= childCount; i++)
517 {
2aefc528
JS
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());
5014bb3a 522 str.Pad(indent, wxT(' '), false);
2aefc528
JS
523 Log(str);
524
8586126c
JS
525 VARIANT var;
526 VariantInit(& var);
527 var.vt = VT_I4;
528 var.lVal = i;
529 IDispatch* pDisp = NULL;
530 IAccessible* childObject = NULL;
531
8586126c
JS
532 if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
533 {
534 wxString str;
535 str.Printf(wxT("This is a real object."));
5014bb3a 536 str.Pad(indent+4, wxT(' '), false);
8586126c
JS
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."));
5014bb3a 550 str.Pad(indent+4, wxT(' '), false);
8586126c
JS
551 Log(str);
552 }
2aefc528 553 // Log(wxT(""));
8586126c
JS
554 }
555
556}
557
2aefc528
JS
558// Get info for a child (id > 0) or object (id == 0)
559void 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}
a37e4a07
JS
596
597/*
598 * SplitterWindowAccessible implementation
599 */
600
601// Gets the name of the specified object.
602wxAccStatus 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.
7d418908 630wxAccStatus SplitterWindowAccessible::HitTest(const wxPoint& pt, int* childId, wxAccessible** WXUNUSED(childObject))
a37e4a07
JS
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).
651wxAccStatus 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.
680wxAccStatus 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 {
7d418908 690 if (splitter->GetSplitMode() != wxSPLIT_VERTICAL)
a37e4a07
JS
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 }
a37e4a07 704 }
7d418908
JS
705 return wxACC_FALSE;
706 #if 0
707 // below line is not executed due to earlier return
a37e4a07 708 break;
7d418908 709 #endif
a37e4a07
JS
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 {
7d418908 727 if (splitter->GetSplitMode() != wxSPLIT_HORIZONTAL)
a37e4a07
JS
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 }
a37e4a07 741 }
7d418908 742 return wxACC_FALSE;
a37e4a07 743 }
7d418908
JS
744 #if 0
745 // below line is not executed due to earlier return
a37e4a07 746 break;
7d418908 747 #endif
a37e4a07
JS
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 }
a37e4a07
JS
763 return wxACC_FALSE;
764 }
7d418908
JS
765 #if 0
766 // below line is not executed due to earlier return
a37e4a07 767 break;
7d418908 768 #endif
a37e4a07
JS
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 }
a37e4a07
JS
784 return wxACC_FALSE;
785 }
7d418908
JS
786 #if 0
787 // below line is not executed due to earlier return
a37e4a07 788 break;
7d418908 789 #endif
a37e4a07
JS
790
791 case wxNAVDIR_RIGHT:
792 {
7d418908 793 if (splitter->GetSplitMode() != wxSPLIT_HORIZONTAL)
a37e4a07
JS
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 }
a37e4a07 807 }
7d418908
JS
808 // Can't go right spatially if split horizontally.
809 return wxACC_FALSE;
a37e4a07 810 }
7d418908
JS
811 #if 0
812 // below line is not executed due to earlier return
a37e4a07 813 break;
7d418908 814 #endif
a37e4a07
JS
815
816 case wxNAVDIR_UP:
817 {
7d418908 818 if (splitter->GetSplitMode() != wxSPLIT_VERTICAL)
a37e4a07
JS
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 }
a37e4a07
JS
831 }
832
7d418908
JS
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
a37e4a07 837 break;
7d418908 838 #endif
a37e4a07
JS
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.
848wxAccStatus 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.
882wxAccStatus 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.
7d418908 943wxAccStatus SplitterWindowAccessible::GetParent(wxAccessible** WXUNUSED(parent))
a37e4a07
JS
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).
7d418908 952wxAccStatus SplitterWindowAccessible::DoDefaultAction(int WXUNUSED(childId))
a37e4a07
JS
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."
7d418908 963wxAccStatus SplitterWindowAccessible::GetDefaultAction(int childId, wxString* WXUNUSED(actionName))
a37e4a07
JS
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.
976wxAccStatus 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.
995wxAccStatus 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
7d418908 1015wxAccStatus SplitterWindowAccessible::GetKeyboardShortcut(int childId, wxString* WXUNUSED(shortcut))
a37e4a07
JS
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.
1028wxAccStatus 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.
1047wxAccStatus 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.
1062wxAccStatus 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.
7d418908 1079wxAccStatus SplitterWindowAccessible::Select(int childId, wxAccSelectionFlags WXUNUSED(selectFlags))
a37e4a07
JS
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'.
7d418908 1095wxAccStatus SplitterWindowAccessible::GetFocus(int* WXUNUSED(childId), wxAccessible** WXUNUSED(child))
a37e4a07
JS
1096{
1097 return wxACC_NOT_IMPLEMENTED;
1098}
1099
1100// Gets a variant representing the selected children
1101// of this object.
1102// Acceptable values:
5014bb3a 1103// - a null variant (IsNull() returns true)
a37e4a07
JS
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
7d418908 1108wxAccStatus SplitterWindowAccessible::GetSelections(wxVariant* WXUNUSED(selections))
a37e4a07
JS
1109{
1110 return wxACC_NOT_IMPLEMENTED;
1111}
1112
7d418908 1113#endif // wxUSE_ACCESSIBILITY