~jconti/recent-notifications/trunk

« back to all changes in this revision

Viewing changes to MessageWindow.py

  • Committer: Jason Conti
  • Date: 2010-02-21 00:51:16 UTC
  • Revision ID: jason.conti@gmail.com-20100221005116-6r8y8tta8f21h3x9
Reorganizing to make it easier to build a package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
MessageWindow.py
3
 
by Jason Conti
4
 
February 19, 2010
5
 
 
6
 
Popup window for viewing notifications.
7
 
"""
8
 
 
9
 
import gnomeapplet
10
 
import gtk
11
 
import pango
12
 
 
13
 
class MessageWindow(gtk.Window):
14
 
  """Shows the log of notification messages."""
15
 
  def __init__(self, parent, limit_messages = 5):
16
 
    gtk.Window.__init__(self)
17
 
 
18
 
    self._parent = parent
19
 
    self._limit_messages = limit_messages
20
 
 
21
 
    self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
22
 
    self.set_decorated(False)
23
 
    self.set_resizable(False)
24
 
    self.stick()
25
 
    self.set_title("Message Window")
26
 
    self.set_border_width(5)
27
 
    self.set_size_request(400, -1)
28
 
 
29
 
    self._vbox = gtk.VBox(True, 5)
30
 
    self.add(self._vbox)
31
 
 
32
 
    self._empty_label = gtk.Label("No messages")
33
 
    self._vbox.pack_start(self._empty_label)
34
 
 
35
 
    self._messages = []
36
 
 
37
 
  def add_message(self, message):
38
 
    """Adds a message to the message window."""
39
 
    widget = MessageWidget(message)
40
 
    self._messages.append(widget)
41
 
    self._vbox.pack_start(widget)
42
 
 
43
 
    if self._empty_label != None:
44
 
      self._vbox.remove(self._empty_label)
45
 
      self._empty_label.destroy()
46
 
      self._empty_label = None
47
 
 
48
 
    if len(self._messages) > self._limit_messages:
49
 
      message = self._messages.pop(0)
50
 
      self._vbox.remove(message)
51
 
      message.destroy()
52
 
 
53
 
  def align_with_parent(self):
54
 
    """Adapted from position_calendar_popup in the GNOME clock applet."""
55
 
    # Get the size of the applet button and the size of this window
56
 
    x, y = self._parent.get_origin()
57
 
    w, h = self.size_request()
58
 
    button_w, button_h = self._parent.get_size()
59
 
 
60
 
    screen = self.get_screen()
61
 
    monitor = None
62
 
 
63
 
    # Figure out which monitor we are on
64
 
    for i in range(screen.get_n_monitors()):
65
 
      m = screen.get_monitor_geometry(i)
66
 
 
67
 
      if x >= m.x and x <= m.x + m.width and y >= m.y and y <= m.y + m.height:
68
 
        monitor = m
69
 
        break
70
 
 
71
 
    # Probably xinerama
72
 
    if monitor == None:
73
 
      monitor = gtk.gdk.Rectangle(0, 0, screen.get_width(), screen.get_height())
74
 
 
75
 
    orient = self._parent.get_orient()
76
 
 
77
 
    # Figure out the x, y coordinates of the window and the gravity depending
78
 
    # on the orientation of the panel
79
 
    if orient == gnomeapplet.ORIENT_RIGHT:  # Panel on left
80
 
      x += button_w
81
 
      if (y + h) > monitor.y + monitor.height:
82
 
        y -= (y + h) - (monitor.y + monitor.height)
83
 
 
84
 
      if (y + h) > (monitor.height / 2):
85
 
        gravity = gtk.gdk.GRAVITY_SOUTH_WEST
86
 
      else:
87
 
        gravity = gtk.gdk.GRAVITY_NORTH_WEST
88
 
 
89
 
    elif orient == gnomeapplet.ORIENT_LEFT: # Panel on right
90
 
      x -= w
91
 
      if (y + h) > monitor.y + monitor.height:
92
 
        y -= (y + h) - (monitor.y + monitor.height)
93
 
 
94
 
      if (y + h) > (monitor.height / 2):
95
 
        gravity = gtk.gdk.GRAVITY_SOUTH_EAST
96
 
      else:
97
 
        gravity = gtk.gdk.GRAVITY_NORTH_EAST
98
 
 
99
 
    elif orient == gnomeapplet.ORIENT_DOWN: # Panel on top
100
 
      y += button_h
101
 
      if (x + w) > monitor.x + monitor.width:
102
 
        x -= (x + w) - (monitor.x + monitor.width)
103
 
 
104
 
      gravity = gtk.gdk.GRAVITY_NORTH_WEST
105
 
 
106
 
    else: # Panel on bottom
107
 
      y -= h
108
 
      if (x + w) > monitor.x + monitor.width:
109
 
        x -= (x + w) - (monitor.x + monitor.width)
110
 
 
111
 
      gravity = gtk.gdk.GRAVITY_SOUTH_WEST
112
 
 
113
 
    self.move(x, y)
114
 
    self.set_gravity(gravity)
115
 
 
116
 
class MessageWidget(gtk.Frame):
117
 
  """Widget to display a Notifications.Message."""
118
 
  def __init__(self, message):
119
 
    gtk.Frame.__init__(self)
120
 
 
121
 
    self._message = message
122
 
 
123
 
    self._vbox = gtk.VBox(False)
124
 
    self.add(self._vbox)
125
 
 
126
 
    self._hbox = gtk.HBox(False)
127
 
    self._vbox.pack_start(self._hbox, True, True)
128
 
 
129
 
    icon_pixbuf = message.get_icon_pixbuf()
130
 
    if icon_pixbuf != None:
131
 
      self._icon_image = gtk.image_new_from_pixbuf(icon_pixbuf)
132
 
      self._icon_image.set_alignment(0, 0)
133
 
      self._icon_image.set_padding(5, 5)
134
 
      self._hbox.pack_start(self._icon_image, False, False)
135
 
 
136
 
    self._text_vbox = gtk.VBox(False)
137
 
    self._hbox.pack_start(self._text_vbox, True, True)
138
 
 
139
 
    self._title_label = gtk.Label(message.summary)
140
 
    self._title_label.set_alignment(0, 0)
141
 
    self._title_label.set_padding(5, 5)
142
 
    attr = pango.AttrList()
143
 
    attr.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1))
144
 
    self._title_label.set_attributes(attr)
145
 
    self._text_vbox.pack_start(self._title_label, False, False)
146
 
 
147
 
    self._body_label = MessageBody(message.body)
148
 
    self._body_label.set_alignment(0, 0)
149
 
    self._body_label.set_padding(5, 5)
150
 
    self._body_label.set_line_wrap(True)
151
 
    self._text_vbox.pack_start(self._body_label, True, True)
152
 
 
153
 
    self._timestamp_label = gtk.Label(message.formatted_timestamp() + " from " + message.app_name)
154
 
    self._timestamp_label.set_padding(5, 5)
155
 
    attr = pango.AttrList()
156
 
    attr.insert(pango.AttrScale(pango.SCALE_SMALL, 0, -1))
157
 
    self._timestamp_label.set_attributes(attr)
158
 
    self._vbox.pack_start(self._timestamp_label, False, False)
159
 
 
160
 
class MessageBody(gtk.Label):
161
 
  """Implements a workaround from:
162
 
    http://www.16software.com/blog/dynamic-label-wrapping-in-gtk
163
 
    that fixes the label overflow problems I have been having
164
 
    with a long message body."""
165
 
  def __init__(self, text):
166
 
    gtk.Label.__init__(self, text)
167
 
 
168
 
    self.set_line_wrap(True)
169
 
    self.connect("size-allocate", self.on_size_allocate)
170
 
 
171
 
  def on_size_allocate(self, widget, rect):
172
 
    self.set_size_request(rect.width - 10, -1)