File: popupwindow.py

package info (click to toggle)
idjc 0.8.17-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, sid
  • size: 9,628 kB
  • sloc: python: 20,415; ansic: 15,941; sh: 4,869; makefile: 189; sed: 16
file content (144 lines) | stat: -rw-r--r-- 6,258 bytes parent folder | download
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
#   popupwindow.py: for when standard gtk tooltips just don't cut it
#   Copyright (C) 2007, 2011 Stephen Fairchild (s-fairchild@users.sourceforge.net)
#
#   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 in the file entitled COPYING.
#   If not, see <http://www.gnu.org/licenses/>.

from __future__ import print_function

__all__ = ['PopupWindow']

import gobject
import gtk
from .gtkstuff import threadslock, timeout_add, source_remove


class PopupWindow:
    def message(self, text):
        if self.messages:
            print("PopupWindow:", text)

        
    def set_messages(self, boolean):
        """Show status messages on the console when boolean = true."""
        

        self.messages = boolean and True or False
        
    def get_messages(self):
        return self.messages
    

    class new_popup_window(gtk.Window):
        def __init__(self):
            gtk.Window.__init__(self, gtk.WINDOW_POPUP)
            gtk.Window.set_decorated(self, False)
    

    @threadslock
    def timeout_callback(self):
        class bugout:
            def __init__(self, parent, text):
                if parent.popup_window is not None:
                    parent.popup_window.destroy()
                    parent.popup_window = None
                parent.message(text)
        try:
            self.timer_count += 1
            self.total_timer_count += 1
            if self.timer_count == self.popuptime:
                if not self.timeout or self.total_timer_count < \
                                                self.popuptime + self.timeout:
                    self.popup_window = self.new_popup_window()
                    if self.winpopulate_callback(self.popup_window, \
                                            self.widget, self.x, self.y) != -1:
                        self.popup_window.realize()
                        # Calculate the popup window positioning.
                        w_popup = self.popup_window.get_size()[0]
                        # Get root window width.
                        w_root = self.popup_window.get_screen(
                                        ).get_root_window().get_geometry()[2]
                        offset = w_root - int(self.x_root) - w_popup - 4
                        if offset > 0:  # Right justify if needed.
                            offset = 0
                        x_pos = int(self.x_root) + 4 + offset
                        # No right justification for popups that won't fit.
                        if x_pos < 0:
                            # Display against left window edge.
                            x_pos = 0
                        self.popup_window.move(x_pos, int(self.y_root) + 4)
                        self.popup_window.show()
                        self.message("popup window created")
                    else:
                        raise bugout(self, "window populate callback returned"
                                                    " -1 -- window cancelled")
                else:
                    raise bugout(self, "timeout exceeded")
            if self.timer_count > self.popdowntime:
                raise bugout(self, "popdown time reached")
        except bugout:
            return False
        else:
            return True
    
    def handle_mouse(self, widget, event, data):
        self.timer_count = 0
        # Store absolute mouse x and y coordiates.
        self.x_root = event.x_root
        self.y_root = event.y_root
        # This information could be useful too.
        self.x = event.x
        self.y = event.y
        # Any event triggers destruction of popup windows currently open.
        if self.popup_window is not None:
            self.popup_window.destroy()
            source_remove(self.timeout_id)
            self.popup_window = None
            self.message("popup window destroyed due to the sensing of an "
                                                        "event, timer removed")
            if data == "leave": return False
        if data == "enter" and self.inside_widget == False:
            self.timeout_id = timeout_add(100, self.timeout_callback)
            self.inside_widget = True
            self.total_timer_count = 0
            self.message("timer started")
        if data == "leave":
            if self.inside_widget:
                source_remove(self.timeout_id)
                self.inside_widget = False
                self.message("timer removed")
        if data == "button" or data == "scroll" or self.inhibit_callback() \
                                                        and self.inside_widget:
            source_remove(self.timeout_id)
            self.message("timer removed")
    
    def dummy(self): return False
    
    def __init__(self, widget, popuptime, popdowntime, timeout, \
                                winpopulate_callback, inhibit_callback = None):
        self.widget = widget
        self.popuptime = popuptime
        self.popdowntime = popdowntime
        self.timeout = timeout
        self.winpopulate_callback = winpopulate_callback
        self.inhibit_callback = inhibit_callback or self.dummy
        self.popup_window = None
        self.inside_widget = False
        self.messages = False
        self.widget.connect("motion_notify_event", self.handle_mouse, "move")
        self.widget.connect("enter_notify_event", self.handle_mouse, "enter")
        self.widget.connect("leave_notify_event", self.handle_mouse, "leave")
        self.widget.connect("button_press_event", self.handle_mouse, "button")
        self.widget.connect("button_release_event", self.handle_mouse, "button")
        self.widget.connect("scroll_event", self.handle_mouse, "scroll")