Re-implement the treeview 'first letter search' that could crash if the users pressed...
authordpage <dpage@a7884b65-44f6-0310-8a51-81a127f17b15>
Wed, 11 Mar 2009 15:23:32 +0000 (15:23 +0000)
committerdpage <dpage@a7884b65-44f6-0310-8a51-81a127f17b15>
Wed, 11 Mar 2009 15:23:32 +0000 (15:23 +0000)
git-svn-id: svn://svn.pgadmin.org/trunk/pgadmin3@7673 a7884b65-44f6-0310-8a51-81a127f17b15

pgadmin/ctl/ctlTree.cpp
pgadmin/include/ctl/ctlTree.h

index e28afb450b6ef0fa848cc93382542b7bc269cad1..05d69c4a4b78e9f482f76491134adb40455ac636 100644 (file)
-//////////////////////////////////////////////////////////////////////////\r
-//\r
-// pgAdmin III - PostgreSQL Tools\r
-// RCS-ID:      $Id$\r
-// Copyright (C) 2002 - 2009, The pgAdmin Development Team\r
-// This software is released under the Artistic Licence\r
-//\r
-// ctlTree.cpp - wxTreeCtrl containing pgObjects\r
-//\r
-//////////////////////////////////////////////////////////////////////////\r
-\r
-// wxWindows headers\r
-#include <wx/wx.h>\r
-\r
-// App headers\r
-#include "pgAdmin3.h"\r
-#include "ctl/ctlTree.h"\r
-\r
-#include "schema/pgObject.h"\r
-#include "schema/pgCollection.h"\r
-#include "schema/pgServer.h"\r
-\r
-\r
-ctlTree::ctlTree(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)\r
-: wxTreeCtrl(parent, id, pos, size, style)\r
-{\r
-}\r
-\r
-\r
-void ctlTree::RemoveDummyChild(pgObject *obj)\r
-{\r
-    wxCookieType cookie;\r
-    wxTreeItemId childItem=GetFirstChild(obj->GetId(), cookie);\r
-    if (childItem && !GetItemData(childItem))\r
-    {\r
-        // The child was a dummy item, which will be replaced by the following ShowTreeDetail by true items\r
-        Delete(childItem);\r
-    }\r
-}\r
-\r
-\r
-pgObject *ctlTree::GetObject(wxTreeItemId id)\r
-{\r
-    if (id)\r
-        return (pgObject*)GetItemData(id);\r
-    return 0;\r
-}\r
-\r
-\r
-pgCollection *ctlTree::GetParentCollection(wxTreeItemId id)\r
-{\r
-    pgCollection *coll=(pgCollection*)GetParentObject(id);\r
-    if (coll && coll->IsCollection())\r
-        return coll;\r
-    return 0;\r
-}\r
-\r
-\r
-void ctlTree::SetItemImage(const wxTreeItemId& item, int image, wxTreeItemIcon which)\r
-{\r
-    wxTreeCtrl::SetItemImage(item, image, which);\r
-    \r
-    wxTreeItemData *data = GetItemData(item);\r
-\r
-    // Set the item colour\r
-    if (data)\r
-    {\r
-       if (((pgObject *)data)->GetMetaType() == PGM_SERVER)\r
-       {\r
-           if (!((pgServer *)data)->GetColour().IsEmpty())\r
-               SetItemBackgroundColour(item, wxColour(((pgServer *)data)->GetColour()));\r
-       }\r
-       else if (((pgObject *)data)->GetServer())\r
-       {\r
-           if (!((pgObject *)data)->GetServer()->GetColour().IsEmpty())\r
-               SetItemBackgroundColour(item, wxColour(((pgObject *)data)->GetServer()->GetColour()));\r
-       }\r
-    }\r
-}\r
-\r
-wxTreeItemId ctlTree::AppendItem(const wxTreeItemId& parent, const wxString& text, int image, int selImage, wxTreeItemData* data)\r
-{\r
-    wxTreeItemId itm = wxTreeCtrl::AppendItem(parent, text, image, selImage, data); \r
-\r
-    // Set the item colour\r
-    if (data)\r
-    {\r
-        if (((pgObject *)data)->GetMetaType() == PGM_SERVER)\r
-        {\r
-            if (!((pgServer *)data)->GetColour().IsEmpty())\r
-                SetItemBackgroundColour(itm, wxColour(((pgServer *)data)->GetColour()));\r
-        }\r
-        else if (((pgObject *)data)->GetServer())\r
-        {\r
-            if (!((pgObject *)data)->GetServer()->GetColour().IsEmpty())\r
-                SetItemBackgroundColour(itm, wxColour(((pgObject *)data)->GetServer()->GetColour()));\r
-        }\r
-    }\r
-\r
-    return itm;\r
-}\r
-\r
-wxTreeItemId ctlTree::AppendObject(pgObject *parent, pgObject *object)\r
-{\r
-    wxString label;\r
-    wxTreeItemId item;\r
-\r
-    if (object->IsCollection())\r
-        label = object->GetTypeName();\r
-    else\r
-        label = object->GetDisplayName();\r
-    item = AppendItem(parent->GetId(), label, object->GetIconId(), -1, object);\r
-    if (object->IsCollection())\r
-        object->ShowTreeDetail(this);\r
-    else if (object->WantDummyChild())\r
-        AppendItem(object->GetId(), wxT("Dummy"));\r
-\r
-    return item;\r
-}\r
-\r
-\r
-pgCollection *ctlTree::AppendCollection(pgObject *parent, pgaFactory &factory)\r
-{\r
-    pgCollection *collection=factory.CreateCollection(parent);\r
-    AppendObject(parent, collection);\r
-    return collection;\r
-}\r
-\r
-\r
-pgObject *ctlTree::FindObject(pgaFactory &factory, wxTreeItemId parent)\r
-{\r
-    wxCookieType cookie;\r
-    wxTreeItemId item = GetFirstChild(parent, cookie);\r
-    while (item)\r
-    {\r
-        pgObject *obj=(pgObject*)GetItemData(item);\r
-        if (obj && obj->IsCreatedBy(factory))\r
-            return obj;\r
-        item = GetNextChild(parent, cookie);\r
-    }\r
-    return 0;\r
-}\r
-\r
-\r
-pgCollection *ctlTree::FindCollection(pgaFactory &factory, wxTreeItemId parent)\r
-{\r
-    pgaFactory *cf=factory.GetCollectionFactory();\r
-    if (!cf)\r
-        return 0;\r
-\r
-    pgCollection *collection=(pgCollection*)FindObject(*cf, parent);\r
-\r
-    if (!collection || !collection->IsCollection())\r
-        return 0;\r
-    return collection;\r
-}\r
-\r
-\r
-//////////////////////\r
-\r
-treeObjectIterator::treeObjectIterator(ctlTree *brow, pgObject *obj)\r
-{\r
-    browser=brow;\r
-    object=obj;\r
-}\r
-\r
-\r
-pgObject *treeObjectIterator::GetNextObject()\r
-{\r
-    if (!object ||!browser)\r
-        return 0;\r
-\r
-    if (!lastItem)\r
-        lastItem = browser->GetFirstChild(object->GetId(), cookie);\r
-    else\r
-        lastItem = browser->GetNextChild(object->GetId(), cookie);\r
-\r
-    if (lastItem)\r
-        return browser->GetObject(lastItem);\r
-    else\r
-        object=0;\r
-\r
-    return 0;\r
-}\r
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id$
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the Artistic Licence
+//
+// ctlTree.cpp - wxTreeCtrl containing pgObjects
+//
+//////////////////////////////////////////////////////////////////////////
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+#include "ctl/ctlTree.h"
+
+#include "schema/pgObject.h"
+#include "schema/pgCollection.h"
+#include "schema/pgServer.h"
+
+BEGIN_EVENT_TABLE(ctlTree, wxTreeCtrl)
+    EVT_CHAR(ctlTree::OnChar)
+END_EVENT_TABLE()
+
+int level = 0;
+
+wxTreeItemId ctlTree::FindItem(const wxTreeItemId& item, const wxString& str)
+{
+    wxTreeItemId resultItem;
+    wxTreeItemId currItem = item;
+    if (!currItem.IsOk())
+        return currItem;
+    
+    wxString val = GetItemText(currItem);
+
+    // Ignore Dummy Nodes
+    if (!(val == wxT("Dummy") && GetItemData(item) == NULL) && val.Lower().StartsWith(str))
+    {
+        return currItem;
+    }
+    
+    if (HasChildren(currItem))
+    {
+        wxTreeItemIdValue cookie;
+        wxTreeItemId childItem = GetFirstChild(currItem, cookie);
+        level++;
+        resultItem = FindItem(childItem, str);
+        if (resultItem.IsOk())
+        {
+            level--;
+            return resultItem;
+        }
+        level--;
+    }
+    
+    currItem = GetNextSibling(currItem);
+    
+    if (currItem.IsOk())
+        resultItem = FindItem(currItem, str);
+
+    return resultItem;
+}
+
+void ctlTree::OnChar(wxKeyEvent& event)
+{
+    int keyCode = event.GetKeyCode();
+    if ( !event.HasModifiers() &&
+         ((keyCode >= '0' && keyCode <= '9') ||
+          (keyCode >= 'a' && keyCode <= 'z') ||
+          (keyCode >= 'A' && keyCode <= 'Z')))
+    {
+        wxChar ch = (wxChar)keyCode;
+        wxTreeItemId currItem = GetSelection();
+        if (!currItem.IsOk())
+            return;
+
+        wxTreeItemId matchItem = FindItem(currItem, wxString(ch).Lower());
+        if (matchItem.IsOk())
+        {
+            EnsureVisible(matchItem);
+            SelectItem(matchItem);
+        }
+    }
+    else
+    {
+        event.Skip(true);
+    }
+}
+
+ctlTree::ctlTree(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+: wxTreeCtrl(parent, id, pos, size, style)
+{
+}
+
+
+void ctlTree::RemoveDummyChild(pgObject *obj)
+{
+    wxCookieType cookie;
+    wxTreeItemId childItem=GetFirstChild(obj->GetId(), cookie);
+    if (childItem && !GetItemData(childItem))
+    {
+        // The child was a dummy item, which will be replaced by the following ShowTreeDetail by true items
+        Delete(childItem);
+    }
+}
+
+
+pgObject *ctlTree::GetObject(wxTreeItemId id)
+{
+    if (id)
+        return (pgObject*)GetItemData(id);
+    return 0;
+}
+
+
+pgCollection *ctlTree::GetParentCollection(wxTreeItemId id)
+{
+    pgCollection *coll=(pgCollection*)GetParentObject(id);
+    if (coll && coll->IsCollection())
+        return coll;
+    return 0;
+}
+
+
+void ctlTree::SetItemImage(const wxTreeItemId& item, int image, wxTreeItemIcon which)
+{
+    wxTreeCtrl::SetItemImage(item, image, which);
+    
+    wxTreeItemData *data = GetItemData(item);
+
+    // Set the item colour
+    if (data)
+    {
+       if (((pgObject *)data)->GetMetaType() == PGM_SERVER)
+       {
+           if (!((pgServer *)data)->GetColour().IsEmpty())
+               SetItemBackgroundColour(item, wxColour(((pgServer *)data)->GetColour()));
+       }
+       else if (((pgObject *)data)->GetServer())
+       {
+           if (!((pgObject *)data)->GetServer()->GetColour().IsEmpty())
+               SetItemBackgroundColour(item, wxColour(((pgObject *)data)->GetServer()->GetColour()));
+       }
+    }
+}
+
+wxTreeItemId ctlTree::AppendItem(const wxTreeItemId& parent, const wxString& text, int image, int selImage, wxTreeItemData* data)
+{
+    wxTreeItemId itm = wxTreeCtrl::AppendItem(parent, text, image, selImage, data); 
+
+    // Set the item colour
+    if (data)
+    {
+        if (((pgObject *)data)->GetMetaType() == PGM_SERVER)
+        {
+            if (!((pgServer *)data)->GetColour().IsEmpty())
+                SetItemBackgroundColour(itm, wxColour(((pgServer *)data)->GetColour()));
+        }
+        else if (((pgObject *)data)->GetServer())
+        {
+            if (!((pgObject *)data)->GetServer()->GetColour().IsEmpty())
+                SetItemBackgroundColour(itm, wxColour(((pgObject *)data)->GetServer()->GetColour()));
+        }
+    }
+
+    return itm;
+}
+
+wxTreeItemId ctlTree::AppendObject(pgObject *parent, pgObject *object)
+{
+    wxString label;
+    wxTreeItemId item;
+
+    if (object->IsCollection())
+        label = object->GetTypeName();
+    else
+        label = object->GetDisplayName();
+    item = AppendItem(parent->GetId(), label, object->GetIconId(), -1, object);
+    if (object->IsCollection())
+        object->ShowTreeDetail(this);
+    else if (object->WantDummyChild())
+        AppendItem(object->GetId(), wxT("Dummy"));
+
+    return item;
+}
+
+
+pgCollection *ctlTree::AppendCollection(pgObject *parent, pgaFactory &factory)
+{
+    pgCollection *collection=factory.CreateCollection(parent);
+    AppendObject(parent, collection);
+    return collection;
+}
+
+
+pgObject *ctlTree::FindObject(pgaFactory &factory, wxTreeItemId parent)
+{
+    wxCookieType cookie;
+    wxTreeItemId item = GetFirstChild(parent, cookie);
+    while (item)
+    {
+        pgObject *obj=(pgObject*)GetItemData(item);
+        if (obj && obj->IsCreatedBy(factory))
+            return obj;
+        item = GetNextChild(parent, cookie);
+    }
+    return 0;
+}
+
+
+pgCollection *ctlTree::FindCollection(pgaFactory &factory, wxTreeItemId parent)
+{
+    pgaFactory *cf=factory.GetCollectionFactory();
+    if (!cf)
+        return 0;
+
+    pgCollection *collection=(pgCollection*)FindObject(*cf, parent);
+
+    if (!collection || !collection->IsCollection())
+        return 0;
+    return collection;
+}
+
+
+//////////////////////
+
+treeObjectIterator::treeObjectIterator(ctlTree *brow, pgObject *obj)
+{
+    browser=brow;
+    object=obj;
+}
+
+
+pgObject *treeObjectIterator::GetNextObject()
+{
+    if (!object ||!browser)
+        return 0;
+
+    if (!lastItem)
+        lastItem = browser->GetFirstChild(object->GetId(), cookie);
+    else
+        lastItem = browser->GetNextChild(object->GetId(), cookie);
+
+    if (lastItem)
+        return browser->GetObject(lastItem);
+    else
+        object=0;
+
+    return 0;
+}
index d34c9b9aceba267c34e10de18c8763c4c301e966..7d83250ebab7be39d82fee6c4c1d508e2b386d27 100644 (file)
@@ -1,57 +1,63 @@
-//////////////////////////////////////////////////////////////////////////\r
-//\r
-// pgAdmin III - PostgreSQL Tools\r
-// RCS-ID:      $Id$\r
-// Copyright (C) 2002 - 2009, The pgAdmin Development Team\r
-// This software is released under the Artistic Licence\r
-//\r
-// ctlTree.h - wxTreeCtrl containing pgObjects\r
-//\r
-//////////////////////////////////////////////////////////////////////////\r
-\r
-#ifndef CTLTREE_H\r
-#define CTLTREE_H\r
-\r
-// wxWindows headers\r
-#include <wx/wx.h>\r
-#include <wx/treectrl.h>\r
-\r
-class pgObject;\r
-class pgCollection;\r
-class pgaFactory;\r
-\r
-\r
-\r
-class ctlTree : public wxTreeCtrl\r
-{\r
-public:\r
-    ctlTree(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS);\r
-    void SetItemImage(const wxTreeItemId& item, int image, wxTreeItemIcon which = wxTreeItemIcon_Normal);\r
-    wxTreeItemId AppendItem(const wxTreeItemId& parent, const wxString& text, int image = -1, int selImage = -1, wxTreeItemData* data = NULL);\r
-    wxTreeItemId AppendObject(pgObject *parent, pgObject *object);\r
-    void RemoveDummyChild(pgObject *obj);\r
-    pgCollection *AppendCollection(pgObject *parent, pgaFactory &factory);\r
-    pgObject *GetObject(wxTreeItemId id);\r
-    pgObject *GetParentObject(wxTreeItemId id) { return GetObject(GetItemParent(id)); }\r
-    pgCollection *GetParentCollection(wxTreeItemId id);\r
-    pgObject *FindObject(pgaFactory &factory, wxTreeItemId parent);\r
-    pgCollection *FindCollection(pgaFactory &factory, wxTreeItemId parent);\r
-};\r
-\r
-\r
-class treeObjectIterator\r
-{\r
-public:\r
-    treeObjectIterator(ctlTree *browser, pgObject *obj);\r
-    pgObject *GetNextObject();\r
-\r
-private:\r
-    wxTreeItemId lastItem;\r
-    ctlTree *browser;\r
-    pgObject *object;\r
-    wxCookieType cookie;\r
-};\r
-\r
-\r
-\r
-#endif\r
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id$
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the Artistic Licence
+//
+// ctlTree.h - wxTreeCtrl containing pgObjects
+//
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef CTLTREE_H
+#define CTLTREE_H
+
+// wxWindows headers
+#include <wx/wx.h>
+#include <wx/treectrl.h>
+
+class pgObject;
+class pgCollection;
+class pgaFactory;
+
+
+
+class ctlTree : public wxTreeCtrl
+{
+public:
+    ctlTree(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS);
+    void SetItemImage(const wxTreeItemId& item, int image, wxTreeItemIcon which = wxTreeItemIcon_Normal);
+    wxTreeItemId AppendItem(const wxTreeItemId& parent, const wxString& text, int image = -1, int selImage = -1, wxTreeItemData* data = NULL);
+    wxTreeItemId AppendObject(pgObject *parent, pgObject *object);
+    void RemoveDummyChild(pgObject *obj);
+    pgCollection *AppendCollection(pgObject *parent, pgaFactory &factory);
+    pgObject *GetObject(wxTreeItemId id);
+    pgObject *GetParentObject(wxTreeItemId id) { return GetObject(GetItemParent(id)); }
+    pgCollection *GetParentCollection(wxTreeItemId id);
+    pgObject *FindObject(pgaFactory &factory, wxTreeItemId parent);
+    pgCollection *FindCollection(pgaFactory &factory, wxTreeItemId parent);
+    wxTreeItemId FindItem(const wxTreeItemId& item, const wxString& str);
+
+    DECLARE_EVENT_TABLE()
+
+private:
+    void OnChar(wxKeyEvent& event);
+};
+
+
+class treeObjectIterator
+{
+public:
+    treeObjectIterator(ctlTree *browser, pgObject *obj);
+    pgObject *GetNextObject();
+
+private:
+    wxTreeItemId lastItem;
+    ctlTree *browser;
+    pgObject *object;
+    wxCookieType cookie;
+};
+
+
+
+#endif