]> Shamusworld >> Repos - architektonas/blob - src/applicationwindow.cpp
Preliminary Add Line tool work...
[architektonas] / src / applicationwindow.cpp
1 //
2 // applicationwindow.cpp: Architektonas
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -------------------------------------------------------------
12 // JLH  03/22/2011  Created this file
13 // JLH  09/29/2011  Added simple zoom in/out functionality
14 // JLH  10/03/2011  Fixed zoom tool to zoom in/out from center of screen
15 //
16
17 // FIXED:
18 //
19 //
20 // STILL TO BE DONE:
21 //
22 //
23
24 // Uncomment this for debugging...
25 //#define DEBUG
26 //#define DEBUGFOO                      // Various tool debugging...
27 //#define DEBUGTP                               // Toolpalette debugging...
28
29 #include "applicationwindow.h"
30
31 #include "about.h"
32 #include "drawingview.h"
33 #include "generaltab.h"
34 #include "painter.h"
35 #include "settingsdialog.h"
36
37
38 ApplicationWindow::ApplicationWindow(): settings("Underground Software", "Architektonas")
39 {
40         drawing = new DrawingView(this);
41         drawing->setMouseTracking(true);                // We want *all* mouse events...!
42         setCentralWidget(drawing);
43
44         aboutWin = new AboutWindow(this);
45
46 //      ((TTEdit *)qApp)->charWnd = new CharWindow(this);
47
48         setWindowIcon(QIcon(":/res/atns-icon.png"));
49         setWindowTitle("Architektonas");
50
51         CreateActions();
52         CreateMenus();
53         CreateToolbars();
54
55         //      Create status bar
56         statusBar()->showMessage(tr("Ready"));
57
58         ReadSettings();
59
60 //      connect(textEdit->document(), SIGNAL(contentsChanged()),
61 //                      this, SLOT(documentWasModified()));
62
63 //      setCurrentFile("");
64         setUnifiedTitleAndToolBarOnMac(true);
65
66 //      ((TTEdit *)qApp)->charWnd->show();//eh?
67         Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
68 }
69
70 void ApplicationWindow::closeEvent(QCloseEvent * event)
71 {
72         WriteSettings();
73         event->accept();                                                        // Use ignore() if can't close for some reason
74         //Do we have a memory leak here if we don't delete the font in the Object???
75 }
76
77 //void ApplicationWindow::FileOpen(void)
78 //{
79 //}
80
81 void ApplicationWindow::FixAngle(void)
82 {
83         Object::SetFixedAngle(fixAngleAct->isChecked());
84 }
85
86 void ApplicationWindow::FixLength(void)
87 {
88         Object::SetFixedLength(fixLengthAct->isChecked());
89 }
90
91 void ApplicationWindow::DeleteTool(void)
92 {
93         Object::SetDeleteActive(deleteAct->isChecked());
94 }
95
96 void ApplicationWindow::DimensionTool(void)
97 {
98         Object::SetDimensionActive(addDimensionAct->isChecked());
99 }
100
101 void ApplicationWindow::RotateTool(void)
102 {
103         drawing->SetRotateToolActive(rotateAct->isChecked());
104 }
105
106 void ApplicationWindow::AddLineTool(void)
107 {
108         addCircleAct->setChecked(false);
109         addArcAct->setChecked(false);
110         rotateAct->setChecked(false);
111         RotateTool();
112         drawing->SetAddLineToolActive(addLineAct->isChecked());
113 }
114
115 void ApplicationWindow::ZoomInTool(void)
116 {
117         double zoomFactor = 2.0;
118 /*
119 We need to find the center of the screen, then figure out where the new corner
120 will be in the zoomed in window.
121
122 So we know in Qt coords, the center is found via:
123 size.width()  / 2 --> xCenter
124 size.height() / 2 --> yCenter
125
126 transform x/yCenter to Cartesian coordinates. So far, so good.
127
128 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
129 (after subtracting from center, that is...)
130 */
131         QSize size = drawing->size();
132         Vector center(size.width() / 2.0, size.height() / 2.0);
133 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
134         center = Painter::QtToCartesianCoords(center);
135 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
136         Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
137 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
138         Painter::origin = newOrigin;
139
140 //printf("Zoom in... level going from %02f to ", Painter::zoom);
141         // This just zooms leaving origin intact... should zoom in at the current center! [DONE]
142         Painter::zoom *= zoomFactor;
143         drawing->update();
144 }
145
146 void ApplicationWindow::ZoomOutTool(void)
147 {
148 /*
149 Ok, real example.
150 center = (436, 311)
151 origin = (223, 160.5)
152 newOrigin should be (-10, -10)
153 Why isn't it?
154
155 center - origin = (213, 150.5)
156 origin - center = (-213, -150.5)
157 x 2 = (-426, -301)
158 + center = (-10, -10)
159
160 */
161         double zoomFactor = 2.0;
162         QSize size = drawing->size();
163         Vector center(size.width() / 2.0, size.height() / 2.0);
164 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
165         center = Painter::QtToCartesianCoords(center);
166 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
167 //      Vector newOrigin = (center - Painter::origin) * zoomFactor;
168 //      Vector newOrigin = center - (Painter::origin * zoomFactor);
169         Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
170 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
171         Painter::origin = newOrigin;
172 //printf("Zoom out...\n");
173         // This just zooms leaving origin intact... should zoom out at the current center! [DONE]
174         Painter::zoom /= zoomFactor;
175         drawing->update();
176 }
177
178 void ApplicationWindow::HelpAbout(void)
179 {
180         aboutWin->show();
181 }
182
183 void ApplicationWindow::Settings(void)
184 {
185         SettingsDialog dlg(this);
186         dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
187
188         if (dlg.exec() == false)
189                 return;
190
191         // Deal with stuff here (since user hit "OK" button...)
192         drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
193         WriteSettings();
194 }
195
196 void ApplicationWindow::CreateActions(void)
197 {
198         exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
199                 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
200         connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
201
202         fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
203                 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
204         connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
205
206         fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
207                 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
208         connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
209
210         deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/generic-tool.png"), QKeySequence(), true);
211         connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
212
213         addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
214         connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
215
216         addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/generic-tool.png"), QKeySequence("A,L"), true);
217         connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
218
219         addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/generic-tool.png"), QKeySequence("A,C"), true);
220
221         addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/generic-tool.png"), QKeySequence("A,A"), true);
222
223         aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
224         connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
225
226         rotateAct = CreateAction(tr("&Rotate Objects"), tr("Rotate"), tr("Rotate object(s) around an arbitrary center."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("R,O")), true);
227         connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
228
229         zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
230         connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
231
232         zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
233         connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
234
235         fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n")));
236
237         fileOpenAct = CreateAction(tr("&Open Drawing"), tr("Open Drawing"), tr("Opens an existing drawing from a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+o")));
238
239         fileSaveAct = CreateAction(tr("&Save Drawing"), tr("Save Drawing"), tr("Saves the current drawing to a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+s")));
240
241         fileSaveAsAct = CreateAction(tr("Save Drawing &As"), tr("Save As"), tr("Saves the current drawing to a file with a different name."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+Shift+s")));
242
243         fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w")));
244
245         settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence());
246         connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
247
248 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
249 /*      QActionGroup * group = new QActionGroup(this);
250         group->addAction(deleteAct);
251         group->addAction(addDimensionAct);
252         group->addAction(addLineAct);
253         group->addAction(addCircleAct);
254         group->addAction(addArcAct);//*/
255 }
256
257 //
258 // Consolidates action creation from a multi-step process to a single-step one.
259 //
260 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
261         QIcon icon, QKeySequence key, bool checkable/*= false*/)
262 {
263         QAction * action = new QAction(icon, name, this);
264         action->setToolTip(tooltip);
265         action->setStatusTip(statustip);
266         action->setShortcut(key);
267         action->setCheckable(checkable);
268
269         return action;
270 }
271
272 //
273 // This is essentially the same as the previous function, but this allows more
274 // than one key sequence to be added as key shortcuts.
275 //
276 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
277         QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
278 {
279         QAction * action = new QAction(icon, name, this);
280         action->setToolTip(tooltip);
281         action->setStatusTip(statustip);
282         QList<QKeySequence> keyList;
283         keyList.append(key1);
284         keyList.append(key2);
285         action->setShortcuts(keyList);
286         action->setCheckable(checkable);
287
288         return action;
289 }
290
291 void ApplicationWindow::CreateMenus(void)
292 {
293         QMenu * menu = menuBar()->addMenu(tr("&File"));
294         menu->addAction(fileNewAct);
295         menu->addAction(fileOpenAct);
296         menu->addAction(fileSaveAct);
297         menu->addAction(fileSaveAsAct);
298         menu->addAction(fileCloseAct);
299         menu->addSeparator();
300         menu->addAction(exitAct);
301
302         menu = menuBar()->addMenu(tr("&View"));
303         menu->addAction(zoomInAct);
304         menu->addAction(zoomOutAct);
305
306         menu = menuBar()->addMenu(tr("&Edit"));
307         menu->addAction(fixAngleAct);
308         menu->addAction(fixLengthAct);
309         menu->addAction(rotateAct);
310         menu->addSeparator();
311         menu->addAction(deleteAct);
312         menu->addSeparator();
313         menu->addAction(addLineAct);
314         menu->addAction(addCircleAct);
315         menu->addAction(addArcAct);
316         menu->addAction(addDimensionAct);
317         menu->addSeparator();
318         menu->addAction(settingsAct);
319
320         menu = menuBar()->addMenu(tr("&Help"));
321         menu->addAction(aboutAct);
322 }
323
324 void ApplicationWindow::CreateToolbars(void)
325 {
326         QToolBar * toolbar = addToolBar(tr("File"));
327         toolbar->addAction(exitAct);
328
329         toolbar = addToolBar(tr("View"));
330         toolbar->addAction(zoomInAct);
331         toolbar->addAction(zoomOutAct);
332
333         toolbar = addToolBar(tr("Edit"));
334         toolbar->addAction(fixAngleAct);
335         toolbar->addAction(fixLengthAct);
336         toolbar->addAction(rotateAct);
337         toolbar->addAction(deleteAct);
338         toolbar->addAction(addLineAct);
339         toolbar->addAction(addCircleAct);
340         toolbar->addAction(addArcAct);
341         toolbar->addAction(addDimensionAct);
342 }
343
344 void ApplicationWindow::ReadSettings(void)
345 {
346         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
347         QSize size = settings.value("size", QSize(400, 400)).toSize();
348         drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
349         resize(size);
350         move(pos);
351 //      pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
352 //      size = settings.value("charWndSize", QSize(200, 200)).toSize();
353 //      ((TTEdit *)qApp)->charWnd->resize(size);
354 //      ((TTEdit *)qApp)->charWnd->move(pos);
355 }
356
357 void ApplicationWindow::WriteSettings(void)
358 {
359         settings.setValue("pos", pos());
360         settings.setValue("size", size());
361         settings.setValue("useAntialiasing", drawing->useAntialiasing);
362 //      settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
363 //      settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
364 }