New Widget class FListView to allow a multi-column data view

This commit is contained in:
Markus Gans 2017-07-18 23:50:51 +02:00
parent a998706e5e
commit d8c41b879d
12 changed files with 1719 additions and 17 deletions

1
.gitignore vendored
View File

@ -38,6 +38,7 @@ test/transparent
test/input-dialog
test/choice
test/listbox
test/listview
test/mandelbrot
test/keyboard
test/mouse

View File

@ -1,3 +1,8 @@
2017-07-18 Markus Gans <guru.mail@muenster.de>
* New Widget class FListView (filled with FListViewItem)
to allow a multi-column data view
* Add the listview example to demonstrate FListView
2017-07-11 Markus Gans <guru.mail@muenster.de>
* New class FTermBuffer to buffer terminal outputs
* Add the possibility to print from the terminal buffer

View File

@ -23,6 +23,7 @@ libfinal_la_SOURCES = \
fswitch.cpp \
flabel.cpp \
flistbox.cpp \
flistview.cpp \
fmenu.cpp \
fdialoglistmenu.cpp \
fmenubar.cpp \
@ -69,6 +70,7 @@ finalcutinclude_HEADERS = \
flabel.h \
flineedit.h \
flistbox.h \
flistview.h \
fmenu.h \
fdialoglistmenu.h \
fmenubar.h \

View File

@ -20,6 +20,7 @@ INCLUDE_HEADERS = \
flabel.h \
flineedit.h \
flistbox.h \
flistview.h \
fmenu.h \
fdialoglistmenu.h \
fmenubar.h \
@ -72,6 +73,7 @@ OBJS = \
fswitch.o \
flabel.o \
flistbox.o \
flistview.o \
fmenu.o \
fdialoglistmenu.o \
fmenubar.o \

View File

@ -20,6 +20,7 @@ INCLUDE_HEADERS = \
flabel.h \
flineedit.h \
flistbox.h \
flistview.h \
fmenu.h \
fdialoglistmenu.h \
fmenubar.h \
@ -72,6 +73,7 @@ OBJS = \
fswitch.o \
flabel.o \
flistbox.o \
flistview.o \
fmenu.o \
fdialoglistmenu.o \
fmenubar.o \

View File

@ -131,12 +131,12 @@ libfinal_la_LIBADD =
am_libfinal_la_OBJECTS = fstring.lo fpoint.lo frect.lo fscrollbar.lo \
fprogressbar.lo flineedit.lo fbutton.lo fbuttongroup.lo \
ftogglebutton.lo fradiobutton.lo fcheckbox.lo fswitch.lo \
flabel.lo flistbox.lo fmenu.lo fdialoglistmenu.lo fmenubar.lo \
fmenuitem.lo fradiomenuitem.lo fcheckmenuitem.lo fmenulist.lo \
fdialog.lo fscrollview.lo fwindow.lo fmessagebox.lo \
ftooltip.lo ffiledialog.lo ftextview.lo fstatusbar.lo fterm.lo \
fvterm.lo fevent.lo foptiattr.lo foptimove.lo ftermbuffer.lo \
fapp.lo fwidget.lo fobject.lo
flabel.lo flistbox.lo flistview.lo fmenu.lo fdialoglistmenu.lo \
fmenubar.lo fmenuitem.lo fradiomenuitem.lo fcheckmenuitem.lo \
fmenulist.lo fdialog.lo fscrollview.lo fwindow.lo \
fmessagebox.lo ftooltip.lo ffiledialog.lo ftextview.lo \
fstatusbar.lo fterm.lo fvterm.lo fevent.lo foptiattr.lo \
foptimove.lo ftermbuffer.lo fapp.lo fwidget.lo fobject.lo
libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -389,6 +389,7 @@ libfinal_la_SOURCES = \
fswitch.cpp \
flabel.cpp \
flistbox.cpp \
flistview.cpp \
fmenu.cpp \
fdialoglistmenu.cpp \
fmenubar.cpp \
@ -433,6 +434,7 @@ finalcutinclude_HEADERS = \
flabel.h \
flineedit.h \
flistbox.h \
flistview.h \
fmenu.h \
fdialoglistmenu.h \
fmenubar.h \
@ -554,6 +556,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flabel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flineedit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flistbox.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flistview.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmenu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmenubar.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmenuitem.Plo@am__quote@

1282
src/flistview.cpp Normal file

File diff suppressed because it is too large Load Diff

219
src/flistview.h Normal file
View File

@ -0,0 +1,219 @@
// File: flistview.h
// Provides: class FListViewItem
// class FListView
//
// Inheritance diagram
// ═══════════════════
//
// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏
// ▕ FObject ▏ ▕ FTerm ▏
// ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏
// ▲ ▲
// │ │
// └─────┬─────┘
// │
// ▕▔▔▔▔▔▔▔▔▏
// ▕ FVTerm ▏
// ▕▁▁▁▁▁▁▁▁▏
// ▲
// │
// ▕▔▔▔▔▔▔▔▔▔▏
// ▕ FWidget ▏
// ▕▁▁▁▁▁▁▁▁▁▏
// ▲
// │
// ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
// ▕ FListView ▏- - - -▕ FListViewItem ▏
// ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
//
#ifndef FLISTVIEW_H
#define FLISTVIEW_H
#include "fscrollbar.h"
#include "fstring.h"
#include "ftermbuffer.h"
#include "fwidget.h"
// class forward declaration
class FListView;
//----------------------------------------------------------------------
// class FListViewItem
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class FListViewItem : public FObject
{
public:
FListViewItem (const FListViewItem&); // copy constructor
FListViewItem (FListView*);
FListViewItem ( const std::vector<FString>&
, FWidget::data_ptr = 0
, FListView* = 0);
// Destructor
~FListViewItem();
// Assignment operator (=)
FListViewItem& operator = (const FListViewItem&);
// Accessors
const char* getClassName() const;
uInt getCount() const;
private:
// Friend classes
friend class FListView;
// Data Member
std::vector<FString> column_line;
FWidget::data_ptr data_pointer;
};
#pragma pack(pop)
// FListViewItem inline functions
//----------------------------------------------------------------------
inline const char* FListViewItem::getClassName() const
{ return "FListViewItem"; }
//----------------------------------------------------------------------
inline uInt FListViewItem::getCount() const
{ return uInt(column_line.size()); }
//----------------------------------------------------------------------
// class FListView
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class FListView : public FWidget
{
public:
// Typedef
typedef std::vector<FListViewItem*> listViewItems;
// Using-declaration
using FWidget::setGeometry;
// Constructor
explicit FListView (FWidget* = 0);
// Destructor
~FListView();
// Accessors
const char* getClassName() const;
// Mutators
void setGeometry (int, int, int, int, bool = true);
// Methods
virtual int addColumn (const FString&, int = USE_MAX_SIZE);
void insert (FListViewItem*);
void insert ( const std::vector<FString>&
, data_ptr = 0
, FListView* = 0 );
void insert ( const std::vector<long>&
, data_ptr = 0
, FListView* = 0 );
listViewItems::iterator index2iterator (int);
// Event handlers
void onKeyPress (FKeyEvent*);
void onMouseDown (FMouseEvent*);
void onMouseUp (FMouseEvent*);
void onMouseMove (FMouseEvent*);
void onMouseDoubleClick (FMouseEvent*);
void onWheel (FWheelEvent*);
void onTimer (FTimerEvent*);
void onFocusIn (FFocusEvent*);
void onFocusOut (FFocusEvent*);
// Callback methods
void cb_VBarChange (FWidget*, data_ptr);
void cb_HBarChange (FWidget*, data_ptr);
protected:
// Methods
void adjustYOffset();
void adjustSize();
private:
// Typedef
struct Header
{
public:
Header()
: name()
, width (0)
, fixed_width (-1)
{ }
~Header()
{ }
FString name;
int width;
bool fixed_width;
};
typedef std::vector<Header> headerItems;
// Constants
static const int USE_MAX_SIZE = -1;
// Disable copy constructor
FListView (const FListView&);
// Disable assignment operator (=)
FListView& operator = (const FListView&);
// Methods
void init();
void draw();
void drawColumnLabels();
void drawList();
void recalculateHorizontalBar (int);
void recalculateVerticalBar (int);
void processClick();
void processChanged();
// Data Members
listViewItems data;
headerItems header;
FTermBuffer headerline;
FScrollbar* vbar;
FScrollbar* hbar;
fc::dragScroll drag_scroll;
bool scroll_timer;
int scroll_repeat;
int scroll_distance;
int current;
int xoffset;
int yoffset;
int nf_offset;
int max_line_width;
};
#pragma pack(pop)
// FListView inline functions
//----------------------------------------------------------------------
inline const char* FListView::getClassName() const
{ return "FListView"; }
//----------------------------------------------------------------------
inline FListView::listViewItems::iterator FListView::index2iterator (int index)
{
listViewItems::iterator iter = data.begin();
std::advance (iter, index);
return iter;
}
#endif // FLISTVIEW_H

View File

@ -11,6 +11,7 @@ noinst_PROGRAMS = \
input-dialog \
choice \
listbox \
listview \
opti-move \
termcap \
string-operations \
@ -32,6 +33,7 @@ dialog_SOURCES = dialog.cpp
input_dialog_SOURCES = input-dialog.cpp
choice_SOURCES = choice.cpp
listbox_SOURCES = listbox.cpp
listview_SOURCES = listview.cpp
opti_move_SOURCES = opti-move.cpp
string_operations_SOURCES = string-operations.cpp
mandelbrot_SOURCES = mandelbrot.cpp

View File

@ -83,8 +83,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = hello$(EXEEXT) dialog$(EXEEXT) input-dialog$(EXEEXT) \
choice$(EXEEXT) listbox$(EXEEXT) opti-move$(EXEEXT) \
termcap$(EXEEXT) string-operations$(EXEEXT) \
choice$(EXEEXT) listbox$(EXEEXT) listview$(EXEEXT) \
opti-move$(EXEEXT) termcap$(EXEEXT) string-operations$(EXEEXT) \
mandelbrot$(EXEEXT) calculator$(EXEEXT) watch$(EXEEXT) \
term-attributes$(EXEEXT) transparent$(EXEEXT) \
keyboard$(EXEEXT) mouse$(EXEEXT) timer$(EXEEXT) \
@ -129,6 +129,9 @@ keyboard_LDADD = $(LDADD)
am_listbox_OBJECTS = listbox.$(OBJEXT)
listbox_OBJECTS = $(am_listbox_OBJECTS)
listbox_LDADD = $(LDADD)
am_listview_OBJECTS = listview.$(OBJEXT)
listview_OBJECTS = $(am_listview_OBJECTS)
listview_LDADD = $(LDADD)
am_mandelbrot_OBJECTS = mandelbrot.$(OBJEXT)
mandelbrot_OBJECTS = $(am_mandelbrot_OBJECTS)
mandelbrot_LDADD = $(LDADD)
@ -204,19 +207,20 @@ am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
SOURCES = $(calculator_SOURCES) $(choice_SOURCES) $(dialog_SOURCES) \
$(hello_SOURCES) $(input_dialog_SOURCES) $(keyboard_SOURCES) \
$(listbox_SOURCES) $(mandelbrot_SOURCES) $(menu_SOURCES) \
$(mouse_SOURCES) $(opti_move_SOURCES) $(scrollview_SOURCES) \
$(string_operations_SOURCES) $(term_attributes_SOURCES) \
$(termcap_SOURCES) $(timer_SOURCES) $(transparent_SOURCES) \
$(ui_SOURCES) $(watch_SOURCES) $(windows_SOURCES)
DIST_SOURCES = $(calculator_SOURCES) $(choice_SOURCES) \
$(dialog_SOURCES) $(hello_SOURCES) $(input_dialog_SOURCES) \
$(keyboard_SOURCES) $(listbox_SOURCES) $(mandelbrot_SOURCES) \
$(listbox_SOURCES) $(listview_SOURCES) $(mandelbrot_SOURCES) \
$(menu_SOURCES) $(mouse_SOURCES) $(opti_move_SOURCES) \
$(scrollview_SOURCES) $(string_operations_SOURCES) \
$(term_attributes_SOURCES) $(termcap_SOURCES) $(timer_SOURCES) \
$(transparent_SOURCES) $(ui_SOURCES) $(watch_SOURCES) \
$(windows_SOURCES)
DIST_SOURCES = $(calculator_SOURCES) $(choice_SOURCES) \
$(dialog_SOURCES) $(hello_SOURCES) $(input_dialog_SOURCES) \
$(keyboard_SOURCES) $(listbox_SOURCES) $(listview_SOURCES) \
$(mandelbrot_SOURCES) $(menu_SOURCES) $(mouse_SOURCES) \
$(opti_move_SOURCES) $(scrollview_SOURCES) \
$(string_operations_SOURCES) $(term_attributes_SOURCES) \
$(termcap_SOURCES) $(timer_SOURCES) $(transparent_SOURCES) \
$(ui_SOURCES) $(watch_SOURCES) $(windows_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -371,6 +375,7 @@ dialog_SOURCES = dialog.cpp
input_dialog_SOURCES = input-dialog.cpp
choice_SOURCES = choice.cpp
listbox_SOURCES = listbox.cpp
listview_SOURCES = listview.cpp
opti_move_SOURCES = opti-move.cpp
string_operations_SOURCES = string-operations.cpp
mandelbrot_SOURCES = mandelbrot.cpp
@ -458,6 +463,10 @@ listbox$(EXEEXT): $(listbox_OBJECTS) $(listbox_DEPENDENCIES) $(EXTRA_listbox_DEP
@rm -f listbox$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(listbox_OBJECTS) $(listbox_LDADD) $(LIBS)
listview$(EXEEXT): $(listview_OBJECTS) $(listview_DEPENDENCIES) $(EXTRA_listview_DEPENDENCIES)
@rm -f listview$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(listview_OBJECTS) $(listview_LDADD) $(LIBS)
mandelbrot$(EXEEXT): $(mandelbrot_OBJECTS) $(mandelbrot_DEPENDENCIES) $(EXTRA_mandelbrot_DEPENDENCIES)
@rm -f mandelbrot$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(mandelbrot_OBJECTS) $(mandelbrot_LDADD) $(LIBS)
@ -523,6 +532,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input-dialog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyboard.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listbox.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listview.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mandelbrot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mouse.Po@am__quote@

174
test/listview.cpp Normal file
View File

@ -0,0 +1,174 @@
// File: listview.cpp
#include <iostream>
#include <fstream>
#include "fapp.h"
#include "fdialog.h"
#include "flistview.h"
#include "fmessagebox.h"
//----------------------------------------------------------------------
// class Listbox
//----------------------------------------------------------------------
#pragma pack(push)
#pragma pack(1)
class Listview : public FDialog
{
public:
// Constructor
explicit Listview (FWidget* = 0);
// Destructor
~Listview();
private:
// Disable copy constructor
Listview (const Listview&);
// Disable assignment operator (=)
Listview& operator = (const Listview&);
// Event handlers
void onClose (FCloseEvent*);
// Callback methods
void cb_exitApp (FWidget*, data_ptr);
};
#pragma pack(pop)
//----------------------------------------------------------------------
Listview::Listview (FWidget* parent)
: FDialog(parent)
{
// Create FListView object
FListView* listView = new FListView (this);
listView->setGeometry(2, 1, 33, 14);
// Add columns to the view
listView->addColumn ("City");
listView->addColumn ("Condition");
listView->addColumn ("Temp.", 7);
listView->addColumn ("Humidity");
listView->addColumn ("Pressure");
// Populate FListView with a list of items
std::string weather[][5] =
{
{ "Alexandria", "Sunny", "31°C", "61%", "1006.4 mb" },
{ "Amsterdam", "Cloudy", "21°C", "82%", "1021.3 mb" },
{ "Baghdad", "Fair", "47°C", "9%", "1001.0 mb" },
{ "Bangkok", "Partly Cloudy", "30°C", "69%", "1002.0 mb" },
{ "Beijing", "Fair", "31°C", "68%", "1007.1 mb" },
{ "Berlin", "Cloudy", "22°C", "53%", "1022.0 mb" },
{ "Bogotá", "Fair", "9°C", "95%", "1028.5 mb" },
{ "Budapest", "Partly Cloudy", "23°C", "37%", "1020.7 mb" },
{ "Buenos Aires", "Cloudy", "7°C", "73%", "1019.0 mb" },
{ "Cairo", "Fair", "39°C", "22%", "1006.1 mb" },
{ "Cape Town", "Partly Cloudy", "12°C", "45%", "1030.1 mb" },
{ "Chicago", "Mostly Cloudy", "21°C", "81%", "1014.9 mb" },
{ "Delhi", "Haze", "33°C", "68%", "998.0 mb" },
{ "Dhaka", "Haze", "32°C", "64%", "996.3 mb" },
{ "Houston", "Cloudy", "23°C", "100%", "1014.2 mb" },
{ "Istanbul", "Mostly Cloudy", "27°C", "61%", "1011.2 mb" },
{ "Jakarta", "Fair", "28°C", "71%", "1009.1 mb" },
{ "Jerusalem", "Sunny", "35°C", "17%", "1005.8 mb" },
{ "Johannesburg", "Fair", "18°C", "16%", "1020.0 mb" },
{ "Karachi", "Mostly Cloudy", "29°C", "76%", "998.0 mb" },
{ "Lagos", "Mostly Cloudy", "27°C", "86%", "1014.6 mb" },
{ "Lima", "Cloudy", "17°C", "83%", "1017.3 mb" },
{ "London", "Cloudy", "23°C", "71%", "1023.0 mb" },
{ "Los Angeles", "Fair", "21°C", "78%", "1011.9 mb" },
{ "Madrid", "Fair", "32°C", "35%", "1020.0 mb" },
{ "Mexico City", "Partly Cloudy", "14°C", "79%", "1028.5 mb" },
{ "Moscow", "Partly Cloudy", "24°C", "54%", "1014.2 mb" },
{ "Mumbai", "Haze", "28°C", "77%", "1003.0 mb" },
{ "New York City", "Sunny", "21°C", "80%", "1014.2 mb" },
{ "Paris", "Partly Cloudy", "27°C", "57%", "1024.4 mb" },
{ "Reykjavík", "Mostly Cloudy", "11°C", "76%", "998.6 mb" },
{ "Rio de Janeiro", "Fair", "24°C", "64%", "1022.0 mb" },
{ "Rome", "Fair", "32°C", "18%", "1014.2 mb" },
{ "Saint Petersburg", "Mostly Cloudy", "18°C", "55%", "1014.6 mb" },
{ "São Paulo", "Fair", "19°C", "53%", "1024.0 mb" },
{ "Seoul", "Cloudy", "26°C", "87%", "1012.2 mb" },
{ "Shanghai", "Fair", "32°C", "69%", "1009.1 mb" },
{ "Singapore", "Mostly Cloudy", "29°C", "73%", "1009.1 mb" },
{ "Tehran", "Fair", "36°C", "14%", "1013.2 mb" },
{ "Tokyo", "Mostly Cloudy", "28°C", "67%", "1009.1 mb" },
{ "Zurich", "Mostly Cloudy", "23°C", "44%", "1023.7 mb" }
};
const int lastItem = int(sizeof(weather) / sizeof(weather[0])) - 1;
for (int i=0; i <= lastItem; i++)
{
std::vector<FString> line (&weather[i][0], &weather[i][0] + 5);
listView->insert (line);
}
// Quit button
FButton* Quit = new FButton (this);
Quit->setGeometry(24, 16, 10, 1);
Quit->setText (L"&Quit");
// Add some function callbacks
Quit->addCallback
(
"clicked",
F_METHOD_CALLBACK (this, &Listview::cb_exitApp)
);
}
//----------------------------------------------------------------------
Listview::~Listview()
{ }
//----------------------------------------------------------------------
void Listview::onClose (FCloseEvent* ev)
{
int ret = FMessageBox::info ( this, "Quit"
, "Do you really want\n"
"to quit the program ?"
, FMessageBox::Yes
, FMessageBox::No );
if ( ret == FMessageBox::Yes )
ev->accept();
else
ev->ignore();
}
//----------------------------------------------------------------------
void Listview::cb_exitApp (FWidget*, data_ptr)
{
close();
}
//----------------------------------------------------------------------
// main part
//----------------------------------------------------------------------
int main (int argc, char* argv[])
{
if ( argv[1] && ( std::strcmp(argv[1], "--help") == 0
|| std::strcmp(argv[1], "-h") == 0 ) )
{
std::cout << "Generic options:" << std::endl
<< " -h, --help "
<< "Display this help and exit" << std::endl;
FApplication::print_cmd_Options();
std::exit(EXIT_SUCCESS);
}
FApplication app(argc, argv);
Listview d(&app);
d.setText (L"Listview");
d.setGeometry (int(1 + (app.getWidth() - 37) / 2), 3, 37, 20);
d.setShadow();
app.setMainWidget(&d);
d.show();
return app.exec();
}