1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SD_SLIDESORTER_FOCUS_MANAGER_HXX
25 #define SD_SLIDESORTER_FOCUS_MANAGER_HXX
26 
27 #include <model/SlsSharedPageDescriptor.hxx>
28 
29 #include <sal/types.h>
30 #include <tools/link.hxx>
31 #include <vector>
32 
33 namespace sd { namespace slidesorter {
34 class SlideSorter;
35 } }
36 
37 
38 namespace sd { namespace slidesorter { namespace controller {
39 
40 /** This class manages the focus of the slide sorter.  There is the focus
41     page which is or is not focused.  Initialized to point to the first page
42     it can be set to other pages by using the MoveFocus() method.  The
43     focused state of the focus page can be toggled with the ToggleFocus()
44     method.
45 */
46 class FocusManager
47 {
48 public:
49     /** Create a new focus manager that operates on the pages of the model
50         associated with the given controller.  The focus page is set to the
51         first page.  Focused state is off.
52     */
53     FocusManager (SlideSorter& rSlideSorter);
54 
55     ~FocusManager (void);
56 
57     enum FocusMoveDirection
58     {
59         FMD_NONE,
60         FMD_LEFT,
61         FMD_RIGHT,
62         FMD_UP,
63         FMD_DOWN
64     };
65 
66     /** Move the focus from the currently focused page to one that is
67         displayed adjacent to it, either vertically or horizontally.
68         @param eDirection
69             Direction in which to move the focus.  Wrap around is done
70             differently when moving vertically or horizontally.  Vertical
71             wrap around takes place in the same column, i.e. when you are
72             in the top row and move up you come out in the bottom row in the
73             same column.  Horizontal wrap around moves to the next
74             (FMD_RIGHT) or previous (FMD_LEFT) page.  Moving to the right
75             from the last page goes to the first page and vice versa.
76             When FMD_NONE is given, the current page index is checked for
77             being valid.  If it is not, then it is set to the nearest valid
78             page index.
79     */
80     void MoveFocus (FocusMoveDirection eDirection);
81 
82     /** Show the focus indicator of the current slide.
83         @param bScrollToFocus
84             When <TRUE/> (the default) then the view is scrolled so that the
85             focus rectangle lies inside its visible area.
86     */
87     void ShowFocus (const bool bScrollToFocus = true);
88 
89     /** Hide the focus indicator.
90     */
91     void HideFocus (void);
92 
93     /** Toggle the focused state of the current slide.
94         @return
95             Returns the focused state of the focus page after the call.
96     */
97     bool ToggleFocus (void);
98 
99     /** Return whether the window managed by the called focus manager has
100         the input focus of the application.
101     */
102     bool HasFocus (void) const;
103 
104     /** Return the descriptor of the page that currently has the focus.
105         @return
106             When there is no page that currently has the focus then NULL is
107             returned.
108     */
109     model::SharedPageDescriptor GetFocusedPageDescriptor (void) const;
110 
111     /** Return the index of the page that currently has the focus as it is
112         accepted by the slide sorter model.
113         @return
114             When there is no page that currently has the focus then -1 is
115             returned.
116     */
117     sal_Int32 GetFocusedPageIndex (void) const;
118 
119     /** Set the focused page to the one described by the given page
120         descriptor.  The visibility of the focus indicator is not modified.
121         @param rDescriptor
122             One of the page descriptors that are currently managed by the
123             SlideSorterModel.
124     */
125     void SetFocusedPage (const model::SharedPageDescriptor& rDescriptor);
126 
127     /** Set the focused page to the one described by the given page
128         index.  The visibility of the focus indicator is not modified.
129         @param nPageIndex
130             A valid page index that is understood by the SlideSorterModel.
131     */
132     void SetFocusedPage (sal_Int32 nPageIndex);
133 
134     void SetFocusedPageToCurrentPage (void);
135 
136     /** Return <TRUE/> when the focus indicator is currently shown.  A
137         prerequisite is that the window managed by this focus manager has
138         the input focus as indicated by a <TRUE/> return value of
139         HasFocus().  It is not necessary that the focus indicator is
140         visible.  It may have been scrolled outside the visible area.
141     */
142     bool IsFocusShowing (void) const;
143 
144     /** Add a listener that is called when the focus is shown or hidden or
145         set to another page object.
146         @param rListener
147             When this method is called multiple times for the same listener
148             the second and all following calls are ignored.  Each listener
149             is added only once.
150     */
151     void AddFocusChangeListener (const Link& rListener);
152 
153     /** Remove a focus change listener.
154         @param rListener
155             It is save to pass a listener that was not added are has been
156             removed previously.  Such calls are ignored.
157     */
158     void RemoveFocusChangeListener (const Link& rListener);
159 
160     /** Move focus to sibling outside the actual slide sorter.  This is
161         typically the tool bar with the close button.
162     */
163     void SetFocusToToolBox (void);
164 
165     /** Create an instance of this class to temporarily hide the focus
166         indicator.  It is restored to its former visibility state when the
167         FocusHider is destroyed.
168     */
169     class FocusHider
170     {
171     public:
172         FocusHider (FocusManager&);
173         ~FocusHider (void);
174     private:
175         bool mbFocusVisible;
176         FocusManager& mrManager;
177     };
178 
179 private:
180     SlideSorter& mrSlideSorter;
181 
182     /** Index of the page that may be focused.  It is -1 when the model
183         contains no page.
184     */
185     sal_Int32 mnPageIndex;
186 
187     /** This flag indicates whether the page pointed to by mpFocusDescriptor
188         has the focus.
189     */
190     bool mbPageIsFocused;
191 
192     ::std::vector<Link> maFocusChangeListeners;
193 
194     /** When vertical wrap is active then pressing UP in the top row moves
195         the focus to the bottom row, DOWN in the bottom row moves the focus
196         to the top row.
197     */
198     bool mbIsVerticalWrapActive;
199 
200     /** Reset the focus state of the given descriptor and request a repaint
201         so that the focus indicator is hidden.
202         @param pDescriptor
203             When NULL is given then the call is ignored.
204     */
205     void HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor);
206 
207     /** Set the focus state of the given descriptor, scroll it into the
208         visible area and request a repaint so that the focus indicator is
209         made visible.
210         @param pDescriptor
211             When NULL is given then the call is ignored.
212         @param bScrollToFocus
213             When <TRUE/> (the default) then the view is scrolled so that the
214             focus rectangle lies inside its visible area.
215     */
216     void ShowFocusIndicator (
217         const model::SharedPageDescriptor& rpDescriptor,
218         const bool bScrollToFocus);
219 
220     /** Call all currently registered listeners that a focus change has
221         happened.  The focus may be hidden or shown or moved from one page
222         object to another.
223     */
224     void NotifyFocusChangeListeners (void) const;
225 };
226 
227 } } } // end of namespace ::sd::slidesorter::controller
228 
229 #endif
230