* src/DisplayState.py: Correct and add comments.
svn: r5546
This commit is contained in:
parent
dcbe6c9326
commit
070e1f07b8
@ -1,3 +1,6 @@
|
|||||||
|
2005-12-13 Alex Roitman <shura@gramps-project.org>
|
||||||
|
* src/DisplayState.py: Correct and add comments.
|
||||||
|
|
||||||
2005-12-13 Don Allingham <don@gramps-project.org>
|
2005-12-13 Don Allingham <don@gramps-project.org>
|
||||||
* src/EditPerson.py: fix after merge
|
* src/EditPerson.py: fix after merge
|
||||||
* src/GrampsDbBase.py: fix after merge
|
* src/GrampsDbBase.py: fix after merge
|
||||||
|
@ -132,61 +132,122 @@ class History(GrampsDBCallback.GrampsDBCallback):
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class GrampsWindowManager:
|
class GrampsWindowManager:
|
||||||
|
"""
|
||||||
|
Manage hierarchy of open GRAMPS windows.
|
||||||
|
|
||||||
|
This class's purpose is to manage the hierarchy of open windows.
|
||||||
|
The idea is to maintain the tree of branches and leaves.
|
||||||
|
A leaf does not have children and corresponds to a single open window.
|
||||||
|
A branch has children and corresponds to a group of windows.
|
||||||
|
|
||||||
|
We will follow the convention of having first leaf in any given
|
||||||
|
branch represent a parent window of the group, and the rest of the
|
||||||
|
children leaves/branches represent windows spawned from the parent.
|
||||||
|
|
||||||
|
The tree structure is maintained as a list of items.
|
||||||
|
Items which are lists are branches.
|
||||||
|
Items which are not lists are leaves.
|
||||||
|
|
||||||
|
Lookup of an item is done via track sequence. The elements of
|
||||||
|
the track sequence specify the lookup order: [2,3,1] means
|
||||||
|
'take the second item of the tree, take its third child, and
|
||||||
|
then the first child of that child'.
|
||||||
|
|
||||||
|
Lookup can be also done by ID for windows that are identifiable.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# initialize empty tree and lookup dictionary
|
||||||
self.window_tree = []
|
self.window_tree = []
|
||||||
self.id2item = {}
|
self.id2item = {}
|
||||||
|
|
||||||
def get_item_from_node(self,node):
|
def get_item_from_track(self,track):
|
||||||
|
# Recursively find an item given track sequence
|
||||||
item = self.window_tree
|
item = self.window_tree
|
||||||
for index in node:
|
for index in track:
|
||||||
item = item[index]
|
item = item[index]
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def get_window_from_id(self,window_id):
|
def get_item_from_id(self,item_id):
|
||||||
return self.id2item.get(window_id,None)
|
# Find an item given its ID
|
||||||
|
# Return None if the ID is not found
|
||||||
|
return self.id2item.get(item_id,None)
|
||||||
|
|
||||||
def close_node(self,node):
|
def close_item(self,track):
|
||||||
import traceback
|
# This is called when item needs to be closed
|
||||||
traceback.print_stack()
|
# Closes all its children and then removes the item from the tree.
|
||||||
item = self.get_item_from_node(node)
|
item = self.get_item_from_track(track)
|
||||||
self.close_item_recursively(item)
|
last_item = self.close_item_recursively(item)
|
||||||
self.remove_node(node)
|
# now we have the only surviving item from possibly a huge
|
||||||
|
# nested group of items
|
||||||
|
if last_item.window_id:
|
||||||
|
del self.id2item[last_item.window_id]
|
||||||
|
last_item.window.destroy()
|
||||||
|
self.remove_item(track)
|
||||||
|
|
||||||
def close_item_recursively(self,item):
|
def close_item_recursively(self,item):
|
||||||
|
# This function calls children's close_item() method
|
||||||
|
# to let the children go away cleanly. Then it returns
|
||||||
|
# the actual window item to later remove from dictionary
|
||||||
|
# and delete.
|
||||||
if type(item) == list:
|
if type(item) == list:
|
||||||
|
# If this item is a branch
|
||||||
|
# close the children except for the first one
|
||||||
for sub_item in item[1:]:
|
for sub_item in item[1:]:
|
||||||
self.close_item_recursively(sub_item)
|
self.close_item(sub_item)
|
||||||
|
# return the first child
|
||||||
|
the_item = item[0]
|
||||||
else:
|
else:
|
||||||
if item.window_id:
|
# This item is a leaf -- no children to close
|
||||||
del self.id2item[item.window_id]
|
# return itself
|
||||||
item.window.destroy()
|
the_item = item
|
||||||
|
return the_item
|
||||||
def add_item(self,node,item):
|
|
||||||
|
def remove_item(self,track):
|
||||||
|
# We need the whole gymnastics below because our item
|
||||||
|
# may actually be a list consisting of a single real
|
||||||
|
# item and empty lists.
|
||||||
|
|
||||||
|
# find the track corresponding to the parent item
|
||||||
|
parent_track = track[:-1]
|
||||||
|
# find index of our item in parent
|
||||||
|
child_in_parent = track[-1:][0]
|
||||||
|
# obtain parent item and remove our item from it
|
||||||
|
parent_item = self.get_item_from_track(parent_track)
|
||||||
|
parent_item.pop(child_in_parent)
|
||||||
|
# Rebuild menu
|
||||||
|
self.build_windows_menu()
|
||||||
|
|
||||||
|
def add_item(self,track,item):
|
||||||
|
# if the item is identifiable then we need to remember
|
||||||
|
# its id so that in the future we recall this window
|
||||||
|
# instead of spawning a new one
|
||||||
if item.window_id:
|
if item.window_id:
|
||||||
self.id2item[item.window_id] = item
|
self.id2item[item.window_id] = item
|
||||||
|
|
||||||
parent_item = self.get_item_from_node(node)
|
# Make sure we have a track
|
||||||
assert type(parent_item) == list or node == [], \
|
parent_item = self.get_item_from_track(track)
|
||||||
"Gwm: add_item: Incorrect node."
|
assert type(parent_item) == list or track == [], \
|
||||||
|
"Gwm: add_item: Incorrect track."
|
||||||
|
|
||||||
|
# Prepare a new item, depending on whether it is branch or leaf
|
||||||
if item.submenu_label:
|
if item.submenu_label:
|
||||||
# This is an item with potential children
|
# This is an item with potential children -- branch
|
||||||
new_item = [item]
|
new_item = [item]
|
||||||
else:
|
else:
|
||||||
# This is an item without children
|
# This is an item without children -- leaf
|
||||||
new_item = item
|
new_item = item
|
||||||
parent_item.append(new_item)
|
|
||||||
new_node = node + [len(parent_item) + 1]
|
|
||||||
self.build_windows_menu()
|
|
||||||
return new_node
|
|
||||||
|
|
||||||
def remove_node(self,node):
|
# append new item to the parent
|
||||||
parent_node = node[:-1]
|
parent_item.append(new_item)
|
||||||
child_in_parent = node[-1:][0]
|
|
||||||
item = self.get_item_from_node(parent_node)
|
# rebuild the Windows menu based on the new tree
|
||||||
item.pop(child_in_parent)
|
|
||||||
self.build_windows_menu()
|
self.build_windows_menu()
|
||||||
|
|
||||||
|
# prepare new track corresponding to the added item and return it
|
||||||
|
new_track = track + [len(parent_item)-1]
|
||||||
|
return new_track
|
||||||
|
|
||||||
def call_back_factory(self,item):
|
def call_back_factory(self,item):
|
||||||
if type(item) != list:
|
if type(item) != list:
|
||||||
def f(obj):
|
def f(obj):
|
||||||
@ -217,7 +278,7 @@ class ManagedWindow:
|
|||||||
event, and presenting itself when selected or attempted to create again.
|
event, and presenting itself when selected or attempted to create again.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,uistate,node,window_key,submenu_label,menu_label):
|
def __init__(self,uistate,track,window_key,submenu_label,menu_label):
|
||||||
"""
|
"""
|
||||||
Create child windows and add itself to menu, if not there already.
|
Create child windows and add itself to menu, if not there already.
|
||||||
|
|
||||||
@ -227,13 +288,13 @@ class ManagedWindow:
|
|||||||
|
|
||||||
import DisplayState
|
import DisplayState
|
||||||
class SomeWindowClass(DisplayState.ManagedWindow):
|
class SomeWindowClass(DisplayState.ManagedWindow):
|
||||||
def __init__(self,uistate,dbstate,node):
|
def __init__(self,uistate,dbstate,track):
|
||||||
window_id = self # Or e.g. window_id = person.handle
|
window_id = self # Or e.g. window_id = person.handle
|
||||||
submenu_label = None # This window cannot have children
|
submenu_label = None # This window cannot have children
|
||||||
menu_label = 'Menu label for this window'
|
menu_label = 'Menu label for this window'
|
||||||
DisplayState.ManagedWindow.__init__(self,
|
DisplayState.ManagedWindow.__init__(self,
|
||||||
uistate,
|
uistate,
|
||||||
node,
|
track,
|
||||||
window_id,
|
window_id,
|
||||||
submenu_label,
|
submenu_label,
|
||||||
menu_label)
|
menu_label)
|
||||||
@ -244,8 +305,8 @@ class ManagedWindow:
|
|||||||
...
|
...
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if uistate.gwm.get_window_from_id(window_key):
|
if uistate.gwm.get_item_from_id(window_key):
|
||||||
uistate.gwm.get_window_from_id(window_key).present()
|
uistate.gwm.get_item_from_id(window_key).present()
|
||||||
self.already_exist = True
|
self.already_exist = True
|
||||||
else:
|
else:
|
||||||
self.already_exist = False
|
self.already_exist = False
|
||||||
@ -253,7 +314,7 @@ class ManagedWindow:
|
|||||||
self.submenu_label = submenu_label
|
self.submenu_label = submenu_label
|
||||||
self.menu_label = menu_label
|
self.menu_label = menu_label
|
||||||
self.uistate = uistate
|
self.uistate = uistate
|
||||||
self.node = self.uistate.gwm.add_item(node,self)
|
self.track = self.uistate.gwm.add_item(track,self)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
@ -261,7 +322,7 @@ class ManagedWindow:
|
|||||||
|
|
||||||
Takes care of closing children and removing itself from menu.
|
Takes care of closing children and removing itself from menu.
|
||||||
"""
|
"""
|
||||||
self.uistate.gwm.close_node(self.node)
|
self.uistate.gwm.close_item(self.track)
|
||||||
|
|
||||||
def present(self):
|
def present(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user