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