Continue with wx->gtk portage.
Callbacks for mouse events are "almost" working in this commit.
This commit is contained in:
parent
b8876a7632
commit
f70b1af2f3
|
@ -1,8 +1,8 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
# vim: set fdm=indent ts=2 sw=2 sts=2 et tw=80 cc=+1 mouse=a nu : #
|
|
||||||
# import wx
|
# import wx
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from threading import Timer
|
||||||
# from time import clock
|
# from time import clock
|
||||||
# import copy
|
# import copy
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@ import wx.lib.wxcairo
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import GLib, Gio, Gtk, Gdk
|
from gi.repository import GLib, Gio, Gtk, Gdk, GObject
|
||||||
|
GObject.threads_init()
|
||||||
|
|
||||||
# import ase
|
# import ase
|
||||||
from ase.data import covalent_radii
|
from ase.data import covalent_radii
|
||||||
|
@ -101,16 +102,22 @@ class ClusterViewer(Gtk.Window):
|
||||||
#self.Bind(wx.EVT_TIMER, self.__evt_timer_cb, self.timer)
|
#self.Bind(wx.EVT_TIMER, self.__evt_timer_cb, self.timer)
|
||||||
|
|
||||||
self.drawing_area.add_events(Gdk.EventMask.SCROLL_MASK |
|
self.drawing_area.add_events(Gdk.EventMask.SCROLL_MASK |
|
||||||
Gdk.EventMask.POINTER_MOTION_MASK |
|
#Gdk.EventMask.POINTER_MOTION_MASK |
|
||||||
Gdk.EventMask.BUTTON1_MOTION_MASK)
|
Gdk.EventMask.BUTTON_PRESS_MASK |
|
||||||
|
Gdk.EventMask.BUTTON_RELEASE_MASK |
|
||||||
|
Gdk.EventMask.BUTTON1_MOTION_MASK |
|
||||||
|
Gdk.EventMask.BUTTON3_MOTION_MASK)
|
||||||
|
|
||||||
self.connect("size-allocate", self.__evt_size_cb)
|
self.connect("size-allocate", self.__evt_size_cb)
|
||||||
self.drawing_area.connect("draw", self.__evt_draw_cb)
|
self.drawing_area.connect("draw", self.__evt_draw_cb)
|
||||||
self.drawing_area.connect("scroll-event", self.__evt_mousewheel_cb)
|
self.drawing_area.connect("scroll-event", self.__evt_mousewheel_cb)
|
||||||
self.drawing_area.connect("motion-notify-event", self.__evt_motion_cb)
|
self.drawing_area.connect("motion-notify-event", self.__evt_motion_cb)
|
||||||
#self.drawing_area.connect("button-press-event", self.__evt_press_cb)
|
self.drawing_area.connect("button-press-event", self.__evt_press_cb)
|
||||||
|
self.drawing_area.connect("button-release-event", self.__evt_release_cb)
|
||||||
#self.drawing_area.connect("button-release-event", self.__evt_release_cb)
|
#self.drawing_area.connect("button-release-event", self.__evt_release_cb)
|
||||||
|
|
||||||
|
self.timer_id = None
|
||||||
|
|
||||||
def show_emitter(self, show=True, alpha=0.25):
|
def show_emitter(self, show=True, alpha=0.25):
|
||||||
_opts = self.sprites_opts.copy()
|
_opts = self.sprites_opts.copy()
|
||||||
if show:
|
if show:
|
||||||
|
@ -123,11 +130,11 @@ class ClusterViewer(Gtk.Window):
|
||||||
"""
|
"""
|
||||||
Attach an Atoms object to the view.
|
Attach an Atoms object to the view.
|
||||||
|
|
||||||
This will translate the model to the center of mass, move the model
|
This will translate the model to the center of mass, move the model
|
||||||
center to the center of screen and adjust the scale to the largest
|
center to the center of screen and adjust the scale to the largest
|
||||||
dimension of the model
|
dimension of the model
|
||||||
|
|
||||||
:param rescale: if True, the zoom is computed to view the atoms; if
|
:param rescale: if True, the zoom is computed to view the atoms; if
|
||||||
False, a fixed zoom value is used
|
False, a fixed zoom value is used
|
||||||
"""
|
"""
|
||||||
if atoms is None:
|
if atoms is None:
|
||||||
|
@ -149,7 +156,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.atoms_center_of_mass = atoms.get_center_of_mass()
|
self.atoms_center_of_mass = atoms.get_center_of_mass()
|
||||||
# get the largest dimension
|
# get the largest dimension
|
||||||
p = atoms.get_positions()
|
p = atoms.get_positions()
|
||||||
self.atoms_largest_dimension = np.max(np.amax(p, axis=0) -
|
self.atoms_largest_dimension = np.max(np.amax(p, axis=0) -
|
||||||
np.amin(p, axis=0))
|
np.amin(p, axis=0))
|
||||||
if self.atoms_largest_dimension == 0:
|
if self.atoms_largest_dimension == 0:
|
||||||
self.atoms_largest_dimension = 1.0
|
self.atoms_largest_dimension = 1.0
|
||||||
|
@ -203,8 +210,8 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.translation_matrix[-1, (0, 1)] = (x, y)
|
self.translation_matrix[-1, (0, 1)] = (x, y)
|
||||||
self.update_projection_matrix()
|
self.update_projection_matrix()
|
||||||
|
|
||||||
def select_atoms(self, x, y, w=None, h=None, append=False,
|
def select_atoms(self, x, y, w=None, h=None, append=False, toggle=False):
|
||||||
toggle=False):
|
print("Append=", append, "Toggle=", toggle)
|
||||||
selection = np.array([])
|
selection = np.array([])
|
||||||
if w is None and h is None:
|
if w is None and h is None:
|
||||||
# get the projections
|
# get the projections
|
||||||
|
@ -237,10 +244,10 @@ class ClusterViewer(Gtk.Window):
|
||||||
selection = p[:, -1].astype(int)
|
selection = p[:, -1].astype(int)
|
||||||
|
|
||||||
if toggle:
|
if toggle:
|
||||||
#print(self.selection)
|
print(self.selection)
|
||||||
# whether atoms in the current selection were previously selected
|
# whether atoms in the current selection were previously selected
|
||||||
i = np.in1d(self.selection, selection)
|
i = np.in1d(self.selection, selection)
|
||||||
#print(i)
|
print(i)
|
||||||
self.selection = self.selection[np.invert(i)]
|
self.selection = self.selection[np.invert(i)]
|
||||||
|
|
||||||
if append:
|
if append:
|
||||||
|
@ -261,8 +268,9 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.update_drawing()
|
self.update_drawing()
|
||||||
|
|
||||||
def __evt_size_cb(self, widget, data):
|
def __evt_size_cb(self, widget, data):
|
||||||
#self.timer.Stop()
|
#self.timer.cancel()
|
||||||
#self.timer.Start(self.refresh_delay)
|
#self.timer.start()
|
||||||
|
self._postpone_drawing()
|
||||||
size = self.get_size()
|
size = self.get_size()
|
||||||
self.back_buffer = cairo.ImageSurface(cairo.FORMAT_RGB24, *size)
|
self.back_buffer = cairo.ImageSurface(cairo.FORMAT_RGB24, *size)
|
||||||
self.create_background_sprite(*size)
|
self.create_background_sprite(*size)
|
||||||
|
@ -283,6 +291,53 @@ class ClusterViewer(Gtk.Window):
|
||||||
if event.AltDown():
|
if event.AltDown():
|
||||||
self.mode |= self.MODE_SELECTION_TOGGLE
|
self.mode |= self.MODE_SELECTION_TOGGLE
|
||||||
|
|
||||||
|
def __evt_press_cb(self, widget, event):
|
||||||
|
if event.button == 1:
|
||||||
|
print("press_cb", event.state)
|
||||||
|
self.mx = event.x
|
||||||
|
self.my = event.y
|
||||||
|
self.capture_screen()
|
||||||
|
if event.state & Gdk.ModifierType.CONTROL_MASK:
|
||||||
|
self.mode |= self.MODE_SELECTION
|
||||||
|
if event.state & Gdk.ModifierType.SHIFT_MASK:
|
||||||
|
self.mode |= self.MODE_SELECTION_APPEND
|
||||||
|
if event.state & Gdk.ModifierType.MOD1_MASK:
|
||||||
|
self.mode |= self.MODE_SELECTION_TOGGLE
|
||||||
|
|
||||||
|
def __evt_release_cb(self, widget, event):
|
||||||
|
if event.button not in (1,3):
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.mode & self.MODE_SELECTION:
|
||||||
|
self.mode ^= self.MODE_SELECTION
|
||||||
|
# search for atoms in the selection box
|
||||||
|
x, y = event.x, event.y
|
||||||
|
w = h = None
|
||||||
|
if self.mode & self.MODE_SELECTION_BOX:
|
||||||
|
self.mode ^= self.MODE_SELECTION_BOX
|
||||||
|
x, y, w, h = self.selection_box
|
||||||
|
|
||||||
|
append = False
|
||||||
|
if self.mode & self.MODE_SELECTION_APPEND:
|
||||||
|
self.mode ^= self.MODE_SELECTION_APPEND
|
||||||
|
append = True
|
||||||
|
|
||||||
|
toggle = False
|
||||||
|
if self.mode & self.MODE_SELECTION_TOGGLE:
|
||||||
|
self.mode ^= self.MODE_SELECTION_TOGGLE
|
||||||
|
toggle = True
|
||||||
|
|
||||||
|
self.select_atoms(x, y, w, h, append=append, toggle=toggle)
|
||||||
|
|
||||||
|
if self.mode == self.MODE_TRANSLATION:
|
||||||
|
self.mode ^= self.MODE_TRANSLATION
|
||||||
|
|
||||||
|
if self.mode & self.MODE_ROTATION:
|
||||||
|
self.mode ^= self.MODE_ROTATION
|
||||||
|
|
||||||
|
self.update_drawing(light=False)
|
||||||
|
|
||||||
|
|
||||||
def __evt_left_up_cb(self, event):
|
def __evt_left_up_cb(self, event):
|
||||||
if self.mode & self.MODE_SELECTION:
|
if self.mode & self.MODE_SELECTION:
|
||||||
self.mode ^= self.MODE_SELECTION
|
self.mode ^= self.MODE_SELECTION
|
||||||
|
@ -351,9 +406,12 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.update_drawing()
|
self.update_drawing()
|
||||||
|
|
||||||
def __evt_motion_cb(self, widget, event):
|
def __evt_motion_cb(self, widget, event):
|
||||||
#self.timer.Stop()
|
#self.timer.cancel()
|
||||||
#self.timer.Start(self.refresh_delay)
|
#self.timer.start()
|
||||||
if True:#event.state & Gdk.ModifierType.BUTTON1_MASK:
|
self._postpone_drawing()
|
||||||
|
self._update_flag = True
|
||||||
|
GLib.timeout_add(self.refresh_delay, self.update_drawing, False)
|
||||||
|
if event.state & Gdk.ModifierType.BUTTON1_MASK:
|
||||||
print("motion cb...", bool(event.state &
|
print("motion cb...", bool(event.state &
|
||||||
Gdk.ModifierType.BUTTON1_MASK))
|
Gdk.ModifierType.BUTTON1_MASK))
|
||||||
mx, my = event.x, event.y
|
mx, my = event.x, event.y
|
||||||
|
@ -374,11 +432,11 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.translate_atoms(self.ox, self.oy)
|
self.translate_atoms(self.ox, self.oy)
|
||||||
self.update_drawing()
|
self.update_drawing()
|
||||||
#elif event.RightIsDown():
|
#elif event.RightIsDown():
|
||||||
elif event.state & Gdk.ModifierType.BUTTON2_MASK:
|
elif event.state & Gdk.ModifierType.BUTTON3_MASK:
|
||||||
self.mode = self.MODE_ROTATION
|
self.mode = self.MODE_ROTATION
|
||||||
theta = 2. * (float(self.scale0) / self.scale)
|
theta = 2. * (float(self.scale0) / self.scale)
|
||||||
theta = max(1., theta)
|
theta = max(1., theta)
|
||||||
mx, my = event.GetPosition()
|
mx, my = event.x, event.y
|
||||||
dx, dy = (mx - self.mx, my - self.my)
|
dx, dy = (mx - self.mx, my - self.my)
|
||||||
self.mx, self.my = (mx, my)
|
self.mx, self.my = (mx, my)
|
||||||
|
|
||||||
|
@ -433,8 +491,9 @@ class ClusterViewer(Gtk.Window):
|
||||||
else:
|
else:
|
||||||
#rot = event.GetWheelRotation()
|
#rot = event.GetWheelRotation()
|
||||||
rot = event.direction
|
rot = event.direction
|
||||||
#self.timer.Stop()
|
#self.timer.cancel()
|
||||||
#self.timer.Start(self.refresh_delay)
|
#self.timer.start()
|
||||||
|
self._postpone_drawing()
|
||||||
if rot == Gdk.ScrollDirection.UP:
|
if rot == Gdk.ScrollDirection.UP:
|
||||||
factor = self.scale * 1.1
|
factor = self.scale * 1.1
|
||||||
im_factor = 1 * 1.1
|
im_factor = 1 * 1.1
|
||||||
|
@ -445,6 +504,29 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.scale_atoms(factor)
|
self.scale_atoms(factor)
|
||||||
self.update_drawing()
|
self.update_drawing()
|
||||||
|
|
||||||
|
|
||||||
|
def target_fn(self):
|
||||||
|
print("Timer function!!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _postpone_drawing(self):
|
||||||
|
if self.timer_id:
|
||||||
|
GLib.source_remove(self.timer_id)
|
||||||
|
self.timer_id = GLib.timeout_add(self.refresh_delay,
|
||||||
|
self.update_drawing, False)
|
||||||
|
|
||||||
|
|
||||||
|
def __postpone_drawing(self):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
self.timer.cancel()
|
||||||
|
except:
|
||||||
|
#self.timer = Timer(self.refresh_delay, self.update_drawing,
|
||||||
|
# kwargs={'light_mode': False})
|
||||||
|
self.timer = Timer(self.refresh_delay, self.target_fn)
|
||||||
|
self.timer.start()
|
||||||
|
print("Timer created")
|
||||||
|
|
||||||
def capture_screen(self):
|
def capture_screen(self):
|
||||||
# get size of screen
|
# get size of screen
|
||||||
w, h = self.get_size()
|
w, h = self.get_size()
|
||||||
|
@ -514,7 +596,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
return surface, overlay
|
return surface, overlay
|
||||||
|
|
||||||
for i, a in enumerate(atom_numbers):
|
for i, a in enumerate(atom_numbers):
|
||||||
surface, overlay = create_surface(a,
|
surface, overlay = create_surface(a,
|
||||||
alpha=self.sprites_opts['alpha'],
|
alpha=self.sprites_opts['alpha'],
|
||||||
glow=self.sprites_opts['glow'])
|
glow=self.sprites_opts['glow'])
|
||||||
atom_surfaces[0, i] = surface
|
atom_surfaces[0, i] = surface
|
||||||
|
@ -565,7 +647,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
self.atom_surfaces = atom_surfaces
|
self.atom_surfaces = atom_surfaces
|
||||||
try:
|
try:
|
||||||
absorber_number = self.atoms[self.atoms.info['absorber']].number
|
absorber_number = self.atoms[self.atoms.info['absorber']].number
|
||||||
self.absorber_surface = create_surface(absorber_number, alpha=1,
|
self.absorber_surface = create_surface(absorber_number, alpha=1,
|
||||||
glow=True)
|
glow=True)
|
||||||
except:
|
except:
|
||||||
self.atoms.info['absorber'] = -1
|
self.atoms.info['absorber'] = -1
|
||||||
|
@ -622,10 +704,10 @@ class ClusterViewer(Gtk.Window):
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_v2p_matrix(cls, left, right, bottom, top, near, far):
|
def create_v2p_matrix(cls, left, right, bottom, top, near, far):
|
||||||
"""
|
"""
|
||||||
creates the matrix that transforms coordinates from view space (space
|
creates the matrix that transforms coordinates from view space (space
|
||||||
defined by the bounding box passed as argument) to projection space
|
defined by the bounding box passed as argument) to projection space
|
||||||
|
|
||||||
this transformation is a scale and offset that maps [left; right],
|
this transformation is a scale and offset that maps [left; right],
|
||||||
[bottom; top], [near; far] to [-1;1], [-1;1], [0;1]
|
[bottom; top], [near; far] to [-1;1], [-1;1], [0;1]
|
||||||
"""
|
"""
|
||||||
v2p_matrix = np.eye(4) * -1
|
v2p_matrix = np.eye(4) * -1
|
||||||
|
@ -685,12 +767,12 @@ class ClusterViewer(Gtk.Window):
|
||||||
scalebar_bb_width = 200
|
scalebar_bb_width = 200
|
||||||
scalebar_bb_height = 20
|
scalebar_bb_height = 20
|
||||||
ctx.set_source_rgba(0., 0., 0., 0.7)
|
ctx.set_source_rgba(0., 0., 0., 0.7)
|
||||||
ctx.rectangle(x + w - scalebar_bb_width - 6, h - scalebar_bb_height - 6,
|
ctx.rectangle(x + w - scalebar_bb_width - 6, h - scalebar_bb_height - 6,
|
||||||
scalebar_bb_width, scalebar_bb_height)
|
scalebar_bb_width, scalebar_bb_height)
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
|
|
||||||
ctx.set_source_rgb(1, 1, 1)
|
ctx.set_source_rgb(1, 1, 1)
|
||||||
ctx.rectangle(x + w - scalebar_bb_width, h - scalebar_bb_height, 100,
|
ctx.rectangle(x + w - scalebar_bb_width, h - scalebar_bb_height, 100,
|
||||||
scalebar_bb_height - 12)
|
scalebar_bb_height - 12)
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
|
|
||||||
|
@ -890,7 +972,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
v2 = projections[f[3], :3] - projections[f[0], :3]
|
v2 = projections[f[3], :3] - projections[f[0], :3]
|
||||||
# cross multiply them to get the normal
|
# cross multiply them to get the normal
|
||||||
n = np.cross(v2, v1)
|
n = np.cross(v2, v1)
|
||||||
# If the normal z coordinate is <0, the plane is not visible, so,
|
# If the normal z coordinate is <0, the plane is not visible, so,
|
||||||
# draw it first, otherwise draw it last
|
# draw it first, otherwise draw it last
|
||||||
if n[-1] > 0:
|
if n[-1] > 0:
|
||||||
ind.append(i)
|
ind.append(i)
|
||||||
|
@ -997,6 +1079,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
allocation = self.drawing_area.get_allocation()
|
allocation = self.drawing_area.get_allocation()
|
||||||
self.drawing_area.queue_draw_area(allocation.x, allocation.y,
|
self.drawing_area.queue_draw_area(allocation.x, allocation.y,
|
||||||
allocation.width, allocation.height)
|
allocation.width, allocation.height)
|
||||||
|
return False
|
||||||
|
|
||||||
def swap_buffers(self):
|
def swap_buffers(self):
|
||||||
if self.back_buffer:
|
if self.back_buffer:
|
||||||
|
@ -1007,7 +1090,7 @@ class ClusterViewer(Gtk.Window):
|
||||||
bitmap = wx.lib.wxcairo.BitmapFromImageSurface(back_buffer)
|
bitmap = wx.lib.wxcairo.BitmapFromImageSurface(back_buffer)
|
||||||
dc = wx.PaintDC(self)
|
dc = wx.PaintDC(self)
|
||||||
dc.DrawBitmap(bitmap, 0, 0)
|
dc.DrawBitmap(bitmap, 0, 0)
|
||||||
|
|
||||||
def __evt_draw_cb(self, da, ctx):
|
def __evt_draw_cb(self, da, ctx):
|
||||||
if self.back_buffer:
|
if self.back_buffer:
|
||||||
print("Draw called.", ctx)
|
print("Draw called.", ctx)
|
||||||
|
@ -1022,6 +1105,7 @@ if __name__ == "__main__":
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
MgO = bulk('MgO', crystalstructure='rocksalt', a=4.21, cubic=True)
|
MgO = bulk('MgO', crystalstructure='rocksalt', a=4.21, cubic=True)
|
||||||
|
MgO = MgO.repeat((10,10,10))
|
||||||
#view(MgO)
|
#view(MgO)
|
||||||
|
|
||||||
#app = wx.App(False)
|
#app = wx.App(False)
|
||||||
|
|
Loading…
Reference in New Issue