summaryrefslogtreecommitdiff
path: root/library/CustomGrid.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 16:56:14 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 16:56:14 +0200
commit1046c195a9bbac24678c06310a4dd56b10347244 (patch)
tree89ad9f6fe3e538d65ef973b628ed9284b6c99e9f /library/CustomGrid.cpp
parent1.14 (diff)
downloadFreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.tar.gz
FreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.tar.bz2
FreeFileSync-1046c195a9bbac24678c06310a4dd56b10347244.zip
1.15
Diffstat (limited to 'library/CustomGrid.cpp')
-rw-r--r--library/CustomGrid.cpp879
1 files changed, 616 insertions, 263 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index 25ceb537..95300a2b 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -3,24 +3,28 @@
#include "resources.h"
#include <wx/dc.h>
#include "../algorithm.h"
+#include "resources.h"
+
+using namespace xmlAccess;
+
-const unsigned int MinimumRows = 15;
+const unsigned int MIN_ROW_COUNT = 15;
//class containing pure grid data: basically the same as wxGridStringTable, but adds cell formatting
-class CustomGridTableBase : public wxGridStringTable
+class CustomGridTable : public wxGridTableBase
{
public:
- CustomGridTableBase(int numRows, int numCols) :
- wxGridStringTable(numRows, numCols),
+ CustomGridTable() :
+ wxGridTableBase(),
lightBlue(80, 110, 255),
lightGrey(212, 208, 200),
- gridIdentifier(0),
- gridRefUI(0),
- gridData(0),
- lastNrRows(MinimumRows) {}
+ gridRefUI(NULL),
+ gridData(NULL),
+ lastNrRows(0),
+ lastNrCols(0) {}
- ~CustomGridTableBase() {}
+ virtual ~CustomGridTable() {}
void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData)
@@ -30,182 +34,56 @@ public:
}
- void SetGridIdentifier(int id)
- {
- gridIdentifier = id;
- }
-
//###########################################################################
//grid standard input output methods, redirected directly to gridData to improve performance
virtual int GetNumberRows()
{
if (gridRefUI)
- return max(gridRefUI->size(), MinimumRows);
+ return std::max(gridRefUI->size(), MIN_ROW_COUNT);
else
- return MinimumRows; //grid is initialized with this number of rows
+ return 0; //grid is initialized with zero number of rows
}
- virtual bool IsEmptyCell( int row, int col )
+ virtual int GetNumberCols() //virtual used by middle grid!
{
- return (GetValue(row, col) == wxEmptyString);
+ return columnPositions.size();
}
- wxString evaluateCmpResult(const CompareFilesResult result, const bool selectedForSynchronization)
+ virtual bool IsEmptyCell( int row, int col )
{
- if (selectedForSynchronization)
- switch (result)
- {
- case FILE_LEFT_SIDE_ONLY:
- return wxT("<|");
- break;
- case FILE_RIGHT_SIDE_ONLY:
- return wxT("|>");
- break;
- case FILE_RIGHT_NEWER:
- return wxT(">>");
- break;
- case FILE_LEFT_NEWER:
- return wxT("<<");
- break;
- case FILE_DIFFERENT:
- return wxT("!=");
- break;
- case FILE_EQUAL:
- return wxT("==");
- break;
- default:
- assert (false);
- return wxEmptyString;
- }
- else return wxT("(-)");
+ return (GetValue(row, col) == wxEmptyString);
}
- virtual wxString GetValue(int row, int col)
- {
- if (gridRefUI)
- {
- if (unsigned(row) < gridRefUI->size())
- {
- const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
- wxString fileSize; //tmp string
-
- switch (gridIdentifier)
- {
- case 1:
- if (col < 4)
- {
- if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
- {
- switch (col)
- {
- case 0: //filename
- return wxEmptyString;
- case 1: //relative path
- return gridLine.fileDescrLeft.relativeName;
- case 2: //file size
- return _("<Directory>");
- case 3: //date
- return wxEmptyString;
- }
- }
- else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
- {
- switch (col)
- {
- case 0: //filename
- return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 1: //relative path
- return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 2: //file size
- return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrLeft.fileSize.ToString());
- case 3: //date
- return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw);
- }
- }
- }
- else
- assert (false);
-
- break;
-
- case 2:
- if (col < 4)
- {
- if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
- {
- switch (col)
- {
- case 0: //filename
- return wxEmptyString;
- case 1: //relative path
- return gridLine.fileDescrRight.relativeName;
- case 2: //file size
- return _("<Directory>");
- case 3: //date
- return wxEmptyString;
- }
- }
- else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE)
- {
- switch (col)
- {
- case 0: //filename
- return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 1: //relative path
- return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
- case 2: //file size
- return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrRight.fileSize.ToString());
- case 3: //date
- return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw);
- }
- }
- }
- else
- assert (false);
-
- break;
+ virtual wxString GetValue(int row, int col) = 0;
- case 3:
- if (col < 1)
- return evaluateCmpResult(gridLine.cmpResult, gridLine.selectedForSynchronization);
- else
- assert (false);
- break;
- default:
- assert (false);
- break;
- }
- }
- }
- //if data is not found:
- return wxEmptyString;
- }
-
-
- virtual void SetValue( int row, int col, const wxString& value )
+ virtual void SetValue(int row, int col, const wxString& value)
{
assert (false); //should not be used, since values are retrieved directly from gridRefUI
}
+
virtual void Clear()
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
}
- virtual bool InsertRows( size_t pos = 0, size_t numRows = 1 )
+
+ virtual bool InsertRows(size_t pos = 0, size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
}
- virtual bool AppendRows( size_t numRows = 1 )
+
+ virtual bool AppendRows(size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
}
- virtual bool DeleteRows( size_t pos = 0, size_t numRows = 1 )
+
+ virtual bool DeleteRows(size_t pos = 0, size_t numRows = 1)
{
assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI}
return true;
@@ -216,7 +94,7 @@ public:
{
if (gridRefUI)
{
- int currentNrRows = GetNumberRows();
+ const int currentNrRows = GetNumberRows();
if (lastNrRows < currentNrRows)
{
@@ -243,79 +121,326 @@ public:
}
lastNrRows = currentNrRows;
}
- }
-//###########################################################################
- enum RowColor {BLUE, GREY, NONE};
+ const int currentNrCols = GetNumberCols();
- inline //redundant command
- RowColor getRowColor(int row) //rows that are filtered out are shown in different color
- {
- if (gridRefUI)
+ if (lastNrCols < currentNrCols)
{
- if (unsigned(row) < gridRefUI->size())
+ if (GetView())
{
- const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
-
- //mark filtered rows
- if (!cmpLine.selectedForSynchronization)
- return BLUE;
- //mark directories
- else if (gridIdentifier == 1 && cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
- return GREY;
- else if (gridIdentifier == 2 && cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
- return GREY;
- else
- return NONE;
+ wxGridTableMessage msg(this,
+ wxGRIDTABLE_NOTIFY_COLS_APPENDED,
+ currentNrCols - lastNrCols);
+
+ GetView()->ProcessTableMessage( msg );
}
}
- return NONE;
+ else if (lastNrCols > currentNrCols)
+ {
+ if (GetView())
+ {
+ wxGridTableMessage msg(this,
+ wxGRIDTABLE_NOTIFY_COLS_DELETED,
+ 0,
+ lastNrCols - currentNrCols);
+
+ GetView()->ProcessTableMessage( msg );
+ }
+ }
+ lastNrCols = currentNrCols;
}
+//###########################################################################
- wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
+ virtual wxString GetColLabelValue( int col )
{
- wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind);
+ return CustomGrid::getTypeName(getTypeAtPos(col));
+ }
+
+
+ virtual wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
+ {
+ const wxColour& color = getRowColor(row);
- // MARK FILTERED ROWS:
+ //add color to some rows
+ wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind);
if (result)
- { //if kind is not a cell or row attribute, we have to clone the cell attribute, since we don't want to change e.g. all column attribs
- if (result->GetKind() != wxGridCellAttr::Cell && result->GetKind() != wxGridCellAttr::Row)
+ {
+ if (result->GetBackgroundColour() == color)
{
- wxGridCellAttr* attr = result->Clone();
+ return result;
+ }
+ else //grid attribute might be referenced by other nodes, so clone it!
+ {
+ wxGridCellAttr* attr = result->Clone(); //attr has ref-count 1
result->DecRef();
result = attr;
}
-
- RowColor color = getRowColor(row);
- if (color == BLUE)
- result->SetBackgroundColour(lightBlue);
- else if (color == GREY)
- result->SetBackgroundColour(lightGrey);
- else
- result->SetBackgroundColour(*wxWHITE);
}
else
- {
- result = new wxGridCellAttr;
+ result = new wxGridCellAttr; //created with ref-count 1
- RowColor color = getRowColor(row);
- if (color == BLUE)
- result->SetBackgroundColour(lightBlue);
- else if (color == GREY)
- result->SetBackgroundColour(lightGrey);
- }
+ result->SetBackgroundColour(color);
return result;
}
-private:
+
+ void setupColumns(const std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes>& positions)
+ {
+ columnPositions = positions;
+ updateGridSizes(); //add or remove columns
+ }
+
+
+ XmlGlobalSettings::ColumnTypes getTypeAtPos(unsigned pos) const
+ {
+ if (pos < columnPositions.size())
+ return columnPositions[pos];
+ else
+ return XmlGlobalSettings::ColumnTypes(1000);
+ }
+
+
+protected:
+ virtual const wxColour& getRowColor(int row) = 0; //rows that are filtered out are shown in different color
+
+ std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes> columnPositions;
+
wxColour lightBlue;
wxColour lightGrey;
- int gridIdentifier;
GridView* gridRefUI; //(very fast) access to underlying grid data :)
FileCompareResult* gridData;
int lastNrRows;
+ int lastNrCols;
+};
+
+
+class CustomGridTableLeft : public CustomGridTable
+{
+public:
+ CustomGridTableLeft() : CustomGridTable() {}
+ ~CustomGridTableLeft() {}
+
+ virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ //mark directories
+ else if (cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
+ return lightGrey;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return wxEmptyString;
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrLeft.relativeName.c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ return _("<Directory>");
+ case XmlGlobalSettings::DATE: //date
+ return wxEmptyString;
+ }
+ }
+ else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ {
+ wxString fileSize = gridLine.fileDescrLeft.fileSize.ToString(); //tmp string
+ return globalFunctions::includeNumberSeparator(fileSize);
+ }
+ case XmlGlobalSettings::DATE: //date
+ return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw);
+ }
+ }
+ }
+ }
+ //if data is not found:
+ return wxEmptyString;
+ }
+};
+
+
+class CustomGridTableMiddle : public CustomGridTable
+{
+public:
+ CustomGridTableMiddle() : CustomGridTable()
+ {
+ lastNrCols = 1; //ensure CustomGridTable::updateGridSizes() is working correctly
+ }
+ ~CustomGridTableMiddle() {}
+
+ //virtual impl.
+ int GetNumberCols()
+ {
+ return 1;
+ }
+
+
+ int selectedForSynchronization(const unsigned int row) // 0 == false, 1 == true, -1 == not defined
+ {
+ if (gridRefUI && row < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (cmpLine.selectedForSynchronization)
+ return 1;
+ else
+ return 0;
+ }
+ return -1;
+ }
+
+
+ //virtual impl.
+ const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ switch (gridLine.cmpResult)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ return wxT("<|");
+ case FILE_RIGHT_SIDE_ONLY:
+ return wxT("|>");
+ case FILE_RIGHT_NEWER:
+ return wxT(">>");
+ case FILE_LEFT_NEWER:
+ return wxT("<<");
+ case FILE_DIFFERENT:
+ return wxT("!=");
+ case FILE_EQUAL:
+ return wxT("==");
+ default:
+ assert (false);
+ return wxEmptyString;
+ }
+ }
+ }
+ //if data is not found:
+ return wxEmptyString;
+ }
+};
+
+
+class CustomGridTableRight : public CustomGridTable
+{
+public:
+ CustomGridTableRight() : CustomGridTable() {}
+ ~CustomGridTableRight() {}
+
+ //virtual impl.
+ const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
+ {
+ if (gridRefUI && unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]];
+
+ //mark filtered rows
+ if (!cmpLine.selectedForSynchronization)
+ return lightBlue;
+ //mark directories
+ else if (cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
+ return lightGrey;
+ else
+ return *wxWHITE;
+ }
+ return *wxWHITE;
+ }
+
+ //virtual impl.
+ wxString GetValue(int row, int col)
+ {
+ if (gridRefUI)
+ {
+ if (unsigned(row) < gridRefUI->size())
+ {
+ const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]];
+
+ if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return wxEmptyString;
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrRight.relativeName.c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ return _("<Directory>");
+ case XmlGlobalSettings::DATE: //date
+ return wxEmptyString;
+ }
+ }
+ else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE)
+ {
+ switch (getTypeAtPos(col))
+ {
+ case XmlGlobalSettings::FILENAME: //filename
+ return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::REL_PATH: //relative path
+ return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str();
+ case XmlGlobalSettings::SIZE: //file size
+ {
+ wxString fileSize = gridLine.fileDescrRight.fileSize.ToString(); //tmp string
+ return globalFunctions::includeNumberSeparator(fileSize);
+ }
+ case XmlGlobalSettings::DATE: //date
+ return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw);
+ }
+ }
+ }
+ }
+ //if data is not found:
+ return wxEmptyString;
+ }
};
@@ -333,26 +458,33 @@ CustomGrid::CustomGrid(wxWindow *parent,
m_gridLeft(NULL), m_gridRight(NULL), m_gridMiddle(NULL),
gridDataTable(NULL),
currentSortColumn(-1),
- sortMarker(NULL) {}
-
-
-CustomGrid::~CustomGrid() {}
-
-
-bool CustomGrid::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+ sortMarker(NULL)
{
- //use custom wxGridTableBase class for management of large sets of formatted data.
- //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default.
-
- gridDataTable = new CustomGridTableBase(numRows, numCols);
- SetTable(gridDataTable, true, selmode); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
- return true;
+ //set color of selections
+ wxColour darkBlue(40, 35, 140);
+ SetSelectionBackground(darkBlue);
+ SetSelectionForeground(*wxWHITE);
}
-void CustomGrid::deactivateScrollbars()
+void CustomGrid::initSettings(bool enableScrollbars,
+ CustomGrid* gridLeft,
+ CustomGrid* gridRight,
+ CustomGrid* gridMiddle,
+ GridView* gridRefUI,
+ FileCompareResult* gridData)
{
- scrollbarsEnabled = false;
+ scrollbarsEnabled = enableScrollbars;
+
+ //these grids will scroll together
+ assert(gridLeft && gridRight && gridMiddle);
+ m_gridLeft = gridLeft;
+ m_gridRight = gridRight;
+ m_gridMiddle = gridMiddle;
+
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridRefUI, gridData);
}
@@ -380,7 +512,7 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are
if (y1 != y2 || y2 != y3)
{
- int yMax = max(y1, max(y2, y3));
+ int yMax = std::max(y1, std::max(y2, y3));
if (::leadGrid == m_gridLeft) //do not handle case (y1 == yMax) here!!! Avoid back coupling!
m_gridLeft->SetMargins(0, 0);
@@ -404,90 +536,311 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are
}
-//this method is called when grid view changes: useful for parallel updating of multiple grids
-void CustomGrid::DoPrepareDC(wxDC& dc)
+void CustomGrid::updateGridSizes()
{
- wxScrollHelper::DoPrepareDC(dc);
+ assert(gridDataTable);
+ gridDataTable->updateGridSizes();
+}
- int x, y = 0;
- if (this == ::leadGrid) //avoid back coupling
- {
- if (this == m_gridLeft)
+
+void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap)
+{
+ currentSortColumn = sortColumn;
+ sortMarker = bitmap;
+}
+
+
+void CustomGrid::DrawColLabel(wxDC& dc, int col)
+{
+ wxGrid::DrawColLabel(dc, col);
+
+ if (col == currentSortColumn)
+ dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+}
+
+
+void CustomGrid::setColumnAttributes(const xmlAccess::XmlGlobalSettings::ColumnAttributes& attr)
+{
+ //remove special alignment for column "size"
+ for (int i = 0; i < GetNumberCols(); ++i)
+ if (getTypeAtPos(i) == XmlGlobalSettings::SIZE)
{
- GetViewStart(&x, &y);
- m_gridRight->Scroll(x, y);
- m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i);
+ cellAttributes->SetAlignment(wxALIGN_LEFT,wxALIGN_CENTRE);
+ SetColAttr(i, cellAttributes);
+ break;
}
- else if (this == m_gridRight)
+//----------------------------------------------------------------------------------
+ setSortMarker(-1); //clear sorting marker
+
+ columnSettings.clear();
+ if (attr.size() == 0)
+ { //default settings:
+ xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry;
+ newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME;
+ newEntry.visible = true;
+ newEntry.position = 0;
+ newEntry.width = 138;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::REL_PATH;
+ newEntry.position = 1;
+ newEntry.width = 118;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::SIZE;
+ newEntry.position = 2;
+ newEntry.width = 67;
+ columnSettings.push_back(newEntry);
+
+ newEntry.type = xmlAccess::XmlGlobalSettings::DATE;
+ newEntry.position = 3;
+ newEntry.width = 113;
+ columnSettings.push_back(newEntry);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i)
{
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(x, y);
- m_gridMiddle->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ XmlGlobalSettings::ColumnAttrib newEntry;
+
+ if (i < attr.size())
+ newEntry = attr[i];
+ else
+ {
+ newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME;
+ newEntry.visible = true;
+ newEntry.position = i;
+ newEntry.width = 100;
+ }
+ columnSettings.push_back(newEntry);
}
- else if (this == m_gridMiddle)
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByType);
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that each type exists only once
+ columnSettings[i].type = XmlGlobalSettings::ColumnTypes(i);
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly);
+ for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that positions are numbered correctly
+ columnSettings[i].position = i;
+
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility);
+ }
+
+ std::vector<XmlGlobalSettings::ColumnTypes> newPositions;
+ for (unsigned int i = 0; i < columnSettings.size() && columnSettings[i].visible; ++i) //hidden columns are sorted to the end of vector!
+ newPositions.push_back(columnSettings[i].type);
+
+ //set column positions
+ assert(gridDataTable);
+ gridDataTable->setupColumns(newPositions);
+
+ //set column width (set them after setupColumns!)
+ for (unsigned int i = 0; i < newPositions.size(); ++i)
+ SetColSize(i, columnSettings[i].width);
+
+//--------------------------------------------------------------------------------------------------------
+ //set special alignment for column "size"
+ for (int i = 0; i < GetNumberCols(); ++i)
+ if (getTypeAtPos(i) == XmlGlobalSettings::SIZE)
{
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(-1, y);
- m_gridRight->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i);
+ cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE);
+ SetColAttr(i, cellAttributes); //make filesize right justified on grids
+ break;
}
- }
+
+ ClearSelection();
+ ForceRefresh();
}
-//these classes will scroll together, hence the name ;)
-void CustomGrid::setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle)
+xmlAccess::XmlGlobalSettings::ColumnAttributes CustomGrid::getColumnAttributes()
{
- assert(gridLeft && gridRight && gridMiddle);
+ sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility);
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
+ xmlAccess::XmlGlobalSettings::ColumnAttributes output;
+ xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry;
+ for (unsigned int i = 0; i < columnSettings.size(); ++i)
+ {
+ newEntry = columnSettings[i];
+ if (newEntry.visible) //hidden columns are sorted to the end of vector!
+ newEntry.width = GetColSize(i);
+ output.push_back(newEntry);
+ }
- assert(gridDataTable);
- if (this == m_gridLeft)
- gridDataTable->SetGridIdentifier(1);
- else if (this == m_gridRight)
- gridDataTable->SetGridIdentifier(2);
- else if (this == m_gridMiddle)
- gridDataTable->SetGridIdentifier(3);
- else
- assert (false);
+ return output;
}
-void CustomGrid::setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData)
-{ //set underlying grid data
+XmlGlobalSettings::ColumnTypes CustomGrid::getTypeAtPos(unsigned pos) const
+{
assert(gridDataTable);
- gridDataTable->setGridDataTable(gridRefUI, gridData);
+ return gridDataTable->getTypeAtPos(pos);
}
-void CustomGrid::updateGridSizes()
+wxString CustomGrid::getTypeName(XmlGlobalSettings::ColumnTypes colType)
{
- assert(gridDataTable);
- gridDataTable->updateGridSizes();
+ switch (colType)
+ {
+ case XmlGlobalSettings::FILENAME:
+ return _("Filename");
+ case XmlGlobalSettings::REL_PATH:
+ return _("Relative path");
+ case XmlGlobalSettings::SIZE:
+ return _("Size");
+ case XmlGlobalSettings::DATE:
+ return _("Date");
+ default:
+ return wxEmptyString;
+ }
}
+//############################################################################################
+//CustomGrid specializations
-void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap)
+CustomGridLeft::CustomGridLeft(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
{
- currentSortColumn = sortColumn;
- sortMarker = bitmap;
+ //use custom wxGridTableBase class for management of large sets of formatted data.
+ //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default.
+ gridDataTable = new CustomGridTableLeft();
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+ return true;
}
-void CustomGrid::DrawColLabel(wxDC& dc, int col)
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridLeft::DoPrepareDC(wxDC& dc)
{
- assert(0 <= col && col < 4);
+ wxScrollHelper::DoPrepareDC(dc);
- wxGrid::DrawColLabel(dc, col);
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
+ {
+ GetViewStart(&x, &y);
+ m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
+ m_gridRight->Scroll(x, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ }
+}
- if (col == currentSortColumn)
+
+//----------------------------------------------------------------------------------------
+CustomGridMiddle::CustomGridMiddle(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+{
+ CustomGridTableMiddle* newTable = new CustomGridTableMiddle();
+ gridDataTable = newTable;
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+
+ //display checkboxes (representing bool values) if row is enabled for synchronization
+ SetDefaultRenderer(new GridCellRendererAddCheckbox(newTable)); //SetDefaultRenderer takes ownership!
+
+ return true;
+}
+
+
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridMiddle::DoPrepareDC(wxDC& dc)
+{
+ wxScrollHelper::DoPrepareDC(dc);
+
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
{
- dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+ GetViewStart(&x, &y);
+ m_gridLeft->Scroll(-1, y);
+ m_gridRight->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
}
}
+
+void CustomGridMiddle::GridCellRendererAddCheckbox::Draw(wxGrid& grid,
+ wxGridCellAttr& attr,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected)
+{
+ const int selected = m_gridDataTable->selectedForSynchronization(row);
+ if (selected < 0) //no valid row
+ {
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+ return;
+ }
+
+ const int shift = std::min(11 + 3, rect.GetWidth()); //11 is width of checkbox image
+
+ wxRect rectShrinked(rect);
+
+ //clean first block of rect that will receive image of checkbox
+ rectShrinked.SetWidth(shift);
+ dc.SetPen(*wxWHITE_PEN);
+ dc.SetBrush(*wxWHITE_BRUSH);
+ dc.DrawRectangle(rectShrinked);
+
+ //print image into first block
+ rectShrinked.SetX(1);
+ if (selected > 0)
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ else //if (selected == 0) -> redundant
+ dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+
+ //print second block (default): display compare result
+ rectShrinked.SetWidth(rect.GetWidth() - shift);
+ rectShrinked.SetX(shift);
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+}
+
+
+//----------------------------------------------------------------------------------------
+CustomGridRight::CustomGridRight(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name) {}
+
+
+bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+{
+ gridDataTable = new CustomGridTableRight();
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+ return true;
+}
+
+
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridRight::DoPrepareDC(wxDC& dc)
+{
+ wxScrollHelper::DoPrepareDC(dc);
+
+ int x, y = 0;
+ if (this == ::leadGrid) //avoid back coupling
+ {
+ GetViewStart(&x, &y);
+ m_gridLeft->Scroll(x, y);
+ m_gridMiddle->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
+ }
+}
bgstack15