]> Shamusworld >> Repos - architektonas/blob - src/applicationwindow.cpp
36c256fb588fb789a7d968f39c84da871c34d8f0
[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 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 // We want certain tools to be exclusive, and this approach isn't working correctly...
92 void ApplicationWindow::DeleteTool(void)
93 {
94         
95         ClearUIToolStatesExcept(deleteAct);
96         SetInternalToolStates();
97 }
98
99 void ApplicationWindow::DimensionTool(void)
100 {
101         ClearUIToolStatesExcept(addDimensionAct);
102         SetInternalToolStates();
103 }
104
105 void ApplicationWindow::RotateTool(void)
106 {
107         ClearUIToolStatesExcept(rotateAct);
108         SetInternalToolStates();
109 }
110
111 void ApplicationWindow::AddLineTool(void)
112 {
113         ClearUIToolStatesExcept(addLineAct);
114         SetInternalToolStates();
115 }
116
117 void ApplicationWindow::AddCircleTool(void)
118 {
119         ClearUIToolStatesExcept(addCircleAct);
120         SetInternalToolStates();
121 }
122
123 void ApplicationWindow::ZoomInTool(void)
124 {
125         double zoomFactor = 2.0;
126 /*
127 We need to find the center of the screen, then figure out where the new corner
128 will be in the zoomed in window.
129
130 So we know in Qt coords, the center is found via:
131 size.width()  / 2 --> xCenter
132 size.height() / 2 --> yCenter
133
134 transform x/yCenter to Cartesian coordinates. So far, so good.
135
136 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
137 (after subtracting from center, that is...)
138 */
139         QSize size = drawing->size();
140         Vector center(size.width() / 2.0, size.height() / 2.0);
141 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
142         center = Painter::QtToCartesianCoords(center);
143 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
144         Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
145 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
146         Painter::origin = newOrigin;
147
148 //printf("Zoom in... level going from %02f to ", Painter::zoom);
149         // This just zooms leaving origin intact... should zoom in at the current center! [DONE]
150         Painter::zoom *= zoomFactor;
151         drawing->update();
152 }
153
154 void ApplicationWindow::ZoomOutTool(void)
155 {
156 /*
157 Ok, real example.
158 center = (436, 311)
159 origin = (223, 160.5)
160 newOrigin should be (-10, -10)
161 Why isn't it?
162
163 center - origin = (213, 150.5)
164 origin - center = (-213, -150.5)
165 x 2 = (-426, -301)
166 + center = (-10, -10)
167
168 */
169         double zoomFactor = 2.0;
170         QSize size = drawing->size();
171         Vector center(size.width() / 2.0, size.height() / 2.0);
172 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
173         center = Painter::QtToCartesianCoords(center);
174 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
175 //      Vector newOrigin = (center - Painter::origin) * zoomFactor;
176 //      Vector newOrigin = center - (Painter::origin * zoomFactor);
177         Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
178 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
179         Painter::origin = newOrigin;
180 //printf("Zoom out...\n");
181         // This just zooms leaving origin intact... should zoom out at the current center! [DONE]
182         Painter::zoom /= zoomFactor;
183         drawing->update();
184 }
185
186 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
187 {
188         if (exception != addArcAct)
189                 addArcAct->setChecked(false);
190
191         if (exception != addCircleAct)
192                 addCircleAct->setChecked(false);
193
194         if (exception != addDimensionAct)
195                 addDimensionAct->setChecked(false);
196
197         if (exception != addLineAct)
198                 addLineAct->setChecked(false);
199
200         if (exception != addPolygonAct)
201                 addPolygonAct->setChecked(false);
202
203         if (exception != deleteAct)
204                 deleteAct->setChecked(false);
205
206         if (exception != rotateAct)
207                 rotateAct->setChecked(false);
208 }
209
210 void ApplicationWindow::SetInternalToolStates(void)
211 {
212         Object::SetDeleteActive(deleteAct->isChecked());
213         Object::SetDimensionActive(addDimensionAct->isChecked());
214         drawing->SetRotateToolActive(rotateAct->isChecked());
215         drawing->SetAddLineToolActive(addLineAct->isChecked());
216         drawing->SetAddCircleToolActive(addCircleAct->isChecked());
217 }
218
219 void ApplicationWindow::HelpAbout(void)
220 {
221         aboutWin->show();
222 }
223
224 void ApplicationWindow::Settings(void)
225 {
226         SettingsDialog dlg(this);
227         dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
228
229         if (dlg.exec() == false)
230                 return;
231
232         // Deal with stuff here (since user hit "OK" button...)
233         drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
234         WriteSettings();
235 }
236
237 void ApplicationWindow::CreateActions(void)
238 {
239         exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
240                 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
241         connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
242
243         fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
244                 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
245         connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
246
247         fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
248                 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
249         connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
250
251         deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(), true);
252         connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
253
254         addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
255         connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
256
257         addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
258         connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
259
260         addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
261         connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
262
263         addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
264
265         addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
266
267         aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
268         connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
269
270         rotateAct = CreateAction(tr("&Rotate Objects"), tr("Rotate"), tr("Rotate object(s) around an arbitrary center."), QIcon(":/res/rotate-tool.png"), QKeySequence(tr("R,O")), true);
271         connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
272
273         zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
274         connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
275
276         zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
277         connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
278
279         fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n")));
280
281         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")));
282
283         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")));
284
285         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")));
286
287         fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w")));
288
289         settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence());
290         connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
291
292 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
293 /*      QActionGroup * group = new QActionGroup(this);
294         group->addAction(deleteAct);
295         group->addAction(addDimensionAct);
296         group->addAction(addLineAct);
297         group->addAction(addCircleAct);
298         group->addAction(addArcAct);//*/
299 }
300
301 //
302 // Consolidates action creation from a multi-step process to a single-step one.
303 //
304 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
305         QIcon icon, QKeySequence key, bool checkable/*= false*/)
306 {
307         QAction * action = new QAction(icon, name, this);
308         action->setToolTip(tooltip);
309         action->setStatusTip(statustip);
310         action->setShortcut(key);
311         action->setCheckable(checkable);
312
313         return action;
314 }
315
316 //
317 // This is essentially the same as the previous function, but this allows more
318 // than one key sequence to be added as key shortcuts.
319 //
320 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
321         QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
322 {
323         QAction * action = new QAction(icon, name, this);
324         action->setToolTip(tooltip);
325         action->setStatusTip(statustip);
326         QList<QKeySequence> keyList;
327         keyList.append(key1);
328         keyList.append(key2);
329         action->setShortcuts(keyList);
330         action->setCheckable(checkable);
331
332         return action;
333 }
334
335 void ApplicationWindow::CreateMenus(void)
336 {
337         QMenu * menu = menuBar()->addMenu(tr("&File"));
338         menu->addAction(fileNewAct);
339         menu->addAction(fileOpenAct);
340         menu->addAction(fileSaveAct);
341         menu->addAction(fileSaveAsAct);
342         menu->addAction(fileCloseAct);
343         menu->addSeparator();
344         menu->addAction(exitAct);
345
346         menu = menuBar()->addMenu(tr("&View"));
347         menu->addAction(zoomInAct);
348         menu->addAction(zoomOutAct);
349
350         menu = menuBar()->addMenu(tr("&Edit"));
351         menu->addAction(fixAngleAct);
352         menu->addAction(fixLengthAct);
353         menu->addAction(rotateAct);
354         menu->addSeparator();
355         menu->addAction(deleteAct);
356         menu->addSeparator();
357         menu->addAction(addLineAct);
358         menu->addAction(addCircleAct);
359         menu->addAction(addArcAct);
360         menu->addAction(addPolygonAct);
361         menu->addAction(addDimensionAct);
362         menu->addSeparator();
363         menu->addAction(settingsAct);
364
365         menu = menuBar()->addMenu(tr("&Help"));
366         menu->addAction(aboutAct);
367 }
368
369 void ApplicationWindow::CreateToolbars(void)
370 {
371         QToolBar * toolbar = addToolBar(tr("File"));
372         toolbar->addAction(exitAct);
373
374         toolbar = addToolBar(tr("View"));
375         toolbar->addAction(zoomInAct);
376         toolbar->addAction(zoomOutAct);
377
378         toolbar = addToolBar(tr("Edit"));
379         toolbar->addAction(fixAngleAct);
380         toolbar->addAction(fixLengthAct);
381         toolbar->addAction(rotateAct);
382         toolbar->addAction(deleteAct);
383         toolbar->addAction(addLineAct);
384         toolbar->addAction(addCircleAct);
385         toolbar->addAction(addArcAct);
386         toolbar->addAction(addPolygonAct);
387         toolbar->addAction(addDimensionAct);
388 }
389
390 void ApplicationWindow::ReadSettings(void)
391 {
392         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
393         QSize size = settings.value("size", QSize(400, 400)).toSize();
394         drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
395         resize(size);
396         move(pos);
397 //      pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
398 //      size = settings.value("charWndSize", QSize(200, 200)).toSize();
399 //      ((TTEdit *)qApp)->charWnd->resize(size);
400 //      ((TTEdit *)qApp)->charWnd->move(pos);
401 }
402
403 void ApplicationWindow::WriteSettings(void)
404 {
405         settings.setValue("pos", pos());
406         settings.setValue("size", size());
407         settings.setValue("useAntialiasing", drawing->useAntialiasing);
408 //      settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
409 //      settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
410 }