#!/usr/bin/python

""" TODO:
  - context menu for 
       Insert Child
       Delete Tree
       Comment Out
       Cut
       Copy
       Paste
  - split off type specs and carry them around extra?
  - insert: allow typing of code or insertion of node (in the latter case, sanity check for operators)
  - delete: delete tree (and maybe put into trash or something)
  - comment out: put something into "rem" node.
  - drag&drop refactoring
  - searching
  - colorized IDs
  - selection
  - editing in text view: cause reparsing and updating of tree!
"""
import pygtk
pygtk.require("2.0")
import gtk
from StringIO import StringIO

in_ = "in"
colonequal = ":="
prog = [in_, [colonequal, "x", "2"], "x"]
def list_P(obj):
  return isinstance(obj, list)
C_NAME = 0
C_DISPLAYSTRING = 1
store = gtk.TreeStore(str, str)

def summarize_tree(tree, iter, path):
  dest = StringIO()
  model = tree.props.model
  summarize(model, iter, dest)
  rep = dest.getvalue().replace("\n", "")
  model.set_value(iter, C_DISPLAYSTRING, rep)
def unsummarize_tree(tree, iter, path):
  model = tree.props.model
  name = model.get_value(iter, C_NAME)
  model.set_value(iter, C_DISPLAYSTRING, name)
def load_part(parent, obj):
  if list_P(obj):
    iter = store.append(parent, (obj[0], obj[0], ))
    for item in obj[1:]:
      load_part(iter, item)
    dest = StringIO()
    #summarize(model, iter, dest)
    summarize_tree(tree, iter, None)
  else:
    store.append(parent, (str(obj), str(obj), ))
def load_prog(prog):
  load_part(None, prog)
def summarize(model, parent, dest):
  iter = model.iter_children(parent)
  p = iter
  if p:
    dest.write("(")
  name = model.get_value(parent, C_NAME)
  dest.write(name)
  while iter:
    dest.write(" ")
    summarize(model, iter, dest)
    iter = model.iter_next(iter)
  if p:
    dest.write(")")

tree = gtk.TreeView()
tree.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
tree.connect("test-collapse-row", summarize_tree)
tree.connect("test-expand-row", unsummarize_tree)
cell0 = gtk.CellRendererText()
cell0.props.editable = True
def update_cells_from_text(cell, pathstr, newtext):
  model = tree.props.model
  #path = tuple(map(int, pathstr.split(":"))) # FIXME gtk.TreePath(pathstr) # model.get_path_from_string(pathstr)
  iter = model.get_iter_from_string(pathstr)
  path = model.get_path(iter)
  # FIXME check & update
  expanded = tree.row_expanded(path)
  print(expanded)
  if expanded:
    model.set_value(iter, C_NAME, newtext)
  model.set_value(iter, C_DISPLAYSTRING, newtext)
cell0.connect("edited", update_cells_from_text)
col0 = gtk.TreeViewColumn("N")
col0.pack_start(cell0, True)
col0.add_attribute(cell0, "text", C_DISPLAYSTRING)
tree.append_column(col0)
tree.props.model = store
# TODO set_cursor, grab_focus
# tree.set_reorderable(True) # incompatible with drag&drop
targets = [
  ("text/plain", 0, 1), # mime type, flags, user-internal id
]
actions = gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_LINK | gtk.gdk.ACTION_ASK
tree.enable_model_drag_source(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON2_MASK | gtk.gdk.BUTTON3_MASK | gtk.gdk.MOD1_MASK | gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK, targets, actions)
tree.enable_model_drag_dest(targets, actions)
tree.expand_all()
tree.collapse_all()
# column.pack_start, pack_end
scroller = gtk.ScrolledWindow()
scroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
scroller.add(tree)

textbuffer = gtk.TextBuffer()
textview = gtk.TextView(textbuffer)
textscroller = gtk.ScrolledWindow()
textscroller.add(textview)

def update_textview(selection):
  model, paths = selection.get_selected_rows()
  if len(paths) == 1:
    path = paths[0]
    dest = StringIO()
    iter = store.get_iter(path)
    summarize(store, iter, dest)
    text = dest.getvalue()
    textbuffer.set_text(text)
  else:
    textbuffer.set_text("No selection")
tree.get_selection().connect("changed", update_textview)

textscroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
box = gtk.HBox()
# TODO splitter
box.pack_start(scroller, True, True)
box.pack_start(textscroller, True, True)
window = gtk.Window()
window.connect("delete-event", gtk.main_quit)
window.add(box)
window.show_all()
load_prog(prog)
gtk.main()
