FListViewItem now provides checkable list view items
This commit is contained in:
parent
e40a233d64
commit
3953dc19fa
|
@ -52,6 +52,7 @@ examples/input-dialog
|
|||
examples/choice
|
||||
examples/listbox
|
||||
examples/listview
|
||||
examples/checklist
|
||||
examples/treeview
|
||||
examples/mandelbrot
|
||||
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>
|
||||
* Clicking on the column header in FListView now changes the sort order
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ noinst_PROGRAMS = \
|
|||
choice \
|
||||
listbox \
|
||||
listview \
|
||||
checklist \
|
||||
treeview \
|
||||
opti-move \
|
||||
termcap \
|
||||
|
@ -37,6 +38,7 @@ input_dialog_SOURCES = input-dialog.cpp
|
|||
choice_SOURCES = choice.cpp
|
||||
listbox_SOURCES = listbox.cpp
|
||||
listview_SOURCES = listview.cpp
|
||||
checklist_SOURCES = checklist.cpp
|
||||
treeview_SOURCES = treeview.cpp
|
||||
opti_move_SOURCES = opti-move.cpp
|
||||
string_operations_SOURCES = string-operations.cpp
|
||||
|
|
|
@ -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)
|
||||
, Quit(this)
|
||||
{
|
||||
// Create FListView object
|
||||
// Set FListView geometry
|
||||
listView.setGeometry(2, 1, 33, 14);
|
||||
|
||||
// Add columns to the view
|
||||
|
|
|
@ -130,7 +130,7 @@ class Treeview : public finalcut::FDialog
|
|||
// Methods
|
||||
virtual void adjustSize();
|
||||
|
||||
// Event handlers
|
||||
// Event handler
|
||||
void onClose (finalcut::FCloseEvent*);
|
||||
|
||||
// Data Members
|
||||
|
@ -302,7 +302,7 @@ Treeview::Treeview (finalcut::FWidget* parent)
|
|||
, listView(this)
|
||||
, Quit(this)
|
||||
{
|
||||
// Create FListView object
|
||||
// Set FListView geometry
|
||||
listView.setGeometry(2, 1, 53, 14);
|
||||
|
||||
// Add columns to the view
|
||||
|
|
|
@ -896,7 +896,7 @@ void FListBox::draw()
|
|||
}
|
||||
}
|
||||
|
||||
drawLabel();
|
||||
drawHeadline();
|
||||
|
||||
if ( isMonochron() )
|
||||
setReverse(false);
|
||||
|
@ -923,7 +923,7 @@ void FListBox::draw()
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FListBox::drawLabel()
|
||||
void FListBox::drawHeadline()
|
||||
{
|
||||
if ( text.isNull() || text.isEmpty() )
|
||||
return;
|
||||
|
|
|
@ -167,6 +167,8 @@ FListViewItem::FListViewItem (const FListViewItem& item)
|
|||
, visible_lines(1)
|
||||
, expandable(false)
|
||||
, is_expand(false)
|
||||
, checkable(false)
|
||||
, is_checked(false)
|
||||
{
|
||||
FObject* parent = getParent();
|
||||
|
||||
|
@ -192,6 +194,8 @@ FListViewItem::FListViewItem (FObjectIterator parent_iter)
|
|||
, visible_lines(1)
|
||||
, expandable(false)
|
||||
, is_expand(false)
|
||||
, checkable(false)
|
||||
, is_checked(false)
|
||||
{
|
||||
insert (this, parent_iter);
|
||||
}
|
||||
|
@ -207,6 +211,8 @@ FListViewItem::FListViewItem ( const FStringList& cols
|
|||
, visible_lines(1)
|
||||
, expandable(false)
|
||||
, is_expand(false)
|
||||
, checkable(false)
|
||||
, is_checked(false)
|
||||
{
|
||||
if ( cols.empty() )
|
||||
return;
|
||||
|
@ -325,7 +331,7 @@ FObject::FObjectIterator FListViewItem::insert ( FListViewItem* child
|
|||
//----------------------------------------------------------------------
|
||||
void FListViewItem::expand()
|
||||
{
|
||||
if ( is_expand || ! hasChildren() )
|
||||
if ( isExpand() || ! hasChildren() )
|
||||
return;
|
||||
|
||||
is_expand = true;
|
||||
|
@ -334,7 +340,7 @@ void FListViewItem::expand()
|
|||
//----------------------------------------------------------------------
|
||||
void FListViewItem::collapse()
|
||||
{
|
||||
if ( ! is_expand )
|
||||
if ( ! isExpand() )
|
||||
return;
|
||||
|
||||
is_expand = false;
|
||||
|
@ -346,7 +352,7 @@ void FListViewItem::collapse()
|
|||
template <typename Compare>
|
||||
void FListViewItem::sort (Compare cmp)
|
||||
{
|
||||
if ( ! expandable )
|
||||
if ( ! isExpandable() )
|
||||
return;
|
||||
|
||||
// Sort the top level
|
||||
|
@ -418,6 +424,20 @@ std::size_t FListViewItem::getVisibleLines()
|
|||
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()
|
||||
{
|
||||
|
@ -611,8 +631,10 @@ FListView::FListView (FWidget* parent)
|
|||
, scroll_timer(false)
|
||||
, tree_view(false)
|
||||
, hide_sort_indicator(false)
|
||||
, has_checkable_items(false)
|
||||
, clicked_expander_pos(-1, -1)
|
||||
, clicked_column_pos(-1, -1)
|
||||
, clicked_header_pos(-1, -1)
|
||||
, clicked_checkbox_item(0)
|
||||
, xoffset(0)
|
||||
, nf_offset(0)
|
||||
, max_line_width(1)
|
||||
|
@ -802,14 +824,11 @@ FObject::FObjectIterator FListView::insert ( FListViewItem* item
|
|||
, FObjectIterator parent_iter )
|
||||
{
|
||||
FObjectIterator item_iter;
|
||||
int line_width;
|
||||
int element_count;
|
||||
|
||||
if ( parent_iter == FListView::null_iter )
|
||||
return FListView::null_iter;
|
||||
|
||||
line_width = determineLineWidth (item);
|
||||
recalculateHorizontalBar (line_width);
|
||||
beforeInsertion(item); // preprocessing
|
||||
|
||||
if ( parent_iter == root )
|
||||
{
|
||||
|
@ -835,19 +854,7 @@ FObject::FObjectIterator FListView::insert ( FListViewItem* item
|
|||
else
|
||||
item_iter = FListView::null_iter;
|
||||
|
||||
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();
|
||||
|
||||
element_count = int(getCount());
|
||||
recalculateVerticalBar (element_count);
|
||||
afterInsertion(); // post-processing
|
||||
return item_iter;
|
||||
}
|
||||
|
||||
|
@ -964,6 +971,11 @@ void FListView::onKeyPress (FKeyEvent* ev)
|
|||
ev->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_space:
|
||||
keySpace();
|
||||
ev->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_up:
|
||||
stepBackward();
|
||||
ev->accept();
|
||||
|
@ -1059,26 +1071,41 @@ void FListView::onMouseDown (FMouseEvent* ev)
|
|||
|
||||
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;
|
||||
|
||||
if ( new_pos < int(getCount()) )
|
||||
setRelativePosition (mouse_y - 2);
|
||||
|
||||
const FListViewItem* item = getCurrentItem();
|
||||
|
||||
if ( tree_view )
|
||||
{
|
||||
const FListViewItem* item = getCurrentItem();
|
||||
int indent = int(item->getDepth() << 1); // indent = 2 * depth
|
||||
indent = int(item->getDepth() << 1); // indent = 2 * depth
|
||||
|
||||
if ( item->isExpandable() && mouse_x - 2 == indent - xoffset )
|
||||
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() )
|
||||
drawList();
|
||||
|
||||
|
@ -1107,15 +1134,18 @@ void FListView::onMouseUp (FMouseEvent* ev)
|
|||
|
||||
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 )
|
||||
{
|
||||
FListViewItem* item = getCurrentItem();
|
||||
indent = int(item->getDepth() << 1); // indent = 2 * depth
|
||||
|
||||
if ( item->isExpandable()
|
||||
&& 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() )
|
||||
setReverse(false);
|
||||
|
@ -1548,7 +1595,7 @@ void FListView::draw()
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FListView::drawColumnLabels()
|
||||
void FListView::drawHeadlines()
|
||||
{
|
||||
std::vector<charData>::const_iterator first, last;
|
||||
headerItems::const_iterator iter;
|
||||
|
@ -1562,6 +1609,9 @@ void FListView::drawColumnLabels()
|
|||
iter = header.begin();
|
||||
headerline.clear();
|
||||
|
||||
if ( hasCheckableItems() )
|
||||
drawHeaderBorder(4);
|
||||
|
||||
while ( iter != header.end() )
|
||||
{
|
||||
const FString& text = iter->name;
|
||||
|
@ -1572,7 +1622,7 @@ void FListView::drawColumnLabels()
|
|||
continue;
|
||||
}
|
||||
|
||||
drawColumnText(iter);
|
||||
drawHeadlineLabel(iter);
|
||||
++iter;
|
||||
}
|
||||
|
||||
|
@ -1643,35 +1693,37 @@ void FListView::drawListLine ( const FListViewItem* item
|
|||
, bool is_focus
|
||||
, bool is_current )
|
||||
{
|
||||
std::size_t indent = item->getDepth() << 1; // indent = 2 * depth
|
||||
|
||||
// Set line color and attributes
|
||||
setLineAttributes (is_current, is_focus);
|
||||
|
||||
// Print the entry
|
||||
std::size_t indent = item->getDepth() << 1; // indent = 2 * depth
|
||||
FString line = getLinePrefix (item, indent);
|
||||
|
||||
// Print columns
|
||||
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 checkbox_space = 4;
|
||||
static const std::size_t ellipsis_length = 2;
|
||||
|
||||
const FString& text = item->column_list[i];
|
||||
std::size_t width = std::size_t(header[i].width);
|
||||
const FString& text = item->column_list[col];
|
||||
std::size_t width = std::size_t(header[col].width);
|
||||
std::size_t txt_length = text.getLength();
|
||||
// Increment the value of i for the column position
|
||||
// and the next iteration
|
||||
i++;
|
||||
fc::text_alignment align = getColumnAlignment(int(i));
|
||||
col++;
|
||||
fc::text_alignment align = getColumnAlignment(int(col));
|
||||
std::size_t align_offset = getAlignOffset (align, txt_length, width);
|
||||
|
||||
if ( tree_view && i == 1 )
|
||||
if ( tree_view && col == 1 )
|
||||
{
|
||||
width -= indent;
|
||||
width--;
|
||||
width -= (indent + 1);
|
||||
|
||||
if ( item->isCheckable() )
|
||||
width -= checkbox_space;
|
||||
}
|
||||
|
||||
// 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
|
||||
, std::size_t indent )
|
||||
{
|
||||
FString line = "";
|
||||
FString line;
|
||||
|
||||
if ( tree_view )
|
||||
{
|
||||
if ( indent > 0 )
|
||||
line = FString(indent, L' ');
|
||||
|
||||
if ( item->expandable )
|
||||
if ( item->isExpandable() )
|
||||
{
|
||||
if ( item->is_expand )
|
||||
if ( item->isExpand() )
|
||||
{
|
||||
line += wchar_t(fc::BlackDownPointingTriangle); // ▼
|
||||
line += L' ';
|
||||
|
@ -1779,6 +1852,9 @@ inline FString FListView::getLinePrefix ( const FListViewItem* item
|
|||
else
|
||||
line = L" ";
|
||||
|
||||
if ( item->isCheckable() )
|
||||
line += getCheckBox(item);
|
||||
|
||||
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
|
||||
static const std::size_t leading_space = 1;
|
||||
|
@ -1932,6 +2008,31 @@ int FListView::determineLineWidth (FListViewItem* item)
|
|||
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)
|
||||
{
|
||||
|
@ -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_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;
|
||||
iter = header.begin();
|
||||
|
||||
|
@ -1983,8 +2085,8 @@ void FListView::mouseColumnClicked()
|
|||
if ( click_width > iter->width )
|
||||
click_width = iter->width;
|
||||
|
||||
if ( column_pos > column_start
|
||||
&& column_pos <= column_start + click_width )
|
||||
if ( header_pos > header_start
|
||||
&& header_pos <= header_start + click_width )
|
||||
{
|
||||
if ( has_sort_indicator && sort_order == fc::ascending )
|
||||
setColumnSort (column, fc::descending);
|
||||
|
@ -1995,7 +2097,7 @@ void FListView::mouseColumnClicked()
|
|||
|
||||
if ( isVisible() )
|
||||
{
|
||||
drawColumnLabels();
|
||||
drawHeadlines();
|
||||
drawList();
|
||||
updateTerminal();
|
||||
flush_out();
|
||||
|
@ -2003,7 +2105,7 @@ void FListView::mouseColumnClicked()
|
|||
break;
|
||||
}
|
||||
|
||||
column_start += leading_space + iter->width;
|
||||
header_start += leading_space + iter->width;
|
||||
column++;
|
||||
++iter;
|
||||
}
|
||||
|
@ -2167,6 +2269,15 @@ void FListView::processChanged()
|
|||
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)
|
||||
{
|
||||
|
@ -2569,7 +2680,7 @@ void FListView::cb_HBarChange (FWidget*, data_ptr)
|
|||
|
||||
if ( isVisible() )
|
||||
{
|
||||
drawColumnLabels();
|
||||
drawHeadlines();
|
||||
drawList();
|
||||
updateTerminal();
|
||||
flush_out();
|
||||
|
|
|
@ -245,7 +245,7 @@ class FListBox : public FWidget
|
|||
// Methods
|
||||
void init();
|
||||
virtual void draw();
|
||||
void drawLabel();
|
||||
void drawHeadline();
|
||||
void drawList();
|
||||
void drawListLine (int, listBoxItems::iterator, bool);
|
||||
void printLeftBracket (fc::brackets_type);
|
||||
|
|
|
@ -98,11 +98,14 @@ class FListViewItem : public FObject
|
|||
FWidget::data_ptr getData() const;
|
||||
uInt getDepth() const;
|
||||
|
||||
// Mutator
|
||||
// Mutators
|
||||
void setText (int, const FString&);
|
||||
void setData (FWidget::data_ptr);
|
||||
void setCheckable (bool);
|
||||
void setChecked (bool);
|
||||
|
||||
// Inquiry
|
||||
bool isChecked() const;
|
||||
bool isExpand() const;
|
||||
|
||||
// Methods
|
||||
|
@ -114,6 +117,7 @@ class FListViewItem : public FObject
|
|||
private:
|
||||
// Inquiry
|
||||
bool isExpandable() const;
|
||||
bool isCheckable() const;
|
||||
|
||||
// Methods
|
||||
template <typename Compare>
|
||||
|
@ -130,6 +134,8 @@ class FListViewItem : public FObject
|
|||
std::size_t visible_lines;
|
||||
bool expandable;
|
||||
bool is_expand;
|
||||
bool checkable;
|
||||
bool is_checked;
|
||||
|
||||
// Friend class
|
||||
friend class FListView;
|
||||
|
@ -155,6 +161,14 @@ inline FWidget::data_ptr FListViewItem::getData() const
|
|||
inline void FListViewItem::setData (FWidget::data_ptr 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
|
||||
{ return is_expand; }
|
||||
|
@ -163,6 +177,10 @@ inline bool FListViewItem::isExpand() const
|
|||
inline bool FListViewItem::isExpandable() const
|
||||
{ return expandable; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FListViewItem::isCheckable() const
|
||||
{ return checkable; }
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FListViewIterator
|
||||
|
@ -352,21 +370,24 @@ class FListView : public FWidget
|
|||
, std::size_t
|
||||
, std::size_t );
|
||||
virtual void draw();
|
||||
void drawColumnLabels();
|
||||
void drawHeadlines();
|
||||
void drawList();
|
||||
void drawListLine (const FListViewItem*, bool, bool);
|
||||
void setLineAttributes (bool, bool);
|
||||
FString getCheckBox (const FListViewItem* item);
|
||||
FString getLinePrefix (const FListViewItem*, 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 drawColumnEllipsis ( headerItems::const_iterator&
|
||||
, const FString& );
|
||||
void updateDrawing (bool, bool);
|
||||
int determineLineWidth (FListViewItem* item);
|
||||
int determineLineWidth (FListViewItem*);
|
||||
void beforeInsertion (FListViewItem*);
|
||||
void afterInsertion();
|
||||
void recalculateHorizontalBar (int);
|
||||
void recalculateVerticalBar (int);
|
||||
void mouseColumnClicked();
|
||||
void mouseHeaderClicked();
|
||||
void wheelUp (int);
|
||||
void wheelDown (int);
|
||||
bool dragScrollUp (int);
|
||||
|
@ -377,6 +398,7 @@ class FListView : public FWidget
|
|||
FObjectIterator appendItem (FListViewItem*);
|
||||
void processClick();
|
||||
void processChanged();
|
||||
void keySpace();
|
||||
void keyLeft (int&);
|
||||
void keyRight (int&);
|
||||
void keyHome();
|
||||
|
@ -393,6 +415,7 @@ class FListView : public FWidget
|
|||
void scrollTo (const FPoint &);
|
||||
void scrollTo (int, int);
|
||||
void scrollBy (int, int);
|
||||
bool hasCheckableItems() const;
|
||||
|
||||
// Callback methods
|
||||
void cb_VBarChange (FWidget*, data_ptr);
|
||||
|
@ -415,8 +438,10 @@ class FListView : public FWidget
|
|||
bool scroll_timer;
|
||||
bool tree_view;
|
||||
bool hide_sort_indicator;
|
||||
bool has_checkable_items;
|
||||
FPoint clicked_expander_pos;
|
||||
FPoint clicked_column_pos;
|
||||
FPoint clicked_header_pos;
|
||||
const FListViewItem* clicked_checkbox_item;
|
||||
int xoffset;
|
||||
int nf_offset;
|
||||
int max_line_width;
|
||||
|
@ -537,6 +562,10 @@ inline FObject::FObjectIterator FListView::endOfList()
|
|||
inline void FListView::scrollTo (const FPoint& pos)
|
||||
{ scrollTo(pos.getX(), pos.getY()); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FListView::hasCheckableItems() const
|
||||
{ return has_checkable_items; }
|
||||
|
||||
} // namespace finalcut
|
||||
|
||||
#endif // FLISTVIEW_H
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
#error "Only <final/final.h> can be included directly."
|
||||
#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!"
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue