[access] do not use timer to reduce response time
[framework/uifw/elementary.git] / doc / widget_hierarchy.py
1 #!/usr/bin/env python
2
3 import re
4 import os
5 import sys
6 import pickle
7 from optparse import OptionParser
8
9 def print_node(a, b, on_tree=False):
10     if on_tree:
11         rank = "source"
12     else:
13         rank = "same"
14
15     i_list = ifaces.get(a)
16     if i_list:
17         for iface in i_list:
18             if_instance = a + iface
19             if_node_tuple = (if_instance, a) if on_tree else (a, if_instance)
20
21             print '"%s" [label="",shape=circle,width=0.2]' % if_instance
22             print '"%s" -> "%s" [label="%s", color=transparent]' \
23                 % (if_instance, if_instance, iface)
24             print '{rank="%s" "%s" -> "%s" [arrowhead="none"];}' \
25                 % ((rank,) + if_node_tuple)
26
27     i_list = ifaces.get(b)
28     if i_list:
29         for iface in i_list:
30             if_instance = b + iface
31             if_node_tuple = (if_instance, b) if on_tree else (b, if_instance)
32
33             print '"%s" [label="",shape=circle,width=0.2]' % if_instance
34             print '"%s" -> "%s" [label="%s", color=transparent]' \
35                 % (if_instance, if_instance, iface)
36             print '{rank="%s" "%s" -> "%s" [arrowhead="none"];}' \
37                 % ((rank,) + if_node_tuple)
38
39     print '"%s" -> "%s"' % (a, b), '[arrowhead="empty"];' \
40         if on_tree else '[arrowtail="empty",dir=back];'
41
42 def topological_sort(dep_map, value):
43     hierarchy = []
44
45     def sort_do(dep_map, value):
46         if value is None:
47             return
48
49         hierarchy.insert(0, value)
50         sort_do(dep_map, dep_map.get(value, None))
51
52     sort_do(dep_map, value)
53
54     return hierarchy
55
56 def hierachy_build(files_list):
57     cls_map = {"Elm_Widget_Smart_Class": "widget"}
58
59     for path in files_list:
60         contents = ''.join(l[:-1] for l in open(path))
61         m = re.search(class_re, contents)
62         iface_m = re.search(class_iface_re, contents)
63         if m is not None:
64             items.setdefault(m.group(3), []).append(m.group(1))
65             if m.group(2) != m.group(3):
66                 cls_map[m.group(2)] = m.group(1)
67         if iface_m is not None:
68             items.setdefault(iface_m.group(3), []).append(iface_m.group(1))
69             if iface_m.group(2) != iface_m.group(3):
70                 cls_map[iface_m.group(2)] = iface_m.group(1)
71             #hardcoding scrollable now, for brevity -- it may change in future
72             ifaces.setdefault(iface_m.group(1), []).append('scrollable')
73
74     for k, v in items.iteritems():
75         clsname = cls_map.get(k, k)
76         for c in v:
77             hierarchy[c] = clsname
78
79 def files_list_build(d):
80     files_list = []
81     for f in os.listdir(d):
82         if f.endswith('.c'):
83             files_list.append(d + '/' + f)
84
85     return files_list
86
87 #widget name, widget class, parent class
88 class_re = 'EVAS_SMART_SUBCLASS_NEW.*?,.*?_elm_(\w+).*?,.*?(\w+).*?,.*?(\w+)'
89
90 #widget name, widget class, parent class
91 class_iface_re = \
92     'EVAS_SMART_SUBCLASS_IFACE_NEW.*?,.*?_elm_(\w+).*?,.*?(\w+).*?,.*?(\w+)'
93
94 usage = "usage: %prog -s <DIRECTORY> -o <OUTPUT_FILE>\n" \
95     "       %prog -w <WIDGET_NAME> -i <INPUT_FILE>\n" \
96     "       %prog -t -i <INPUT_FILE>\n"
97 parser = OptionParser(usage=usage)
98 parser.add_option(
99     "-s", "--scan", dest="scan_dir", default=None, type="str",
100     help="scan for .h/.c files, at the given path, and build the whole" +
101     " widget tree")
102 parser.add_option(
103     "-o", "--output", dest="output_file", default=None, type="str",
104     help="path of the output scanning file (widget tree)")
105
106 parser.add_option(
107     "-w", "--widget", dest="widget", default=None, type="str",
108     help="name of an specific widget to generate a hierarchy tree for")
109 parser.add_option(
110     "-i", "--input", dest="input_file", default=None, type="str",
111     help="path of the input (widget tree) where to get data from")
112
113 parser.add_option(
114     "-t", "--tree", action="store_true", dest="tree",
115     help="generate the whole hierarchy tree")
116
117 opts, args = parser.parse_args()
118
119 if (not opts.scan_dir and not opts.widget and not opts.tree) \
120       or (opts.scan_dir and opts.widget) \
121       or (opts.scan_dir and opts.tree) or \
122       (opts.tree and opts.widget):
123     sys.exit(parser.print_usage())
124
125 if opts.scan_dir and not opts.output_file:
126     sys.exit(parser.print_usage())
127
128 if opts.widget and not opts.input_file:
129     sys.exit(parser.print_usage())
130
131 if opts.tree and not opts.input_file:
132     sys.exit(parser.print_usage())
133
134 items = {}
135 hierarchy = {}
136 ifaces = {}
137
138 if opts.scan_dir:
139     files = files_list_build(opts.scan_dir)
140     hierachy_build(files)
141     pickle.dump([hierarchy, ifaces], open(opts.output_file, "wb" ))
142     sys.exit()
143
144 if opts.tree:
145     print "digraph elm { node [shape=box];"
146     print "rankdir=RL;"
147
148     f = open(opts.input_file)
149     if not f:
150         sys.exit("Bad input file path")
151
152     hierarchy, ifaces = pickle.load(f)
153
154     for cls, parent in hierarchy.items():
155         print_node(cls, parent, True);
156
157     print "}"
158
159 if opts.widget:
160     print "digraph elm { node [shape=box];"
161
162     f = open(opts.input_file)
163     if not f:
164         sys.exit("Bad input file path")
165
166     hierarchy, ifaces = pickle.load(f)
167     l = topological_sort(hierarchy, opts.widget)
168
169     def pairs(lst):
170         for i in range(1, len(lst)):
171             yield lst[i-1], lst[i]
172
173     for i1, i2 in pairs(l):
174         print_node(i1, i2);
175
176     print "}"