7 assert gtk
.pygtk_version
>= (2, 8)
9 from core
.pysize_fs_tree
import pysize_tree
10 from ui
.utils
import human_unit
16 class PysizeWidget(gtk
.DrawingArea
):
17 def __init__(self
, options
, args
):
18 super(PysizeWidget
, self
).__init
__()
19 self
.connect('expose-event', self
._expose
)
20 self
.connect('realize', self
._realize
)
21 self
.connect('motion-notify-event', self
._motion
)
22 self
.connect('configure-event', self
._configure
)
23 self
.connect('key-press-event', self
._key
_press
)
24 self
.connect('button-press-event', self
._button
_press
)
25 self
.connect('button-release-event', self
._button
_release
)
26 self
.set_flags(gtk
.CAN_FOCUS
)
27 self
.modify_font(pango
.FontDescription('Monospace 12'))
28 self
.options
= options
30 self
.needs_tree
= True
31 self
.tree
= pysize_tree(args
[0], options
.max_depth
, 1.0)
32 self
.selected_items
= []
33 self
.cursor_item
= None
34 self
.button_press_node
= None
36 def _get_node_here(self
, event
):
37 for node
in self
.tree
.root
:
38 if node
.contains_point(event
):
41 def _button_press(self
, widget
, event
):
42 node
= self
._get
_node
_here
(event
)
43 if not node
is self
.button_press_node
:
44 self
.button_press_node
= node
47 def _button_release(self
, widget
, event
):
48 node
= self
._get
_node
_here
(event
)
49 same_as_press
= node
is self
.button_press_node
50 self
.button_press_node
= None
52 if event
.state
& gtk
.gdk
.CONTROL_MASK
:
53 self
.selected_items
.append(node
)
55 self
.selected_items
= [node
]
58 def _key_press(self
, widget
, event
):
60 gtk
.keysyms
.Left
: self
.tree
.get_parent
,
61 gtk
.keysyms
.Up
: self
.tree
.get_previous_sibling
,
62 gtk
.keysyms
.Right
: self
.tree
.get_first_child
,
63 gtk
.keysyms
.Down
: self
.tree
.get_next_sibling
66 action
= directions
.get(event
.keyval
, None)
67 if action
and not self
.cursor_item
is None:
68 new_selection
= action(self
.cursor_item
)
69 if not new_selection
in (None, self
.tree
.root
):
70 self
.cursor_item
= new_selection
73 def _realize(self
, widget
):
74 events
= self
.window
.get_events()
75 events |
= gtk
.gdk
.POINTER_MOTION_MASK
76 events |
= gtk
.gdk
.POINTER_MOTION_HINT_MASK
77 events |
= gtk
.gdk
.KEY_PRESS_MASK
78 events |
= gtk
.gdk
.BUTTON_PRESS_MASK
79 events |
= gtk
.gdk
.BUTTON_RELEASE_MASK
80 self
.window
.set_events(events
)
81 self
.window
.get_pointer()
83 def _configure(self
, widget
, event
):
84 self
.needs_tree
= True
86 def _motion(self
, widget
, event
):
87 prev_selection
= new_selection
= self
.cursor_item
88 for node
in self
.tree
.root
:
89 was_selected
= node
is prev_selection
90 if node
.contains_point(event
) != (node
is prev_selection
):
91 (x0
, x1
, y0
, y1
) = node
.rectangle
92 x0
= int(x0
- LINE_WIDTH
)
93 x1
= int(x1
+ LINE_WIDTH
)
94 y0
= int(y0
- LINE_WIDTH
)
95 y1
= int(y1
+ LINE_WIDTH
)
96 if node
is prev_selection
:
100 self
.cursor_item
= new_selection
101 widget
.queue_draw_area(x0
, y0
, x1
- x0
, y1
- y0
)
102 if prev_selection
is new_selection
:
103 self
.window
.get_pointer()
105 def _expose(self
, widget
, event
):
106 context
= widget
.window
.cairo_create()
108 # set a clip region for the expose event
109 context
.rectangle(event
.area
.x
, event
.area
.y
,
110 event
.area
.width
, event
.area
.height
)
114 self
.window
.get_pointer()
117 def _draw_text(self
, context
, text
, x0
, x1
, y0
, y1
):
118 pl
= self
.create_pango_layout(text
)
121 pl
.set_width(int(w
*pango
.SCALE
))
122 pl
.set_ellipsize(pango
.ELLIPSIZE_MIDDLE
)
123 (real_w
, real_h
) = pl
.get_pixel_size()
124 if real_w
> w
or real_h
> h
:
126 if real_w
+w
/20.0 < w
:
128 context
.move_to(x0
, y0
+(h
-real_h
)/2.0)
129 context
.set_source_rgb(0, 0, 0)
130 context
.show_layout(pl
)
133 def _get_item_colors(self
, item
, colors
):
134 if item
is self
.cursor_item
:
135 colors
= map(lambda c
: c
+0.2, colors
)
136 if item
in self
.selected_items
:
138 if item
is self
.button_press_node
:
139 colors
= map(lambda c
: c
+0.2, colors
)
142 def _draw_box(self
, context
, x0
, x1
, y0
, y1
, item
):
147 item
.rectangle
= (x0
, x1
, y0
, y1
)
151 context
.arc(x0
+ RADIUS
, y0
+ RADIUS
, RADIUS
,
152 - math
.pi
, - math
.pi
/ 2.0)
153 context
.rel_line_to(x1
- x0
- 2*RADIUS
, 0)
154 context
.arc(x1
- RADIUS
, y0
+ RADIUS
, RADIUS
,
156 context
.rel_line_to(0, y1
- y0
- 2*RADIUS
)
157 context
.arc(x1
- RADIUS
, y1
- RADIUS
, RADIUS
,
159 context
.rel_line_to(- x1
+ x0
+ 2*RADIUS
, 0)
160 context
.arc(x0
+ RADIUS
, y1
- RADIUS
, RADIUS
,
161 math
.pi
/ 2.0, math
.pi
)
164 context
.set_source_rgb(0, 0, 0)
165 context
.stroke_preserve()
167 gradient
= cairo
.LinearGradient(0, y0
, 0, y1
)
168 colors
= self
._get
_item
_colors
(item
, [0.5, 0.5, 1.0, 0.0, 0.5, 1.0])
169 gradient
.add_color_stop_rgb(0.0, *colors
[:3])
170 gradient
.add_color_stop_rgb(1.0, *colors
[3:])
171 context
.set_source(gradient
)
174 context
.rectangle(x0
, y0
, x1
- x0
, y1
- y0
)
175 context
.set_source_rgb(0, 0, 0)
176 context
.stroke_preserve()
178 colors
= self
._get
_item
_colors
(item
, [0, 0.5, 1.0])
179 context
.set_source_rgb(*colors
)
182 name
= item
.get_name()
183 size
= human_unit(item
.size
)
184 if not self
._draw
_text
(context
, name
+ '\n' + size
, x0
, x1
, y0
, y1
):
185 first
, second
= name
, size
186 if not item
.is_real():
187 first
, second
= second
, first
188 if not self
._draw
_text
(context
, first
, x0
, x1
, y0
, y1
):
189 self
._draw
_text
(context
, second
, x0
, x1
, y0
, y1
)
191 def _draw_boxes(self
, context
, item
, depth
, offset
):
192 w
= self
.allocation
.width
193 h
= self
.allocation
.height
194 x0
= depth
* (w
- 1.0) / self
.tree
.height
195 x1
= (depth
+ 1.0) * (w
- 1.0) / self
.tree
.height
196 y0
= (h
- 1.0) * offset
/ self
.tree
.root
.size
197 y1
= (h
- 1.0) * (offset
+ item
.size
) / self
.tree
.root
.size
199 self
._draw
_box
(context
, x0
, x1
, y0
, y1
, item
)
201 for child
in item
.get_children():
202 self
._draw
_boxes
(context
, child
, depth
, offset
)
205 def _draw(self
, context
):
207 self
.tree
= pysize_tree(self
.args
[0], self
.options
.max_depth
,
208 2*RADIUS
/self
.allocation
.height
)
209 self
.needs_tree
= False
210 if not self
.tree
.root
:
212 context
.set_line_width(LINE_WIDTH
)
214 for child
in self
.tree
.root
.get_children():
215 self
._draw
_boxes
(context
, child
, 0, offset
)