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