~jconti/recent-notifications/trunk

« back to all changes in this revision

Viewing changes to recent_notifications/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)