reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

listview.hpp (5225B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #ifndef REAPACK_LISTVIEW_HPP
     19 #define REAPACK_LISTVIEW_HPP
     20 
     21 #include "control.hpp"
     22 
     23 #include "event.hpp"
     24 #include "filter.hpp"
     25 #include "serializer.hpp"
     26 
     27 #include <functional>
     28 #include <optional>
     29 #include <vector>
     30 
     31 class Menu;
     32 
     33 class ListView : public Control {
     34 public:
     35   enum SortOrder { AscendingOrder, DescendingOrder };
     36 
     37   enum ColumnFlag {
     38     NoLabelFlag  = 1<<0,
     39     CollapseFlag = 1<<1,
     40     FilterFlag   = 1<<2,
     41   };
     42 
     43   enum ColumnDataType {
     44     UserType,
     45     VersionType,
     46     TimeType,
     47   };
     48 
     49   struct Cell {
     50     Cell() : userData(nullptr) {}
     51     Cell(const Cell &) = delete;
     52 
     53     std::string value;
     54     void *userData;
     55   };
     56 
     57   class Row {
     58   public:
     59     Row(void *data, ListView *);
     60     Row(const Row &) = delete;
     61     ~Row() { delete[] m_cells; }
     62 
     63     void *userData;
     64 
     65     int index() const { return userIndex; }
     66 
     67     const Cell &cell(const int i) const { return m_cells[i]; }
     68     void setCell(const int i, const std::string &, void *data = nullptr);
     69     void setChecked(bool check = true);
     70 
     71     std::vector<std::string> filterValues() const;
     72 
     73   protected:
     74     friend ListView;
     75     int viewIndex;
     76     int userIndex;
     77 
     78   private:
     79     ListView *m_list;
     80     Cell *m_cells;
     81   };
     82 
     83   struct Column {
     84     std::string label;
     85     int width;
     86     int flags;
     87     ColumnDataType dataType;
     88 
     89     bool test(ColumnFlag f) const { return (flags & f) != 0; }
     90     int compare(const Cell &, const Cell &) const;
     91   };
     92 
     93   // Use before modifying the list's content. It will re-sort and/or re-filter the
     94   // list automatically when destructed and, on Windows, also prevents flickering.
     95   class BeginEdit {
     96   public:
     97     BeginEdit(ListView *lv) : m_list(lv), m_inhibit(lv) {}
     98     ~BeginEdit() { m_list->endEdit(); }
     99 
    100   private:
    101     ListView *m_list;
    102     InhibitControl m_inhibit;
    103   };
    104 
    105   typedef std::vector<Column> Columns;
    106 
    107   ListView(HWND handle, const Columns & = {});
    108 
    109   void reserveRows(size_t count) { m_rows.reserve(count); }
    110   Row *createRow(void *data = nullptr);
    111   Row *row(size_t index) const { return m_rows[index].get(); }
    112   void removeRow(int index);
    113   int rowCount() const { return static_cast<int>(m_rows.size()); }
    114   int visibleRowCount() const;
    115   bool empty() const { return m_rows.empty(); }
    116 
    117   void clear();
    118   void reset();
    119   void autoSizeHeader();
    120   void enableIcons();
    121 
    122   int currentIndex() const;
    123   bool headerHitTest(int x, int y) const;
    124   int itemUnder(int x, int y, bool *overIcon = nullptr) const;
    125   int itemUnderMouse(bool *overIcon = nullptr) const;
    126 
    127   int scroll() const;
    128   void setScroll(int);
    129 
    130   void setSelected(int index, bool select);
    131   void select(int index) { setSelected(index, true); }
    132   void unselect(int index) { setSelected(index, false); }
    133   void selectAll();
    134   void unselectAll();
    135   int selectionSize() const;
    136   bool hasSelection() const { return selectionSize() > 0; }
    137   std::vector<int> selection(bool sort = true) const;
    138 
    139   int addColumn(const Column &);
    140   const Column &column(int index) const { return m_cols[index]; }
    141   void resizeColumn(int index, int width);
    142   int columnWidth(int index) const;
    143   int columnCount() const;
    144 
    145   void sortByColumn(int index, SortOrder order = AscendingOrder, bool user = false);
    146   void setFilter(const std::string &);
    147   void endEdit();
    148 
    149   void restoreState(Serializer::Data &);
    150   void saveState(Serializer::Data &) const;
    151   void resetColumns();
    152 
    153   Event<void()> onSelect;
    154   Event<void()> onIconClick;
    155   Event<void()> onActivate;
    156   Event<bool(Menu &, int index)> onFillContextMenu;
    157 
    158 protected:
    159   friend Row;
    160 
    161   void updateCell(int row, int cell);
    162   void setRowIcon(int row, int icon);
    163 
    164 private:
    165   struct Sort {
    166     int column = -1;
    167     SortOrder order = AscendingOrder;
    168   };
    169 
    170   enum DirtyFlag {
    171     NeedSortFlag    = 1<<0,
    172     NeedReindexFlag = 1<<1,
    173     NeedFilterFlag  = 1<<2,
    174   };
    175 
    176   void onNotify(LPNMHDR, LPARAM) override;
    177   bool onContextMenu(HWND, int, int) override;
    178 
    179   void setExStyle(int style, bool enable = true);
    180   void setSortArrow(bool);
    181   void onItemChanged(LPARAM lpnmlistview);
    182   void onClick(bool dbclick);
    183   void onColumnClick(LPARAM lpnmlistview);
    184   int translate(int userIndex) const;
    185   int translateBack(int internalIndex) const;
    186   void headerMenu(int x, int y);
    187   void insertItem(int viewIndex, int rowIndex);
    188   void sort();
    189   void reindexVisible();
    190   void filter();
    191 
    192   int m_dirty;
    193   Filter m_filter;
    194 
    195   bool m_customizable;
    196   std::vector<Column> m_cols;
    197   std::vector<std::unique_ptr<Row>> m_rows;
    198   std::optional<Sort> m_sort;
    199   std::optional<Sort> m_defaultSort;
    200 };
    201 
    202 #endif