~ubuntu-branches/ubuntu/utopic/gnome-chemistry-utils/utopic

« back to all changes in this revision

Viewing changes to plugins/paint/bonds/newman.cc

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-10 21:30:51 UTC
  • mfrom: (1.1.15) (2.1.25 sid)
  • Revision ID: package-import@ubuntu.com-20130510213051-mswxsp3vitsgqspm
Tags: 0.14.2-1ubuntu1
* Sync with Debian. Remaining change:
  - Build-depend on firefox-dev instead of xulrunner-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- C++ -*-
 
2
 
 
3
/*
 
4
 * GChemPaint bonds plugin
 
5
 * newman.cc
 
6
 *
 
7
 * Copyright (C) 2012 Jean Bréfort <jean.brefort@normalesup.org>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU General Public License as
 
11
 * published by the Free Software Foundation; either version 3 of the
 
12
 * License, or (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software
 
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 
22
 * USA
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
#include "newman.h"
 
27
#include <gcp/application.h>
 
28
#include <gcp/atom.h>
 
29
#include <gcp/bond.h>
 
30
#include <gcp/document.h>
 
31
#include <gcp/theme.h>
 
32
#include <gcp/view.h>
 
33
#include <gcugtk/ui-builder.h>
 
34
#include <gccv/canvas.h>
 
35
#include <gccv/circle.h>
 
36
#include <gccv/group.h>
 
37
#include <gccv/line.h>
 
38
 
 
39
class gcpNewmanToolPrivate
 
40
{
 
41
public:
 
42
        static void OnLengthChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
43
        static void OnOrderChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
44
        static void OnForeBondsChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
45
        static void OnRearBondsChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
46
        static void OnForeFirstAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
47
        static void OnRearFirstAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
48
        static void OnForeBondAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
49
        static void OnRearBondAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool);
 
50
};
 
51
 
 
52
void gcpNewmanToolPrivate::OnLengthChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
53
{
 
54
        tool->m_pApp->GetActiveDocument ()->SetBondLength (gtk_spin_button_get_value (btn));
 
55
}
 
56
 
 
57
void gcpNewmanToolPrivate::OnOrderChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
58
{
 
59
        tool->m_Order = gtk_spin_button_get_value_as_int (btn);
 
60
        switch (tool->m_Order) {
 
61
        case 1:
 
62
                gtk_spin_button_set_value (tool->m_ForeBondsBtn, 3);
 
63
                gtk_spin_button_set_value (tool->m_RearBondsBtn, 3);
 
64
                gtk_spin_button_set_value (tool->m_RearFirstAngleBtn, tool->m_ForeFirstAngle * 180. / M_PI - 180.);
 
65
                break;
 
66
        case 2:
 
67
                gtk_spin_button_set_value (tool->m_ForeBondsBtn, 2);
 
68
                gtk_spin_button_set_value (tool->m_RearBondsBtn, 2);
 
69
                gtk_spin_button_set_value (tool->m_RearFirstAngleBtn, tool->m_ForeFirstAngle * 180. / M_PI);
 
70
                break;
 
71
        }
 
72
}
 
73
 
 
74
void gcpNewmanToolPrivate::OnForeBondsChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
75
{
 
76
        tool->m_ForeBonds = gtk_spin_button_get_value_as_int (btn);
 
77
        switch (tool->m_ForeBonds) {
 
78
        case 2:
 
79
                gtk_spin_button_set_value (tool->m_ForeBondAngleBtn, 180.);
 
80
                break;
 
81
        case 3:
 
82
                gtk_spin_button_set_value (tool->m_ForeBondAngleBtn, 120.);
 
83
                break;
 
84
        }
 
85
}
 
86
 
 
87
void gcpNewmanToolPrivate::OnRearBondsChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
88
{
 
89
        tool->m_RearBonds = gtk_spin_button_get_value_as_int (btn);
 
90
        switch (tool->m_RearBonds) {
 
91
        case 2:
 
92
                gtk_spin_button_set_value (tool->m_RearBondAngleBtn, 180.);
 
93
                break;
 
94
        case 3:
 
95
                gtk_spin_button_set_value (tool->m_RearBondAngleBtn, 120.);
 
96
                break;
 
97
        }
 
98
}
 
99
 
 
100
void gcpNewmanToolPrivate::OnForeFirstAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
101
{
 
102
        tool->m_ForeFirstAngle = gtk_spin_button_get_value_as_int (btn) * M_PI / 180.;
 
103
}
 
104
 
 
105
void gcpNewmanToolPrivate::OnForeBondAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
106
{
 
107
        tool->m_ForeBondAngle = gtk_spin_button_get_value_as_int (btn) * M_PI / 180.;
 
108
}
 
109
 
 
110
void gcpNewmanToolPrivate::OnRearFirstAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
111
{
 
112
        tool->m_RearFirstAngle = gtk_spin_button_get_value_as_int (btn) * M_PI / 180.;
 
113
}
 
114
 
 
115
void gcpNewmanToolPrivate::OnRearBondAngleChanged (GtkSpinButton *btn, gcpNewmanTool *tool)
 
116
{
 
117
        tool->m_RearBondAngle = gtk_spin_button_get_value_as_int (btn) * M_PI / 180.;
 
118
}
 
119
 
 
120
gcpNewmanTool::gcpNewmanTool (gcp::Application *App): gcp::Tool (App, "Newman")
 
121
{
 
122
        m_ForeBonds = m_RearBonds = 3;
 
123
        m_ForeFirstAngle = M_PI / 2.;
 
124
        m_RearFirstAngle = -M_PI / 2.;
 
125
        m_ForeBondAngle = m_RearBondAngle = M_PI / 1.5;
 
126
        m_Order = 1;
 
127
}
 
128
 
 
129
gcpNewmanTool::~gcpNewmanTool ()
 
130
{
 
131
}
 
132
 
 
133
bool gcpNewmanTool::OnClicked ()
 
134
{
 
135
        if (m_pObject != NULL)
 
136
                return false;
 
137
        // create the item
 
138
        gcp::Document* doc = m_pView->GetDoc ();
 
139
        double length = doc->GetBondLength () * m_dZoomFactor;
 
140
        double angle;
 
141
        int i;
 
142
        gccv::Line *line;
 
143
        gccv::Group *group = new gccv::Group (m_pView->GetCanvas ());
 
144
        m_Item = group;
 
145
        gccv::Circle *circle = new gccv::Circle (group, m_x0, m_y0, length / 3., NULL);
 
146
        circle->SetFillColor (0);
 
147
        circle->SetLineColor (GO_COLOR_BLACK);
 
148
        angle = m_ForeFirstAngle;
 
149
        for (i = 0; i < m_ForeBonds; i++) {
 
150
                line = new gccv::Line (group, m_x0, m_y0, m_x0 + length * cos (angle), m_y0 - length * sin (angle), NULL);
 
151
                line->SetLineColor (GO_COLOR_BLACK);
 
152
                angle += m_ForeBondAngle;
 
153
        }
 
154
        angle = m_RearFirstAngle;
 
155
        for (i = 0; i < m_RearBonds; i++) {
 
156
                line = new gccv::Line (group, m_x0 + length / 3. * cos (angle),
 
157
                                       m_y0 - length / 3. * sin (angle),
 
158
                                       m_x0 + length * cos (angle),
 
159
                                       m_y0 - length * sin (angle), NULL);
 
160
                line->SetLineColor (GO_COLOR_BLACK);
 
161
                angle += m_RearBondAngle;
 
162
        }
 
163
        return true;
 
164
}
 
165
 
 
166
void gcpNewmanTool::OnDrag ()
 
167
{
 
168
        delete m_Item;
 
169
        gcp::Document* doc = m_pView->GetDoc ();
 
170
        double length = doc->GetBondLength () * m_dZoomFactor;
 
171
        double angle;
 
172
        int i;
 
173
        gccv::Line *line;
 
174
        gccv::Group *group = new gccv::Group (m_pView->GetCanvas ());
 
175
        m_Item = group;
 
176
        gccv::Circle *circle = new gccv::Circle (group, m_x, m_y, length / 3., NULL);
 
177
        circle->SetFillColor (0);
 
178
        circle->SetLineColor (GO_COLOR_BLACK);
 
179
        angle = m_ForeFirstAngle;
 
180
        for (i = 0; i < m_ForeBonds; i++) {
 
181
                line = new gccv::Line (group, m_x, m_y, m_x + length * cos (angle), m_y - length * sin (angle), NULL);
 
182
                line->SetLineColor (GO_COLOR_BLACK);
 
183
                angle += m_ForeBondAngle;
 
184
        }
 
185
        angle = m_RearFirstAngle;
 
186
        for (i = 0; i < m_RearBonds; i++) {
 
187
                line = new gccv::Line (group, m_x + length / 3. * cos (angle),
 
188
                                       m_y - length / 3. * sin (angle),
 
189
                                       m_x + length * cos (angle),
 
190
                                       m_y - length * sin (angle), NULL);
 
191
                line->SetLineColor (GO_COLOR_BLACK);
 
192
                angle += m_RearBondAngle;
 
193
        }
 
194
}
 
195
 
 
196
void gcpNewmanTool::OnRelease ()
 
197
{
 
198
        delete m_Item;
 
199
        m_Item = NULL;
 
200
        gcp::Document* doc = m_pView->GetDoc ();
 
201
        double bl = doc->GetBondLength (), dz = bl / 2.;
 
202
        double angle;
 
203
        int i;
 
204
        // add the atoms and bonds
 
205
        // for now, we only add carbon atoms, and never merge with existing atoms
 
206
        // using 3d coordinates, front atoms at +bond_length/2 rear atoms at -bond_length/2
 
207
        m_x /= m_dZoomFactor;
 
208
        m_y /= m_dZoomFactor;
 
209
        gcp::Atom *atom = new gcp::Atom (6, m_x, m_y, -bl / 2.), *atom0;
 
210
        doc->AddAtom (atom);
 
211
        angle = m_RearFirstAngle;
 
212
        for (i = 0; i < m_RearBonds; i++) {
 
213
                atom0 = new gcp::Atom (6, m_x + bl * cos (angle), m_y - bl * sin (angle), -dz);
 
214
                doc->AddAtom (atom0);
 
215
                doc->AddBond (new gcp::Bond (atom, atom0, 1));
 
216
                angle += m_RearBondAngle;
 
217
        }
 
218
        atom0 = new gcp::Atom (6, m_x, m_y, dz);
 
219
        doc->AddAtom (atom0);
 
220
        gcp::Bond *bond = new gcp::Bond (atom, atom0, 1);
 
221
        doc->AddBond (bond); // add to doc before setting the type so that the radius will be correct
 
222
        bond->SetType (gcp::NewmanBondType);
 
223
        angle = m_ForeFirstAngle;
 
224
        for (i = 0; i < m_ForeBonds; i++) {
 
225
                atom = new gcp::Atom (6, m_x + bl * cos (angle), m_y - bl * sin (angle), -dz);
 
226
                doc->AddAtom (atom);
 
227
                doc->AddBond (new gcp::Bond (atom0, atom, 1));
 
228
                angle += m_ForeBondAngle;
 
229
        }
 
230
        gcp::Operation *op = doc-> GetNewOperation (gcp::GCP_ADD_OPERATION);
 
231
        op->AddObject (bond->GetMolecule ());
 
232
        doc->FinishOperation ();
 
233
        // ensure that rear bonds don't go up to the center
 
234
        m_pView->Update (bond->GetMolecule ());
 
235
}
 
236
 
 
237
GtkWidget *gcpNewmanTool::GetPropertyPage ()
 
238
{
 
239
        gcugtk::UIBuilder *builder = new gcugtk::UIBuilder (UIDIR"/newman.ui", GETTEXT_PACKAGE);
 
240
        m_LengthBtn = GTK_SPIN_BUTTON (builder->GetWidget ("bond-length-btn"));
 
241
        g_signal_connect (m_LengthBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnLengthChanged), this);
 
242
        m_OrderBtn = GTK_SPIN_BUTTON (builder->GetWidget ("order-btn"));
 
243
        gtk_spin_button_set_value (m_OrderBtn, m_Order);
 
244
        g_signal_connect (m_OrderBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnOrderChanged), this);
 
245
        m_ForeBondsBtn = GTK_SPIN_BUTTON (builder->GetWidget ("fore-bonds-btn"));
 
246
        gtk_spin_button_set_value (m_ForeBondsBtn, m_ForeBonds);
 
247
        g_signal_connect (m_ForeBondsBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnForeBondsChanged), this);
 
248
        m_RearBondsBtn = GTK_SPIN_BUTTON (builder->GetWidget ("rear-bonds-btn"));
 
249
        gtk_spin_button_set_value (m_RearBondsBtn, m_RearBonds);
 
250
        g_signal_connect (m_RearBondsBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnRearBondsChanged), this);
 
251
        m_ForeFirstAngleBtn = GTK_SPIN_BUTTON (builder->GetWidget ("fore-first-angle-btn"));
 
252
        gtk_spin_button_set_value (m_ForeFirstAngleBtn, m_ForeFirstAngle * 180. / M_PI);
 
253
        g_signal_connect (m_ForeFirstAngleBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnForeFirstAngleChanged), this);
 
254
        m_RearFirstAngleBtn = GTK_SPIN_BUTTON (builder->GetWidget ("rear-first-angle-btn"));
 
255
        gtk_spin_button_set_value (m_RearFirstAngleBtn, m_RearFirstAngle * 180. / M_PI);
 
256
        g_signal_connect (m_RearFirstAngleBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnRearFirstAngleChanged), this);
 
257
        m_ForeBondAngleBtn = GTK_SPIN_BUTTON (builder->GetWidget ("fore-angle-btn"));
 
258
        gtk_spin_button_set_value (m_ForeBondAngleBtn, m_ForeBondAngle * 180. / M_PI);
 
259
        g_signal_connect (m_ForeBondAngleBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnForeBondAngleChanged), this);
 
260
        m_RearBondAngleBtn = GTK_SPIN_BUTTON (builder->GetWidget ("rear-angle-btn"));
 
261
        gtk_spin_button_set_value (m_RearBondAngleBtn, m_RearBondAngle * 180. / M_PI);
 
262
        g_signal_connect (m_RearBondAngleBtn, "value-changed", G_CALLBACK (gcpNewmanToolPrivate::OnRearBondAngleChanged), this);
 
263
        // FIXME: implement
 
264
        GtkWidget *res = builder->GetRefdWidget ("newman");
 
265
        delete builder;
 
266
        return res;
 
267
}
 
268
 
 
269
void gcpNewmanTool::Activate ()
 
270
{
 
271
        gcp::Document *pDoc = m_pApp->GetActiveDocument ();
 
272
        gtk_spin_button_set_value (m_LengthBtn, pDoc->GetBondLength ());
 
273
}