summaryrefslogtreecommitdiffstats
path: root/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/controller/SlsFocusManager.cxx')
-rw-r--r--sd/source/ui/slidesorter/controller/SlsFocusManager.cxx245
1 files changed, 245 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
new file mode 100644
index 000000000..59027f5a8
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <controller/SlsFocusManager.hxx>
+
+#include <SlideSorter.hxx>
+#include <controller/SlideSorterController.hxx>
+#include <controller/SlsCurrentSlideManager.hxx>
+#include <controller/SlsVisibleAreaManager.hxx>
+#include <model/SlideSorterModel.hxx>
+#include <model/SlsPageDescriptor.hxx>
+#include <view/SlideSorterView.hxx>
+#include <view/SlsLayouter.hxx>
+#include <osl/diagnose.h>
+
+#include <Window.hxx>
+#include <sdpage.hxx>
+
+namespace sd::slidesorter::controller {
+
+FocusManager::FocusManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mnPageIndex(0),
+ mbPageIsFocused(false)
+{
+ if (mrSlideSorter.GetModel().GetPageCount() > 0)
+ mnPageIndex = 0;
+}
+
+FocusManager::~FocusManager()
+{
+}
+
+void FocusManager::MoveFocus (FocusMoveDirection eDirection)
+{
+ if (!(mnPageIndex >= 0 && mbPageIsFocused))
+ return;
+
+ HideFocusIndicator (GetFocusedPageDescriptor());
+
+ const sal_Int32 nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount());
+ const sal_Int32 nPageCount (mrSlideSorter.GetModel().GetPageCount());
+ switch (eDirection)
+ {
+ case FocusMoveDirection::Left:
+ if (mnPageIndex > 0)
+ mnPageIndex -= 1;
+ break;
+
+ case FocusMoveDirection::Right:
+ if (mnPageIndex < nPageCount-1)
+ mnPageIndex += 1;
+ break;
+
+ case FocusMoveDirection::Up:
+ {
+ const sal_Int32 nCandidate (mnPageIndex - nColumnCount);
+ if (nCandidate >= 0)
+ {
+ // Move the focus the previous row.
+ mnPageIndex = nCandidate;
+ }
+ }
+ break;
+
+ case FocusMoveDirection::Down:
+ {
+ const sal_Int32 nCandidate (mnPageIndex + nColumnCount);
+ if (nCandidate < nPageCount)
+ {
+ // Move the focus to the next row.
+ mnPageIndex = nCandidate;
+ }
+ }
+ break;
+ }
+
+ if (mnPageIndex < 0)
+ {
+ OSL_ASSERT(mnPageIndex>=0);
+ mnPageIndex = 0;
+ }
+ else if (mnPageIndex >= nPageCount)
+ {
+ OSL_ASSERT(mnPageIndex<nPageCount);
+ mnPageIndex = nPageCount - 1;
+ }
+
+ if (mbPageIsFocused)
+ {
+ ShowFocusIndicator(GetFocusedPageDescriptor(), true);
+ }
+}
+
+void FocusManager::ShowFocus (const bool bScrollToFocus)
+{
+ mbPageIsFocused = true;
+ ShowFocusIndicator(GetFocusedPageDescriptor(), bScrollToFocus);
+}
+
+void FocusManager::HideFocus()
+{
+ mbPageIsFocused = false;
+ HideFocusIndicator(GetFocusedPageDescriptor());
+}
+
+bool FocusManager::ToggleFocus()
+{
+ if (mnPageIndex >= 0)
+ {
+ if (mbPageIsFocused)
+ HideFocus ();
+ else
+ ShowFocus ();
+ }
+ return mbPageIsFocused;
+}
+
+bool FocusManager::HasFocus() const
+{
+ return mrSlideSorter.GetContentWindow()->HasFocus();
+}
+
+model::SharedPageDescriptor FocusManager::GetFocusedPageDescriptor() const
+{
+ return mrSlideSorter.GetModel().GetPageDescriptor(mnPageIndex);
+}
+
+bool FocusManager::SetFocusedPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor)
+ {
+ FocusHider aFocusHider (*this);
+ mnPageIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+ return true;
+ }
+ return false;
+}
+
+void FocusManager::SetFocusedPage (sal_Int32 nPageIndex)
+{
+ FocusHider aFocusHider (*this);
+ mnPageIndex = nPageIndex;
+}
+
+bool FocusManager::SetFocusedPageToCurrentPage()
+{
+ return SetFocusedPage(mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
+}
+
+bool FocusManager::IsFocusShowing() const
+{
+ return HasFocus() && mbPageIsFocused;
+}
+
+void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor)
+ {
+ mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, false);
+
+ // Hide focus should also fire the focus event, Currently, only accessibility add the focus listener
+ NotifyFocusChangeListeners();
+ }
+}
+
+void FocusManager::ShowFocusIndicator (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bScrollToFocus)
+{
+ if (!rpDescriptor)
+ return;
+
+ mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, true);
+
+ if (bScrollToFocus)
+ {
+ // Scroll the focused page object into the visible area and repaint
+ // it, so that the focus indicator becomes visible.
+ mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
+ }
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+
+ NotifyFocusChangeListeners();
+}
+
+void FocusManager::AddFocusChangeListener (const Link<LinkParamNone*,void>& rListener)
+{
+ if (::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener)
+ == maFocusChangeListeners.end())
+ {
+ maFocusChangeListeners.push_back (rListener);
+ }
+}
+
+void FocusManager::RemoveFocusChangeListener (const Link<LinkParamNone*,void>& rListener)
+{
+ maFocusChangeListeners.erase (
+ ::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener));
+}
+
+void FocusManager::NotifyFocusChangeListeners() const
+{
+ // Create a copy of the listener list to be safe when that is modified.
+ ::std::vector<Link<LinkParamNone*,void>> aListeners (maFocusChangeListeners);
+
+ // Tell the selection change listeners that the selection has changed.
+ for (const auto& rListener : aListeners)
+ {
+ rListener.Call(nullptr);
+ }
+}
+
+FocusManager::FocusHider::FocusHider (FocusManager& rManager)
+: mbFocusVisible(rManager.IsFocusShowing())
+, mrManager(rManager)
+{
+ mrManager.HideFocus();
+}
+
+FocusManager::FocusHider::~FocusHider() COVERITY_NOEXCEPT_FALSE
+{
+ if (mbFocusVisible)
+ mrManager.ShowFocus();
+}
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */