FListViewItem now provides checkable list view items
This commit is contained in:
parent
e40a233d64
commit
3953dc19fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -52,6 +52,7 @@ examples/input-dialog
|
|||||||
examples/choice
|
examples/choice
|
||||||
examples/listbox
|
examples/listbox
|
||||||
examples/listview
|
examples/listview
|
||||||
|
examples/checklist
|
||||||
examples/treeview
|
examples/treeview
|
||||||
examples/mandelbrot
|
examples/mandelbrot
|
||||||
examples/keyboard
|
examples/keyboard
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2018-11-18 Markus Gans <guru.mail@muenster.de>
|
||||||
|
* The FListViewItem class now provides checkable list view items
|
||||||
|
* Adding the checklist example to demonstrate the checkable FListViewItems
|
||||||
|
|
||||||
2018-11-12 Markus Gans <guru.mail@muenster.de>
|
2018-11-12 Markus Gans <guru.mail@muenster.de>
|
||||||
* Clicking on the column header in FListView now changes the sort order
|
* Clicking on the column header in FListView now changes the sort order
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ noinst_PROGRAMS = \
|
|||||||
choice \
|
choice \
|
||||||
listbox \
|
listbox \
|
||||||
listview \
|
listview \
|
||||||
|
checklist \
|
||||||
treeview \
|
treeview \
|
||||||
opti-move \
|
opti-move \
|
||||||
termcap \
|
termcap \
|
||||||
@ -37,6 +38,7 @@ input_dialog_SOURCES = input-dialog.cpp
|
|||||||
choice_SOURCES = choice.cpp
|
choice_SOURCES = choice.cpp
|
||||||
listbox_SOURCES = listbox.cpp
|
listbox_SOURCES = listbox.cpp
|
||||||
listview_SOURCES = listview.cpp
|
listview_SOURCES = listview.cpp
|
||||||
|
checklist_SOURCES = checklist.cpp
|
||||||
treeview_SOURCES = treeview.cpp
|
treeview_SOURCES = treeview.cpp
|
||||||
opti_move_SOURCES = opti-move.cpp
|
opti_move_SOURCES = opti-move.cpp
|
||||||
string_operations_SOURCES = string-operations.cpp
|
string_operations_SOURCES = string-operations.cpp
|
||||||
|
207
examples/checklist.cpp
Normal file
207
examples/checklist.cpp
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
* checklist.cpp - Example for FListView widget with checkboxes *
|
||||||
|
* *
|
||||||
|
* This file is part of the Final Cut widget toolkit *
|
||||||
|
* *
|
||||||
|
* Copyright 2017-2018 Markus Gans *
|
||||||
|
* *
|
||||||
|
* The Final Cut is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 3 of *
|
||||||
|
* the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* The Final Cut is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this program. If not, see *
|
||||||
|
* <http://www.gnu.org/licenses/>. *
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <final/final.h>
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// class CheckList
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
class CheckList : public finalcut::FDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
explicit CheckList (finalcut::FWidget* = 0);
|
||||||
|
// Destructor
|
||||||
|
~CheckList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disable copy constructor
|
||||||
|
CheckList (const CheckList&);
|
||||||
|
// Disable assignment operator (=)
|
||||||
|
CheckList& operator = (const CheckList&);
|
||||||
|
|
||||||
|
// Method
|
||||||
|
void populate();
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
virtual void onKeyPress (finalcut::FKeyEvent*);
|
||||||
|
virtual void onClose (finalcut::FCloseEvent*);
|
||||||
|
|
||||||
|
// Callback method
|
||||||
|
void cb_showList (finalcut::FWidget*, data_ptr);
|
||||||
|
|
||||||
|
// Data Members
|
||||||
|
finalcut::FListView listView;
|
||||||
|
finalcut::FStatusBar status_bar;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
CheckList::CheckList (finalcut::FWidget* parent)
|
||||||
|
: finalcut::FDialog(parent)
|
||||||
|
, listView(this)
|
||||||
|
, status_bar(this)
|
||||||
|
{
|
||||||
|
setText (L"Shopping list");
|
||||||
|
setShadow();
|
||||||
|
setGeometry (int(1 + (parent->getWidth() - 30) / 2), 5, 30, 13);
|
||||||
|
listView.ignorePadding();
|
||||||
|
listView.setGeometry (1, 2, getWidth(), getHeight() - 1);
|
||||||
|
|
||||||
|
// Add columns to the view
|
||||||
|
listView.addColumn ("Item");
|
||||||
|
listView.addColumn ("Priority", 12);
|
||||||
|
|
||||||
|
// Set the type of sorting
|
||||||
|
listView.setColumnSortType (1, finalcut::fc::by_name);
|
||||||
|
listView.setColumnSortType (2, finalcut::fc::by_name);
|
||||||
|
|
||||||
|
// Statusbar at the bottom
|
||||||
|
finalcut::FString separator;
|
||||||
|
separator << ' ' << wchar_t(finalcut::fc::BoxDrawingsVertical) << ' ';
|
||||||
|
listView.setStatusbarMessage ( finalcut::FString()
|
||||||
|
<< "<Q> exit" << separator
|
||||||
|
<< "<Space> select an item" << separator
|
||||||
|
<< "<Enter> see your pick list");
|
||||||
|
|
||||||
|
// Populate FListView with a list of items
|
||||||
|
populate();
|
||||||
|
|
||||||
|
// Add callback method
|
||||||
|
listView.addCallback
|
||||||
|
(
|
||||||
|
"clicked",
|
||||||
|
F_METHOD_CALLBACK (this, &CheckList::cb_showList)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
CheckList::~CheckList() // destructor
|
||||||
|
{ }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void CheckList::populate()
|
||||||
|
{
|
||||||
|
std::string list[][2] =
|
||||||
|
{
|
||||||
|
{ "Milk", "Highest" },
|
||||||
|
{ "Cheese", "High" },
|
||||||
|
{ "Yoghurt", "Medium" },
|
||||||
|
{ "Bread", "Low" },
|
||||||
|
{ "Eggs", "High" },
|
||||||
|
{ "Toothpaste", "Medium" },
|
||||||
|
{ "Apples", "Lowest" },
|
||||||
|
{ "Bananas", "Medium" },
|
||||||
|
{ "Fish", "Medium" },
|
||||||
|
{ "Lemons", "Low" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const int lastItem = int(sizeof(list) / sizeof(list[0])) - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i <= lastItem; i++)
|
||||||
|
{
|
||||||
|
const finalcut::FStringList line (&list[i][0], &list[i][0] + 2);
|
||||||
|
finalcut::FObject::FObjectIterator iter = listView.insert (line);
|
||||||
|
finalcut::FListViewItem* item = static_cast<finalcut::FListViewItem*>(*iter);
|
||||||
|
item->setCheckable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void CheckList::onKeyPress (finalcut::FKeyEvent* ev)
|
||||||
|
{
|
||||||
|
if ( ! ev )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ev->key() == 'q'
|
||||||
|
|| ev->key() == finalcut::fc::Fkey_escape
|
||||||
|
|| ev->key() == finalcut::fc::Fkey_escape_mintty )
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
ev->accept();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
finalcut::FDialog::onKeyPress(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void CheckList::onClose (finalcut::FCloseEvent* ev)
|
||||||
|
{
|
||||||
|
finalcut::FApplication::closeConfirmationDialog (this, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void CheckList::cb_showList (finalcut::FWidget*, data_ptr)
|
||||||
|
{
|
||||||
|
finalcut::FListViewIterator iter = listView.beginOfList();
|
||||||
|
finalcut::FString shopping_list;
|
||||||
|
|
||||||
|
while ( iter != listView.endOfList() )
|
||||||
|
{
|
||||||
|
const finalcut::FListViewItem* item = static_cast<finalcut::FListViewItem*>(*iter);
|
||||||
|
|
||||||
|
if ( item->isChecked() )
|
||||||
|
shopping_list << wchar_t(finalcut::fc::Bullet) << ' ' << item->getText(1) << '\n';
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( shopping_list.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Create and show tooltip for two seconds
|
||||||
|
finalcut::FToolTip picklist(this);
|
||||||
|
picklist.setText (shopping_list);
|
||||||
|
picklist.show();
|
||||||
|
sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// main part
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main (int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// Create the application object
|
||||||
|
finalcut::FApplication app(argc, argv);
|
||||||
|
|
||||||
|
// Create main dialog object
|
||||||
|
CheckList d(&app);
|
||||||
|
|
||||||
|
// Set dialog d as main widget
|
||||||
|
app.setMainWidget(&d);
|
||||||
|
|
||||||
|
// Show and start the application
|
||||||
|
d.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
@ -70,7 +70,7 @@ Listview::Listview (finalcut::FWidget* parent)
|
|||||||
, listView(this)
|
, listView(this)
|
||||||
, Quit(this)
|
, Quit(this)
|
||||||
{
|
{
|
||||||
// Create FListView object
|
// Set FListView geometry
|
||||||
listView.setGeometry(2, 1, 33, 14);
|
listView.setGeometry(2, 1, 33, 14);
|
||||||
|
|
||||||
// Add columns to the view
|
// Add columns to the view
|
||||||
|
@ -130,7 +130,7 @@ class Treeview : public finalcut::FDialog
|
|||||||
// Methods
|
// Methods
|
||||||
virtual void adjustSize();
|
virtual void adjustSize();
|
||||||
|
|
||||||
// Event handlers
|
// Event handler
|
||||||
void onClose (finalcut::FCloseEvent*);
|
void onClose (finalcut::FCloseEvent*);
|
||||||
|
|
||||||
// Data Members
|
// Data Members
|
||||||
@ -302,7 +302,7 @@ Treeview::Treeview (finalcut::FWidget* parent)
|
|||||||
, listView(this)
|
, listView(this)
|
||||||
, Quit(this)
|
, Quit(this)
|
||||||
{
|
{
|
||||||
// Create FListView object
|
// Set FListView geometry
|
||||||
listView.setGeometry(2, 1, 53, 14);
|
listView.setGeometry(2, 1, 53, 14);
|
||||||
|
|
||||||
// Add columns to the view
|
// Add columns to the view
|
||||||
|
@ -896,7 +896,7 @@ void FListBox::draw()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawLabel();
|
drawHeadline();
|
||||||
|
|
||||||
if ( isMonochron() )
|
if ( isMonochron() )
|
||||||
setReverse(false);
|
setReverse(false);
|
||||||
@ -923,7 +923,7 @@ void FListBox::draw()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListBox::drawLabel()
|
void FListBox::drawHeadline()
|
||||||
{
|
{
|
||||||
if ( text.isNull() || text.isEmpty() )
|
if ( text.isNull() || text.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
@ -167,6 +167,8 @@ FListViewItem::FListViewItem (const FListViewItem& item)
|
|||||||
, visible_lines(1)
|
, visible_lines(1)
|
||||||
, expandable(false)
|
, expandable(false)
|
||||||
, is_expand(false)
|
, is_expand(false)
|
||||||
|
, checkable(false)
|
||||||
|
, is_checked(false)
|
||||||
{
|
{
|
||||||
FObject* parent = getParent();
|
FObject* parent = getParent();
|
||||||
|
|
||||||
@ -192,6 +194,8 @@ FListViewItem::FListViewItem (FObjectIterator parent_iter)
|
|||||||
, visible_lines(1)
|
, visible_lines(1)
|
||||||
, expandable(false)
|
, expandable(false)
|
||||||
, is_expand(false)
|
, is_expand(false)
|
||||||
|
, checkable(false)
|
||||||
|
, is_checked(false)
|
||||||
{
|
{
|
||||||
insert (this, parent_iter);
|
insert (this, parent_iter);
|
||||||
}
|
}
|
||||||
@ -207,6 +211,8 @@ FListViewItem::FListViewItem ( const FStringList& cols
|
|||||||
, visible_lines(1)
|
, visible_lines(1)
|
||||||
, expandable(false)
|
, expandable(false)
|
||||||
, is_expand(false)
|
, is_expand(false)
|
||||||
|
, checkable(false)
|
||||||
|
, is_checked(false)
|
||||||
{
|
{
|
||||||
if ( cols.empty() )
|
if ( cols.empty() )
|
||||||
return;
|
return;
|
||||||
@ -325,7 +331,7 @@ FObject::FObjectIterator FListViewItem::insert ( FListViewItem* child
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListViewItem::expand()
|
void FListViewItem::expand()
|
||||||
{
|
{
|
||||||
if ( is_expand || ! hasChildren() )
|
if ( isExpand() || ! hasChildren() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
is_expand = true;
|
is_expand = true;
|
||||||
@ -334,7 +340,7 @@ void FListViewItem::expand()
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListViewItem::collapse()
|
void FListViewItem::collapse()
|
||||||
{
|
{
|
||||||
if ( ! is_expand )
|
if ( ! isExpand() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
is_expand = false;
|
is_expand = false;
|
||||||
@ -346,7 +352,7 @@ void FListViewItem::collapse()
|
|||||||
template <typename Compare>
|
template <typename Compare>
|
||||||
void FListViewItem::sort (Compare cmp)
|
void FListViewItem::sort (Compare cmp)
|
||||||
{
|
{
|
||||||
if ( ! expandable )
|
if ( ! isExpandable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Sort the top level
|
// Sort the top level
|
||||||
@ -418,6 +424,20 @@ std::size_t FListViewItem::getVisibleLines()
|
|||||||
return visible_lines;
|
return visible_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void FListViewItem::setCheckable (bool on)
|
||||||
|
{
|
||||||
|
checkable = on;
|
||||||
|
|
||||||
|
if ( *root )
|
||||||
|
{
|
||||||
|
FListView* root_obj = static_cast<FListView*>(*root);
|
||||||
|
|
||||||
|
if ( ! root_obj->hasCheckableItems() && isCheckable() )
|
||||||
|
root_obj->has_checkable_items = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListViewItem::resetVisibleLineCounter()
|
void FListViewItem::resetVisibleLineCounter()
|
||||||
{
|
{
|
||||||
@ -611,8 +631,10 @@ FListView::FListView (FWidget* parent)
|
|||||||
, scroll_timer(false)
|
, scroll_timer(false)
|
||||||
, tree_view(false)
|
, tree_view(false)
|
||||||
, hide_sort_indicator(false)
|
, hide_sort_indicator(false)
|
||||||
|
, has_checkable_items(false)
|
||||||
, clicked_expander_pos(-1, -1)
|
, clicked_expander_pos(-1, -1)
|
||||||
, clicked_column_pos(-1, -1)
|
, clicked_header_pos(-1, -1)
|
||||||
|
, clicked_checkbox_item(0)
|
||||||
, xoffset(0)
|
, xoffset(0)
|
||||||
, nf_offset(0)
|
, nf_offset(0)
|
||||||
, max_line_width(1)
|
, max_line_width(1)
|
||||||
@ -802,14 +824,11 @@ FObject::FObjectIterator FListView::insert ( FListViewItem* item
|
|||||||
, FObjectIterator parent_iter )
|
, FObjectIterator parent_iter )
|
||||||
{
|
{
|
||||||
FObjectIterator item_iter;
|
FObjectIterator item_iter;
|
||||||
int line_width;
|
|
||||||
int element_count;
|
|
||||||
|
|
||||||
if ( parent_iter == FListView::null_iter )
|
if ( parent_iter == FListView::null_iter )
|
||||||
return FListView::null_iter;
|
return FListView::null_iter;
|
||||||
|
|
||||||
line_width = determineLineWidth (item);
|
beforeInsertion(item); // preprocessing
|
||||||
recalculateHorizontalBar (line_width);
|
|
||||||
|
|
||||||
if ( parent_iter == root )
|
if ( parent_iter == root )
|
||||||
{
|
{
|
||||||
@ -835,19 +854,7 @@ FObject::FObjectIterator FListView::insert ( FListViewItem* item
|
|||||||
else
|
else
|
||||||
item_iter = FListView::null_iter;
|
item_iter = FListView::null_iter;
|
||||||
|
|
||||||
if ( itemlist.size() == 1 )
|
afterInsertion(); // post-processing
|
||||||
{
|
|
||||||
// Select first item on insert
|
|
||||||
current_iter = itemlist.begin();
|
|
||||||
// The visible area of the list begins with the first element
|
|
||||||
first_visible_line = itemlist.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort list by a column (only if activated)
|
|
||||||
sort();
|
|
||||||
|
|
||||||
element_count = int(getCount());
|
|
||||||
recalculateVerticalBar (element_count);
|
|
||||||
return item_iter;
|
return item_iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,6 +971,11 @@ void FListView::onKeyPress (FKeyEvent* ev)
|
|||||||
ev->accept();
|
ev->accept();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case fc::Fkey_space:
|
||||||
|
keySpace();
|
||||||
|
ev->accept();
|
||||||
|
break;
|
||||||
|
|
||||||
case fc::Fkey_up:
|
case fc::Fkey_up:
|
||||||
stepBackward();
|
stepBackward();
|
||||||
ev->accept();
|
ev->accept();
|
||||||
@ -1059,26 +1071,41 @@ void FListView::onMouseDown (FMouseEvent* ev)
|
|||||||
|
|
||||||
if ( mouse_x > 1 && mouse_x < int(getWidth()) )
|
if ( mouse_x > 1 && mouse_x < int(getWidth()) )
|
||||||
{
|
{
|
||||||
if ( mouse_y == 1 )
|
if ( mouse_y == 1 ) // Header
|
||||||
{
|
{
|
||||||
clicked_column_pos = ev->getPos();
|
clicked_header_pos = ev->getPos();
|
||||||
}
|
}
|
||||||
else if ( mouse_y > 1 && mouse_y < int(getHeight()) )
|
else if ( mouse_y > 1 && mouse_y < int(getHeight()) ) // List
|
||||||
{
|
{
|
||||||
|
int indent = 0;
|
||||||
int new_pos = first_visible_line.getPosition() + mouse_y - 2;
|
int new_pos = first_visible_line.getPosition() + mouse_y - 2;
|
||||||
|
|
||||||
if ( new_pos < int(getCount()) )
|
if ( new_pos < int(getCount()) )
|
||||||
setRelativePosition (mouse_y - 2);
|
setRelativePosition (mouse_y - 2);
|
||||||
|
|
||||||
|
const FListViewItem* item = getCurrentItem();
|
||||||
|
|
||||||
if ( tree_view )
|
if ( tree_view )
|
||||||
{
|
{
|
||||||
const FListViewItem* item = getCurrentItem();
|
indent = int(item->getDepth() << 1); // indent = 2 * depth
|
||||||
int indent = int(item->getDepth() << 1); // indent = 2 * depth
|
|
||||||
|
|
||||||
if ( item->isExpandable() && mouse_x - 2 == indent - xoffset )
|
if ( item->isExpandable() && mouse_x - 2 == indent - xoffset )
|
||||||
clicked_expander_pos = ev->getPos();
|
clicked_expander_pos = ev->getPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( hasCheckableItems() )
|
||||||
|
{
|
||||||
|
if ( tree_view )
|
||||||
|
indent++; // Plus one space
|
||||||
|
|
||||||
|
if ( mouse_x >= 3 + indent - xoffset
|
||||||
|
&& mouse_x <= 5 + indent - xoffset
|
||||||
|
&& item->isCheckable() )
|
||||||
|
{
|
||||||
|
clicked_checkbox_item = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( isVisible() )
|
if ( isVisible() )
|
||||||
drawList();
|
drawList();
|
||||||
|
|
||||||
@ -1107,15 +1134,18 @@ void FListView::onMouseUp (FMouseEvent* ev)
|
|||||||
|
|
||||||
if ( mouse_x > 1 && mouse_x < int(getWidth()) )
|
if ( mouse_x > 1 && mouse_x < int(getWidth()) )
|
||||||
{
|
{
|
||||||
if ( mouse_y == 1 && clicked_column_pos == ev->getPos() )
|
if ( mouse_y == 1 && clicked_header_pos == ev->getPos() ) // Header
|
||||||
{
|
{
|
||||||
mouseColumnClicked();
|
mouseHeaderClicked();
|
||||||
}
|
}
|
||||||
else if ( mouse_y > 1 && mouse_y < int(getHeight()) )
|
else if ( mouse_y > 1 && mouse_y < int(getHeight()) ) // List
|
||||||
{
|
{
|
||||||
|
int indent = 0;
|
||||||
|
FListViewItem* item = getCurrentItem();
|
||||||
|
|
||||||
if ( tree_view )
|
if ( tree_view )
|
||||||
{
|
{
|
||||||
FListViewItem* item = getCurrentItem();
|
indent = int(item->getDepth() << 1); // indent = 2 * depth
|
||||||
|
|
||||||
if ( item->isExpandable()
|
if ( item->isExpandable()
|
||||||
&& clicked_expander_pos == ev->getPos() )
|
&& clicked_expander_pos == ev->getPos() )
|
||||||
@ -1132,13 +1162,30 @@ void FListView::onMouseUp (FMouseEvent* ev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( hasCheckableItems() )
|
||||||
|
{
|
||||||
|
if ( tree_view )
|
||||||
|
indent++; // Plus one space
|
||||||
|
|
||||||
|
if ( mouse_x >= 3 + indent - xoffset
|
||||||
|
&& mouse_x <= 5 + indent - xoffset
|
||||||
|
&& clicked_checkbox_item == item )
|
||||||
|
{
|
||||||
|
item->setChecked(! item->isChecked());
|
||||||
|
|
||||||
|
if ( isVisible() )
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
processChanged();
|
processChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clicked_expander_pos.setPoint(-1, -1);
|
clicked_expander_pos.setPoint(-1, -1);
|
||||||
clicked_column_pos.setPoint(-1, -1);
|
clicked_header_pos.setPoint(-1, -1);
|
||||||
|
clicked_checkbox_item = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -1521,7 +1568,7 @@ void FListView::draw()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawColumnLabels();
|
drawHeadlines();
|
||||||
|
|
||||||
if ( isMonochron() )
|
if ( isMonochron() )
|
||||||
setReverse(false);
|
setReverse(false);
|
||||||
@ -1548,7 +1595,7 @@ void FListView::draw()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListView::drawColumnLabels()
|
void FListView::drawHeadlines()
|
||||||
{
|
{
|
||||||
std::vector<charData>::const_iterator first, last;
|
std::vector<charData>::const_iterator first, last;
|
||||||
headerItems::const_iterator iter;
|
headerItems::const_iterator iter;
|
||||||
@ -1562,6 +1609,9 @@ void FListView::drawColumnLabels()
|
|||||||
iter = header.begin();
|
iter = header.begin();
|
||||||
headerline.clear();
|
headerline.clear();
|
||||||
|
|
||||||
|
if ( hasCheckableItems() )
|
||||||
|
drawHeaderBorder(4);
|
||||||
|
|
||||||
while ( iter != header.end() )
|
while ( iter != header.end() )
|
||||||
{
|
{
|
||||||
const FString& text = iter->name;
|
const FString& text = iter->name;
|
||||||
@ -1572,7 +1622,7 @@ void FListView::drawColumnLabels()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawColumnText(iter);
|
drawHeadlineLabel(iter);
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1643,35 +1693,37 @@ void FListView::drawListLine ( const FListViewItem* item
|
|||||||
, bool is_focus
|
, bool is_focus
|
||||||
, bool is_current )
|
, bool is_current )
|
||||||
{
|
{
|
||||||
std::size_t indent = item->getDepth() << 1; // indent = 2 * depth
|
|
||||||
|
|
||||||
// Set line color and attributes
|
// Set line color and attributes
|
||||||
setLineAttributes (is_current, is_focus);
|
setLineAttributes (is_current, is_focus);
|
||||||
|
|
||||||
// Print the entry
|
// Print the entry
|
||||||
|
std::size_t indent = item->getDepth() << 1; // indent = 2 * depth
|
||||||
FString line = getLinePrefix (item, indent);
|
FString line = getLinePrefix (item, indent);
|
||||||
|
|
||||||
// Print columns
|
// Print columns
|
||||||
if ( ! item->column_list.empty() )
|
if ( ! item->column_list.empty() )
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < item->column_list.size(); )
|
for (std::size_t col = 0; col < item->column_list.size(); )
|
||||||
{
|
{
|
||||||
static const std::size_t leading_space = 1;
|
static const std::size_t leading_space = 1;
|
||||||
|
static const std::size_t checkbox_space = 4;
|
||||||
static const std::size_t ellipsis_length = 2;
|
static const std::size_t ellipsis_length = 2;
|
||||||
|
|
||||||
const FString& text = item->column_list[i];
|
const FString& text = item->column_list[col];
|
||||||
std::size_t width = std::size_t(header[i].width);
|
std::size_t width = std::size_t(header[col].width);
|
||||||
std::size_t txt_length = text.getLength();
|
std::size_t txt_length = text.getLength();
|
||||||
// Increment the value of i for the column position
|
// Increment the value of i for the column position
|
||||||
// and the next iteration
|
// and the next iteration
|
||||||
i++;
|
col++;
|
||||||
fc::text_alignment align = getColumnAlignment(int(i));
|
fc::text_alignment align = getColumnAlignment(int(col));
|
||||||
std::size_t align_offset = getAlignOffset (align, txt_length, width);
|
std::size_t align_offset = getAlignOffset (align, txt_length, width);
|
||||||
|
|
||||||
if ( tree_view && i == 1 )
|
if ( tree_view && col == 1 )
|
||||||
{
|
{
|
||||||
width -= indent;
|
width -= (indent + 1);
|
||||||
width--;
|
|
||||||
|
if ( item->isCheckable() )
|
||||||
|
width -= checkbox_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert alignment spaces
|
// Insert alignment spaces
|
||||||
@ -1749,20 +1801,41 @@ inline void FListView::setLineAttributes ( bool is_current
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline FString FListView::getCheckBox (const FListViewItem* item)
|
||||||
|
{
|
||||||
|
FString checkbox;
|
||||||
|
|
||||||
|
if ( isNewFont() )
|
||||||
|
{
|
||||||
|
checkbox = ( item->isChecked() ) ? CHECKBOX_ON : CHECKBOX;
|
||||||
|
checkbox += L' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checkbox = L"[ ] ";
|
||||||
|
|
||||||
|
if ( item->isChecked() )
|
||||||
|
checkbox[1] = wchar_t(fc::Times); // Times ×
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkbox;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
inline FString FListView::getLinePrefix ( const FListViewItem* item
|
inline FString FListView::getLinePrefix ( const FListViewItem* item
|
||||||
, std::size_t indent )
|
, std::size_t indent )
|
||||||
{
|
{
|
||||||
FString line = "";
|
FString line;
|
||||||
|
|
||||||
if ( tree_view )
|
if ( tree_view )
|
||||||
{
|
{
|
||||||
if ( indent > 0 )
|
if ( indent > 0 )
|
||||||
line = FString(indent, L' ');
|
line = FString(indent, L' ');
|
||||||
|
|
||||||
if ( item->expandable )
|
if ( item->isExpandable() )
|
||||||
{
|
{
|
||||||
if ( item->is_expand )
|
if ( item->isExpand() )
|
||||||
{
|
{
|
||||||
line += wchar_t(fc::BlackDownPointingTriangle); // ▼
|
line += wchar_t(fc::BlackDownPointingTriangle); // ▼
|
||||||
line += L' ';
|
line += L' ';
|
||||||
@ -1779,6 +1852,9 @@ inline FString FListView::getLinePrefix ( const FListViewItem* item
|
|||||||
else
|
else
|
||||||
line = L" ";
|
line = L" ";
|
||||||
|
|
||||||
|
if ( item->isCheckable() )
|
||||||
|
line += getCheckBox(item);
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1813,7 +1889,7 @@ inline void FListView::drawHeaderBorder (std::size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListView::drawColumnText (headerItems::const_iterator& iter)
|
void FListView::drawHeadlineLabel (headerItems::const_iterator& iter)
|
||||||
{
|
{
|
||||||
// Print lable text
|
// Print lable text
|
||||||
static const std::size_t leading_space = 1;
|
static const std::size_t leading_space = 1;
|
||||||
@ -1932,6 +2008,31 @@ int FListView::determineLineWidth (FListViewItem* item)
|
|||||||
return line_width;
|
return line_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline void FListView::beforeInsertion (FListViewItem* item)
|
||||||
|
{
|
||||||
|
int line_width = determineLineWidth (item);
|
||||||
|
recalculateHorizontalBar (line_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline void FListView::afterInsertion()
|
||||||
|
{
|
||||||
|
if ( itemlist.size() == 1 )
|
||||||
|
{
|
||||||
|
// Select first item on insert
|
||||||
|
current_iter = itemlist.begin();
|
||||||
|
// The visible area of the list begins with the first element
|
||||||
|
first_visible_line = itemlist.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort list by a column (only if activated)
|
||||||
|
sort();
|
||||||
|
|
||||||
|
int element_count = int(getCount());
|
||||||
|
recalculateVerticalBar (element_count);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListView::recalculateHorizontalBar (int len)
|
void FListView::recalculateHorizontalBar (int len)
|
||||||
{
|
{
|
||||||
@ -1963,11 +2064,12 @@ void FListView::recalculateVerticalBar (int element_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FListView::mouseColumnClicked()
|
void FListView::mouseHeaderClicked()
|
||||||
{
|
{
|
||||||
int column_start = 2;
|
|
||||||
int column = 1;
|
int column = 1;
|
||||||
int column_pos = clicked_column_pos.getX() + xoffset;
|
int checkbox_offset = ( hasCheckableItems() ) ? 4 : 0;
|
||||||
|
int header_start = 2 + checkbox_offset;
|
||||||
|
int header_pos = clicked_header_pos.getX() + xoffset;
|
||||||
headerItems::const_iterator iter;
|
headerItems::const_iterator iter;
|
||||||
iter = header.begin();
|
iter = header.begin();
|
||||||
|
|
||||||
@ -1983,8 +2085,8 @@ void FListView::mouseColumnClicked()
|
|||||||
if ( click_width > iter->width )
|
if ( click_width > iter->width )
|
||||||
click_width = iter->width;
|
click_width = iter->width;
|
||||||
|
|
||||||
if ( column_pos > column_start
|
if ( header_pos > header_start
|
||||||
&& column_pos <= column_start + click_width )
|
&& header_pos <= header_start + click_width )
|
||||||
{
|
{
|
||||||
if ( has_sort_indicator && sort_order == fc::ascending )
|
if ( has_sort_indicator && sort_order == fc::ascending )
|
||||||
setColumnSort (column, fc::descending);
|
setColumnSort (column, fc::descending);
|
||||||
@ -1995,7 +2097,7 @@ void FListView::mouseColumnClicked()
|
|||||||
|
|
||||||
if ( isVisible() )
|
if ( isVisible() )
|
||||||
{
|
{
|
||||||
drawColumnLabels();
|
drawHeadlines();
|
||||||
drawList();
|
drawList();
|
||||||
updateTerminal();
|
updateTerminal();
|
||||||
flush_out();
|
flush_out();
|
||||||
@ -2003,7 +2105,7 @@ void FListView::mouseColumnClicked()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
column_start += leading_space + iter->width;
|
header_start += leading_space + iter->width;
|
||||||
column++;
|
column++;
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
@ -2167,6 +2269,15 @@ void FListView::processChanged()
|
|||||||
emitCallback("row-changed");
|
emitCallback("row-changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline void FListView::keySpace()
|
||||||
|
{
|
||||||
|
FListViewItem* item = getCurrentItem();
|
||||||
|
|
||||||
|
if ( item->isCheckable() )
|
||||||
|
item->setChecked(! item->isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
inline void FListView::keyLeft (int& first_line_position_before)
|
inline void FListView::keyLeft (int& first_line_position_before)
|
||||||
{
|
{
|
||||||
@ -2569,7 +2680,7 @@ void FListView::cb_HBarChange (FWidget*, data_ptr)
|
|||||||
|
|
||||||
if ( isVisible() )
|
if ( isVisible() )
|
||||||
{
|
{
|
||||||
drawColumnLabels();
|
drawHeadlines();
|
||||||
drawList();
|
drawList();
|
||||||
updateTerminal();
|
updateTerminal();
|
||||||
flush_out();
|
flush_out();
|
||||||
|
@ -245,7 +245,7 @@ class FListBox : public FWidget
|
|||||||
// Methods
|
// Methods
|
||||||
void init();
|
void init();
|
||||||
virtual void draw();
|
virtual void draw();
|
||||||
void drawLabel();
|
void drawHeadline();
|
||||||
void drawList();
|
void drawList();
|
||||||
void drawListLine (int, listBoxItems::iterator, bool);
|
void drawListLine (int, listBoxItems::iterator, bool);
|
||||||
void printLeftBracket (fc::brackets_type);
|
void printLeftBracket (fc::brackets_type);
|
||||||
|
@ -98,11 +98,14 @@ class FListViewItem : public FObject
|
|||||||
FWidget::data_ptr getData() const;
|
FWidget::data_ptr getData() const;
|
||||||
uInt getDepth() const;
|
uInt getDepth() const;
|
||||||
|
|
||||||
// Mutator
|
// Mutators
|
||||||
void setText (int, const FString&);
|
void setText (int, const FString&);
|
||||||
void setData (FWidget::data_ptr);
|
void setData (FWidget::data_ptr);
|
||||||
|
void setCheckable (bool);
|
||||||
|
void setChecked (bool);
|
||||||
|
|
||||||
// Inquiry
|
// Inquiry
|
||||||
|
bool isChecked() const;
|
||||||
bool isExpand() const;
|
bool isExpand() const;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@ -114,6 +117,7 @@ class FListViewItem : public FObject
|
|||||||
private:
|
private:
|
||||||
// Inquiry
|
// Inquiry
|
||||||
bool isExpandable() const;
|
bool isExpandable() const;
|
||||||
|
bool isCheckable() const;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
template <typename Compare>
|
template <typename Compare>
|
||||||
@ -130,6 +134,8 @@ class FListViewItem : public FObject
|
|||||||
std::size_t visible_lines;
|
std::size_t visible_lines;
|
||||||
bool expandable;
|
bool expandable;
|
||||||
bool is_expand;
|
bool is_expand;
|
||||||
|
bool checkable;
|
||||||
|
bool is_checked;
|
||||||
|
|
||||||
// Friend class
|
// Friend class
|
||||||
friend class FListView;
|
friend class FListView;
|
||||||
@ -155,6 +161,14 @@ inline FWidget::data_ptr FListViewItem::getData() const
|
|||||||
inline void FListViewItem::setData (FWidget::data_ptr data)
|
inline void FListViewItem::setData (FWidget::data_ptr data)
|
||||||
{ data_pointer = data; }
|
{ data_pointer = data; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline void FListViewItem::setChecked (bool checked)
|
||||||
|
{ is_checked = checked; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline bool FListViewItem::isChecked() const
|
||||||
|
{ return is_checked; }
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
inline bool FListViewItem::isExpand() const
|
inline bool FListViewItem::isExpand() const
|
||||||
{ return is_expand; }
|
{ return is_expand; }
|
||||||
@ -163,6 +177,10 @@ inline bool FListViewItem::isExpand() const
|
|||||||
inline bool FListViewItem::isExpandable() const
|
inline bool FListViewItem::isExpandable() const
|
||||||
{ return expandable; }
|
{ return expandable; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline bool FListViewItem::isCheckable() const
|
||||||
|
{ return checkable; }
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// class FListViewIterator
|
// class FListViewIterator
|
||||||
@ -352,21 +370,24 @@ class FListView : public FWidget
|
|||||||
, std::size_t
|
, std::size_t
|
||||||
, std::size_t );
|
, std::size_t );
|
||||||
virtual void draw();
|
virtual void draw();
|
||||||
void drawColumnLabels();
|
void drawHeadlines();
|
||||||
void drawList();
|
void drawList();
|
||||||
void drawListLine (const FListViewItem*, bool, bool);
|
void drawListLine (const FListViewItem*, bool, bool);
|
||||||
void setLineAttributes (bool, bool);
|
void setLineAttributes (bool, bool);
|
||||||
|
FString getCheckBox (const FListViewItem* item);
|
||||||
FString getLinePrefix (const FListViewItem*, std::size_t);
|
FString getLinePrefix (const FListViewItem*, std::size_t);
|
||||||
void drawSortIndicator (std::size_t&, std::size_t);
|
void drawSortIndicator (std::size_t&, std::size_t);
|
||||||
void drawColumnText (headerItems::const_iterator&);
|
void drawHeadlineLabel (headerItems::const_iterator&);
|
||||||
void drawHeaderBorder (std::size_t);
|
void drawHeaderBorder (std::size_t);
|
||||||
void drawColumnEllipsis ( headerItems::const_iterator&
|
void drawColumnEllipsis ( headerItems::const_iterator&
|
||||||
, const FString& );
|
, const FString& );
|
||||||
void updateDrawing (bool, bool);
|
void updateDrawing (bool, bool);
|
||||||
int determineLineWidth (FListViewItem* item);
|
int determineLineWidth (FListViewItem*);
|
||||||
|
void beforeInsertion (FListViewItem*);
|
||||||
|
void afterInsertion();
|
||||||
void recalculateHorizontalBar (int);
|
void recalculateHorizontalBar (int);
|
||||||
void recalculateVerticalBar (int);
|
void recalculateVerticalBar (int);
|
||||||
void mouseColumnClicked();
|
void mouseHeaderClicked();
|
||||||
void wheelUp (int);
|
void wheelUp (int);
|
||||||
void wheelDown (int);
|
void wheelDown (int);
|
||||||
bool dragScrollUp (int);
|
bool dragScrollUp (int);
|
||||||
@ -377,6 +398,7 @@ class FListView : public FWidget
|
|||||||
FObjectIterator appendItem (FListViewItem*);
|
FObjectIterator appendItem (FListViewItem*);
|
||||||
void processClick();
|
void processClick();
|
||||||
void processChanged();
|
void processChanged();
|
||||||
|
void keySpace();
|
||||||
void keyLeft (int&);
|
void keyLeft (int&);
|
||||||
void keyRight (int&);
|
void keyRight (int&);
|
||||||
void keyHome();
|
void keyHome();
|
||||||
@ -393,6 +415,7 @@ class FListView : public FWidget
|
|||||||
void scrollTo (const FPoint &);
|
void scrollTo (const FPoint &);
|
||||||
void scrollTo (int, int);
|
void scrollTo (int, int);
|
||||||
void scrollBy (int, int);
|
void scrollBy (int, int);
|
||||||
|
bool hasCheckableItems() const;
|
||||||
|
|
||||||
// Callback methods
|
// Callback methods
|
||||||
void cb_VBarChange (FWidget*, data_ptr);
|
void cb_VBarChange (FWidget*, data_ptr);
|
||||||
@ -415,8 +438,10 @@ class FListView : public FWidget
|
|||||||
bool scroll_timer;
|
bool scroll_timer;
|
||||||
bool tree_view;
|
bool tree_view;
|
||||||
bool hide_sort_indicator;
|
bool hide_sort_indicator;
|
||||||
|
bool has_checkable_items;
|
||||||
FPoint clicked_expander_pos;
|
FPoint clicked_expander_pos;
|
||||||
FPoint clicked_column_pos;
|
FPoint clicked_header_pos;
|
||||||
|
const FListViewItem* clicked_checkbox_item;
|
||||||
int xoffset;
|
int xoffset;
|
||||||
int nf_offset;
|
int nf_offset;
|
||||||
int max_line_width;
|
int max_line_width;
|
||||||
@ -537,6 +562,10 @@ inline FObject::FObjectIterator FListView::endOfList()
|
|||||||
inline void FListView::scrollTo (const FPoint& pos)
|
inline void FListView::scrollTo (const FPoint& pos)
|
||||||
{ scrollTo(pos.getX(), pos.getY()); }
|
{ scrollTo(pos.getX(), pos.getY()); }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
inline bool FListView::hasCheckableItems() const
|
||||||
|
{ return has_checkable_items; }
|
||||||
|
|
||||||
} // namespace finalcut
|
} // namespace finalcut
|
||||||
|
|
||||||
#endif // FLISTVIEW_H
|
#endif // FLISTVIEW_H
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
#error "Only <final/final.h> can be included directly."
|
#error "Only <final/final.h> can be included directly."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __cplusplus < 199711L
|
#if !defined (__cplusplus)
|
||||||
|
#error "You need a C++ compiler like g++ or clang++"
|
||||||
|
#elif __cplusplus > 1 && __cplusplus < 199711L
|
||||||
#error "Your C++ compiler does not support the C++98 standard!"
|
#error "Your C++ compiler does not support the C++98 standard!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user