From 7c05c2f20877e3177b7b33c5ef173c10cd60ff53 Mon Sep 17 00:00:00 2001 From: Don Ho Date: Sun, 10 Feb 2013 20:11:18 +0000 Subject: [PATCH] [NEW] FunctionList: restore the previous state. git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@1020 f5eea248-9336-0410-98b8-ebc06183d4e3 --- PowerEditor/src/Notepad_plus.rc | 2 +- .../FunctionList/functionListPanel.cpp | 113 +++++++++--------- .../FunctionList/functionListPanel.h | 3 + .../src/WinControls/ProjectPanel/TreeView.cpp | 96 +++++++++++++++ .../src/WinControls/ProjectPanel/TreeView.h | 21 +++- 5 files changed, 174 insertions(+), 61 deletions(-) diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc index 9579fc5e..307de1f1 100644 --- a/PowerEditor/src/Notepad_plus.rc +++ b/PowerEditor/src/Notepad_plus.rc @@ -451,7 +451,7 @@ BEGIN MENUITEM "Document Map", IDM_VIEW_DOC_MAP - //MENUITEM "Function List", IDM_VIEW_FUNC_LIST + MENUITEM "Function List", IDM_VIEW_FUNC_LIST MENUITEM SEPARATOR MENUITEM "Synchronize Vertical Scrolling", IDM_VIEW_SYNSCROLLV MENUITEM "Synchronize Horizontal Scrolling", IDM_VIEW_SYNSCROLLH diff --git a/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp b/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp index 7dc47a28..3e2e041a 100644 --- a/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp +++ b/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp @@ -46,7 +46,9 @@ void FunctionListPanel::addEntry(const TCHAR *nodeName, const TCHAR *displayText { itemParent = _treeView.searchSubItemByName(nodeName, root); if (!itemParent) - itemParent = _treeView.addItem(nodeName, root, NULL, posStr); + { + itemParent = _treeView.addItem(nodeName, root, NULL, TEXT("-1")); + } } else itemParent = root; @@ -268,57 +270,44 @@ generic_string FunctionListPanel::parseSubLevel(size_t begin, size_t end, std::v } } +void FunctionListPanel::addInTreeStateArray(TreeStateNode tree2Update) +{ + bool found = false; + for (size_t i = 0; i < _treeStates.size(); i++) + { + if (_treeStates[i]._extraData == tree2Update._extraData) + { + _treeStates[i] = tree2Update; + found = true; + } + } + if (!found) + _treeStates.push_back(tree2Update); + +} + +TreeStateNode* FunctionListPanel::getFromTreeStateArray(generic_string fullFilePath) +{ + for (size_t i = 0; i < _treeStates.size(); i++) + { + if (_treeStates[i]._extraData == fullFilePath) + return &_treeStates[i]; + } + return NULL; +} + void FunctionListPanel::reload() { // clean up + TreeStateNode currentTree; + bool isOK = _treeView.retrieveFoldingStateTo(currentTree, _treeView.getRoot()); + if (isOK) + addInTreeStateArray(currentTree); removeAllEntries(); -/* - generic_string funcBegin = TEXT("^[\\t ]*"); - generic_string qualifier_maybe = TEXT("((static|const)[\\s]+)?"); - generic_string returnType = TEXT("[\\w]+"); - generic_string space_starMaybe = TEXT("([\\s]+|\\*[\\s]+|[\\s]+\\*|[\\s]+\\*[\\s]+)"); - generic_string classQualifier_maybe = TEXT("([\\w_]+[\\s]*::)?"); - generic_string funcName = TEXT("(?!(if|whil|for))[\\w_]+"); - generic_string const_maybe = TEXT("([\\s]*const[\\s]*)?"); - generic_string space_maybe = TEXT("[\\s]*"); - generic_string params = TEXT("\\([\\n\\w_,*&\\s]*\\)"); - generic_string funcBody = TEXT("\\{"); - generic_string space_eol_maybe = TEXT("[\\n\\s]*"); - - generic_string function = funcBegin + qualifier_maybe + returnType + space_starMaybe + classQualifier_maybe + funcName + space_maybe + params + const_maybe + space_eol_maybe + funcBody; - generic_string secondSearch = funcName + space_maybe; - secondSearch += TEXT("\\("); - - vector regExpr1; - vector regExpr2; - - regExpr1.push_back(secondSearch); - regExpr1.push_back(funcName); - - generic_string secondSearch_className = TEXT("[\\w_]+(?=[\\s]*::)"); - regExpr2.push_back(secondSearch_className); - - generic_string classRegExpr = TEXT("^[\\t ]*(class|struct)[\\t ]+[\\w]+[\\s]*(:[\\s]*(public|protected|private)[\\s]+[\\w]+[\\s]*)?\\{"); - vector classRegExprArray; - generic_string str1 = TEXT("(class|struct)[\\t ]+[\\w]+"); - generic_string str2 = TEXT("[\\t ]+[\\w]+"); - generic_string str3 = TEXT("[\\w]+"); - classRegExprArray.push_back(str1.c_str()); - classRegExprArray.push_back(str2.c_str()); - - //classRegExprArray.push_back(str3.c_str()); - //parse(fi, 0, docLen, function.c_str(), regExpr1, regExpr2); - - - const TCHAR bodyOpenSymbol[] = TEXT("\\{"); - const TCHAR bodyCloseSymbol[] = TEXT("\\}"); - parse2(fi, 0, docLen, classRegExpr.c_str(), classRegExprArray, bodyOpenSymbol, bodyCloseSymbol, function.c_str(), regExpr1); -*/ - vector fi; - generic_string fullFilePath = ((*_ppEditView)->getCurrentBuffer())->getFileName(); - TCHAR *fn = ::PathFindFileName(fullFilePath.c_str()); + + const TCHAR *fn = ((*_ppEditView)->getCurrentBuffer())->getFileName(); TCHAR *ext = ::PathFindExtension(fn); if (_funcParserMgr.parse(fi, ext)) @@ -345,8 +334,20 @@ void FunctionListPanel::reload() } } HTREEITEM root = _treeView.getRoot(); + const TCHAR *fullFilePath = ((*_ppEditView)->getCurrentBuffer())->getFullPathName(); if (root) - _treeView.expand(root); + { + _treeView.setItemParam(root, fullFilePath); + TreeStateNode *previousTree = getFromTreeStateArray(fullFilePath); + if (!previousTree) + { + _treeView.expand(root); + } + else + { + _treeView.restoreFoldingStateFrom(*previousTree, root); + } + } } void FunctionListPanel::init(HINSTANCE hInst, HWND hPere, ScintillaEditView **ppEditView) { @@ -354,20 +355,13 @@ void FunctionListPanel::init(HINSTANCE hInst, HWND hPere, ScintillaEditView **pp _ppEditView = ppEditView; generic_string funcListXmlPath = (NppParameters::getInstance())->getUserPath(); PathAppend(funcListXmlPath, TEXT("functionList.xml")); - /*_isValidated = */_funcParserMgr.init(funcListXmlPath, ppEditView); + _funcParserMgr.init(funcListXmlPath, ppEditView); } void FunctionListPanel::notified(LPNMHDR notification) { if((notification->hwndFrom == _treeView.getHSelf())) { - /* - TCHAR textBuffer[MAX_PATH]; - TVITEM tvItem; - tvItem.mask = TVIF_TEXT | TVIF_PARAM; - tvItem.pszText = textBuffer; - tvItem.cchTextMax = MAX_PATH; - */ switch (notification->code) { case NM_DBLCLK: @@ -382,9 +376,12 @@ void FunctionListPanel::notified(LPNMHDR notification) if (posStr) { int pos = generic_atoi(posStr->c_str()); - int sci_line = (*_ppEditView)->execute(SCI_LINEFROMPOSITION, pos); - (*_ppEditView)->execute(SCI_ENSUREVISIBLE, sci_line); - (*_ppEditView)->execute(SCI_GOTOPOS, pos); + if (pos != -1) + { + int sci_line = (*_ppEditView)->execute(SCI_LINEFROMPOSITION, pos); + (*_ppEditView)->execute(SCI_ENSUREVISIBLE, sci_line); + (*_ppEditView)->execute(SCI_GOTOPOS, pos); + } } } break; diff --git a/PowerEditor/src/WinControls/FunctionList/functionListPanel.h b/PowerEditor/src/WinControls/FunctionList/functionListPanel.h index 409cd4d9..f8fc3333 100644 --- a/PowerEditor/src/WinControls/FunctionList/functionListPanel.h +++ b/PowerEditor/src/WinControls/FunctionList/functionListPanel.h @@ -105,8 +105,11 @@ private: FunctionParsersManager _funcParserMgr; std::vector _funcInfos; std::vector< std::pair > _skipZones; + std::vector _treeStates; generic_string parseSubLevel(size_t begin, size_t end, std::vector< generic_string > dataToSearch, int & foundPos); size_t getBodyClosePos(size_t begin, const TCHAR *bodyOpenSymbol, const TCHAR *bodyCloseSymbol); void notified(LPNMHDR notification); + void addInTreeStateArray(TreeStateNode tree2Update); + TreeStateNode* getFromTreeStateArray(generic_string fullFilePath); }; #endif // FUNCLISTPANEL_H diff --git a/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp b/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp index 623655a9..48b404f9 100644 --- a/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp +++ b/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp @@ -67,6 +67,28 @@ LRESULT TreeView::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) return ::CallWindowProc(_defaultProc, hwnd, Message, wParam, lParam); } + +bool TreeView::setItemParam(HTREEITEM Item2Set, const TCHAR *paramStr) +{ + if (!Item2Set) + return false; + + TVITEM tvItem; + tvItem.hItem = Item2Set; + tvItem.mask = TVIF_PARAM; + + SendMessage(_hSelf, TVM_GETITEM, 0,(LPARAM)&tvItem); + + if (!tvItem.lParam) + tvItem.lParam = (LPARAM)(new generic_string(paramStr)); + else + { + *((generic_string *)tvItem.lParam) = paramStr; + } + SendMessage(_hSelf, TVM_SETITEM, 0,(LPARAM)&tvItem); + return true; +} + HTREEITEM TreeView::addItem(const TCHAR *itemName, HTREEITEM hParentItem, int iImage, const TCHAR *filePath) { TVITEM tvi; @@ -464,3 +486,77 @@ bool TreeView::canDragOut(HTREEITEM targetItem) } return true; } + +bool TreeView::retrieveFoldingStateTo(TreeStateNode & treeState2Construct, HTREEITEM treeviewNode) +{ + if (!treeviewNode) + return false; + + TCHAR textBuffer[MAX_PATH]; + TVITEM tvItem; + tvItem.hItem = treeviewNode; + tvItem.pszText = textBuffer; + tvItem.cchTextMax = MAX_PATH; + tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE; + SendMessage(_hSelf, TVM_GETITEM, 0,(LPARAM)&tvItem); + + treeState2Construct._label = textBuffer; + treeState2Construct._isExpanded = (tvItem.state & TVIS_EXPANDED) != 0; + treeState2Construct._isSelected = (tvItem.state & TVIS_SELECTED) != 0; + + if (tvItem.lParam) + { + treeState2Construct._extraData = *((generic_string *)tvItem.lParam); + } + + int i = 0; + for (HTREEITEM hItem = getChildFrom(treeviewNode); hItem != NULL; hItem = getNextSibling(hItem)) + { + treeState2Construct._children.push_back(TreeStateNode()); + retrieveFoldingStateTo(treeState2Construct._children.at(i), hItem); + i++; + } + return true; +} + +bool TreeView::restoreFoldingStateFrom(const TreeStateNode & treeState2Compare, HTREEITEM treeviewNode) +{ + if (!treeviewNode) + return false; + + TCHAR textBuffer[MAX_PATH]; + TVITEM tvItem; + tvItem.hItem = treeviewNode; + tvItem.pszText = textBuffer; + tvItem.cchTextMax = MAX_PATH; + tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE; + SendMessage(_hSelf, TVM_GETITEM, 0,(LPARAM)&tvItem); + + if (treeState2Compare._label != textBuffer) + return false; + + if (tvItem.lParam) + { + if (treeState2Compare._extraData != *((generic_string *)tvItem.lParam)) + return false; + } + + if (treeState2Compare._isExpanded) //= (tvItem.state & TVIS_EXPANDED) != 0; + expand(treeviewNode); + else + fold(treeviewNode); + + if (treeState2Compare._isSelected) //= (tvItem.state & TVIS_SELECTED) != 0; + selectItem(treeviewNode); + + int i = 0; + bool isOk = true; + for (HTREEITEM hItem = getChildFrom(treeviewNode); hItem != NULL; hItem = getNextSibling(hItem)) + { + isOk = restoreFoldingStateFrom(treeState2Compare._children.at(i), hItem); + if (!isOk) + break; + i++; + } + return isOk; +} diff --git a/PowerEditor/src/WinControls/ProjectPanel/TreeView.h b/PowerEditor/src/WinControls/ProjectPanel/TreeView.h index 2379a4b9..f8b91388 100644 --- a/PowerEditor/src/WinControls/ProjectPanel/TreeView.h +++ b/PowerEditor/src/WinControls/ProjectPanel/TreeView.h @@ -30,8 +30,16 @@ #include "window.h" -class TreeView : public Window -{ +struct TreeStateNode { + generic_string _label; + generic_string _extraData; + bool _isExpanded; + bool _isSelected; + std::vector _children; +}; + + +class TreeView : public Window { public: TreeView() : Window(), _isItemDragged(false) {}; @@ -39,6 +47,7 @@ public: virtual void init(HINSTANCE hInst, HWND parent, int treeViewID); virtual void destroy(); HTREEITEM addItem(const TCHAR *itemName, HTREEITEM hParentItem, int iImage, const TCHAR *filePath = NULL); + bool setItemParam(HTREEITEM Item2Set, const TCHAR *paramStr); HTREEITEM searchSubItemByName(const TCHAR *itemName, HTREEITEM hParentItem); void removeItem(HTREEITEM hTreeItem); void removeAllItems(); @@ -64,9 +73,15 @@ public: HTREEITEM getPrevSibling(HTREEITEM hItem) const { return TreeView_GetPrevSibling(_hSelf, hItem); }; + void expand(HTREEITEM hItem) const { TreeView_Expand(_hSelf, hItem, TVE_EXPAND); }; + + void fold(HTREEITEM hItem) const { + TreeView_Expand(_hSelf, hItem, TVE_COLLAPSE); + }; + void toggleExpandCollapse(HTREEITEM hItem) const { TreeView_Expand(_hSelf, hItem, TVE_TOGGLE); }; @@ -90,6 +105,8 @@ public: bool moveDown(HTREEITEM itemToMove); bool moveUp(HTREEITEM itemToMove); bool swapTreeViewItem(HTREEITEM itemGoDown, HTREEITEM itemGoUp); + bool restoreFoldingStateFrom(const TreeStateNode & treeState2Compare, HTREEITEM treeviewNode); + bool retrieveFoldingStateTo(TreeStateNode & treeState2Construct, HTREEITEM treeviewNode); protected: WNDPROC _defaultProc;