1 /* fieldlistview.h
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2002-2019 Ralf Hoffmann.
4  * You can contact me at: ralf@boomerangsworld.de
5  *   or http://www.boomerangsworld.de/worker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #ifndef NEWLISTVIEW_H
23 #define NEWLISTVIEW_H
24 
25 #include "aguixdefs.h"
26 #include "util.h"
27 #include "guielement.h"
28 #include "fieldlvrowdata.h"
29 #include <string>
30 #include <stdio.h>
31 #include <X11/Xlib.h>
32 #include <X11/X.h>
33 #include <set>
34 #include <functional>
35 
36 class AGUIX;
37 class AGUIXFont;
38 
39 class FieldListView:public GUIElement
40 {
41 public:
42   FieldListView( AGUIX *caguix, int cx, int cy, int cwidth, int cheight, int cdata );
43   virtual ~FieldListView();
44   FieldListView( const FieldListView &other );
45   FieldListView &operator=( const FieldListView &other );
46 
47   void setNrOfFields( int nv );
48   int getNrOfFields() const;
49   void setText( int row, int field, std::string text, bool update_simple_set = false );
50   std::string getText( int row, int field ) const;
51   void trimElements();
52   void setFieldWidth( int field, int width );
53   void setFieldWidthQ( int field, int width );
54   void setSize( int rows ); // create/delete needed rows
55   int getUsedWidth( int field );
56   int addRow();
57   int deleteRow( int row );
58   int insertRow( int row );
59   void swapRows( int row1, int row2 );
60   void setStrikeOut( int row, int field, bool nv );
61   bool getStrikeOut( int row, int field ) const;
62   void setStrikeOutStart( int row, int field, size_t nv );
63   size_t getStrikeOutStart( int row, int field ) const;
64 
65   void setXOffset( int nv, bool no_redraw = false );
66   int getMaxTextWidth();
67   void setYOffset( int nv, bool no_redraw = false );
68 
69   typedef enum { ALIGN_LEFT, ALIGN_RIGHT } align_t;
70 
71   void setFieldAlign( int field, align_t nv );
72   void setFieldAlignQ( int field, align_t nv );
73 
74   void setFieldTextQ( int field, const std::string nv );
75   void setFieldText( int field, const std::string nv );
76   std::string getFieldText( int field ) const;
77 
78   // true to merge with following field text
79   void setFieldTextMergedQ( int field, bool nv );
80   void setFieldTextMerged( int field, bool nv );
81   void setFieldTextResizeable( int field, bool nv );
82 
83   virtual void redraw();
84   void redraw( int element );
85   typedef enum { CC_NORMAL = 0, CC_SELECT = 1, CC_ACTIVE = 2, CC_SELACT = 3 } colorclass_t;
86   void setFG( int row, colorclass_t cc, int col );
87   int getFG( int row, colorclass_t cc ) const;
88   void setBG( int row, colorclass_t cc, int col );
89   int getBG( int row, colorclass_t cc ) const;
90   void setSelect( int row, bool nv );
91   void setSelectQ( int row, bool nv );
92   bool getSelect( int row ) const;
93   void setActiveRow( int nv );
94   void setActiveRowQ( int nv );
95   int getActiveRow() const;
96 
97   void setVisMark( int row, bool nv );
98   void setVisMarkQ( int row, bool nv );
99   bool getVisMark( int row ) const;
100 
101   virtual void resize( int w, int h );
102   int getData() const;
103   void setData( int );
104   virtual void flush();
105   virtual bool handleMessage( XEvent *E, Message *msg );
106   int getXOffset() const;
107   int getYOffset() const;
108   int getElements() const;
109   int getMaxDisplayV() const;
110   void setHBarState( int state );
111   void setVBarState( int state );
112   int getHBarState() const;
113   int getVBarState() const;
114   void setVBarWidth( int new_width );
115   int getVBarWidth() const;
116   void setHBarHeight( int new_height );
117   int getHBarHeight() const;
118   void scrollV( int delta, bool no_redraw = false );
119   void scrollV1( int dir, bool no_redraw = false );
120   void setSelectHandler( void (*nsh)( FieldListView*, int element ) );
121   void setSelectHandler( std::function< void( FieldListView*, int element ) > cb );
122   void showActive();
123   void centerActive();
124   int setFont ( const char * );
125   virtual const char *getType() const;
126   virtual bool isType( const char *type ) const;
127   virtual bool isParent( Window ) const;
128   int getRowHeight() const;
129   int getMBG() const;
130   void setMBG( int color );
131 
132   int maximizeX();
133   int getMaximumWidth();
134   int maximizeY();
135   int getMaximumHeight();
136 
137   void showRow( int row, bool redraw = true);
138 
139   void setData( int row, int ndata );
140   int getData( int row, int fallback_value ) const;
141   void setDataExt( int row, FieldLVRowData *ndata );
142   FieldLVRowData *getDataExt( int row ) const;
143 
144   bool isValidRow( int row ) const;
145 
146   typedef enum { PRECOLOR_NONE, PRECOLOR_NORMAL, PRECOLOR_ONLYSELECT, PRECOLOR_ONLYACTIVE, PRECOLOR_NOTSELORACT } precolor_t;
147   void setPreColors( int row, precolor_t mode );
148   void setDisplayFocus( bool nv );
149   bool getDisplayFocus() const;
150 
151   void cond_redraw();
152   bool isRowVisible( int row ) const;
153 
154   void setShowHeader( bool nv );
155   bool getShowHeader() const;
156   int getHeaderHeight() const;
157   void redrawHeader();
158   void setHeaderFG( int col );
159   void setHeaderBG( int col );
160   int getHeaderFG() const;
161   int getHeaderBG() const;
162   int getHScrollStep() const;
163 
164   int getFieldWidth( int field ) const;
165   int getEffectiveFieldWidth( int field );
166 
167   typedef enum {
168     SELECT_BUTTON,
169     ACTIVATE_BUTTON,
170     SCROLL_BUTTON,
171     ENTRY_PRESSED_MSG_BUTTON
172   } buttonfunction_t;
173   static int changeButtonFunction( buttonfunction_t bf, int button, int mod = 0 );
174 
175   typedef enum { MOUSE_SELECT_NORMAL, MOUSE_SELECT_ALT } mouse_select_t;
176   static int changeSelectMode( mouse_select_t nm );
177 
178   class ColorDef
179   {
180   public:
181     ColorDef();
182     ~ColorDef();
183 
184     void setFG( colorclass_t cc, int col );
185     int getFG( colorclass_t cc ) const;
186     void setBG( colorclass_t cc, int col );
187     int getBG( colorclass_t cc ) const;
188   private:
189     int fg[4], bg[4];
190   };
191   void setColor( int row, const ColorDef &col );
192   ColorDef getColor( int row ) const;
193 
194   void simpleRedrawUpdatedRows();
195   void timeLimitedRedraw();
196 
197   void setGlobalFieldSpace( int spacing );
198   int getFieldSpace( int field ) const;
199   void setFieldSpace( int field, int spacing );
200 
201   void setHighlightSegments( int row, int field, const std::vector< size_t > &segments );
202   const std::vector< size_t > *getHighlightSegments( int row, int field ) const;
203   void clearHighlightSegments();
204 
205   void setConsiderHeaderWidthForDynamicWidth( bool nv );
206   bool getConsiderHeaderWidthForDynamicWidth() const;
207 
208   void setDefaultColorMode( precolor_t mode );
209 
210   struct on_demand_data {
on_demand_dataon_demand_data211       on_demand_data() : done( false ),
212                          text_set( false ),
213                          segments_set( false ),
214                          strike_out_set( false )
215       {}
216 
217       bool done;  // indicates that the caller is done with ondemand data
218 
219       std::string text; // the text for the given row x column
220       bool text_set;
221 
222       std::vector< size_t > segments; // highlight segments
223       bool segments_set;
224 
225       bool strike_out;
226       bool strike_out_set;
227 
228       size_t strike_out_start = 0;
229       bool strike_out_start_set = false;
230   };
231 
232   void setOnDemandCallback( std::function< void( FieldListView*,
233                                                  int row,
234                                                  int field,
235                                                  struct on_demand_data &data ) > cb );
236 
237   void clearOnDemandDataAvailableFlag();
238   void clearOnDemandDataAvailableFlag( int row );
239 
240   typedef enum {
241       HEADER_SORT_HINT_NONE,
242       HEADER_SORT_HINT_UP,
243       HEADER_SORT_HINT_DOWN
244   } header_sort_hint_t;
245 
246   void setSortHint( int field, header_sort_hint_t hint );
247   void unsetSortHint();
248 
249     int getRowYPosition( int row );
250 
251     void setShowSelectionInVBar( bool nv );
252 protected:
253   int fields;
254   int *fieldwidth;
255   int *used_width;
256   int *maxrow;
257 
258   align_t *fieldalign;
259   std::string *fieldtext;
260   bool *fieldtextmerged;
261   bool *fieldtextResizeable;
262 
263   std::vector< int > m_header_text_width;
264   std::vector< int > m_field_spacing;
265 
266   int fieldtextclicked;
267 
268   class Content
269   {
270   public:
271     Content();
272     ~Content();
273     Content( const Content &other );
274     Content &operator=( const Content &other );
275     void setText( int field, std::string text );
276     void trim( int newfields );
277     std::string getText( int field ) const;
278     void setFG( colorclass_t cc, int col );
279     int getFG( colorclass_t cc ) const;
280     void setBG( colorclass_t cc, int col );
281     int getBG( colorclass_t cc ) const;
282     void setSelect( bool nv );
283     bool getSelect() const;
284     void setDataExt( FieldLVRowData *ndata );
285     FieldLVRowData *getDataExt() const;
286     void setData( int ndata );
287     int getData() const;
288     void setMark( bool nv );
289     bool getMark() const;
290 
291     void setStrikeOut( int field, bool nv );
292     bool getStrikeOut( int field ) const;
293 
294     void setStrikeOutStart( int field, size_t nv );
295     size_t getStrikeOutStart( int field ) const;
296 
297     void setHighlightSegments( int field, const std::vector< size_t > &segments );
298     const std::vector< size_t > *getHighlightSegments( int field ) const;
299     void clearHighlightSegments();
300 
getOnDemandDataAvailable()301     bool getOnDemandDataAvailable() const
302     {
303         return m_ondemand_data_available;
304     }
305 
setOnDemandDataAvailable(bool nv)306     void setOnDemandDataAvailable( bool nv )
307     {
308         m_ondemand_data_available = nv;
309     }
310   protected:
311     int cur_fields;
312     std::string **texts;
313     std::vector< bool > m_strike_out;
314     std::vector< size_t > m_strike_out_start;
315     std::vector< std::vector< size_t > > *m_highlight_segments;
316 
317     int fg[4], bg[4];
318     bool select;
319     int data;
320     FieldLVRowData *dataExt;
321     bool mark;
322 
323     bool m_ondemand_data_available;
324   };
325   Content **elementarray;
326   int arraysize;
327   int elements;
328 
329   void increaseArray( int newsize );
330   void checkShrink();
331 
332   int xoffset, yoffset, maxdisplayv;
333 
334   void redrawContent();
335   void redrawLine( int element );
336   int activerow;
337 
338   int data;
339   static const char *type;
340   int hbar;
341   int hbar_height;
342   int hbar_dir;
343   bool hbar_pressed;
344   int vbar;
345   int vbar_width;
346   int vbar_dir;
347   bool vbar_pressed;
348   void mredraw();
349   void hbarredraw();
350   void vbarredraw();
351   Window hbarwin,vbarwin;
352   void clearNonElements();
353   void handleExpose( Window msgwin, int ex, int ey, int ew, int eh );
354   virtual void handleSelect( Message *msg );
355   virtual void handleMiddle( Message *msg );
356   void handleThird( Message *msg );
357   void handleHBar( Message *msg );
358   void handleVBar( Message *msg );
359   bool handleKeys( Message *msg );
360   void handleHeader( Message *msg );
361   void handleEntryPressed( Message *msg );
362 
363   void (*selecthandler)( FieldListView*,int element );
364   std::function< void( FieldListView*, int element ) > m_select_handler;
365   void setupBars();
366   virtual void runSelectHandler( int element );
367   void recalcMaxValues();
368 
369   int getHeaderTextWidth( int field );
370 
371   AGUIXFont *font;
372   struct timeval lastwheel;
373   int mbg;
374 
375   int elementHeight, elementWidth, ox, oy;
376   void resetWin( bool doRedraw );
377   int getRowForMouseY( int my ) const;
378 
379   Pixmap buffer;
380   void drawBuffer();
381   void drawBuffer( int dx, int dy, int dw, int dh );
382   void drawBuffer( int element );
383 
384   bool displayFocus;
385   int getInnerWidth() const;
386   int getInnerHeight() const;
387 
388   virtual void doCreateStuff();
389   virtual void doDestroyStuff();
390 
391   void sendScrollEvent( int type );
392 
393   bool cond_changed;
394   bool showHeader;
395   int headerCols[2];
396 
397   int getFieldForPoint( int mx, int my, int *start_x = NULL, int *end_x = NULL );
398 
399   typedef enum { VBAR_IDLE, VBAR_SCROLL, VBAR_SCROLL_UP, VBAR_SCROLL_DOWN } vbarMode_t;
400   vbarMode_t vbarMode;
401   int grabs;
402   int scrollDelta;
403   typedef enum { HBAR_IDLE, HBAR_SCROLL, HBAR_SCROLL_LEFT, HBAR_SCROLL_RIGHT } hbarMode_t;
404   hbarMode_t hbarMode;
405   typedef enum { THIRD_IDLE, THIRD_SCROLL } thirdMode_t;
406   thirdMode_t thirdMode;
407   int scrollXDir, scrollYDir;
408   void updateScrollValues( int mx, int my );
409   int selectRowsRange( int startRow, int endRow, bool state );
410   int singleSelectRow( int row, bool state );
411 
412   typedef enum { SELECT_IDLE, SELECT_HOLD, SELECT_SCROLL_UP, SELECT_SCROLL_DOWN, SELECT_IGNORE } selectMode_t;
413   selectMode_t selectMode;
414   int clickLastSelectedRow, clickFirstSelectedRow;
415   bool clickState;
416   int clickSelected;
417   typedef enum { MIDDLE_IDLE, MIDDLE_HOLD, MIDDLE_SCROLL_UP, MIDDLE_SCROLL_DOWN, MIDDLE_IGNORE } middleMode_t;
418   middleMode_t middleMode;
419 
420   int _last_single_select_row;
421   Time _last_single_select_time;
422   int _last_single_middle_row;
423   Time _last_single_middle_time;
424 
425   typedef enum { HEADER_IDLE, HEADER_CLICK, HEADER_DRAG } headerMode_t;
426   headerMode_t headerMode;
427 
428   void selectModeIgnore();
429   void middleModeIgnore();
430 
431   void prepareBG( bool force = false );
432 
433   Pixmap _header_pixmap;
434   int _header_pixmap_w, _header_pixmap_h;
435   void freeHeaderPixmap();
436   int checkHeaderPixmap( int pw, int ph );
437   int getBorderWidth() const;
438   int drag_base_x;
439   int drag_base_w;
440   Time last_drag_time;
441   int last_drag_clicked;
442   int drag_field;
443   bool header_cursor_set;  // true if cursor for header dragging is set
444 
445   int findPreviousRealField( int f );
446   int getLastField( int *start_x, int *end_x );
447   int findResizeableField( int f );
448 
449   static unsigned int _select_button, _select_buttonmask;
450   static unsigned int _activate_button, _activate_buttonmask, _activate_mod;
451   static unsigned int _scroll_button, _scroll_buttonmask, _scroll_mod;
452   static unsigned int _entry_pressed_msg_button, _entry_pressed_msg_buttonmask, _entry_pressed_msg_mod;
453   static mouse_select_t _select_mode;
454 
455   unsigned int getCurrentMouseButtonState( Window twin );
456 
457   bool checkForValidButtonMod( unsigned int button,
458                                unsigned int keystate,
459                                unsigned int matching_mod );
460 
461   void initStaticDefaultColors();
462 
463   std::set<int> m_updated_rows;
464   bool m_complete_update;
465   struct timeval m_last_update_time;
466 
467   int m_global_field_spacing;
468 
469   bool m_consider_header_for_dynamic_width;
470 
471   precolor_t m_default_color_mode;
472 
473   static ColorDef s_default_element_colors;
474 
475   std::function< void( FieldListView*,
476                        int row,
477                        int field,
478                        struct on_demand_data &data ) > m_ondemand_callback;
479 
480   void updateOnDemandData();
481 
482   struct header_sort_hint {
header_sort_hintheader_sort_hint483       header_sort_hint() : field( -1 ),
484                            hint( HEADER_SORT_HINT_NONE )
485       {}
486       int field;
487       header_sort_hint_t hint;
488   } sort_hint;
489 
490     Pixmap m_vbar_selectbuffer = 0;
491     int m_vbar_selectbuffer_w = -1;
492     int m_vbar_selectbuffer_h = -1;
493     std::vector< bool > m_vbar_select_dirty;
494     std::vector< int > m_vbar_select_count;
495     bool m_vbar_select_some_dirty = false;
496     bool m_show_selection_in_vbar = false;
497     bool m_vbar_rebuild_required = false;
498 
499     void drawSelectStateVBar();
500     void freeVBarSelectBuffer();
501     int checkVBarSelectBuffer( int tw, int th );
502     void updateSelectState( int element, bool only_selected );
503 };
504 
505 #endif
506