]> Shamusworld >> Repos - ttedit/blob - src/mainwindow.cpp
Minor fixes to polygon adding, added Tau constants to math package.
[ttedit] / src / mainwindow.cpp
1 //
2 // MAINWINDOW.CPP - The TrueType Editor
3 // by James L. Hammons
4 // (C) 2004 Underground Software
5 //
6 // JLH = James L. Hammons <jlhamm@acm.org>
7 //
8 // Who  When        What
9 // ---  ----------  -----------------------------------------------------------
10 // JLH  04/10/2002  Created this file
11 // JLH  05/10/2004  Translated file from ASM to CPP
12 // JLH  05/14/2004  Added rudimentary editing capability to tool palette tools
13 // JLH  11/18/2006  Initial port to Linux
14 // JLH  08/27/2008  Fixed tool palette focus problems
15 // JLH  08/28/2008  Split out classes defined here into separate files
16 // JLH  03/05/2009  Initial conversion from wxWidgets to Qt
17 //
18
19 // FIXED:
20 //
21 // - Fix problem with tool palette not getting focus 1st time it's called up
22 //   [DONE]
23 // - Split out windows/classes defined here into their own files [DONE]
24 //
25 // STILL TO BE DONE:
26 //
27 // - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font
28 // - Fix scrolling, zooming, settings (ini)
29 // - Fix problem with character window disappearing when bringing up the tool
30 //   palette
31 //
32
33 // Uncomment this for debugging...
34 #define DEBUG
35 #define DEBUGFOO                        // Various tool debugging...
36 //#define DEBUGTP                               // Toolpalette debugging...
37
38 #include "mainwindow.h"
39 #include "charwindow.h"
40 #include "editwindow.h"
41 #include "global.h"
42 #include "ttedit.h"
43
44
45 MainWindow::MainWindow()
46 {
47         ((TTEdit *)qApp)->charWnd = new CharWindow(this);
48         editWnd = new EditWindow(this);
49         setCentralWidget(editWnd);
50         editWnd->setFocus();
51         setWindowIcon(QIcon(":/res/ttedit.png"));
52         setWindowTitle("TTEdit! - Untitled");
53
54 #if 0
55 //      createActions();
56         newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
57         newAct->setShortcuts(QKeySequence::New);
58         newAct->setStatusTip(tr("Create a new file"));
59         connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
60
61         openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
62         openAct->setShortcuts(QKeySequence::Open);
63         openAct->setStatusTip(tr("Open an existing file"));
64         connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
65
66         aboutQtAct = new QAction(tr("About &Qt"), this);
67         aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
68         connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
69
70 //      createMenus();
71         fileMenu = menuBar()->addMenu(tr("&File"));
72         fileMenu->addAction(newAct);
73         fileMenu->addAction(openAct);
74         fileMenu->addAction(saveAct);
75         fileMenu->addAction(saveAsAct);
76         fileMenu->addSeparator();
77         fileMenu->addAction(exitAct);
78
79         editMenu = menuBar()->addMenu(tr("&Edit"));
80         editMenu->addAction(cutAct);
81         editMenu->addAction(copyAct);
82         editMenu->addAction(pasteAct);
83
84         menuBar()->addSeparator();
85
86         helpMenu = menuBar()->addMenu(tr("&Help"));
87         helpMenu->addAction(aboutAct);
88         helpMenu->addAction(aboutQtAct);
89
90 //      createToolBars();
91         fileToolBar = addToolBar(tr("File"));
92         fileToolBar->addAction(newAct);
93         fileToolBar->addAction(openAct);
94         fileToolBar->addAction(saveAct);
95
96         editToolBar = addToolBar(tr("Edit"));
97         editToolBar->addAction(cutAct);
98         editToolBar->addAction(copyAct);
99         editToolBar->addAction(pasteAct);
100 #else
101         CreateActions();
102         CreateMenus();
103         CreateToolbars();
104 #endif
105
106         //      Create status bar
107         scaleIndicator = new QLabel("Scale: 100%");
108         statusBar()->addPermanentWidget(scaleIndicator);
109         statusBar()->showMessage(tr("Ready"));
110
111         ReadSettings();
112
113 //      connect(textEdit->document(), SIGNAL(contentsChanged()),
114 //                      this, SLOT(documentWasModified()));
115
116 //      setCurrentFile("");
117         setUnifiedTitleAndToolBarOnMac(true);
118
119         ((TTEdit *)qApp)->charWnd->show();//eh?
120 }
121
122
123 //
124 // Consolidates action creation from a multi-step process to a single-step one.
125 //
126 QAction * MainWindow::CreateAction(QString name, QString tooltip, QString
127         statustip, QIcon icon, QKeySequence key, bool checkable/*= false*/)
128 {
129         QAction * action = new QAction(icon, name, this);
130         action->setToolTip(tooltip);
131         action->setStatusTip(statustip);
132         action->setShortcut(key);
133         action->setCheckable(checkable);
134
135         return action;
136 }
137
138
139 //
140 // This is essentially the same as the previous function, but this allows more
141 // than one key sequence to be added as key shortcuts.
142 //
143 QAction * MainWindow::CreateAction(QString name, QString tooltip, QString
144         statustip, QIcon icon, QKeySequence key1, QKeySequence key2, bool
145         checkable/*= false*/)
146 {
147         QAction * action = new QAction(icon, name, this);
148         action->setToolTip(tooltip);
149         action->setStatusTip(statustip);
150         QList<QKeySequence> keyList;
151         keyList.append(key1);
152         keyList.append(key2);
153         action->setShortcuts(keyList);
154         action->setCheckable(checkable);
155
156         return action;
157 }
158
159
160 void MainWindow::CreateActions(void)
161 {
162         newGlyphAct = CreateAction("&New Glyph", "New Glyph", "Create a new glyph", QIcon(), QKeySequence());
163         openFileAct = CreateAction("&Open File", "Open File", "Open a glyph file", QIcon(), QKeySequence("ctrl+o"));
164         saveFileAct = CreateAction("&Save File", "Save File", "Save a glyph file", QIcon(), QKeySequence("ctrl+s"));
165         quitAct = CreateAction("&Quit", "Quit", "Exits from the TTEdit application", QIcon(), QKeySequence("ctrl+q"));
166         zoomInAct = CreateAction("Zoom In", "Zoom In", "Zoom into the canvas", QIcon(), QKeySequence("+"), QKeySequence("="));
167         zoomOutAct = CreateAction("Zoom Out", "Zoom Out", "Zoom out of the canvas", QIcon(), QKeySequence("-"));
168
169         connect(newGlyphAct, SIGNAL(triggered()), this, SLOT(NewGlyph()));
170         connect(openFileAct, SIGNAL(triggered()), this, SLOT(OpenFile()));
171         connect(saveFileAct, SIGNAL(triggered()), this, SLOT(SaveFile()));
172         connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
173         connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomIn()));
174         connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOut()));
175 }
176
177
178 void MainWindow::CreateMenus(void)
179 {
180         QMenu * menu = menuBar()->addMenu(tr("&File"));
181         menu->addAction(newGlyphAct);
182         menu->addAction(openFileAct);
183         menu->addAction(saveFileAct);
184         menu->addSeparator();
185         menu->addAction(quitAct);
186 //      menu->addAction(fileSaveAsAct);
187 //      menu->addAction(fileCloseAct);
188         menu = menuBar()->addMenu(tr("&View"));
189         menu->addAction(zoomInAct);
190         menu->addAction(zoomOutAct);
191 }
192
193
194 void MainWindow::CreateToolbars(void)
195 {
196 }
197
198
199 void MainWindow::closeEvent(QCloseEvent * event)
200 {
201         WriteSettings();
202         event->accept(); // ignore() if can't close for some reason
203 }
204
205
206 void MainWindow::NewGlyph(void)
207 {
208         editWnd->pts.Clear();
209         ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&(editWnd->pts));
210         ((TTEdit *)qApp)->charWnd->update();
211         filename.clear();
212 //      editWnd->polyFirstPoint = true;
213         editWnd->update();
214         setWindowTitle("TTEdit! - Untitled");
215         editWnd->setFocus();
216 }
217
218
219 void MainWindow::OpenFile(void)
220 {
221         filename = QFileDialog::getOpenFileName(this, tr("Open Glyph File"),
222                 "./", tr("Glyph files (*.glyph)"));
223         FILE * file = fopen(filename.toUtf8().data(), "r");
224
225         //need to pop an error box here...
226         if (file == 0)
227                 return;
228
229         editWnd->pts.LoadGlyphFromFile(file);
230         fclose(file);
231
232         ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&(editWnd->pts));
233         ((TTEdit *)qApp)->charWnd->update();
234         editWnd->update();
235         setWindowTitle(QString("TTEdit! - %1").arg(filename));
236         editWnd->setFocus();
237 }
238
239
240 void MainWindow::SaveFile(void)
241 {
242         if (filename.isEmpty())
243                 filename = QFileDialog::getSaveFileName(this, tr("Save Glyph File"),
244                 "./", tr("Glyph files (*.glyph)"));
245
246         FILE * file = fopen(filename.toUtf8().data(), "w");
247
248         //need to pop an error box here...
249         if (file == 0)
250                 return;
251
252         editWnd->pts.SaveGlyphToFile(file);
253         fclose(file);
254         setWindowTitle(QString("TTEdit! - %1").arg(filename));
255         statusBar()->showMessage(tr("File saved."));
256         editWnd->setFocus();
257 }
258
259
260 void MainWindow::ZoomIn(void)
261 {
262         if (Global::zoom == 4.0)
263                 return;
264
265         // Adjust the origin by the width/height by 1/4 (half of the scaled size).
266         // Also, need to adjust for the current zoom level...
267         Vector adjustment = (Global::screenSize / Global::zoom) * 0.25;
268         Global::origin += adjustment;
269
270         Global::zoom *= 2.0;
271
272         scaleIndicator->setText(QString("Scale: %1%").arg(Global::zoom * 100.0));
273         editWnd->update();
274 }
275
276
277 void MainWindow::ZoomOut(void)
278 {
279         if (Global::zoom == 0.25)
280                 return;
281
282         Global::zoom *= 0.5;
283
284         // Adjust the origin by the width/height by 1/4 (half of the scaled size).
285         // Also, need to adjust for the current zoom level...
286         Vector adjustment = (Global::screenSize / Global::zoom) * 0.25;
287         Global::origin -= adjustment;
288
289         scaleIndicator->setText(QString("Scale: %1%").arg(Global::zoom * 100.0));
290         editWnd->update();
291 }
292
293
294 void MainWindow::ReadSettings(void)
295 {
296         QSettings settings("Underground Software", "TTEdit");
297         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
298         QSize size = settings.value("size", QSize(400, 400)).toSize();
299         resize(size);
300         move(pos);
301         pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
302         size = settings.value("charWndSize", QSize(200, 200)).toSize();
303         ((TTEdit *)qApp)->charWnd->resize(size);
304         ((TTEdit *)qApp)->charWnd->move(pos);
305 }
306
307
308 void MainWindow::WriteSettings(void)
309 {
310         QSettings settings("Underground Software", "TTEdit");
311         settings.setValue("pos", pos());
312         settings.setValue("size", size());
313         settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
314         settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
315 }
316
317
318 #if 0
319
320
321 IMPLEMENT_APP(TTEditApp)                                                // Run the main application loop
322
323 bool TTEditApp::OnInit()
324 {
325         wxLog * logTarget = new wxLogStderr();//fopen("!ttedit_log.txt", "wb"));
326         wxLog::SetActiveTarget(logTarget);
327 #ifdef DEBUG
328         OpenDebugLog();
329 #endif
330
331         // Initialize all the top-level window members to NULL.
332         mainFrame = NULL;
333         charWin = NULL;
334         toolPalette = NULL;
335         for(int i=0; i<8; i++)
336                 cur[i] = NULL;
337
338 //Shouldn't we check to see if it was successful? This just assumes
339         CreateResources();
340
341         mainFrame = new TTEditFrame(NULL, _("TTEdit"), wxPoint(155, 165), wxSize(300, 300),
342                 wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE);
343 //              wxMINIMIZE_BOX | wxRESIZE_BOX | wxMAXIMIZE_BOX | | wxSYSTEM_MENU | wxCAPTION);
344
345 //      charWin = new CharWindow(NULL);//, _T("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize);
346         charWin = new CharWindow(mainFrame, _("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize,
347                 wxCAPTION | wxRESIZE_BORDER | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT);
348
349         toolPalette = new ToolWindow(mainFrame, _(""), wxDefaultPosition, wxDefaultSize,
350                 wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT);
351
352         return true;
353 }
354
355 int TTEditApp::OnExit()
356 {
357 #ifdef DEBUG
358         CloseDebugLog();
359 #endif
360         for(int i=0; i<8; i++)
361                 if (cur[i])
362                         delete cur[i];
363
364         return 0;
365 }
366
367 //
368 // OS dependent method of creating cursor (works for Win32 and GTK+)
369 //
370 #define CREATE_CURSOR(storage, name, hsx, hsy) \
371         wxBitmap name##_bitmap(name##_xpm); \
372         wxImage name##_image = name##_bitmap.ConvertToImage(); \
373         name##_image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, hsx); \
374         name##_image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, hsy); \
375         storage = new wxCursor(name##_image);
376
377 void TTEditApp::CreateResources(void)
378 {
379         // This is a sucky way to create cursors, but at least it's cross-platform...
380         // NOTE: Need to fix hotspots on a few... !!! FIX !!! [DONE]
381
382         CREATE_CURSOR(cur[0], cur1, 1, 1);
383         CREATE_CURSOR(cur[1], cur2, 1, 1);
384         CREATE_CURSOR(cur[2], cur3, 11, 11);    // Prolly won't need this soon (scroll)...
385         CREATE_CURSOR(cur[3], cur4, 15, 13);    // Prolly won't need this soon (zoom)...
386         CREATE_CURSOR(cur[4], cur5, 1, 1);
387         CREATE_CURSOR(cur[5], cur6, 1, 1);
388         CREATE_CURSOR(cur[6], cur7, 1, 1);
389         CREATE_CURSOR(cur[7], cur8, 1, 1);
390 }
391
392
393 BEGIN_EVENT_TABLE(TTEditFrame, wxFrame)
394         EVT_MENU(IDM_OPEN, TTEditFrame::OnOpen)
395         EVT_MENU(IDM_EXIT, TTEditFrame::OnExit)
396         EVT_MENU(IDM_ABOUT, TTEditFrame::OnAbout)
397         EVT_MENU(ID_TBCHARWIN, TTEditFrame::OnCharWindow)
398         EVT_CLOSE(TTEditFrame::OnCloseWindow)
399 END_EVENT_TABLE()
400
401 TTEditFrame::TTEditFrame(wxFrame * parent, const wxString &title, const wxPoint &pos,
402         const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style), app(wxGetApp()), mainWindow(NULL)
403 {
404         // Initialize child subwindow members (and hopefully avoid subtle bugs)
405 //      mainWindow = NULL;
406
407         SetIcon(wxICON(ttedit));
408 //      CreateStatusBar(2);                                                     // Create 2 panes
409         int widths[2] = { -1, 120 };
410         wxStatusBar * sb = CreateStatusBar(2, 0);       // Create 2 panes
411         sb->SetStatusWidths(2, widths);
412         wxToolBar * tb = CreateToolBar();
413
414         if (tb != NULL)
415         {
416                 // Create buttons
417
418                 wxBitmap tool1(tool1_xpm);
419                 wxBitmap tool2(tool2_xpm);
420                 wxBitmap tool3(tool3_xpm);
421
422                 tb->AddTool(ID_TBLEFT, _("Prev char"), tool1, _("Go to prev char"), wxITEM_NORMAL);
423                 tb->AddTool(ID_TBRIGHT, _("Next char"), tool2, _("Go to next char"), wxITEM_NORMAL);
424                 tb->AddTool(ID_TBCHARWIN, _("Char Wnd"), tool3, _("Toggle char window"), wxITEM_CHECK);
425                 tb->Realize();
426         }
427
428         // Create a menu bar for the frame
429         menuBar = new wxMenuBar;
430         wxMenu * menu1 = new wxMenu;
431         menu1->Append(IDM_NEW, _("&New\tCtrl+N"), _("Create a new font."));
432         menu1->Append(IDM_OPEN, _("&Open...\tCtrl+O"), _("Opens an existing font."));
433         menu1->Append(IDM_SAVE, _("&Save\tCtrl+S"), _("Save the current font."));
434         menu1->Append(IDM_SAVEAS, _("Save &As..."), _("Save the current font under a different name."));
435         menu1->AppendSeparator();
436         menu1->Append(IDM_EXIT, _("E&xit\tAlt+X"), _("Quits the TTEdit program."));
437         menuBar->Append(menu1, _("&File"));
438         wxMenu * menu2 = new wxMenu;
439         menu2->Append(IDM_HELPTOPICS, _("&Help Topics"), _("Displays the Help contents and index."));
440         menu2->AppendSeparator();
441         menu2->Append(IDM_ABOUT, _("&About TTEdit"), _("Displays information about TTEdit."));
442         menuBar->Append(menu2, _("&Help"));
443         SetMenuBar(menuBar);
444
445         // Create child subwindows
446         mainWindow = new TTEditWindow(this);
447
448         Centre(wxBOTH);                                                         // Centre frame on the screen
449         Show(true);                                                                     // Show the frame
450 }
451
452 TTEditFrame::~TTEditFrame()
453 {
454 }
455
456 void TTEditFrame::OnOpen(wxCommandEvent &e)
457 {
458         wxFileDialog fd(this, _("Choose a font to load"), _(""), _(""), _("TTF files (*.ttf)|*.ttf|All files (*.*)|*.*"), wxOPEN);
459
460         if (fd.ShowModal() != wxID_OK)
461             return;
462
463 // Hmm. The font object is causing a massive crash... (gdb says it's in "Load")
464         if (app.font.Load((char *)fd.GetPath().c_str()) != true)
465         {
466                 wxMessageDialog dlg(NULL, _("Load font failed!"), _("Houston, we have a problem..."), wxOK | wxICON_ERROR);
467                 dlg.ShowModal();
468         }
469
470 //Huzzah! It works! Now just need scaling, scrolling, etc...
471 //      pts = app.font.GetGlyphPoints(45);
472 }
473
474 void TTEditFrame::OnAbout(wxCommandEvent &e)
475 {
476         wxMessageDialog dlg(NULL, _("TrueType Edit v1.0.1\n\nA handy tool for editing TrueType fonts!\nby James \"Shamus\" Hammons\n(C) 2006 Underground Software"), _("About TrueType Edit"), wxOK | wxICON_INFORMATION);
477         dlg.ShowModal();
478 }
479
480 void TTEditFrame::OnExit(wxCommandEvent &e)
481 {
482         app.toolPalette->Destroy();
483         this->Destroy();
484 }
485
486 void TTEditFrame::OnCharWindow(wxCommandEvent &e)
487 {
488         app.charWin->Show(e.IsChecked() ? true : false);
489
490         if (e.IsChecked())
491                 Raise();
492 }
493
494 void TTEditFrame::OnCloseWindow(wxCloseEvent &e)
495 {
496         app.toolPalette->Destroy();
497         this->Destroy();
498 }
499 #endif