Continue with wx->gtk portage.

Callbacks for mouse events are "almost" working
in this commit.
This commit is contained in:
Sylvain Tricot 2021-01-25 13:59:03 +01:00
parent b8876a7632
commit f70b1af2f3
1 changed files with 114 additions and 30 deletions

View File

@ -1,8 +1,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 numpy as np
from threading import Timer
# from time import clock
# import copy
@ -11,7 +11,8 @@ import wx.lib.wxcairo
import gi
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
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.drawing_area.add_events(Gdk.EventMask.SCROLL_MASK |
Gdk.EventMask.POINTER_MOTION_MASK |
Gdk.EventMask.BUTTON1_MOTION_MASK)
#Gdk.EventMask.POINTER_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.drawing_area.connect("draw", self.__evt_draw_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("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.timer_id = None
def show_emitter(self, show=True, alpha=0.25):
_opts = self.sprites_opts.copy()
if show:
@ -123,11 +130,11 @@ class ClusterViewer(Gtk.Window):
"""
Attach an Atoms object to the view.
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
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
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
"""
if atoms is None:
@ -149,7 +156,7 @@ class ClusterViewer(Gtk.Window):
self.atoms_center_of_mass = atoms.get_center_of_mass()
# get the largest dimension
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))
if self.atoms_largest_dimension == 0:
self.atoms_largest_dimension = 1.0
@ -203,8 +210,8 @@ class ClusterViewer(Gtk.Window):
self.translation_matrix[-1, (0, 1)] = (x, y)
self.update_projection_matrix()
def select_atoms(self, x, y, w=None, h=None, append=False,
toggle=False):
def select_atoms(self, x, y, w=None, h=None, append=False, toggle=False):
print("Append=", append, "Toggle=", toggle)
selection = np.array([])
if w is None and h is None:
# get the projections
@ -237,10 +244,10 @@ class ClusterViewer(Gtk.Window):
selection = p[:, -1].astype(int)
if toggle:
#print(self.selection)
print(self.selection)
# whether atoms in the current selection were previously selected
i = np.in1d(self.selection, selection)
#print(i)
print(i)
self.selection = self.selection[np.invert(i)]
if append:
@ -261,8 +268,9 @@ class ClusterViewer(Gtk.Window):
self.update_drawing()
def __evt_size_cb(self, widget, data):
#self.timer.Stop()
#self.timer.Start(self.refresh_delay)
#self.timer.cancel()
#self.timer.start()
self._postpone_drawing()
size = self.get_size()
self.back_buffer = cairo.ImageSurface(cairo.FORMAT_RGB24, *size)
self.create_background_sprite(*size)
@ -283,6 +291,53 @@ class ClusterViewer(Gtk.Window):
if event.AltDown():
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):
if self.mode & self.MODE_SELECTION:
self.mode ^= self.MODE_SELECTION
@ -351,9 +406,12 @@ class ClusterViewer(Gtk.Window):
self.update_drawing()
def __evt_motion_cb(self, widget, event):
#self.timer.Stop()
#self.timer.Start(self.refresh_delay)
if True:#event.state & Gdk.ModifierType.BUTTON1_MASK:
#self.timer.cancel()
#self.timer.start()
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 &
Gdk.ModifierType.BUTTON1_MASK))
mx, my = event.x, event.y
@ -374,11 +432,11 @@ class ClusterViewer(Gtk.Window):
self.translate_atoms(self.ox, self.oy)
self.update_drawing()
#elif event.RightIsDown():
elif event.state & Gdk.ModifierType.BUTTON2_MASK:
elif event.state & Gdk.ModifierType.BUTTON3_MASK:
self.mode = self.MODE_ROTATION
theta = 2. * (float(self.scale0) / self.scale)
theta = max(1., theta)
mx, my = event.GetPosition()
mx, my = event.x, event.y
dx, dy = (mx - self.mx, my - self.my)
self.mx, self.my = (mx, my)
@ -433,8 +491,9 @@ class ClusterViewer(Gtk.Window):
else:
#rot = event.GetWheelRotation()
rot = event.direction
#self.timer.Stop()
#self.timer.Start(self.refresh_delay)
#self.timer.cancel()
#self.timer.start()
self._postpone_drawing()
if rot == Gdk.ScrollDirection.UP:
factor = self.scale * 1.1
im_factor = 1 * 1.1
@ -445,6 +504,29 @@ class ClusterViewer(Gtk.Window):
self.scale_atoms(factor)
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):
# get size of screen
w, h = self.get_size()
@ -514,7 +596,7 @@ class ClusterViewer(Gtk.Window):
return surface, overlay
for i, a in enumerate(atom_numbers):
surface, overlay = create_surface(a,
surface, overlay = create_surface(a,
alpha=self.sprites_opts['alpha'],
glow=self.sprites_opts['glow'])
atom_surfaces[0, i] = surface
@ -565,7 +647,7 @@ class ClusterViewer(Gtk.Window):
self.atom_surfaces = atom_surfaces
try:
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)
except:
self.atoms.info['absorber'] = -1
@ -622,10 +704,10 @@ class ClusterViewer(Gtk.Window):
@classmethod
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
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]
"""
v2p_matrix = np.eye(4) * -1
@ -685,12 +767,12 @@ class ClusterViewer(Gtk.Window):
scalebar_bb_width = 200
scalebar_bb_height = 20
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)
ctx.fill()
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)
ctx.fill()
@ -890,7 +972,7 @@ class ClusterViewer(Gtk.Window):
v2 = projections[f[3], :3] - projections[f[0], :3]
# cross multiply them to get the normal
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
if n[-1] > 0:
ind.append(i)
@ -997,6 +1079,7 @@ class ClusterViewer(Gtk.Window):
allocation = self.drawing_area.get_allocation()
self.drawing_area.queue_draw_area(allocation.x, allocation.y,
allocation.width, allocation.height)
return False
def swap_buffers(self):
if self.back_buffer:
@ -1007,7 +1090,7 @@ class ClusterViewer(Gtk.Window):
bitmap = wx.lib.wxcairo.BitmapFromImageSurface(back_buffer)
dc = wx.PaintDC(self)
dc.DrawBitmap(bitmap, 0, 0)
def __evt_draw_cb(self, da, ctx):
if self.back_buffer:
print("Draw called.", ctx)
@ -1022,6 +1105,7 @@ if __name__ == "__main__":
import wx
MgO = bulk('MgO', crystalstructure='rocksalt', a=4.21, cubic=True)
MgO = MgO.repeat((10,10,10))
#view(MgO)
#app = wx.App(False)