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-2026 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 setPrintRegion (FWidget&, FVTerm::FTermRegion*);
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  // Predicates
130  auto hasBorder() const -> bool;
131  auto isViewportPrint() const -> bool;
132 
133  // Methods
134  void clearArea (wchar_t = L' ');
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  // Accessor
159  auto getPrintRegion() -> FTermRegion* override;
160 
161  // Methods
162  void setHotkeyAccelerator();
163  void initLayout() override;
164  void adjustSize() override;
165  void copyToRegion();
166 
167  private:
168  // Using-declaration
169  using KeyMap = std::unordered_map<FKey, std::function<void()>, EnumHash<FKey>>;
170 
171  // Constants
172  static constexpr std::size_t vertical_border_spacing = 2;
173  static constexpr std::size_t horizontal_border_spacing = 2;
174 
175  // Accessors
176  auto getViewportCursorPos() -> FPoint;
177 
178  // Methods
179  void init();
180  void addLocalPreprocessingHandler();
181  void createViewport (const FSize&) noexcept;
182  void drawText (const FString&, std::size_t);
183  auto getDisplayedTextLength (const FString&, const std::size_t) const -> std::size_t;
184  void setLabelStyle() const;
185  void printLabel (const FString&, std::size_t);
186  void printEllipsis (const FString&);
187  void directFocus();
188  void mapKeyFunctions();
189  void changeSize (const FSize&, bool);
190  void adjustOffsets (int, int, int, int);
191  auto isChangePosition (const int, const int) const -> bool;
192  auto isChangeXPosition (const int) const -> bool;
193  auto isChangeYPosition (const int) const -> bool;
194  void changeX (const std::size_t, const int);
195  void changeY (const std::size_t, const int);
196  void calculateScrollBarPos() const;
197  template <typename Callback>
198  void initScrollBar (FScrollBarPtr&, Orientation, Callback);
199  void setHorizontalScrollBarVisibility() const;
200  void setVerticalScrollBarVisibility() const;
201  void setViewportCursor();
202  auto shouldUpdateScrollBar (FScrollBar::ScrollType) const -> bool;
203  auto getVerticalScrollDistance (const FScrollBar::ScrollType) const -> int;
204  auto getHorizontalScrollDistance (const FScrollBar::ScrollType) const -> int;
205 
206  // Callback methods
207  void cb_vbarChange (const FWidget*);
208  void cb_hbarChange (const FWidget*);
209 
210  // Data members
211  FRect scroll_geometry{1, 1, 1, 1};
212  FRect viewport_geometry{};
213  std::unique_ptr<FTermRegion> viewport{}; // virtual scroll content
214  FString text{};
215  FScrollBarPtr vbar{nullptr};
216  FScrollBarPtr hbar{nullptr};
217  KeyMap key_map{};
218  uInt8 nf_offset{0};
219  bool use_own_print_region{false};
220  bool update_scroll_bar{true};
221  ScrollBarMode v_mode{ScrollBarMode::Auto}; // fc:Auto, fc::Hidden or fc::Scroll
222  ScrollBarMode h_mode{ScrollBarMode::Auto};
223 };
224 
225 // FScrollView inline functions
226 //----------------------------------------------------------------------
227 inline auto FScrollView::getText() & -> FString&
228 { return text; }
229 
230 //----------------------------------------------------------------------
231 inline auto FScrollView::getClassName() const -> FString
232 { return "FScrollView"; }
233 
234 //----------------------------------------------------------------------
235 inline auto FScrollView::getViewportWidth() const -> std::size_t
236 {
237  const auto width = std::size_t(getGeometry().getWidth());
238  const auto viewport_height = getViewportHeight();
239 
240  if ( getScrollHeight() > viewport_height )
241  {
242  const auto total_spacing = vertical_border_spacing + std::size_t(nf_offset);
243  return width > total_spacing
244  ? width - total_spacing
245  : 1;
246  }
247 
248  return width > vertical_border_spacing
249  ? width - vertical_border_spacing
250  : 1;
251 }
252 
253 //----------------------------------------------------------------------
254 inline auto FScrollView::getViewportHeight() const -> std::size_t
255 {
256  const auto height = std::size_t(getGeometry().getHeight());
257 
258  if ( height <= horizontal_border_spacing )
259  return 1;
260 
261  return std::max<std::size_t>(1, height - horizontal_border_spacing);
262 }
263 
264 //----------------------------------------------------------------------
265 inline auto FScrollView::getViewportSize() const -> FSize
266 { return { FSize{getViewportWidth(), getViewportHeight()} }; }
267 
268 //----------------------------------------------------------------------
269 inline auto FScrollView::getScrollWidth() const -> std::size_t
270 { return scroll_geometry.getWidth(); }
271 
272 //----------------------------------------------------------------------
273 inline auto FScrollView::getScrollHeight() const -> std::size_t
274 { return scroll_geometry.getHeight(); }
275 
276 //----------------------------------------------------------------------
277 inline auto FScrollView::getScrollSize() const -> FSize
278 { return scroll_geometry.getSize(); }
279 
280 //----------------------------------------------------------------------
281 inline auto FScrollView::getScrollPos() const -> FPoint
282 { return viewport_geometry.getPos(); }
283 
284 //----------------------------------------------------------------------
285 inline auto FScrollView::getScrollX() const -> int
286 { return viewport_geometry.getX(); }
287 
288 //----------------------------------------------------------------------
289 inline auto FScrollView::getScrollY() const -> int
290 { return viewport_geometry.getY(); }
291 
292 //----------------------------------------------------------------------
293 inline void FScrollView::unsetViewportPrint()
294 { setViewportPrint(false); }
295 
296 //----------------------------------------------------------------------
297 inline void FScrollView::unsetBorder()
298 { setBorder(false); }
299 
300 //----------------------------------------------------------------------
301 inline auto FScrollView::hasBorder() const -> bool
302 { return ! getFlags().feature.no_border; }
303 
304 //----------------------------------------------------------------------
305 inline auto FScrollView::isViewportPrint() const -> bool
306 { return ! use_own_print_region; }
307 
308 //----------------------------------------------------------------------
309 inline void FScrollView::scrollTo (const FPoint& pos)
310 { scrollTo(pos.getX(), pos.getY()); }
311 
312 //----------------------------------------------------------------------
313 inline void FScrollView::print (const FPoint& pos)
314 {
315  if ( use_own_print_region )
316  FWidget::setPrintPos(pos);
317  else
318  setPrintPos(pos);
319 }
320 
321 //----------------------------------------------------------------------
322 template <typename Callback>
323 inline void FScrollView::initScrollBar ( FScrollBarPtr& bar
324  , Orientation o
325  , Callback cb_handler )
326 {
327  finalcut::initScrollBar (bar, o, this, cb_handler);
328  FTermRegion* region = FScrollView::getPrintRegion();
329  finalcut::setPrintRegion (*bar, region);
330 }
331 
332 } // namespace finalcut
333 
334 #endif // FSCROLLVIEW_H
Definition: fevent.h:207
Definition: fevent.h:144
Definition: frect.h:56
Definition: fevent.h:182
Definition: class_template.cpp:25
Definition: fscrollview.h:67
Definition: fpoint.h:50
Definition: fsize.h:55
Definition: fstring.h:82
Definition: fwidget.h:129
Definition: fevent.h:231
Definition: fevent.h:124
Definition: ftypes.h:161