PHP Code:
<?php
// check whether php-gtk installed etc.
checkGtk();
class TextEditor
{
// the initial Vbox that will be added to the GtkWindow
// the HBox will be added to the Vbox
public $init_vbox;
public $init_hbox;
// the open, save and quit buttons that will be on the HBox
public $openBtn;
public $saveBtn;
public $quitBtn;
// the "Save" menu item under the "File" menu dropdown
public $menuSaveItem;
// the main textview
public $textView;
// the main window
public $window;
public $active_file; // the file currently opened
public $default_window_title; // default window title
public function __construct()
{
// instantiate objects
$this->init_vbox = new GtkVBox();
$this->init_hbox = new GtkHBox();
$this->openBtn = new GtkButton("Open");
$this->saveBtn = new GtkButton("Save As...");
$this->quitBtn = new GtkButton("Quit");
// create the window, set the title, default size and destroy action
$this->window = new GtkWindow();
// default window title - title may have additional text appended later
// on
$this->default_window_title = "PHP-GTK Text Editor - Cross Platform!";
$this->window->set_title($this->default_window_title);
$this->window->set_default_size(700,550);
$this->window->connect_simple('delete-event',array($this,"confirmMainQuit")); // delete-event is used instead of destroy as a BOOL value can be returned from the handler method to prevent the window being destroyed
// add and pack
$this->window->add($this->init_vbox);
$this->init_vbox->pack_start($this->init_hbox,FALSE,FALSE);
// add the buttons and spacing
$this->init_hbox->pack_start($this->openBtn,FALSE,FALSE);
$this->init_hbox->pack_start($this->saveBtn,FALSE,FALSE);
// spacing
$this->init_hbox->pack_start(new GtkHBox());
// add quit button
$this->init_hbox->pack_start($this->quitBtn,FALSE,FALSE);
// connect the signals (buttons)
$this->openBtn->connect_simple('clicked',array($this,"menuButtonClicked"),"open");
$this->saveBtn->connect_simple('clicked',array($this,"menuButtonClicked"),"save");
$this->quitBtn->connect_simple('clicked',array($this,"menuButtonClicked"),"quit");
// add the textview
$this->textView = new GtkTextView();
$gtkScrolledWindow = new GtkScrolledWindow();
$gtkScrolledWindow->add($this->textView);
$gtkScrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
$this->init_vbox->pack_start($gtkScrolledWindow);
// add menu bar
$this->addMenu();
// show all widgets, etc.
$this->window->show_all();
// set focus to the textView
$this->window->set_focus($this->textView);
// the main loop
Gtk::main();
}
public function addMenu()
{
/* create the menu */
$file = new GtkMenuItem("File");
$help = new GtkMenuItem("Help");
// create the menubar
$menubar = new GtkMenuBar();
$menubar->append($file);
$menubar->append($help);
// append the menu options
$menu = new GtkMenu();
$menu2 = new GtkMenu();
$open = new GtkMenuItem("Open");
$this->menuSaveItem = new GtkMenuItem("Save As...");
$quit = new GtkMenuItem("Quit");
$about = new GtkMenuItem("About");
// connect the signals
$quit->connect_simple('activate',array($this,'menuOptionClicked'),"quit");
$open->connect_simple('activate',array($this,'menuOptionClicked'),"open");
$this->menuSaveItem->connect_simple('activate',array($this,'menuOptionClicked'),"save");
$menu->append($open);
$menu->append($this->menuSaveItem);
$menu->append($quit);
$menu2->append($about);
$file->set_submenu($menu);
$help->set_submenu($menu2);
$help->set_submenu($menu2);
$this->init_vbox->pack_start($menubar,FALSE,FALSE);
}
public function menuOptionClicked($param)
{
// find out what action to perform
if(is_string($param))
{
switch($param)
{
case "quit":
$get_buffer = $this->textView->get_buffer();
$get_text = $get_buffer->get_text($get_buffer->get_start_iter(), $get_buffer->get_end_iter());
if(strlen($get_text) == 0)
{
Gtk::main_quit();
}
else
{
// warn first
$confirmDialog = $this->confirmationDialogBox("Are you sure?", "You have unsaved changes. If you quit before saving, you will permanently lose any unsaved changes...\n\nAre you sure?");
if(is_int($confirmDialog)) // user wants to quit the application
{
Gtk::main_quit();
}
else // will be an object - user does not want to quit the application
{
$confirmDialog->destroy();
}
}
break;
case "open":
$open = $this->openFileDialog();
break;
case "save":
$this->saveFileDialog();
break;
}
}
}
public function menuButtonClicked($param)
{
// find out what action to perform
if(is_string($param))
{
switch($param)
{
case "quit":
// check whether the user has anything written
$get_buffer = $this->textView->get_buffer();
$get_text = $get_buffer->get_text($get_buffer->get_start_iter(), $get_buffer->get_end_iter());
if(strlen($get_text) == 0)
{
Gtk::main_quit();
}
else
{
// warn first
$confirmDialog = $this->confirmationDialogBox("Are you sure?", "You have unsaved changes. If you quit before saving, you will permanently lose any unsaved changes...\n\nAre you sure?");
if(is_int($confirmDialog)) // user wants to quit the application
{
Gtk::main_quit();
}
else // will be an object - user does not want to quit the application
{
$confirmDialog->destroy();
}
}
break;
case "open":
$this->openFileDialog();
break;
case "save":
$this->saveFileDialog();
break;
}
}
}
public function saveFileDialog()
{
// if a file has been opened
// before...
if(isset($this->active_file) && $this->active_file)
{
// if the file is active (open), then we don't want
// to display a dialog box...
$get_buffer = $this->textView->get_buffer();
$get_text = $get_buffer->get_text($get_buffer->get_start_iter(), $get_buffer->get_end_iter());
$save = file_put_contents($this->active_file, $get_text, LOCK_EX);
$this->window->set_title($this->default_window_title . " - saved at " . date("g:i:s a", time()));
}
else
{ // maybe we do...
$fsave = new GtkFileChooserDialog("Where do you want to save your text file?", NULL, Gtk::FILE_CHOOSER_ACTION_SAVE, array(Gtk::STOCK_OK, Gtk::RESPONSE_OK));
$fsave->show_all();
// check response
if($fsave->run() == Gtk::RESPONSE_OK)
{
// if a file is open, we want to set that as the file to save to
$filesave_name = (!isset($filename)) ? $fsave->get_filename() : $filename;
// save the contents of the textbuffer to the file
$get_buffer = $this->textView->get_buffer();
$get_text = $get_buffer->get_text($get_buffer->get_start_iter(), $get_buffer->get_end_iter());
$save = file_put_contents($filesave_name, $get_text, LOCK_EX);
$this->active_file = $filesave_name;
$this->saveBtn->set_label("Save");
$this->menuSaveItem->set_label("Save");
}
// it will stay displayed otherwise after saving...
$fsave->destroy();
}
}
public function openFileDialog()
{
$fchooser = new GtkFileChooserDialog("Choose the file to open", NULL, Gtk::FILE_CHOOSER_ACTION_OPEN, array(Gtk::STOCK_OK, Gtk::RESPONSE_OK));
$fchooser->show_all();
// check response
if($fchooser->run() == Gtk::RESPONSE_OK)
{
// get the file name
$filename = $fchooser->get_filename();
$contents = file_get_contents($filename);
// output to textview
$set_text = new GtkTextBuffer();
$set_text->set_text($contents);
$this->textView->set_buffer($set_text);
// set active_file
$this->active_file = $filename;
// set save button text
$this->saveBtn->set_label("Save File");
$this->menuSaveItem->set_label("Save File");
}
$fchooser->destroy();
}
public function confirmMainQuit()
{
$get_buffer = $this->textView->get_buffer();
$get_text = $get_buffer->get_text($get_buffer->get_start_iter(), $get_buffer->get_end_iter());
if(strlen($get_text) == 0)
{
Gtk::main_quit();
}
else
{
// warn first
$confirmDialog = $this->confirmationDialogBox("Are you sure?", "You have unsaved changes. If you quit before saving, you will permanently lose any unsaved changes...\n\nAre you sure?");
if(is_int($confirmDialog)) // user wants to quit the application
{
// need to quit the main loop
// if we simply destroy the
// window, the dialog box will
// remain active, and so will the
// application process
Gtk::main_quit();
}
else // will be an object - user does not want to quit the application
{
$confirmDialog->destroy();
return TRUE; // telling php-gtk it has been handled
}
}
}
public function confirmationDialogBox($title,$text)
{
// warn the user first
$dialog = new GtkDialog($title, NULL, Gtk::DIALOG_MODAL, array(Gtk::STOCK_NO, Gtk::RESPONSE_NO, Gtk::STOCK_YES, Gtk::RESPONSE_YES));
$dialog->vbox->add(new GtkLabel($text));
// set the dialog size
$dialog->set_default_size(325,85);
// show all widgets
$dialog->show_all();
if($dialog->run() == Gtk::RESPONSE_YES)
{
return 1;
}
else
{
return $dialog;
}
}
}
$texteditor = new TextEditor();
function checkGtk()
{
if (!class_exists('gtk')) {
$msg = "You cannot run this PHP-GTK application because you do not have PHP-GTK installed. Please install the following dependencies: build-essential php5-cli php5-dev libgtk2.0-dev libglade2-dev and install pecl-cairo, and compile and install PHP-GTK. Then add the PHP-GTK and Cairo extensions to php.ini. General instructions for installation are below:
Make sure you're superuser. You can do this each time using:
sudo
Or elevate to root:
sudo su -
You can get the latest and greatest version of PHP-GTK directly from git (make sure you have the git-core package installed).
If your Linux distribution uses apt, install git-core using:
apt-get install git-core
If your Linux distribution uses yum, install git-core using:
yum install git-core
Make sure you have the necessary dependencies:
If your Linux distribution uses apt:
apt-get install build-essential php5-cli php5-dev libgtk2.0-dev libglade2-dev
If your Linux distribution uses yum:
yum install build-essential php5-cli php5-dev libgtk2.0-dev libglade2-dev
Install pecl-cairo (another dependency)
git clone https://github.com/gtkforphp/cairo.git
phpize
./configure
make
make install
If you're running Ubuntu, it appears libtool is split into separate files and when you try and compile PHP-GTK prior to concatenating the files back into the libtool, you'll get errors similar to:
configure.in:77: warning: LTOPTIONS_VERSION is m4_require’d but not m4_defun’d
aclocal.m4:2912: LT_INIT is expanded from…
aclocal.m4:2947: AC_PROG_LIBTOOL is expanded from…
configure.in:77: the top level
configure.in:77: warning: LTSUGAR_VERSION is m4_require’d but not m4_defun’d
configure.in:77: warning: LTVERSION_VERSION is m4_require’d but not m4_defun’d
configure.in:77: warning: LTOBSOLETE_VERSION is m4_require’d but not
configure.in:51: error: possibly undefined macro: AC_MSG_ERROR
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure:4266: error: possibly undefined macro: AM_PATH_GLIB_2_0
configure:4397: error: possibly undefined macro: AM_PATH_GTK_2_0
./configure: line 4242: syntax error near unexpected token `debug,’
./configure: line 4242: `PHP_GTK_ARG_ENABLE(debug, whether to include debugging symbols,’
If the error is output at the time of compiling PHP-GTK, you need to concatenate the files back into the libtool:
cd /usr/share/aclocal
cp libtool.m4 libtool.m4~backup
chmod 777 libtool.m4
cat lt~obsolete.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 >>libtool.m4
chmod 644 libtool.m4
cd ~/
Clone the PHP-GTK source:
git clone git://github.com/php/php-gtk-src.git
Now it's time to configure and install PHP-GTK:
./buildconf
./configure
make
make install
Once PHP-GTK is installed, you need to add the php-gtk and cairo extensions to the php.ini configuration file. Find the PHP configuration file for php-cli and modify the file - such as:
gedit /etc/php5/cli/php.ini
And add the following to the \"Dynamic Extensions\" section:
extension=php_gtk2.so
extension=cairo.so
";
file_put_contents("ERROR",$msg);
die();
}
}
?>
Bookmarks