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