FINAL CUT
fscrollview.h
1 /***********************************************************************
2 * fscrollview.h - Widget FScrollView (a scrolling area with on-demand *
3 * scroll bars) *
4 * *
5 * This file is part of the FINAL CUT widget toolkit *
6 * *
7 * Copyright 2017-2024 Markus Gans *
8 * *
9 * FINAL CUT is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU Lesser General Public License as *
11 * published by the Free Software Foundation; either version 3 of *
12 * the License, or (at your option) any later version. *
13 * *
14 * FINAL CUT is distributed in the hope that it will be useful, but *
15 * WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU Lesser General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU Lesser General Public *
20 * License along with this program. If not, see *
21 * <http://www.gnu.org/licenses/>. *
22 ***********************************************************************/
23 
24 /* Inheritance diagram
25  * ═══════════════════
26  *
27  * ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏
28  * ▕ FVTerm ▏ ▕ FObject ▏
29  * ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏
30  * ▲ ▲
31  * │ │
32  * └─────┬─────┘
33  * │
34  * ▕▔▔▔▔▔▔▔▔▔▏
35  * ▕ FWidget ▏
36  * ▕▁▁▁▁▁▁▁▁▁▏
37  * ▲
38  * │
39  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏
40  * ▕ FScrollView ▏
41  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏
42  */
43 
44 #ifndef FSCROLLVIEW_H
45 #define FSCROLLVIEW_H
46 
47 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
48  #error "Only <final/final.h> can be included directly."
49 #endif
50 
51 #include <memory>
52 #include <unordered_map>
53 
54 #include "final/fwidget.h"
55 #include "final/widget/fscrollbar.h"
56 
57 namespace finalcut
58 {
59 
60 // FVTerm friend function forward declaration
61 void setPrintArea (FWidget&, FVTerm::FTermArea*);
62 
63 //----------------------------------------------------------------------
64 // class FScrollView
65 //----------------------------------------------------------------------
66 
67 class FScrollView : public FWidget
68 {
69  public:
70  // Using-declaration
71  using FWidget::delAccelerator;
72  using FWidget::print;
73  using FWidget::setGeometry;
74 
75  // Constructor
76  explicit FScrollView (FWidget* = nullptr);
77 
78  // Disable copy constructor
79  FScrollView (const FScrollView&) = delete;
80 
81  // Disable move constructor
82  FScrollView (FScrollView&&) noexcept = delete;
83 
84  // Destructor
85  ~FScrollView() override;
86 
87  // Disable copy assignment operator (=)
88  auto operator = (const FScrollView&) -> FScrollView& = delete;
89 
90  // Disable move assignment operator (=)
91  auto operator = (FScrollView&&) noexcept -> FScrollView& = delete;
92 
93  // Accessors
94  auto getClassName() const -> FString override;
95  auto getText() & -> FString&;
96  auto getViewportWidth() const -> std::size_t;
97  auto getViewportHeight() const -> std::size_t;
98  auto getViewportSize() const -> FSize;
99  auto getScrollWidth() const -> std::size_t;
100  auto getScrollHeight() const -> std::size_t;
101  auto getScrollSize() const -> FSize;
102  auto getScrollPos() const -> FPoint;
103  auto getScrollX() const -> int;
104  auto getScrollY() const -> int;
105 
106  // Mutator
107  virtual void setScrollWidth (std::size_t);
108  virtual void setScrollHeight (std::size_t);
109  virtual void setScrollSize (const FSize&);
110  void setX (int, bool = true) override;
111  void setY (int, bool = true) override;
112  void setPos (const FPoint&, bool = true) override;
113  void setWidth (std::size_t, bool = true) override;
114  void setHeight (std::size_t, bool = true) override;
115  void setSize (const FSize&, bool = true) override;
116  void setGeometry ( const FPoint&, const FSize&
117  , bool = true ) override;
118  auto setCursorPos (const FPoint&) -> bool override;
119  void setPrintPos (const FPoint&) override;
120  void setText (const FString&);
121  void setViewportPrint (bool = true);
122  void unsetViewportPrint();
123  void resetColors() override;
124  void setBorder (bool = true);
125  void unsetBorder();
126  void setHorizontalScrollBarMode (ScrollBarMode);
127  void setVerticalScrollBarMode (ScrollBarMode);
128 
129  // Inquiries
130  auto hasBorder() const -> bool;
131  auto isViewportPrint() const -> bool;
132 
133  // Methods
134  void clearArea (wchar_t = L' ') override;
135  void scrollToX (int);
136  void scrollToY (int);
137  void scrollTo (const FPoint&);
138  void scrollTo (int, int);
139  void scrollBy (int, int);
140  void print (const FPoint&) override;
141  void draw() override;
142  void drawBorder() override;
143  void drawLabel();
144 
145  // Event handlers
146  void onKeyPress (FKeyEvent*) override;
147  void onMouseDown (FMouseEvent*) override;
148  void onMouseUp (FMouseEvent*) override;
149  void onMouseMove (FMouseEvent*) override;
150  void onWheel (FWheelEvent*) override;
151  void onAccel (FAccelEvent*) override;
152  void onFocusIn (FFocusEvent*) override;
153  void onChildFocusIn (FFocusEvent*) override;
154  void onChildFocusOut (FFocusEvent*) override;
155  void onFailAtChildFocus (FFocusEvent*) override;
156 
157  protected:
158  // Using-declaration
159  using FVTerm::clearArea;
160 
161  // Accessor
162  auto getPrintArea() -> FTermArea* override;
163 
164  // Methods
165  void setHotkeyAccelerator();
166  void initLayout() override;
167  void adjustSize() override;
168  void copy2area();
169 
170  private:
171  // Using-declaration
172  using KeyMap = std::unordered_map<FKey, std::function<void()>, EnumHash<FKey>>;
173 
174  // Constants
175  static constexpr std::size_t vertical_border_spacing = 2;
176  static constexpr std::size_t horizontal_border_spacing = 2;
177 
178  // Accessors
179  auto getViewportCursorPos() -> FPoint;
180 
181  // Methods
182  void init();
183  void addLocalPreprocessingHandler();
184  void createViewport (const FSize&) noexcept;
185  void drawText (const FString&, std::size_t);
186  auto getDisplayedTextLength (const FString&, const std::size_t) const -> std::size_t;
187  void setLabelStyle() const;
188  void printLabel (const FString&, std::size_t);
189  void printEllipsis (const FString&);
190  void directFocus();
191  void mapKeyFunctions();
192  void changeSize (const FSize&, bool);
193  void adjustOffsets (int, int, int, int);
194  auto isChangePosition (const int, const int) const -> bool;
195  auto isChangeXPosition (const int) const -> bool;
196  auto isChangeYPosition (const int) const -> bool;
197  void changeX (const std::size_t, const int);
198  void changeY (const std::size_t, const int);
199  void calculateScrollbarPos() const;
200  template <typename Callback>
201  void initScrollbar (FScrollbarPtr&, Orientation, Callback);
202  void setHorizontalScrollBarVisibility() const;
203  void setVerticalScrollBarVisibility() const;
204  void setViewportCursor();
205  auto shouldUpdateScrollbar (FScrollbar::ScrollType) const -> bool;
206  auto getVerticalScrollDistance (const FScrollbar::ScrollType) const -> int;
207  auto getHorizontalScrollDistance (const FScrollbar::ScrollType) const -> int;
208 
209  // Callback methods
210  void cb_vbarChange (const FWidget*);
211  void cb_hbarChange (const FWidget*);
212 
213  // Data members
214  FRect scroll_geometry{1, 1, 1, 1};
215  FRect viewport_geometry{};
216  std::unique_ptr<FTermArea> viewport{}; // virtual scroll content
217  FString text{};
218  FScrollbarPtr vbar{nullptr};
219  FScrollbarPtr hbar{nullptr};
220  KeyMap key_map{};
221  uInt8 nf_offset{0};
222  bool use_own_print_area{false};
223  bool update_scrollbar{true};
224  ScrollBarMode v_mode{ScrollBarMode::Auto}; // fc:Auto, fc::Hidden or fc::Scroll
225  ScrollBarMode h_mode{ScrollBarMode::Auto};
226 };
227 
228 // FScrollView inline functions
229 //----------------------------------------------------------------------
230 inline auto FScrollView::getText() & -> FString&
231 { return text; }
232 
233 //----------------------------------------------------------------------
234 inline auto FScrollView::getClassName() const -> FString
235 { return "FScrollView"; }
236 
237 //----------------------------------------------------------------------
238 inline auto FScrollView::getViewportWidth() const -> std::size_t
239 {
240  return ( getScrollHeight() > getViewportHeight() )
241  ? static_cast<std::size_t>(std::max (1, getGeometry().getX2() -
242  (getGeometry().getX1() - 1) -
243  static_cast<int>(vertical_border_spacing) -
244  static_cast<int>(nf_offset)))
245  : static_cast<std::size_t>(std::max (1, getGeometry().getX2() -
246  (getGeometry().getX1() - 1) -
247  static_cast<int>(vertical_border_spacing)));
248 }
249 
250 //----------------------------------------------------------------------
251 inline auto FScrollView::getViewportHeight() const -> std::size_t
252 {
253  return static_cast<std::size_t>(std::max (1, getGeometry().getY2() -
254  (getGeometry().getY1() - 1) -
255  static_cast<int>(horizontal_border_spacing)));
256 }
257 
258 //----------------------------------------------------------------------
259 inline auto FScrollView::getViewportSize() const -> FSize
260 { return { FSize{getViewportWidth(), getViewportHeight()} }; }
261 
262 //----------------------------------------------------------------------
263 inline auto FScrollView::getScrollWidth() const -> std::size_t
264 { return scroll_geometry.getWidth(); }
265 
266 //----------------------------------------------------------------------
267 inline auto FScrollView::getScrollHeight() const -> std::size_t
268 { return scroll_geometry.getHeight(); }
269 
270 //----------------------------------------------------------------------
271 inline auto FScrollView::getScrollSize() const -> FSize
272 { return scroll_geometry.getSize(); }
273 
274 //----------------------------------------------------------------------
275 inline auto FScrollView::getScrollPos() const -> FPoint
276 { return viewport_geometry.getPos(); }
277 
278 //----------------------------------------------------------------------
279 inline auto FScrollView::getScrollX() const -> int
280 { return viewport_geometry.getX(); }
281 
282 //----------------------------------------------------------------------
283 inline auto FScrollView::getScrollY() const -> int
284 { return viewport_geometry.getY(); }
285 
286 //----------------------------------------------------------------------
287 inline void FScrollView::unsetViewportPrint()
288 { setViewportPrint(false); }
289 
290 //----------------------------------------------------------------------
291 inline void FScrollView::unsetBorder()
292 { setBorder(false); }
293 
294 //----------------------------------------------------------------------
295 inline auto FScrollView::hasBorder() const -> bool
296 { return ! getFlags().feature.no_border; }
297 
298 //----------------------------------------------------------------------
299 inline auto FScrollView::isViewportPrint() const -> bool
300 { return ! use_own_print_area; }
301 
302 //----------------------------------------------------------------------
303 inline void FScrollView::scrollTo (const FPoint& pos)
304 { scrollTo(pos.getX(), pos.getY()); }
305 
306 //----------------------------------------------------------------------
307 inline void FScrollView::print (const FPoint& pos)
308 {
309  if ( use_own_print_area )
310  FWidget::setPrintPos(pos);
311  else
312  setPrintPos(pos);
313 }
314 
315 //----------------------------------------------------------------------
316 template <typename Callback>
317 inline void FScrollView::initScrollbar ( FScrollbarPtr& bar
318  , Orientation o
319  , Callback cb_handler )
320 {
321  finalcut::initScrollbar (bar, o, this, cb_handler);
322  FTermArea* area = FScrollView::getPrintArea();
323  finalcut::setPrintArea (*bar, area);
324 }
325 
326 } // namespace finalcut
327 
328 #endif // FSCROLLVIEW_H
Definition: fevent.h:196
Definition: fevent.h:144
Definition: frect.h:56
Definition: fevent.h:171
Definition: class_template.cpp:25
Definition: fscrollview.h:67
Definition: fpoint.h:50
Definition: fsize.h:55
Definition: fstring.h:79
Definition: fwidget.h:129
Definition: fevent.h:220
Definition: fevent.h:124
Definition: ftypes.h:160