summaryrefslogtreecommitdiff
path: root/doc/widget_hierarchy.py
blob: e2d2569e2fd14f0ab4761fd25f0fc5c634d27554 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env python

import re
import os
import sys
import pickle
from optparse import OptionParser

def print_node(a, b, on_tree=False):
    if on_tree:
        rank = "source"
    else:
        rank = "same"

    i_list = ifaces.get(a)
    if i_list:
        for iface in i_list:
            if_instance = a + iface
            if_node_tuple = (if_instance, a) if on_tree else (a, if_instance)

            print '"%s" [label="",shape=circle,width=0.2]' % if_instance
            print '"%s" -> "%s" [label="%s", color=transparent]' \
                % (if_instance, if_instance, iface)
            print '{rank="%s" "%s" -> "%s" [arrowhead="none"];}' \
                % ((rank,) + if_node_tuple)

    i_list = ifaces.get(b)
    if i_list:
        for iface in i_list:
            if_instance = b + iface
            if_node_tuple = (if_instance, b) if on_tree else (b, if_instance)

            print '"%s" [label="",shape=circle,width=0.2]' % if_instance
            print '"%s" -> "%s" [label="%s", color=transparent]' \
                % (if_instance, if_instance, iface)
            print '{rank="%s" "%s" -> "%s" [arrowhead="none"];}' \
                % ((rank,) + if_node_tuple)

    print '"%s" -> "%s"' % (a, b), '[arrowhead="empty"];' \
        if on_tree else '[arrowtail="empty",dir=back];'

def topological_sort(dep_map, value):
    hierarchy = []

    def sort_do(dep_map, value):
        if value is None:
            return

        hierarchy.insert(0, value)
        sort_do(dep_map, dep_map.get(value, None))

    sort_do(dep_map, value)

    return hierarchy

def hierachy_build(files_list):
    cls_map = {"Elm_Widget_Smart_Class": "widget"}

    for path in files_list:
        contents = ''.join(l[:-1] for l in open(path))
        m = re.search(class_re, contents)
        iface_m = re.search(class_iface_re, contents)
        if m is not None:
            items.setdefault(m.group(3), []).append(m.group(1))
            if m.group(2) != m.group(3):
                cls_map[m.group(2)] = m.group(1)
        if iface_m is not None:
            items.setdefault(iface_m.group(3), []).append(iface_m.group(1))
            if iface_m.group(2) != iface_m.group(3):
                cls_map[iface_m.group(2)] = iface_m.group(1)
            #hardcoding scrollable now, for brevity -- it may change in future
            ifaces.setdefault(iface_m.group(1), []).append('scrollable')

    for k, v in items.iteritems():
        clsname = cls_map.get(k, k)
        for c in v:
            hierarchy[c] = clsname

def files_list_build(d):
    files_list = []
    for f in os.listdir(d):
        if f.endswith('.c'):
            files_list.append(d + '/' + f)

    return files_list

#widget name, widget class, parent class
class_re = 'EVAS_SMART_SUBCLASS_NEW.*?,.*?_elm_(\w+).*?,.*?(\w+).*?,.*?(\w+)'

#widget name, widget class, parent class
class_iface_re = \
    'EVAS_SMART_SUBCLASS_IFACE_NEW.*?,.*?_elm_(\w+).*?,.*?(\w+).*?,.*?(\w+)'

usage = "usage: %prog -s <DIRECTORY> -o <OUTPUT_FILE>\n" \
    "       %prog -w <WIDGET_NAME> -i <INPUT_FILE>\n" \
    "       %prog -t -i <INPUT_FILE>\n"
parser = OptionParser(usage=usage)
parser.add_option(
    "-s", "--scan", dest="scan_dir", default=None, type="str",
    help="scan for .h/.c files, at the given path, and build the whole" +
    " widget tree")
parser.add_option(
    "-o", "--output", dest="output_file", default=None, type="str",
    help="path of the output scanning file (widget tree)")

parser.add_option(
    "-w", "--widget", dest="widget", default=None, type="str",
    help="name of an specific widget to generate a hierarchy tree for")
parser.add_option(
    "-i", "--input", dest="input_file", default=None, type="str",
    help="path of the input (widget tree) where to get data from")

parser.add_option(
    "-t", "--tree", action="store_true", dest="tree",
    help="generate the whole hierarchy tree")

opts, args = parser.parse_args()

if (not opts.scan_dir and not opts.widget and not opts.tree) \
      or (opts.scan_dir and opts.widget) \
      or (opts.scan_dir and opts.tree) or \
      (opts.tree and opts.widget):
    sys.exit(parser.print_usage())

if opts.scan_dir and not opts.output_file:
    sys.exit(parser.print_usage())

if opts.widget and not opts.input_file:
    sys.exit(parser.print_usage())

if opts.tree and not opts.input_file:
    sys.exit(parser.print_usage())

items = {}
hierarchy = {}
ifaces = {}

if opts.scan_dir:
    files = files_list_build(opts.scan_dir)
    hierachy_build(files)
    pickle.dump([hierarchy, ifaces], open(opts.output_file, "wb" ))
    sys.exit()

if opts.tree:
    print "digraph elm { node [shape=box];"
    print "rankdir=RL;"

    f = open(opts.input_file)
    if not f:
        sys.exit("Bad input file path")

    hierarchy, ifaces = pickle.load(f)

    for cls, parent in hierarchy.items():
        print_node(cls, parent, True);

    print "}"

if opts.widget:
    print "digraph elm { node [shape=box];"

    f = open(opts.input_file)
    if not f:
        sys.exit("Bad input file path")

    hierarchy, ifaces = pickle.load(f)
    l = topological_sort(hierarchy, opts.widget)

    def pairs(lst):
        for i in range(1, len(lst)):
            yield lst[i-1], lst[i]

    for i1, i2 in pairs(l):
        print_node(i1, i2);

    print "}"