Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions samples/listctrl/listctrlsample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_EXPORT_FULL_WIDTH, MyFrame::OnExportFullWidth)
EVT_MENU(ID_EXPORT_SIMPLE, MyFrame::OnExportSimple)
EVT_MENU(ID_EXPORT_FINANCIAL, MyFrame::OnExportFinancial)
EVT_MENU(ID_EXPORT_TWO_LISTS, MyFrame::OnExportTwoLists)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
wxEND_EVENT_TABLE()

Expand All @@ -40,6 +41,7 @@ MyFrame::MyFrame(const wxString& title)
menuFile->Append(ID_EXPORT_FULL_WIDTH, "Export to PDF (&Full Width)\tCtrl-F", "Export with columns stretched to page width");
menuFile->Append(ID_EXPORT_SIMPLE, "Export to PDF (&Simple/LaTeX)\tCtrl-L", "Export with LaTeX booktabs-style rules only");
menuFile->Append(ID_EXPORT_FINANCIAL, "Export Financial Data (Lan&dscape)\tCtrl-G", "Export sample ledger with long note cells");
menuFile->Append(ID_EXPORT_TWO_LISTS, "Export Two Lists (different &icons)\tCtrl-I", "Export two list controls with separate image lists");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);

Expand Down Expand Up @@ -284,6 +286,86 @@ void MyFrame::OnExportFinancial(wxCommandEvent& WXUNUSED(event))
fin->Destroy();
}

void MyFrame::OnExportTwoLists(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog saveFileDialog(this, _("Save PDF file"), "", "list_two_lists.pdf",
"PDF files (*.pdf)|*.pdf", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;

// First list: build problems, with its own image list of warning and error icons
wxListCtrl* problems = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLC_REPORT);
problems->Hide();
wxImageList* problemIcons = new wxImageList(16, 16);
problemIcons->Add(wxArtProvider::GetIcon(wxART_WARNING, wxART_MENU, wxSize(16, 16)));
problemIcons->Add(wxArtProvider::GetIcon(wxART_ERROR, wxART_MENU, wxSize(16, 16)));
// AssignImageList() hands ownership to the control, so it is freed on Destroy()
problems->AssignImageList(problemIcons, wxIMAGE_LIST_SMALL);

problems->InsertColumn(0, "Severity", wxLIST_FORMAT_LEFT, 100);
problems->InsertColumn(1, "Message", wxLIST_FORMAT_LEFT, 250);

struct ProblemRow
{
const char* severity;
// Index into problemIcons: 0 = warning, 1 = error
int icon;
const char* message;
};

static const ProblemRow problemRows[] =
{
{ "Warning", 0, "Variable 'total' may be used uninitialized" },
{ "Error", 1, "Undefined reference to 'CalcChecksum'" },
{ "Warning", 0, "Implicit conversion from double to int" },
{ "Error", 1, "No matching overload for 'Format'" },
{ "Warning", 0, "Unused parameter 'event'" },
};

for (const auto& r : problemRows)
{
long idx = problems->InsertItem(problems->GetItemCount(), r.severity, r.icon);
problems->SetItem(idx, 1, r.message);
}

// Second list: test results, with a separate image list holding an OK icon
wxListCtrl* results = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxLC_REPORT);
results->Hide();
wxImageList* okIcons = new wxImageList(16, 16);
okIcons->Add(wxArtProvider::GetIcon(wxART_TICK_MARK, wxART_MENU, wxSize(16, 16)));
results->AssignImageList(okIcons, wxIMAGE_LIST_SMALL);

results->InsertColumn(0, "Test", wxLIST_FORMAT_LEFT, 150);
results->InsertColumn(1, "Result", wxLIST_FORMAT_LEFT, 100);

const char* tests[] = { "Build", "Unit tests", "Integration tests", "Linting", "Packaging" };
for (const auto* test : tests)
{
long idx = results->InsertItem(results->GetItemCount(), test);
results->SetItem(idx, 1, "OK");
results->SetItemImage(idx, 0);
}

// Export both lists into the same document; the icons of each list
// must come from its own image list
wxPdfDocument doc;
doc.AddPage();

wxPdfListCtrlOptions options;
options.SetBorderColour(wxPdfColour(200, 200, 200));

doc.AddList(problems, options);
// Leave a gap below the first table
doc.SetXY(doc.GetLeftMargin(), doc.GetY() + 20);
doc.AddList(results, options);
doc.SaveAsFile(saveFileDialog.GetPath());

problems->Destroy();
results->Destroy();
}

void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
{
Close(true);
Expand Down
4 changes: 3 additions & 1 deletion samples/listctrl/listctrlsample.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class MyFrame : public wxFrame
void OnExportFullWidth(wxCommandEvent& event);
void OnExportSimple(wxCommandEvent& event);
void OnExportFinancial(wxCommandEvent& event);
void OnExportTwoLists(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);

wxListCtrl* m_list;
Expand All @@ -46,7 +47,8 @@ enum
ID_EXPORT_DC,
ID_EXPORT_FULL_WIDTH,
ID_EXPORT_SIMPLE,
ID_EXPORT_FINANCIAL
ID_EXPORT_FINANCIAL,
ID_EXPORT_TWO_LISTS
};

#endif
42 changes: 35 additions & 7 deletions src/pdflistctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <vector>
#include <numeric>
#include <algorithm>
#include <map>

wxPdfListCtrlOptions::wxPdfListCtrlOptions()
{
Expand All @@ -45,12 +46,12 @@ class wxPdfListCtrlExporter
{
public:
wxPdfListCtrlExporter(wxPdfDocument* doc, wxListCtrl* list, const wxPdfListCtrlOptions& options)
: m_doc(doc), m_list(list), m_options(options), m_dc(NULL)
: m_doc(doc), m_list(list), m_options(options), m_dc(NULL), m_exportId(ms_exportCounter++)
{
}

wxPdfListCtrlExporter(wxPdfDC* dc, wxListCtrl* list, const wxPdfListCtrlOptions& options)
: m_doc(dc->GetPdfDocument()), m_list(list), m_options(options), m_dc(dc)
: m_doc(dc->GetPdfDocument()), m_list(list), m_options(options), m_dc(dc), m_exportId(ms_exportCounter++)
{
}

Expand All @@ -72,6 +73,7 @@ class wxPdfListCtrlExporter
// Calculate column widths
size_t colCount = m_list->GetColumnCount();
std::vector<double> colWidths(colCount);
std::vector<int> colAligns(colCount, wxPDF_ALIGN_LEFT);

if (m_options.GetBodyPdfFont().IsValid())
m_doc->SetFont(m_options.GetBodyPdfFont(), wxPDF_FONTSTYLE_REGULAR, 0);
Expand All @@ -83,9 +85,23 @@ class wxPdfListCtrlExporter
for (size_t col = 0; col < colCount; ++col)
{
wxListItem item;
item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH);
item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT);
m_list->GetColumn(col, item);

// Map the column's alignment to the PDF cell alignment
switch (item.GetAlign())
{
case wxLIST_FORMAT_RIGHT:
colAligns[col] = wxPDF_ALIGN_RIGHT;
break;
case wxLIST_FORMAT_CENTRE:
colAligns[col] = wxPDF_ALIGN_CENTER;
break;
default:
colAligns[col] = wxPDF_ALIGN_LEFT;
break;
}

double headerWidth = m_doc->GetStringWidth(item.GetText()) + cellPadding;
double maxContentWidth = 0;

Expand Down Expand Up @@ -403,17 +419,22 @@ class wxPdfListCtrlExporter

double iconX = m_doc->GetX() + 1;
double iconY = m_doc->GetY() + (rowHeight - imgH) / 2;
text = wxS(" ") + text;
m_doc->Cell(colWidths[col], rowHeight, text, border, 0, wxPDF_ALIGN_LEFT, fill ? 1 : 0);
// Indent the text past the icon; only needed when the text
// starts at the left edge where the icon is drawn
if (colAligns[col] == wxPDF_ALIGN_LEFT)
text = wxS(" ") + text;
m_doc->Cell(colWidths[col], rowHeight, text, border, 0, colAligns[col], fill ? 1 : 0);
drawCell = false;
m_doc->Image(wxString::Format(wxS("listicon_%d"), info.GetImage()),
// Include the export ID in the resource name so that icons from
// different image lists don't collide in the document's image cache
m_doc->Image(wxString::Format(wxS("listicon_%d_%d"), m_exportId, info.GetImage()),
bmp.ConvertToImage(), iconX, iconY, imgW, imgH);
}
}
}
if (drawCell)
{
m_doc->Cell(colWidths[col], rowHeight, text, border, 0, wxPDF_ALIGN_LEFT, fill ? 1 : 0);
m_doc->Cell(colWidths[col], rowHeight, text, border, 0, colAligns[col], fill ? 1 : 0);
}
}
curY += rowHeight;
Expand All @@ -438,8 +459,15 @@ class wxPdfListCtrlExporter
wxListCtrl* m_list;
const wxPdfListCtrlOptions& m_options;
wxPdfDC* m_dc;
// Unique ID per export, used to keep icon resource names
// from different image lists apart
int m_exportId;

static int ms_exportCounter;
};

int wxPdfListCtrlExporter::ms_exportCounter = 0;

// --- API Implementation ---

void wxPdfDocument::AddList(wxListCtrl* list, const wxPdfListCtrlOptions& options)
Expand Down
Loading