Skip to content

Instantly share code, notes, and snippets.

@ushiushix
Last active July 25, 2021 09:28
Show Gist options
  • Save ushiushix/87c3927c9d831f66da067bd88f01cc8c to your computer and use it in GitHub Desktop.
Save ushiushix/87c3927c9d831f66da067bd88f01cc8c to your computer and use it in GitHub Desktop.
# -*- coding: UTF-8 -*-
import wx
import sys
import json
from wx.core import TreeItemIcon_Expanded, Treebook
class TreeVisitor:
def __init__(self, tree_ctrl: wx.TreeCtrl, list_ctrl: wx.ListCtrl):
self.tree_ctrl = tree_ctrl
self.list_ctrl = list_ctrl
self.node = None
def visit_node(self, node: wx.TreeItemId):
if node != self.node:
self.tree_ctrl.SelectItem(node)
self.node = node
self.fill_list()
def visit_parent(self):
parent = self.tree_ctrl.GetItemParent(self.node)
if parent.IsOk():
self.visit_node(parent)
def visit_first_child(self):
child, cookie = self.tree_ctrl.GetFirstChild(self.node)
if child.IsOk():
self.visit_node(child)
def visit_item(self, item: wx.ListItem):
name = item.GetText()
child, cookie = self.tree_ctrl.GetFirstChild(self.node)
while child.IsOk():
if self.tree_ctrl.GetItemText(child) == name:
break
else:
child, cookie = self.tree_ctrl.GetNextChild(child, cookie)
if child.IsOk():
self.tree_ctrl.SelectItem(child)
def fill_list(self):
data = self.tree_ctrl.GetItemData(self.node)
if isinstance(data, dict):
self.list_ctrl.DeleteAllItems()
for k,v in data.items():
self.list_ctrl.Append((k, self.format_value(v)))
elif isinstance(data, list):
self.list_ctrl.DeleteAllItems()
for i in range(len(data)):
self.list_ctrl.Append(('[{}]'.format(i), self.format_value(data[i])))
def format_value(self, value):
if isinstance(value, list):
return '[{}]'.format(len(value))
elif isinstance(value, dict):
return '{' + ','.join(value.keys()) + '}'
else:
return value
class DataViewer(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((640, 480))
self.SetTitle("DataViewer")
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND))
self.panel_1 = wx.Panel(self, wx.ID_ANY)
main_sizer = wx.BoxSizer(wx.VERTICAL)
#controls_sizer = wx.BoxSizer(wx.HORIZONTAL)
#main_sizer.Add(controls_sizer, 1, wx.EXPAND, 0)
#controls_sizer.Add((0, 0), 0, 0, 0)
viewer_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(viewer_sizer, 1, wx.EXPAND, 0)
self.data_tree = wx.TreeCtrl(self.panel_1, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.TR_HAS_BUTTONS | wx.TR_NO_BUTTONS)
viewer_sizer.Add(self.data_tree, 1, wx.EXPAND, 0)
self.data_list = wx.ListCtrl(self.panel_1, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES)
self.data_list.AppendColumn("Key", format=wx.LIST_FORMAT_LEFT, width=-1)
self.data_list.AppendColumn("Value", format=wx.LIST_FORMAT_LEFT, width=-1)
viewer_sizer.Add(self.data_list, 1, wx.EXPAND, 0)
self.panel_1.SetSizer(main_sizer)
self.Layout()
self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged, self.data_tree)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnListItemActivated, self.data_list)
self.Bind(wx.EVT_LIST_KEY_DOWN, self.OnListKeyDown, self.data_list)
self.Bind(wx.EVT_TREE_KEY_DOWN, self.OnTreeKeyDown, self.data_tree)
self.load_data()
self.data_tree.ExpandAll()
def load_data(self):
argv = sys.argv
if len(argv) == 2:
with open(argv[1], 'rb') as fp:
self.data = json.load(fp)
else:
self.data = json.load(sys.stdin)
self.root = self.data_tree.AddRoot('Root')
self.data_tree.SetItemData(self.root, self.data)
for key, value in self.data.items():
self.set_tree_data(self.root, key, value)
self.visitor = TreeVisitor(self.data_tree, self.data_list)
self.visitor.visit_node(self.root)
def OnTreeSelChanged(self, event):
item = event.GetItem()
self.visitor.visit_node(item)
def OnListItemActivated(self, event):
item = event.GetItem()
self.visitor.visit_item(item)
def OnListKeyDown(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_BACK:
self.visitor.visit_parent()
else:
event.Skip()
def OnTreeKeyDown(self, event):
keycode = event.GetKeyCode()
if keycode == ord('.'):
self.visitor.visit_first_child()
else:
event.Skip()
def set_tree_data(self, node: wx.TreeItemId, key, value):
id = self.data_tree.AppendItem(node, key)
self.data_tree.SetItemData(id, value)
if isinstance(value, dict):
for k, v in value.items():
self.set_tree_data(id, k, v)
elif isinstance(value, list):
for i in range(len(value)):
self.set_tree_data(id, '[{}]'.format(i), value[i])
# end of class DataViewer
class MyApp(wx.App):
def OnInit(self):
self.frame = DataViewer(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
# end of class MyApp
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment