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