Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/vcl/weld/TreeView.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#pragma once
11
12
#include <vcl/dllapi.h>
13
#include <vcl/weld/ItemView.hxx>
14
15
class OutputDevice;
16
enum class SelectionMode;
17
enum class TxtAlign;
18
19
namespace com::sun::star::graphic
20
{
21
class XGraphic;
22
}
23
24
namespace vcl
25
{
26
typedef OutputDevice RenderContext;
27
}
28
29
namespace weld
30
{
31
enum class ColumnToggleType
32
{
33
    Check,
34
    Radio
35
};
36
37
/* Model column indexes are considered to begin at 0, but with special columns
38
   before index 0. A expander image column (and an additional optional toggle
39
   button column when enable_toggle_buttons is used). Column index -1 is
40
   reserved to access those columns.
41
*/
42
class VCL_DLLPUBLIC TreeView : virtual public ItemView
43
{
44
public:
45
    typedef std::pair<const TreeIter&, int> iter_col;
46
47
    struct IterColText
48
    {
49
        const weld::TreeIter& m_rIter;
50
        int m_nColumn;
51
        OUString m_sText;
52
53
    public:
54
        IterColText(const weld::TreeIter& rIter, int nColumn, const OUString& rText)
55
0
            : m_rIter(rIter)
56
0
            , m_nColumn(nColumn)
57
0
            , m_sText(rText)
58
0
        {
59
0
        }
60
    };
61
62
    // OUString is the id of the row, it may be null to measure the height of a generic line
63
    typedef std::pair<vcl::RenderContext&, const OUString&> get_size_args;
64
    typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, bool, const OUString&>
65
        render_args;
66
67
private:
68
    Link<int, void> m_aColumnHeaderClickedHdl;
69
    Link<const iter_col&, void> m_aRadioToggleHdl;
70
    Link<const TreeIter&, bool> m_aEditingStartedHdl;
71
    Link<const IterColText&, bool> m_aEditingDoneHdl;
72
    // if handler returns false, the expansion of the row is refused
73
    Link<const TreeIter&, bool> m_aExpandingHdl;
74
    // if handler returns false, the collapse of the row is refused
75
    Link<const TreeIter&, bool> m_aCollapsingHdl;
76
    Link<TreeView&, void> m_aVisibleRangeChangedHdl;
77
    Link<TreeView&, void> m_aModelChangedHdl;
78
79
protected:
80
    // if handler returns true, drag is disallowed, consumer can change bool
81
    // arg to false to disable the treeview default dnd icon
82
    Link<bool&, bool> m_aDragBeginHdl;
83
    std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;
84
85
protected:
86
0
    void signal_column_header_clicked(int nColumn) { m_aColumnHeaderClickedHdl.Call(nColumn); }
87
    bool signal_expanding(const TreeIter& rIter)
88
0
    {
89
0
        return !m_aExpandingHdl.IsSet() || m_aExpandingHdl.Call(rIter);
90
0
    }
91
    bool signal_collapsing(const TreeIter& rIter)
92
0
    {
93
0
        return !m_aCollapsingHdl.IsSet() || m_aCollapsingHdl.Call(rIter);
94
0
    }
95
    void signal_visible_range_changed()
96
0
    {
97
0
        if (notify_events_disabled())
98
0
            return;
99
0
        m_aVisibleRangeChangedHdl.Call(*this);
100
0
    }
101
102
    void signal_model_changed()
103
0
    {
104
0
        if (notify_events_disabled())
105
0
            return;
106
0
        m_aModelChangedHdl.Call(*this);
107
0
    }
108
109
    void signal_toggled(const iter_col& rIterCol)
110
0
    {
111
0
        if (notify_events_disabled())
112
0
            return;
113
0
        m_aRadioToggleHdl.Call(rIterCol);
114
0
    }
115
116
0
    bool signal_editing_started(const TreeIter& rIter) { return m_aEditingStartedHdl.Call(rIter); }
117
118
    bool signal_editing_done(const IterColText& rIterText)
119
0
    {
120
0
        return m_aEditingDoneHdl.Call(rIterText);
121
0
    }
122
123
    Link<const TreeIter&, OUString> m_aQueryTooltipHdl;
124
125
    OUString signal_query_tooltip(const TreeIter& rIter)
126
0
    {
127
0
        if (notify_events_disabled())
128
0
            return {};
129
0
        return m_aQueryTooltipHdl.Call(rIter);
130
0
    }
131
132
    Link<render_args, void> m_aRenderHdl;
133
    void signal_custom_render(vcl::RenderContext& rDevice, const tools::Rectangle& rRect,
134
                              bool bSelected, const OUString& rId)
135
0
    {
136
0
        m_aRenderHdl.Call(render_args(rDevice, rRect, bSelected, rId));
137
0
    }
138
139
    Link<get_size_args, Size> m_aGetSizeHdl;
140
    Size signal_custom_get_size(vcl::RenderContext& rDevice, const OUString& rId)
141
0
    {
142
0
        return m_aGetSizeHdl.Call(get_size_args(rDevice, rId));
143
0
    }
144
145
    virtual void do_insert(const TreeIter* pParent, int pos, const OUString* pStr,
146
                           const OUString* pId, const OUString* pIconName,
147
                           VirtualDevice* pImageSurface, bool bChildrenOnDemand, TreeIter* pRet)
148
        = 0;
149
    virtual void do_insert_separator(int pos, const OUString& rId) = 0;
150
    using weld::ItemView::do_set_cursor;
151
    virtual void do_set_toggle(const TreeIter& rIter, TriState bOn, int col = -1) = 0;
152
    virtual void do_set_cursor(int pos) = 0;
153
    virtual void do_scroll_to_row(const TreeIter& rIter) = 0;
154
    virtual int do_iter_n_children(const TreeIter& rIter) const = 0;
155
    virtual bool do_iter_children(TreeIter& rIter) const = 0;
156
    virtual void do_set_children_on_demand(const TreeIter& rIter, bool bChildrenOnDemand) = 0;
157
    virtual void do_remove_selection() = 0;
158
159
public:
160
    virtual void connect_query_tooltip(const Link<const TreeIter&, OUString>& rLink)
161
0
    {
162
0
        assert(!m_aQueryTooltipHdl.IsSet() || !rLink.IsSet());
163
0
        m_aQueryTooltipHdl = rLink;
164
0
    }
165
166
    // see 'expanding on-demand node details' for bChildrenOnDemand of true
167
    void insert(const TreeIter* pParent, int pos, const OUString* pStr, const OUString* pId,
168
                const OUString* pIconName, VirtualDevice* pImageSurface, bool bChildrenOnDemand,
169
                TreeIter* pRet)
170
0
    {
171
0
        disable_notify_events();
172
0
        do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface, bChildrenOnDemand, pRet);
173
0
        enable_notify_events();
174
0
    }
175
176
    void insert(int nRow, TreeIter* pRet = nullptr)
177
0
    {
178
0
        insert(nullptr, nRow, nullptr, nullptr, nullptr, nullptr, false, pRet);
179
0
    }
180
181
0
    void append(TreeIter* pRet = nullptr) { insert(-1, pRet); }
182
183
    void insert(int pos, const OUString& rStr, const OUString* pId, const OUString* pIconName,
184
                VirtualDevice* pImageSurface)
185
0
    {
186
0
        insert(nullptr, pos, &rStr, pId, pIconName, pImageSurface, false, nullptr);
187
0
    }
188
    void insert_text(int pos, const OUString& rStr)
189
0
    {
190
0
        insert(nullptr, pos, &rStr, nullptr, nullptr, nullptr, false, nullptr);
191
0
    }
192
    void append_text(const OUString& rStr)
193
0
    {
194
0
        insert(nullptr, -1, &rStr, nullptr, nullptr, nullptr, false, nullptr);
195
0
    }
196
    void append(const OUString& rId, const OUString& rStr)
197
0
    {
198
0
        insert(nullptr, -1, &rStr, &rId, nullptr, nullptr, false, nullptr);
199
0
    }
200
    void append(const OUString& rId, const OUString& rStr, const OUString& rImage)
201
0
    {
202
0
        insert(nullptr, -1, &rStr, &rId, &rImage, nullptr, false, nullptr);
203
0
    }
204
    void append(const TreeIter* pParent, const OUString& rStr)
205
0
    {
206
0
        insert(pParent, -1, &rStr, nullptr, nullptr, nullptr, false, nullptr);
207
0
    }
208
209
    void insert_separator(int pos, const OUString& rId)
210
0
    {
211
0
        disable_notify_events();
212
0
        do_insert_separator(pos, rId);
213
0
        enable_notify_events();
214
0
    }
215
216
0
    void append_separator(const OUString& rId) { insert_separator(-1, rId); }
217
218
    // Argument is a pair of iter, col describing the toggled node
219
0
    void connect_toggled(const Link<const iter_col&, void>& rLink) { m_aRadioToggleHdl = rLink; }
220
221
    void connect_column_header_clicked(const Link<int, void>& rLink)
222
0
    {
223
0
        m_aColumnHeaderClickedHdl = rLink;
224
0
    }
225
0
    void connect_model_changed(const Link<TreeView&, void>& rLink) { m_aModelChangedHdl = rLink; }
226
227
    /**
228
     * Call before inserting any content and connecting to toggle signals,
229
     * a pre-inserted checkbutton column will exist at the start of every row
230
     * inserted after this call which can be accessed with col index -1
231
     *
232
     * (For the corresponding GtkTreeView definition in the .ui file, the first GtkTreeViewColumn
233
     * must contain a leading GtkCellRendererToggle to be used for this, in addition
234
     * to a renderer for the content referred to by the regular column index of 0.)
235
     */
236
    virtual void enable_toggle_buttons() = 0;
237
238
    /**
239
     * Set the type of all toggle buttons used in the TreeView.
240
     * (By default, check buttons are used.)
241
     *
242
     * Call before inserting any entries.
243
     */
244
    virtual void set_toggle_button_type(ColumnToggleType eType) = 0;
245
246
    virtual void set_clicks_to_toggle(int nToggleBehavior) = 0;
247
248
    // col index -1 gets the first text column
249
    OUString get_text(int row, int col = -1) const;
250
    virtual OUString get_text(const TreeIter& rIter, int col = -1) const = 0;
251
252
    // col index -1 sets the first text column
253
    void set_text(int row, const OUString& rText, int col = -1);
254
    virtual void set_text(const TreeIter& rIter, const OUString& rStr, int col = -1) = 0;
255
256
    // col index -1 sets all columns
257
    void set_sensitive(int row, bool bSensitive, int col = -1);
258
    virtual void set_sensitive(const TreeIter& rIter, bool bSensitive, int col = -1) = 0;
259
260
    virtual bool get_sensitive(const TreeIter& rIter, int col) const = 0;
261
262
    // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column
263
    void set_toggle(int row, TriState eState, int col = -1);
264
    void set_toggle(const TreeIter& rIter, TriState bOn, int col = -1);
265
266
    // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column
267
    TriState get_toggle(int row, int col = -1) const;
268
    virtual TriState get_toggle(const TreeIter& rIter, int col = -1) const = 0;
269
270
    // col index -1 sets the expander image
271
    void set_image(int row, const OUString& rImage, int col = -1);
272
    virtual void set_image(const TreeIter& rIter, const OUString& rImage, int col = -1) = 0;
273
    // col index -1 sets the expander image
274
    void set_image(int row, VirtualDevice& rImage, int col = -1);
275
    virtual void set_image(const TreeIter& rIter, VirtualDevice& rImage, int col = -1) = 0;
276
    // col index -1 sets the expander image
277
    void set_image(int row, const css::uno::Reference<css::graphic::XGraphic>& rImage,
278
                   int col = -1);
279
    virtual void set_image(const TreeIter& rIter,
280
                           const css::uno::Reference<css::graphic::XGraphic>& rImage, int col = -1)
281
        = 0;
282
283
    // col index -1 sets text emphasis for all columns
284
    void set_text_emphasis(int row, bool bOn, int col);
285
    virtual void set_text_emphasis(const TreeIter& rIter, bool bOn, int col) = 0;
286
    bool get_text_emphasis(int row, int col) const;
287
    virtual bool get_text_emphasis(const TreeIter& rIter, int col) const = 0;
288
289
    void set_text_align(int row, TxtAlign eAlign, int col);
290
    virtual void set_text_align(const TreeIter& rIter, TxtAlign eAlign, int col) = 0;
291
292
    virtual void swap(int pos1, int pos2) = 0;
293
    virtual std::vector<int> get_selected_rows() const = 0;
294
295
    void set_font_color(int pos, const Color& rColor);
296
    virtual void set_font_color(const TreeIter& rIter, const Color& rColor) = 0;
297
298
    // scroll to make given row visible, this will also expand all parent rows
299
    // of the row as necessary to make the row visible
300
    void scroll_to_row(int row);
301
    void scroll_to_row(const TreeIter& rIter);
302
303
    bool is_selected(int pos) const;
304
    virtual bool is_selected(const TreeIter& rIter) const = 0;
305
306
    using weld::ItemView::set_cursor;
307
    void set_cursor(int pos)
308
0
    {
309
0
        disable_notify_events();
310
0
        do_set_cursor(pos);
311
0
        enable_notify_events();
312
0
    }
313
314
    //by text
315
    virtual int find_text(const OUString& rText) const = 0;
316
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
317
0
    void select_text(const OUString& rText) { select(find_text(rText)); }
318
0
    void remove_text(const OUString& rText) { remove(find_text(rText)); }
319
    std::vector<OUString> get_selected_rows_text() const
320
0
    {
321
0
        std::vector<int> aRows(get_selected_rows());
322
0
        std::vector<OUString> aRet;
323
0
        aRet.reserve(aRows.size());
324
0
        for (auto a : aRows)
325
0
            aRet.push_back(get_text(a));
326
0
        return aRet;
327
0
    }
328
329
    //by id
330
    virtual int find_id(const OUString& rId) const = 0;
331
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
332
0
    void select_id(const OUString& rId) { select(find_id(rId)); }
333
0
    void remove_id(const OUString& rText) { remove(find_id(rText)); }
334
335
    virtual void copy_iterator(const TreeIter& rSource, TreeIter& rDest) const = 0;
336
337
    // set iter to point to previous node at the current level
338
    virtual bool iter_previous_sibling(TreeIter& rIter) const = 0;
339
    // set iter to point to next node, depth first, then sibling
340
    bool iter_next(TreeIter& rIter) const;
341
    // set iter to point to previous node, sibling first then depth
342
    bool iter_previous(TreeIter& rIter) const;
343
    // set iter to point to first child node
344
    bool iter_children(TreeIter& rIter) const;
345
    bool iter_nth_sibling(TreeIter& rIter, int nChild) const
346
0
    {
347
0
        bool bRet = true;
348
0
        for (int i = 0; i < nChild && bRet; ++i)
349
0
            bRet = iter_next_sibling(rIter);
350
0
        return bRet;
351
0
    }
352
    bool iter_nth_child(TreeIter& rIter, int nChild) const
353
0
    {
354
0
        if (!iter_children(rIter))
355
0
            return false;
356
0
        return iter_nth_sibling(rIter, nChild);
357
0
    }
358
    virtual bool iter_parent(TreeIter& rIter) const = 0;
359
    virtual int get_iter_depth(const TreeIter& rIter) const = 0;
360
    /* Compares two paths. If a appears before b in a tree, then -1 is returned.
361
       If b appears before a , then 1 is returned. If the two nodes are equal,
362
       then 0 is returned.
363
    */
364
    virtual int iter_compare(const TreeIter& rIterA, const TreeIter& rIterB) const;
365
    bool iter_has_child(const TreeIter& rIter) const;
366
    // returns the number of direct children rIter has
367
    int iter_n_children(const TreeIter& rIter) const;
368
369
    //visually indent this row as if it was at get_iter_depth() + nIndentLevel
370
    virtual void set_extra_row_indent(const TreeIter& rIter, int nIndentLevel) = 0;
371
372
    virtual void move_subtree(TreeIter& rNode, const TreeIter* pNewParent, int nIndexInNewParent)
373
        = 0;
374
375
    // call func on each element until func returns true or we run out of elements
376
    virtual void all_foreach(const std::function<bool(TreeIter&)>& func) = 0;
377
    // call func on each visible element until func returns true or we run out of elements
378
    virtual void visible_foreach(const std::function<bool(TreeIter&)>& func) = 0;
379
    // clear the children of pParent (whole tree if nullptr),
380
    // then add nSourceCount rows under pParent, call func on each row
381
    // inserted with an arg of the index that this row will be when bulk insert
382
    // ends.
383
    //
384
    // this enables inserting the entries backwards in models where that is faster,
385
    //
386
    // pFixedWidths is optional, when present each matching entry col text
387
    // width will not be measured, and the fixed width used instead. Use
388
    // sparingly because wider text than the fixed width is clipped and cannot
389
    // be scrolled into view horizontally.
390
    // @param bGoingToSetText needs to be true, if you plan to call set_text inside the insert func.
391
    virtual void bulk_insert_for_each(int nSourceCount,
392
                                      const std::function<void(TreeIter&, int nSourceIndex)>& func,
393
                                      const weld::TreeIter* pParent = nullptr,
394
                                      const std::vector<int>* pFixedWidths = nullptr,
395
                                      bool bGoingToSetText = false,
396
                                      bool bForceForwardInsert = false)
397
        = 0;
398
399
    /* expanding on-demand node details
400
401
    When a node is added with children-on-demand (typically via 'insert' with
402
    bChildrenOnDemand of true), then it shows an expander indicator even if
403
    it doesn't have any "real" child entries (yet).
404
405
    (Depending on the underlying toolkit, implementations may in reality give
406
    the children-on-demand node a 'placeholder' child entry to indicate the
407
    load-on-demand state and ensure the treeview draws/shows the expander
408
    indicator even when there are no "real" entries yet. In that case, this
409
    child doesn't exist for the purposes of any of the iterator methods,
410
    e.g. iter_has_child on an on-demand node which hasn't been expanded yet
411
    is false. Likewise the rest of the iterator methods skip over or otherwise
412
    ignore that node.)
413
414
    Normal usage is the user clicks on the expander, the expansion mechanism
415
    disables on-demand nodes (set_children_on_demand(false)) and calls
416
    any installed expanding-callback (installable via connect_expanding) which
417
    has the opportunity to populate the node with children.
418
419
    If you decide to directly populate the children of an on-demand node
420
    outside of the expanding-callback then you also need to explicitly disable
421
    on-demand mode with set_children_on_demand(false); otherwise the treeview
422
    is in an inconsistent state.  */
423
424
    virtual bool get_row_expanded(const TreeIter& rIter) const = 0;
425
    // expand row will first trigger the callback set via connect_expanding before expanding
426
    virtual void expand_row(const TreeIter& rIter) = 0;
427
    // collapse row will first trigger the callback set via connect_collapsing before collapsing
428
    virtual void collapse_row(const TreeIter& rIter) = 0;
429
430
    // set the empty node to appear as if it has children, true is equivalent
431
    // to 'insert' with a bChildrenOnDemand of true. See notes above.
432
    void set_children_on_demand(const TreeIter& rIter, bool bChildrenOnDemand)
433
0
    {
434
0
        disable_notify_events();
435
0
        do_set_children_on_demand(rIter, bChildrenOnDemand);
436
0
        enable_notify_events();
437
0
    }
438
439
    // return if the node is configured to be populated on-demand
440
    virtual bool get_children_on_demand(const TreeIter& rIter) const = 0;
441
    // set if the expanders are shown or not
442
    virtual void set_show_expanders(bool bShow) = 0;
443
444
0
    void connect_expanding(const Link<const TreeIter&, bool>& rLink) { m_aExpandingHdl = rLink; }
445
0
    void connect_collapsing(const Link<const TreeIter&, bool>& rLink) { m_aCollapsingHdl = rLink; }
446
447
    // rStartLink returns true to allow editing, false to disallow
448
    // rEndLink returns true to accept the edit, false to reject
449
    virtual void connect_editing(const Link<const TreeIter&, bool>& rStartLink,
450
                                 const Link<const IterColText&, bool>& rEndLink)
451
0
    {
452
0
        assert(rStartLink.IsSet() == rEndLink.IsSet() && "should be both on or both off");
453
0
        m_aEditingStartedHdl = rStartLink;
454
0
        m_aEditingDoneHdl = rEndLink;
455
0
    }
456
457
    virtual void start_editing(const weld::TreeIter& rEntry) = 0;
458
    virtual void end_editing() = 0;
459
460
    virtual void connect_visible_range_changed(const Link<TreeView&, void>& rLink)
461
0
    {
462
0
        assert(!m_aVisibleRangeChangedHdl.IsSet() || !rLink.IsSet());
463
0
        m_aVisibleRangeChangedHdl = rLink;
464
0
    }
465
466
    virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rTransferable,
467
                                    sal_uInt8 eDNDConstants)
468
        = 0;
469
470
0
    void connect_drag_begin(const Link<bool&, bool>& rLink) { m_aDragBeginHdl = rLink; }
471
472
    // afterwards, entries will be in default ascending sort order
473
    virtual void make_sorted() = 0;
474
    virtual void make_unsorted() = 0;
475
    virtual bool get_sort_order() const = 0;
476
    virtual void set_sort_order(bool bAscending) = 0;
477
478
    // TRUE ascending, FALSE, descending, INDET, neither (off)
479
    virtual void set_sort_indicator(TriState eState, int nColumn) = 0;
480
    virtual TriState get_sort_indicator(int nColumn) const = 0;
481
482
    virtual int get_sort_column() const = 0;
483
    virtual void set_sort_column(int nColumn) = 0;
484
485
    virtual void
486
    set_sort_func(const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func)
487
0
    {
488
0
        m_aCustomSort = func;
489
0
    }
490
491
    virtual int get_height_rows(int nRows) const = 0;
492
493
    virtual void columns_autosize() = 0;
494
    virtual void set_column_fixed_widths(const std::vector<int>& rWidths) = 0;
495
    virtual void set_column_editables(const std::vector<bool>& rEditables) = 0;
496
    virtual int get_column_width(int nCol) const = 0;
497
    virtual void set_centered_column(int nCol) = 0;
498
    virtual OUString get_column_title(int nColumn) const = 0;
499
    virtual void set_column_title(int nColumn, const OUString& rTitle) = 0;
500
501
    virtual bool get_column_visible(int nColumn) const = 0;
502
    virtual void set_column_visible(int nColumn, bool bVisible) = 0;
503
504
0
    int get_checkbox_column_width() const { return get_approximate_digit_width() * 3 + 6; }
505
506
    virtual void set_selection_mode(SelectionMode eMode) = 0;
507
    virtual int count_selected_rows() const = 0;
508
509
    // remove the selected nodes
510
    void remove_selection()
511
0
    {
512
0
        disable_notify_events();
513
0
        do_remove_selection();
514
0
        enable_notify_events();
515
0
    }
516
517
    // only meaningful is call this from a "changed" callback, true if the change
518
    // was due to mouse hovering over the entry
519
    virtual bool changed_by_hover() const = 0;
520
521
    virtual void vadjustment_set_value(int value) = 0;
522
    virtual int vadjustment_get_value() const = 0;
523
524
    // for custom rendering a cell
525
0
    void connect_custom_get_size(const Link<get_size_args, Size>& rLink) { m_aGetSizeHdl = rLink; }
526
0
    void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; }
527
    // call set_column_custom_renderer after setting custom callbacks
528
    virtual void set_column_custom_renderer(int nColumn, bool bEnable) = 0;
529
    // redraw all rows, typically only useful with custom rendering to redraw due to external
530
    // state change
531
    virtual void queue_draw() = 0;
532
533
    /* with bDnDMode false simply return the row under the point
534
     *
535
     * with bDnDMode true:
536
     * a) return the row which should be dropped on, which may
537
     *    be different from the row the mouse is over in some backends where
538
     *    positioning the mouse on the bottom half of a row indicates to drop
539
     *    after the row
540
     * b) dnd highlight the dest row
541
     */
542
    virtual std::unique_ptr<weld::TreeIter> get_dest_row_at_pos(const Point& rPos, bool bDnDMode,
543
                                                                bool bAutoScroll = true)
544
        = 0;
545
    virtual void unset_drag_dest_row() = 0;
546
    virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0;
547
    // for dragging and dropping between TreeViews, return the active source
548
    virtual TreeView* get_drag_source() const = 0;
549
550
    using Widget::set_sensitive;
551
    using Widget::get_sensitive;
552
553
private:
554
    void last_child(weld::TreeIter& rIter, int nChildren) const;
555
};
556
}
557
558
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */