File: temp_manager.py

package info (click to toggle)
bkchem 0.13.0-6
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,676 kB
  • sloc: python: 42,283; xml: 168; makefile: 10
file content (147 lines) | stat: -rw-r--r-- 5,686 bytes parent folder | download | duplicates (4)
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
145
146
147
#--------------------------------------------------------------------------
#     This file is part of BKchem - a chemical drawing program
#     Copyright (C) 2002-2004 Beda Kosata <beda@zirael.org>

#     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.

#     Complete text of GNU GPL can be found in the file gpl.txt in the
#     main directory of the program

#--------------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------------

"""template manager resides here"""

import math
from oasa.oasa.transform import transform
from molecule import molecule
import xml.dom.minidom as dom
from warnings import warn
import config
import os.path
import os_support
import xml.sax
import misc

from singleton_store import Store, Screen


class template_manager:
  templates = []

  def __init__( self):
    self.templates = []
    self._prepared_templates = []


  def add_template_from_CDML( self, file):
    if not os.path.isfile( file):
      file = os_support.get_path( file, "template")
      if not file:
        warn( "template file %s does not exist - ignoring" % file)
        return
    try:
      doc = dom.parse( file).getElementsByTagName( 'cdml')[0]
    except xml.sax.SAXException: 
      warn( "template file %s cannot be parsed - ignoring" % file)
      return
    # when loading old versions of CDML try to convert them, but do nothing when they cannot be converted
    import CDML_versions
    CDML_versions.transform_dom_to_version( doc, config.current_CDML_version)
    Store.app.paper.onread_id_sandbox_activate()
    added = []
    for tmp in doc.getElementsByTagName('molecule'):
      self.templates.append( tmp)
      m = molecule( Store.app.paper, package=tmp)
      self._prepared_templates.append( m)
      added.append( m)
    Store.app.paper.onread_id_sandbox_finish( apply_to=[]) # just switch the id_managers, no id mangling

  def get_template( self, n):
    return self.templates[n]

  def get_templates_valency( self, name):
    return self._prepared_templates[ name].next_to_t_atom.occupied_valency -1

  def get_template_names( self):
    return [o.name for o in self._prepared_templates]

  def get_transformed_template( self, n, coords, type='empty', paper=None):
    """type is type of connection - 'bond', 'atom1'(for single atom), 'atom2'(for atom with more than 1 bond), 'empty'"""
    pap = paper or Store.app.paper
    pap.onread_id_sandbox_activate() # must be here to mangle the ids
    current = molecule( pap, package=self.templates[n])
    pap.onread_id_sandbox_finish( apply_to= [current]) # id mangling
    current.name = ''
    self._scale_ratio = 1
    trans = transform()
    # type empty - just draws the template - no conection
    if type == 'empty':
      xt1, yt1 = current.t_atom.get_xy()
      xt2, yt2 = current.next_to_t_atom.get_xy()
      x1, y1 = coords
      bond_length = Screen.any_to_px( Store.app.paper.standard.bond_length)
      current.delete_items( [current.t_atom], redraw=0, delete_single_atom=0)
      trans.set_move( -xt2, -yt2)
      trans.set_scaling( bond_length / math.sqrt( (xt1-xt2)**2 + (yt1-yt2)**2))
      trans.set_move( x1, y1)
    #type atom
    elif type == 'atom1' or type == 'atom2':
      xt1, yt1 = current.t_atom.get_xy()
      xt2, yt2 = current.next_to_t_atom.get_xy()
      x1, y1, x2, y2 = coords
      trans.set_move( -xt2, -yt2)
      trans.set_scaling( math.sqrt( (x1-x2)**2 + (y1-y2)**2) / math.sqrt( (xt1-xt2)**2 + (yt1-yt2)**2))
      trans.set_rotation( math.atan2( xt1-xt2, yt1-yt2) - math.atan2( x1-x2, y1-y2))
      trans.set_move( x2, y2)
    #type bond
    elif type == 'bond':
      if not (current.t_bond_first and current.t_bond_second):
        warn( "this template is not capable to be added to bond - sorry.")
        return None
      current.delete_items( [current.t_atom], redraw=0, delete_single_atom=0)
      xt1, yt1 = current.t_bond_first.get_xy()
      xt2, yt2 = current.t_bond_second.get_xy()
      x1, y1, x2, y2 = coords
      self._scale_ratio = math.sqrt( (x1-x2)**2 + (y1-y2)**2) / math.sqrt( (xt1-xt2)**2 + (yt1-yt2)**2) # further needed for bond.bond_width transformation
      trans.set_move( -xt1, -yt1)
      trans.set_rotation( math.atan2( xt1-xt2, yt1-yt2) - math.atan2( x1-x2, y1-y2))
      trans.set_scaling( self._scale_ratio)
      trans.set_move( x1, y1)
    self.transform_template( current, trans)
    #remove obsolete info from template
    if type == 'atom1':
      current.delete_items( [current.t_atom], redraw=0, delete_single_atom=0)
    elif type == 'atom2':
      current.t_atom.x = x1
      current.t_atom.y = y1
    current.t_atom = None
    current.t_bond_first = None
    current.t_bond_second = None
    #return ready template
    return current 
  
  def transform_template( self, temp, trans):
    for a in temp.atoms:
      a.x, a.y = trans.transform_xy( a.x, a.y)
      a.scale_font( self._scale_ratio)
    for b in temp.bonds:
      if b.order != 1:
        b.bond_width *= self._scale_ratio
    # update template according to current default values
    Store.app.paper.apply_current_standard( [temp], template_mode=1)
    # return the ready template
    return temp