Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/jarabe/frame/framewindow.py
blob: 394ba0005ab7a942682b113e8b7ed4b77e18a131 (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
# Copyright (C) 2006-2007 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import gtk
from gtk import gdk
import gobject

from sugar.graphics import style


class FrameContainer(gtk.Bin):
    """A container class for frame panel rendering. Hosts a child 'box' where
    frame elements can be added. Excludes grid-sized squares at each end
    of the frame panel, and a space alongside the inside of the screen where
    a border is drawn."""

    __gtype_name__ = 'SugarFrameContainer'

    def __init__(self, position):
        gtk.Bin.__init__(self)
        self._position = position

        if self.is_vertical():
            box = gtk.VBox()
        else:
            box = gtk.HBox()
        self.add(box)
        box.show()

    def is_vertical(self):
        return self._position in (gtk.POS_LEFT, gtk.POS_RIGHT)

    def do_expose_event(self, event):
        # Draw the inner border as a rectangle
        cr = self.get_parent_window().cairo_create()
        r, g, b, a = style.COLOR_BUTTON_GREY.get_rgba()
        cr.set_source_rgba (r, g, b, a)

        if self.is_vertical():
            x = style.GRID_CELL_SIZE if self._position == gtk.POS_LEFT else 0
            y = style.GRID_CELL_SIZE
            width = style.LINE_WIDTH
            height = self.allocation.height - (style.GRID_CELL_SIZE * 2)
        else:
            x = style.GRID_CELL_SIZE
            y = style.GRID_CELL_SIZE if self._position == gtk.POS_TOP else 0
            height = style.LINE_WIDTH
            width = self.allocation.width - (style.GRID_CELL_SIZE * 2)

        cr.rectangle(x, y, width, height)
        cr.fill()

        gtk.Bin.do_expose_event(self, event)
        return False

    def do_size_request(self, req):
        if self.is_vertical():
            req.height = gdk.screen_height()
            req.width = style.GRID_CELL_SIZE + style.LINE_WIDTH
        else:
            req.width = gdk.screen_width()
            req.height = style.GRID_CELL_SIZE + style.LINE_WIDTH

        self.get_child().size_request()

    def do_size_allocate(self, allocation):
        self.allocation = allocation

        # exclude grid squares at two ends of the frame
        # allocate remaining space to child box, minus the space needed for
        # drawing the border
        allocation = gdk.Rectangle()
        if self.is_vertical():
            allocation.x = 0 if self._position == gtk.POS_LEFT \
                else style.LINE_WIDTH
            allocation.y = style.GRID_CELL_SIZE
            allocation.width = self.allocation.width - style.LINE_WIDTH
            allocation.height = self.allocation.height \
                - (style.GRID_CELL_SIZE * 2)
        else:
            allocation.x = style.GRID_CELL_SIZE
            allocation.y = 0 if self._position == gtk.POS_TOP \
                else style.LINE_WIDTH
            allocation.width = self.allocation.width \
                - (style.GRID_CELL_SIZE * 2)
            allocation.height = self.allocation.height - style.LINE_WIDTH

        self.get_child().size_allocate(allocation)


class FrameWindow(gtk.Window):
    __gtype_name__ = 'SugarFrameWindow'

    def __init__(self, position):
        gtk.Window.__init__(self)
        self.hover = False
        self.size = style.GRID_CELL_SIZE + style.LINE_WIDTH

        accel_group = gtk.AccelGroup()
        self.set_data('sugar-accel-group', accel_group)
        self.add_accel_group(accel_group)

        self._position = position

        self.set_decorated(False)
        self.connect('realize', self._realize_cb)
        self.connect('enter-notify-event', self._enter_notify_cb)
        self.connect('leave-notify-event', self._leave_notify_cb)

        self._container = FrameContainer(position)
        self.add(self._container)
        self._container.show()
        self._update_size()

        screen = gdk.screen_get_default()
        screen.connect('size-changed', self._size_changed_cb)

    def append(self, child, expand=True, fill=True):
        self._container.get_child().pack_start(child, expand=expand, fill=fill)

    def _update_size(self):
        if self._position == gtk.POS_TOP or self._position == gtk.POS_BOTTOM:
            self.resize(gdk.screen_width(), self.size)
        else:
            self.resize(self.size, gdk.screen_height())

    def _realize_cb(self, widget):
        self.window.set_type_hint(gdk.WINDOW_TYPE_HINT_DOCK)
        self.window.set_accept_focus(False)

    def _enter_notify_cb(self, window, event):
        if event.detail != gdk.NOTIFY_INFERIOR:
            self.hover = True

    def _leave_notify_cb(self, window, event):
        if event.detail != gdk.NOTIFY_INFERIOR:
            self.hover = False

    def _size_changed_cb(self, screen):
        self._update_size()