![]() |
PortableGUI |
Hosted by SourceForge Project page |
// Import all PortableGUI include files
#include <portablegui.h>
// Blocksize for load/save operations
#define BLOCKSIZE 4000
// Text field for editing
PGTextArea* g_textArea;
// Main frame window
PGFrame* g_mainFrame;
// Filter for filenames
char* g_sFilter = "Text files (*.txt)$*.txt$All files (*.*)$*.*$";
// File already named?
BOOL g_bHasName = FALSE;
PGString g_sFile;
// Image for about box
PGImage* g_imageAbout;
// Icon for Win/GNOME taskbar
PGIcon* g_icon;
// Forward declarations for new, open and save methods
BOOL doNew();
BOOL doOpen();
BOOL doSave(BOOL verifyOverwrite);
// Update the window title bar
void UpdateTitle();
// Called when user tries to close the main window
class MyWindowListener : public PGWindowListener {
virtual void windowClosing(PGWindow* wnd) {
// Exit the application
getPGApplication()->exit(0);
}
};
// Called when user selects File | Exit
class MyExitListener : public PGActionListener {
// Exit the application
virtual void actionPerformed(PGCallback* from) {
getPGApplication()->exit(0);
}
};
// Called when user selects File | New
class MyNewListener : public PGActionListener {
// Call doNew and update windows title
virtual void actionPerformed(PGCallback* from) {
if (doNew()) g_bHasName = FALSE;
UpdateTitle();
}
};
// Called when user selects File | Open
class MyOpenListener : public PGActionListener {
// Open file
virtual void actionPerformed(PGCallback* from) {
// Create file open dialog
PGFileDialog dial("Open");
dial.setFilter(g_sFilter);
if (g_bHasName) dial.setFile(g_sFile.getValue());
// Display file open dialog
if (dial.showFileOpenDialog(g_mainFrame)) {
g_sFile.setCopyValue(dial.m_sFile.getValue());
g_bHasName = doOpen();
UpdateTitle();
}
}
};
// Called when user selects File | Save
class MySaveListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
if (!g_bHasName) {
// Create file dialog if file has no name yet
PGFileDialog dial("Save");
dial.setFilter(g_sFilter);
// Display file dialog
if (dial.showFileSaveDialog(g_mainFrame)) {
g_sFile.setCopyValue(dial.m_sFile.getValue());
} else {
return;
}
}
// Save file and update window title
g_bHasName = doSave(FALSE);
UpdateTitle();
}
};
// Called when user selects File | Save As
class MySaveAsListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
// Create save as file dialog
PGFileDialog dial("Save As");
dial.setFilter(g_sFilter);
if (g_bHasName) dial.setFile(g_sFile.getValue());
// Display dialog, save and update title
if (dial.showFileSaveDialog(g_mainFrame)) {
g_sFile.setCopyValue(dial.m_sFile.getValue());
g_bHasName = doSave(TRUE);
UpdateTitle();
}
}
};
// Does GtkText support undo?
#ifdef PGWIN
// Called when user selects File | Undo
class MyUndoListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
g_textArea->undoOperation();
}
};
#endif
// Called when user selects Edit | Cut
class MyCutListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
g_textArea->cut();
}
};
// Called when user selects Edit | Copy
class MyCopyListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
g_textArea->copy();
}
};
// Called when user selects Edit | Paste
class MyPasteListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
g_textArea->paste();
}
};
// Called when user selects Edit | Select All
class MySelectAllListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
g_textArea->selectAll();
}
};
// Called when user tries to close the about window
class AboutWindowListener : public PGWindowListener {
virtual void windowClosing(PGWindow* wnd) {
wnd->dispose();
}
};
// Called when user clicks 'Close' button
class MyWindowCloseListener : public PGActionListener {
private:
PGWindow* m_Window;
public:
MyWindowCloseListener(PGWindow* window) {
m_Window = window;
}
virtual void actionPerformed(PGCallback* from) {
m_Window->dispose();
}
};
// Called when user selects Help | About
class MyAboutListener : public PGActionListener {
virtual void actionPerformed(PGCallback* from) {
// Create a new style (used for the about label)
PGStyle* style = new PGStyle();
style->setFont(new PGFont("", PGFONT_BOLD | PGFONT_ITALIC, 16));
// Create about dialog
PGDialog about(g_mainFrame, "About EditPad");
about.setIconImage(g_icon);
about.addWindowListener(new AboutWindowListener());
/***
* Percentlayout
* Component 1 : pl = Preferred size, Left justify
* 2 : 20d = Dummy component size 20 pixels
* 3 : 100% = 100% Stretch of leftover space
* 5 : pc = Preferred size, Center justify
*/
about.setLayout(new PGPercentLayout("pl 5d 100% 5d pl pl 10d pc", 3, PGPERCENTLAYOUT_ALL, TRUE));
// Create about label with large font style style
PGLabel* label = new PGLabel("PortableGUI - EditPad demo");
label->setStyle(style);
about.add(label);
// Create image viewer and some other labels
about.add(new PGImageViewer(g_imageAbout));
about.add(new PGLabel("Written by Jan Struyf"));
about.add(new PGLabel("jan.struyf@cs.kuleuven.ac.be"));
// Create and add close button
PGButton* ok = new PGButton(" &Close ", TRUE);
ok->addActionListener(new MyWindowCloseListener(&about));
about.add(ok);
// Pack components in window and show modal
about.pack();
about.doModal();
}
};
// Update window title bar
void UpdateTitle() {
PGString myTitle;
myTitle.setCopyValue(g_sFile.getValue());
// Check if filename too long
int len = myTitle.getLength();
if (len > 18) {
myTitle.substring(len-18, len);
myTitle.prepend("EditPad - ..");
} else {
myTitle.prepend("EditPad - ");
}
// Set the filename in the title bar
g_mainFrame->setTitle(myTitle.getValue());
}
// Clear text component
BOOL doNew() {
g_textArea->setText("");
return TRUE;
}
// Save file to disk
BOOL doSave(BOOL verifyOverwrite) {
if (verifyOverwrite) {
// Check if file exists
PGFileInputStream input(g_sFile.getValue());
if (input.getError() == PGINPUTSTREAM_ERROR_NONE) {
// File already exists, show message box
input.close();
PGMessageBox box("Save file","File already exists, overwrite?",PGMSGBOX_YES | PGMSGBOX_NO | PGMSGBOX_ICONQUESTION);
if (box.show(g_mainFrame) != PGMSGBOX_YES) return FALSE;
}
}
// Try to open file for output
PGFileOutputStream output(g_sFile.getValue());
if (output.getError() != PGOUTPUTSTREAM_ERROR_NONE) {
// Can't open file, show message box
PGMessageBox box("Save file","Can't create file",PGMSGBOX_OK | PGMSGBOX_ICONERROR);
box.show(g_mainFrame);
return FALSE;
}
// Copy contents of textarea to file
PGString str;
long tot = 0;
// Don't update text component each block (works in GTK only)
g_textArea->setDirectUpdate(FALSE);
long len = g_textArea->getSize();
// Block max size is BLOCKSIZE
do {
// Calculate size for next block
long now = MIN2(BLOCKSIZE, len-tot);
// Get text block from text area and write to disk
g_textArea->getText(&str, tot, tot+now);
int nb = output.write((unsigned char*)str.getValue(), 0, now);
// Maybe out of quota? disk full?
if (nb != (int)now) {
output.close();
PGMessageBox box("Save file","Disk full",PGMSGBOX_OK | PGMSGBOX_ICONERROR);
box.show(g_mainFrame);
return FALSE;
}
tot += now;
} while (tot < len);
g_textArea->setDirectUpdate(TRUE);
// Close file and return true
output.close();
return TRUE;
}
// Load file from disk
BOOL doOpen() {
if (!doNew()) return FALSE;
// Try to open file
PGFileInputStream input(g_sFile.getValue());
if (input.getError() != PGINPUTSTREAM_ERROR_NONE) {
// Can't open file, display message box
PGMessageBox box("Open file","File not found",PGMSGBOX_OK | PGMSGBOX_ICONERROR);
box.show(g_mainFrame);
return FALSE;
}
long tot = 0;
size_t nb = 0;
// Don't update text component each block (works in GTK only)
g_textArea->setDirectUpdate(FALSE);
PGString str;
str.allocateNew(BLOCKSIZE+1);
do {
// Read in next block
nb = input.read((unsigned char*)str.getValue(), 0, BLOCKSIZE);
str.substring(0, nb-1);
tot += nb;
// Append block to text area
g_textArea->append(str.getValue(), FALSE);
} while (nb == BLOCKSIZE);
g_textArea->setDirectUpdate(TRUE);
input.close();
#ifdef PGWIN
// Maximum size for edit in windows
// So, for a serious edit app, you have to write your own edit component
if (tot > 32000) {
PGMessageBox box("Open file","File too large for editor",PGMSGBOX_OK | PGMSGBOX_ICONERROR);
box.show(g_mainFrame);
return FALSE;
}
#endif
return TRUE;
}
// Create the main menu
PGMenuBar* makeMenu() {
PGMenuBar* bar= new PGMenuBar();
// Create file menu
PGMenu* menu = new PGMenu("&File");
PGMenuItem* item = new PGMenuItem("&New");
item->addActionListener(new MyNewListener());
menu->add(item);
item = new PGMenuItem("&Open");
item->addActionListener(new MyOpenListener());
menu->add(item);
item = new PGMenuItem("&Close");
menu->add(item);
menu->add(new PGMenuSeparator());
item = new PGMenuItem("&Save");
item->addActionListener(new MySaveListener());
menu->add(item);
item = new PGMenuItem("Save &As");
item->addActionListener(new MySaveAsListener());
menu->add(item);
menu->add(new PGMenuSeparator());
item = new PGMenuItem("&Exit");
item->addActionListener(new MyExitListener());
menu->add(item);
bar->add(menu);
// Create edit menu
menu = new PGMenu("&Edit");
#ifdef PGWIN
item = new PGMenuItem("&Undo");
item->addActionListener(new MyUndoListener());
menu->add(item);
menu->add(new PGMenuSeparator());
#endif
item = new PGMenuItem("Cu&t");
item->addActionListener(new MyCutListener());
menu->add(item);
item = new PGMenuItem("&Copy");
item->addActionListener(new MyCopyListener());
menu->add(item);
item = new PGMenuItem("&Paste");
item->addActionListener(new MyPasteListener());
menu->add(item);
item = new PGMenuItem("Select A&ll");
item->addActionListener(new MySelectAllListener());
menu->add(item);
bar->add(menu);
// Create help menu
menu = new PGMenu("&Help");
item = new PGMenuItem("&About");
item->addActionListener(new MyAboutListener());
menu->add(item);
bar->add(menu);
return bar;
}
// Mainproc is different for Windows and GTK
PGMAINPROC {
PGApplication app;
// Initialize the app using Mainproc args
PGINIT(app);
// Create main frame window
g_mainFrame = new PGFrame("EditPad");
PGINCREF(g_mainFrame);
// Load about pixmap (BMP fileformat 4 or 8 bits/pixel)
g_imageAbout = new PGImage("../about.bmp", g_mainFrame);
PGINCREF(g_imageAbout);
// Load icon for main window
PGColor background(178,178,180);
g_icon = new PGIcon(new PGImage("../icon.bmp", &background, g_mainFrame));
g_mainFrame->setIconImage(g_icon);
// Add window listener to frame
g_mainFrame->addWindowListener(new MyWindowListener());
// Use simple layoutmanager for the edit control
g_mainFrame->setLayout(new PGBorderLayout(2,2,0,0));
// Create main menu and add menu bar
g_mainFrame->setMenuBar(makeMenu());
// Add text area for editing
g_textArea = new PGTextArea("", 30, 40, PGTEXTAREA_SCROLLBARS_VERTICAL_ONLY);
PGINCREF(g_textArea);
g_mainFrame->add(g_textArea, PGBORDERLAYOUT_CENTER);
// Pack and show the frame
g_mainFrame->pack();
g_mainFrame->setVisible(TRUE);
// Run the main event loop
PGEXITCODE exitCode = app.run();
// Free global references
PGDECREF(g_textArea);
PGDECREF(g_mainFrame);
PGDECREF(g_imageAbout);
return exitCode;
}
| Syntax highlighted by Code2HTML, v. 0.8.8 |
Back to PortableGUI