Coverage for tatlin/lib/ui/basescene.py: 72%
68 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-20 05:56 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-20 05:56 +0000
1# -*- coding: utf-8 -*-
2# Copyright (C) 2011 Denis Kobozev
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software Foundation,
16# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18import wx
19from wx import glcanvas
22class BaseScene(glcanvas.GLCanvas):
23 def __init__(self, parent):
24 try: # the new way
25 super(BaseScene, self).__init__(parent, self._get_display_attributes())
26 except AttributeError: # the old way
27 super(BaseScene, self).__init__(parent, attribList=self._get_attrib_list())
29 self.Hide()
31 self.initialized = False
32 self.context = glcanvas.GLContext(self)
34 self.Bind(wx.EVT_ERASE_BACKGROUND, self._on_erase_background)
35 self.Bind(wx.EVT_SIZE, self._on_size)
36 self.Bind(wx.EVT_PAINT, self._on_paint)
37 self.Bind(wx.EVT_LEFT_DOWN, self._on_mouse_down)
38 self.Bind(wx.EVT_MOTION, self._on_mouse_motion)
40 # make it unnecessary for the scene to be in focus to respond to the
41 # mouse wheel by binding the mouse wheel event to the parent; if we
42 # bound the event to the scene itself, the user would have to click on
43 # the scene before scrolling each time the scene loses focus (users who
44 # have the fortune of being able to use a window manager that has a
45 # setting for focus-follows-mouse wouldn't care either way, since their
46 # wm would handle it for them)
47 parent.Bind(wx.EVT_MOUSEWHEEL, self._on_mouse_wheel)
49 methods = [
50 "init",
51 "display",
52 "reshape",
53 "button_press",
54 "button_motion",
55 "wheel_scroll",
56 ]
57 for method in methods:
58 if not hasattr(self, method):
59 raise Exception("Method %s() is not implemented" % method)
61 @staticmethod
62 def _get_display_attributes():
63 """Get the display attributes when using wxPython 4.1 or later."""
64 for depth in [32, 24, 16, 8]:
65 dispAttrs = glcanvas.GLAttributes()
66 dispAttrs.PlatformDefaults().DoubleBuffer().Depth(depth).EndList()
68 if glcanvas.GLCanvas.IsDisplaySupported(dispAttrs):
69 return dispAttrs
70 else:
71 raise Exception("No suitable depth buffer value found")
73 @staticmethod
74 def _get_attrib_list():
75 """Get the display attributes when using wxPython 4.0 or earlier."""
76 for depth in [32, 24, 16, 8]:
77 attrib_list = [
78 glcanvas.WX_GL_RGBA,
79 glcanvas.WX_GL_DOUBLEBUFFER,
80 glcanvas.WX_GL_DEPTH_SIZE,
81 depth,
82 0,
83 ]
85 if glcanvas.GLCanvas.IsDisplaySupported(attrib_list):
86 return attrib_list
87 else:
88 raise Exception("No suitable depth buffer value found")
90 def invalidate(self):
91 self.Refresh(False)
93 def _on_erase_background(self, event):
94 pass # Do nothing, to avoid flashing on MSW. Doesn't seem to be working, though :(
96 def _on_size(self, event):
97 wx.CallAfter(self._set_viewport)
98 event.Skip()
100 def _set_viewport(self):
101 self.SetCurrent(self.context)
102 size = self.GetClientSize()
103 self.reshape(size.width, size.height)
105 def _on_paint(self, event):
106 dc = wx.PaintDC(self)
107 self.SetCurrent(self.context)
108 if not self.initialized:
109 self.init()
110 self.initialized = True
111 size = self.GetClientSize()
112 self.display(size.width, size.height)
113 self.SwapBuffers()
115 def _on_mouse_down(self, event):
116 self.SetFocus()
117 x, y = event.GetPosition()
118 self.button_press(x, y)
120 def _on_mouse_motion(self, event):
121 x, y = event.GetPosition()
122 left = event.LeftIsDown()
123 middle = event.MiddleIsDown()
124 right = event.RightIsDown()
125 self.button_motion(x, y, left, middle, right)
127 def _on_mouse_wheel(self, event):
128 self.wheel_scroll(event.GetWheelRotation())