diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:09:24 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:09:24 +0200 |
commit | b5f042a6c132c1b97cf03c4615bab966c23f57d2 (patch) | |
tree | 1cb057a0ffd51264bb3c9807e2133505ce312eb1 /library/custom_grid.cpp | |
parent | 3.11 (diff) | |
download | FreeFileSync-b5f042a6c132c1b97cf03c4615bab966c23f57d2.tar.gz FreeFileSync-b5f042a6c132c1b97cf03c4615bab966c23f57d2.tar.bz2 FreeFileSync-b5f042a6c132c1b97cf03c4615bab966c23f57d2.zip |
3.12
Diffstat (limited to 'library/custom_grid.cpp')
-rw-r--r-- | library/custom_grid.cpp | 293 |
1 files changed, 175 insertions, 118 deletions
diff --git a/library/custom_grid.cpp b/library/custom_grid.cpp index b510717f..e7a724a0 100644 --- a/library/custom_grid.cpp +++ b/library/custom_grid.cpp @@ -599,9 +599,6 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft, m_gridRight = gridRight; m_gridMiddle = gridMiddle; - //set underlying grid data - setGridDataTable(gridDataView); - //enhance grid functionality; identify leading grid by keyboard input or scroll action Connect(wxEVT_KEY_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this); Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(CustomGrid::onGridAccess), NULL, this); @@ -626,7 +623,8 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft, void CustomGrid::release() //release connection to ffs3::GridView { - setGridDataTable(NULL); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(NULL); //kind of "disable" griddatatable; don't delete it with SetTable(NULL)! May be used by wxGridCellStringRenderer } @@ -955,6 +953,13 @@ void CustomGrid::adjustGridHeights(wxEvent& event) } +void CustomGrid::updateGridSizes() +{ + if(getGridDataTable()) + getGridDataTable()->updateGridSizes(); +} + + void CustomGrid::setSortMarker(SortMarker marker) { m_marker = marker; @@ -1175,7 +1180,48 @@ CustomGridRim::CustomGridRim(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGrid(parent, id, pos, size, style, name), fileIconsAreEnabled(false) {} + CustomGrid(parent, id, pos, size, style, name), fileIconsAreEnabled(false), otherGrid(NULL) +{ + Connect(wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler(CustomGridRim::OnResizeColumn), NULL, this); //row-based tooltip +} + + +void CustomGridRim::setOtherGrid(CustomGridRim* other) //call during initialization! +{ + otherGrid = other; +} + + +void CustomGridRim::OnResizeColumn(wxGridSizeEvent& event) +{ + //Resize columns on both sides in parallel + const int thisCol = event.GetRowOrCol(); + + if (!otherGrid || thisCol < 0 || thisCol >= GetNumberCols()) return; + + const xmlAccess::ColumnTypes thisColType = getTypeAtPos(thisCol); + + for (int i = 0; i < otherGrid->GetNumberCols(); ++i) + if (otherGrid->getTypeAtPos(i) == thisColType) + { + otherGrid->SetColSize(i, GetColSize(thisCol)); + otherGrid->ForceRefresh(); + break; + } +} + + +//this method is called when grid view changes: useful for parallel updating of multiple grids +void CustomGridRim::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) +{ + if (!otherGrid) return; + + int x = 0; + int y = 0; + GetViewStart(&x, &y); + gridMiddle->Scroll(-1, y); + otherGrid->Scroll(x, y); +} template <SelectedSide side> @@ -1217,21 +1263,25 @@ void CustomGridRim::setTooltip(const wxMouseEvent& event) } } - wxToolTip* tt = GetGridWindow()->GetToolTip(); - if (!tt) - //wxWidgets bug: tooltip multiline property is defined by first tooltip text containing newlines or not (same is true for maximum width) - GetGridWindow()->SetToolTip(new wxToolTip(wxT("a b\n\ - a b"))); //ugly, but is working (on Windows) - tt = GetGridWindow()->GetToolTip(); //should be bound by now - if (tt && tt->GetTip() != toolTip) - tt->SetTip(toolTip); -} + wxToolTip* tt = GetGridWindow()->GetToolTip(); -void CustomGridRim::updateGridSizes() -{ - assert(getGridDataTable()); - getGridDataTable()->updateGridSizes(); + const wxString currentTip = tt ? tt->GetTip() : wxString(); + if (toolTip != currentTip) + { + if (toolTip.IsEmpty()) + GetGridWindow()->SetToolTip(NULL); //wxGTK doesn't allow wxToolTip with empty text! + else + { + //wxWidgets bug: tooltip multiline property is defined by first tooltip text containing newlines or not (same is true for maximum width) + if (!tt) + GetGridWindow()->SetToolTip(new wxToolTip(wxT("a b\n\ + a b"))); //ugly, but is working (on Windows) + tt = GetGridWindow()->GetToolTip(); //should be bound by now + if (tt) + tt->SetTip(toolTip); + } + } } @@ -1353,8 +1403,8 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) newPositions.push_back(columnSettings[i].type); //set column positions - assert(getGridDataTable()); - getGridDataTable()->setupColumns(newPositions); + if (getGridDataTableRim()) + getGridDataTableRim()->setupColumns(newPositions); //set column width (set them after setupColumns!) for (size_t i = 0; i < newPositions.size(); ++i) @@ -1379,8 +1429,10 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) xmlAccess::ColumnTypes CustomGridRim::getTypeAtPos(size_t pos) const { - assert(getGridDataTable()); - return getGridDataTable()->getTypeAtPos(pos); + if (getGridDataTableRim()) + return getGridDataTableRim()->getTypeAtPos(pos); + else + return xmlAccess::DIRECTORY; } @@ -1408,13 +1460,6 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType) } -CustomGridTableRim* CustomGridRim::getGridDataTable() -{ - //let the non-const call the const version: see Meyers Effective C++ - return const_cast<CustomGridTableRim*>(static_cast<const CustomGridRim*>(this)->getGridDataTable()); -} - - void CustomGridRim::autoSizeColumns() //performance optimized column resizer (analog to wxGrid::AutoSizeColumns() { for (int col = 0; col < GetNumberCols(); ++col) @@ -1474,9 +1519,9 @@ void CustomGridRim::enableFileIcons(const bool value) fileIconsAreEnabled = value; if (value) - SetDefaultRenderer(new GridCellRenderer<true>(loadIconSuccess, getGridDataTable())); //SetDefaultRenderer takes ownership! + SetDefaultRenderer(new GridCellRenderer<true>(loadIconSuccess, getGridDataTableRim())); //SetDefaultRenderer takes ownership! else - SetDefaultRenderer(new GridCellRenderer<false>(loadIconSuccess, getGridDataTable())); + SetDefaultRenderer(new GridCellRenderer<false>(loadIconSuccess, getGridDataTableRim())); Refresh(); } @@ -1504,13 +1549,22 @@ CustomGridRim::VisibleRowRange CustomGridRim::getVisibleRows() } +inline +CustomGridTableRim* CustomGridRim::getGridDataTableRim() const +{ + return dynamic_cast<CustomGridTableRim*>(getGridDataTable()); //I'm tempted to use a static cast here... +} + + void CustomGridRim::getIconsToBeLoaded(std::vector<Zstring>& newLoad) //loads all (not yet) drawn icons { newLoad.clear(); if (fileIconsAreEnabled) //don't check too often! give worker thread some time to fetch data { - const CustomGridTableRim* gridDataTable = getGridDataTable(); + const CustomGridTableRim* gridDataTable = getGridDataTableRim(); + if (!gridDataTable) return; + const VisibleRowRange rowsOnScreen = getVisibleRows(); const int totalCols = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberCols(); const int totalRows = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberRows(); @@ -1596,54 +1650,46 @@ CustomGridLeft::CustomGridLeft(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) + CustomGridRim(parent, id, pos, size, style, name) { GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridLeft::OnMouseMovement), NULL, this); //row-based tooltip } -void CustomGridLeft::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<LEFT_SIDE>(event); - event.Skip(); -} - - bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { //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 - + SetTable(new CustomGridTableLeft, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor return true; } -void CustomGridLeft::setGridDataTable(const GridView* gridDataView) +void CustomGridLeft::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(gridDataView); + + CustomGridRim::setOtherGrid(gridRight); + + CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); } -const CustomGridTableRim* CustomGridLeft::getGridDataTable() const +void CustomGridLeft::OnMouseMovement(wxMouseEvent& event) { - return gridDataTable; + CustomGridRim::setTooltip<LEFT_SIDE>(event); + event.Skip(); } -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridLeft::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) +CustomGridTable* CustomGridLeft::getGridDataTable() const { - int x = 0; - int y = 0; - GetViewStart(&x, &y); - - gridMiddle->Scroll(-1, y); //scroll in y-direction only - gridRight->Scroll(x, y); + return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! } @@ -1654,51 +1700,44 @@ CustomGridRight::CustomGridRight(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) + CustomGridRim(parent, id, pos, size, style, name) { GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridRight::OnMouseMovement), NULL, this); //row-based tooltip } -void CustomGridRight::OnMouseMovement(wxMouseEvent& event) -{ - CustomGridRim::setTooltip<RIGHT_SIDE>(event); - event.Skip(); -} - - 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 - + SetTable(new CustomGridTableRight, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor return true; } -void CustomGridRight::setGridDataTable(const GridView* gridDataView) +void CustomGridRight::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(gridDataView); + + CustomGridRim::setOtherGrid(gridLeft); + + CustomGridRim::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); } -const CustomGridTableRim* CustomGridRight::getGridDataTable() const +void CustomGridRight::OnMouseMovement(wxMouseEvent& event) { - return gridDataTable; + CustomGridRim::setTooltip<RIGHT_SIDE>(event); + event.Skip(); } -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGridRight::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) +CustomGridTable* CustomGridRight::getGridDataTable() const { - int x = 0; - int y = 0; - GetViewStart(&x, &y); - gridLeft->Scroll(x, y); - gridMiddle->Scroll(-1, y); + return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! } @@ -1706,7 +1745,7 @@ void CustomGridRight::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMidd class GridCellRendererMiddle : public wxGridCellStringRenderer { public: - GridCellRendererMiddle(const CustomGridMiddle* middleGrid) : m_gridMiddle(middleGrid) {}; + GridCellRendererMiddle(const CustomGridMiddle& middleGrid) : m_gridMiddle(middleGrid) {}; virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -1716,7 +1755,7 @@ public: bool isSelected); private: - const CustomGridMiddle* const m_gridMiddle; + const CustomGridMiddle& m_gridMiddle; }; @@ -1744,7 +1783,6 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent, selectionPos(BLOCKPOS_CHECK_BOX), highlightedRow(-1), highlightedPos(BLOCKPOS_CHECK_BOX), - gridDataTable(NULL), toolTip(new CustomTooltip) { SetLayoutDirection(wxLayout_LeftToRight); // @@ -1765,38 +1803,55 @@ CustomGridMiddle::~CustomGridMiddle() {} //non-inline destructor for std::auto_p bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { - gridDataTable = new CustomGridTableMiddle; - SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor + SetTable(new CustomGridTableMiddle, 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 GridCellRendererMiddle(this)); //SetDefaultRenderer takes ownership! + SetDefaultRenderer(new GridCellRendererMiddle(*this)); //SetDefaultRenderer takes ownership! return true; } -#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method -void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) -{ - wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh); -} -#endif - - -void CustomGridMiddle::setGridDataTable(const GridView* gridDataView) //called once on startup +void CustomGridMiddle::initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView + CustomGridMiddle* gridMiddle, + CustomGridRight* gridRight, + const ffs3::GridView* gridDataView) { //set underlying grid data - assert(gridDataTable); - gridDataTable->setGridDataTable(gridDataView); + assert(getGridDataTable()); + getGridDataTable()->setGridDataTable(gridDataView); #ifdef FFS_LINUX //get rid of scrollbars; Linux: change policy for GtkScrolledWindow GtkWidget* gridWidget = wxWindow::m_widget; GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget); gtk_scrolled_window_set_policy(scrolledWindow, GTK_POLICY_NEVER, GTK_POLICY_NEVER); #endif + + CustomGrid::initSettings(gridLeft, gridMiddle, gridRight, gridDataView); } +CustomGridTable* CustomGridMiddle::getGridDataTable() const +{ + return static_cast<CustomGridTable*>(GetTable()); //one of the few cases where no dynamic_cast is required! +} + + +inline +CustomGridTableMiddle* CustomGridMiddle::getGridDataTableMiddle() const +{ + return static_cast<CustomGridTableMiddle*>(getGridDataTable()); +} + + +#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method +void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) +{ + wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh); +} +#endif + + void CustomGridMiddle::OnMouseMovement(wxMouseEvent& event) { const int rowOld = highlightedRow; @@ -1836,14 +1891,17 @@ void CustomGridMiddle::OnLeaveWindow(wxMouseEvent& event) void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) { - const FileSystemObject* const fsObj = gridDataTable->getRawData(rowNumber); + if (!getGridDataTableMiddle()) + return; + + const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(rowNumber); if (fsObj == NULL) //if invalid row... { toolTip->hide(); return; } - if (gridDataTable->syncPreviewIsActive()) //synchronization preview + if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview { const SyncOperation syncOp = fsObj->getSyncOperation(); switch (syncOp) @@ -1963,6 +2021,9 @@ void CustomGridMiddle::OnLeftMouseUp(wxMouseEvent& event) int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) { + if (!getGridDataTableMiddle()) + return 0; + int row = -1; int x = -1; int y = -1; @@ -1978,9 +2039,9 @@ int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) if (row >= 0) { - const FileSystemObject* const fsObj = gridDataTable->getRawData(row); + const FileSystemObject* const fsObj = getGridDataTableMiddle()->getRawData(row); if ( fsObj != NULL && //if valid row... - gridDataTable->syncPreviewIsActive() && + getGridDataTableMiddle()->syncPreviewIsActive() && fsObj->getSyncOperation() != SO_EQUAL) //in sync-preview equal files shall be treated as in cmp result, i.e. as full checkbox { // cell: @@ -2012,8 +2073,8 @@ int CustomGridMiddle::mousePosToRow(wxPoint pos, BlockPosition* block) void CustomGridMiddle::enableSyncPreview(bool value) { - assert(gridDataTable); - gridDataTable->enableSyncPreview(value); + assert(getGridDataTableMiddle()); + getGridDataTableMiddle()->enableSyncPreview(value); if (value) GetGridColLabelWindow()->SetToolTip(_("Synchronization Preview")); @@ -2022,13 +2083,6 @@ void CustomGridMiddle::enableSyncPreview(bool value) } -void CustomGridMiddle::updateGridSizes() -{ - assert(gridDataTable); - gridDataTable->updateGridSizes(); -} - - void GridCellRendererMiddle::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -2037,12 +2091,12 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, bool isSelected) { //retrieve grid data - const FileSystemObject* const fsObj = m_gridMiddle->gridDataTable->getRawData(row); + const FileSystemObject* const fsObj = m_gridMiddle.getGridDataTableMiddle() ? m_gridMiddle.getGridDataTableMiddle()->getRawData(row) : NULL; if (fsObj != NULL) //if valid row... { if (rect.GetWidth() > CHECK_BOX_WIDTH) { - const bool rowIsHighlighted = row == m_gridMiddle->highlightedRow; + const bool rowIsHighlighted = row == m_gridMiddle.highlightedRow; wxRect rectShrinked(rect); @@ -2055,7 +2109,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, //HIGHLIGHTNING (checkbox): if ( rowIsHighlighted && - m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) + m_gridMiddle.highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) { if (fsObj->isActive()) dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("checkboxTrueFocus")), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); @@ -2074,14 +2128,14 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); //print remaining block - if (m_gridMiddle->gridDataTable->syncPreviewIsActive()) //synchronization preview + if (m_gridMiddle.getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview { //print sync direction into second block //HIGHLIGHTNING (sync direction): if ( rowIsHighlighted && - m_gridMiddle->highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files - switch (m_gridMiddle->highlightedPos) + m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files + switch (m_gridMiddle.highlightedPos) { case CustomGridMiddle::BLOCKPOS_CHECK_BOX: break; @@ -2153,9 +2207,12 @@ void CustomGridMiddle::DrawColLabel(wxDC& dc, int col) { CustomGrid::DrawColLabel(dc, col); + if (!getGridDataTableMiddle()) + return; + const wxRect rect(GetColLeft(col), 0, GetColWidth(col), GetColLabelSize()); - if (gridDataTable->syncPreviewIsActive()) + if (getGridDataTableMiddle()->syncPreviewIsActive()) dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("syncViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); else dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("cmpViewSmall")), rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); |