/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "AccessibleFocusManager.hxx"
#include "AccessibleNotes.hxx"
#include "PresenterAccessibility.hxx"
#include "PresenterTextView.hxx"
#include <strings.hrc>
#include <sdresid.hxx>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>
namespace sdext::presenter {
AccessibleNotes::AccessibleNotes(
const OUString& rsName)
: AccessibleObject(AccessibleRole::PANEL, rsName)
{
}
rtl::Reference<AccessibleObject> AccessibleNotes::Create(
const Reference<awt::XWindow>& rxContentWindow,
const Reference<awt::XWindow>& rxBorderWindow,
const std::shared_ptr<PresenterTextView>& rpTextView)
{
const OUString sName = SdResId(STR_A11Y_PRESENTER_NOTES);
rtl::Reference<AccessibleNotes> pObject (
new AccessibleNotes(sName));
pObject->LateInitialization();
pObject->SetTextView(rpTextView);
pObject->UpdateStateSet();
pObject->SetWindow(rxContentWindow, rxBorderWindow);
return pObject;
}
void AccessibleNotes::SetTextView (
const std::shared_ptr<PresenterTextView>& rpTextView)
{
::std::vector<rtl::Reference<AccessibleObject> > aChildren;
// Release any listeners to the current text view.
if (mpTextView)
{
mpTextView->GetCaret()->SetCaretMotionBroadcaster(
::std::function<
void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
mpTextView->SetTextChangeBroadcaster(
::std::function<
void ()>());
}
mpTextView = rpTextView;
if (!mpTextView)
return;
// Create a new set of children, one for each paragraph.
const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
{
rtl::Reference<AccessibleParagraph> pParagraph (
new AccessibleParagraph(
rpTextView->GetParagraph(nIndex),
nIndex));
pParagraph->LateInitialization();
pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
pParagraph->SetAccessibleParent(
this);
aChildren.emplace_back(pParagraph.get());
}
maChildren.swap(aChildren);
FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
// Dispose the old children. (This will remove them from the focus
// manager).
for (
const auto& rxChild : aChildren)
{
if (rxChild.is())
rxChild->dispose();
}
// This class acts as a controller of who broadcasts caret motion
// events and handles text changes. Register the corresponding
// listeners here.
mpTextView->GetCaret()->SetCaretMotionBroadcaster(
[
this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
{
return this->NotifyCaretChange(a, b, c, d); });
mpTextView->SetTextChangeBroadcaster(
[
this]() {
return SetTextView(mpTextView); });
}
void AccessibleNotes::SetWindow (
const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
const css::uno::Reference<css::awt::XWindow>& rxBorderWindow)
{
AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);
// Set the windows at the children as well, so that every paragraph can
// setup its geometry.
for (
auto& rxChild : maChildren)
{
rxChild->SetWindow(rxContentWindow, rxBorderWindow);
}
}
void AccessibleNotes::NotifyCaretChange (
const sal_Int32 nOldParagraphIndex,
const sal_Int32 nOldCharacterIndex,
const sal_Int32 nNewParagraphIndex,
const sal_Int32 nNewCharacterIndex)
{
AccessibleFocusManager::Instance()->FocusObject(
nNewParagraphIndex >= 0
? maChildren[nNewParagraphIndex]
:
this);
if (nOldParagraphIndex != nNewParagraphIndex)
{
// Moved caret from one paragraph to another (or showed or
// hid the caret). Move focus from one accessible
// paragraph to another.
if (nOldParagraphIndex >= 0)
{
maChildren[nOldParagraphIndex]->FireAccessibleEvent(
AccessibleEventId::CARET_CHANGED,
Any(nOldCharacterIndex),
Any(sal_Int32(-1)));
}
if (nNewParagraphIndex >= 0)
{
maChildren[nNewParagraphIndex]->FireAccessibleEvent(
AccessibleEventId::CARET_CHANGED,
Any(sal_Int32(-1)),
Any(nNewCharacterIndex));
}
}
else if (nNewParagraphIndex >= 0)
{
// Caret moved inside one paragraph.
maChildren[nNewParagraphIndex]->FireAccessibleEvent(
AccessibleEventId::CARET_CHANGED,
Any(nOldCharacterIndex),
Any(nNewCharacterIndex));
}
}
}
// end of namespace ::sd::presenter
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */