All pastes #593901 Raw Edit

Marc Quinton

public php v1 · immutable
#593901 ·published 2007-06-28 16:30 UTC
rendered paste body
<?php/** * Author: Marc Quinton * Licence : LGPL * *  DesktopGadget : a small window displaying some information (a clock here) ;  *	 - you can move this window around the screen with mouse, *   - window can be closed, iconified (need GtkStatusIcon to remap, but not implemented) *	 - window position is stored in INI file (based on script filename) *  this is a "popup window" ; could be a Toplevel window with no decoration and with some attributes set. * *  * * see : http://gtk.php.net/manual/en/gdk.enum.windowtypehint.php */# allways display errors during developpement.error_reporting(E_ALL);define ('DIR', dirname(__FILE__));define ('INI', basename(__FILE__, '.php') . '.ini' );class Config {	protected $data;	protected $changed;	protected $auto_save;	protected $file;	protected $defaults;	public function __construct($defaults=null, $file=INI){		$this->data = array();		if($file == null)			$this->file = $this->get_default_file();		else			$this->file = $file;		$this->set_defaults($defaults);		$this->load();		$this->changed = false;		$this->auto_save = true;	}	public function __destruct(){		if($this->changed){			$this->save();		}	}	public function __get($name){		return $this->data[$name];	}	public function __set($name, $value){		# echo "Config::set($name=$value)\n";		if(isset($this->data[$name])){			if($this->data[$name] != $value){				$this->data[$name] = $value;				$this->changed = true;			}		} else{			$this->data[$name] = $value;			$this->changed = true;		}	}	public function __isset($name){		return isset($this->data[$name]);	}	public function __unset($name){		unset($this->data[$name]);	}	public function keys(){		return array_keys($this->data);	}	public function save(){		$bool = file_put_contents($this->file(), serialize($this->data));		if($bool === false)			throw new Exception('error writing file ' . $this->file());		$this->changed = false;		return $bool;	}	public function load(){		if(file_exists($this->file())){			$this->data = unserialize(file_get_contents($this->file()));			return true;		}		return false;	}	protected function get_default_file(){		return basename(__FILE__, '.php') . '.ini' ;	}	protected function set_defaults($defaults){		$this->data = $defaults;	}	protected function file(){		return $this->file;	}}class Frame extends GtkEventBox{	protected $container;	public function __construct($border_color='#aaa', $background='#EEE', $border_width=1){		parent::__construct();		$this->set_border_width(0);		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse($border_color));		$this->container = new GtkEventBox();		parent::add($this->container);		$this->container->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse($background));		$this->container->set_border_width($border_width);	}	public function add($w){		$this->container->add($w);	}}class Button extends GtkEventBox{	protected $label;	protected $callbacks;		public function __construct($label){		parent::__construct();		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#EEE'));			$frame = new Frame();			$this->add($frame);				$frame->add($this->label = new GtkLabel($label));				$this->label->modify_font(new PangoFontDescription('Sans Bold 6'));			$this->add_events(Gdk::BUTTON_PRESS_MASK);		$this->connect('button-press-event',  array($this, 'button_press_event'));		# $this->connect('motion-notify-event', array($this, 'motion_notify_event'));		$this->callbacks = array();		$this->set_border_width(0);		}	public function connect($signal, $callback){		if($signal == 'clicked'){			$this->callbacks[] = $callback;		}		else			parent::connect($signal, $callback);	}	public function motion_notify_event($w, $event){		return true;	}	public function button_press_event($selft, $event){		foreach($this->callbacks as $callback){			call_user_func($callback, $event);		}		return true;	}}class MovableWidget extends GtkEventBox{	protected $clic_point;	protected $config;	public function __construct($config=null){		parent::__construct();		$this->add_events(Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK);		$this->connect('motion-notify-event', array($this, 'motion_notify_event'));		$this->connect('button-press-event',  array($this, 'button_press_event'));		$this->connect_simple('realize', array($this, 'on_realize'));		$this->click_point = null;		if($config == null)			$this->config = new Config();		else			$this->config = $config;		$this->set_border_width(0);	}	public function on_realize(){		if(isset($this->config->x)){			$this->get_window()->move($this->config->x, $this->config->y);		}	}	public function button_press_event($w, $event){		$this->click_point = array(			'x_root' => $event->x_root,			'y_root' => $event->y_root		);	}	# move window location following mouse.	public function motion_notify_event($w, $event){		$state = $event->state & ~(Gdk::BUTTON_MOTION_MASK);		# no button press		if($state == 0)			return;		$win = $this->get_window();		$pos = $win->get_position();		$x = $pos[0] + $event->x_root - $this->click_point['x_root'];		$y = $pos[1] + $event->y_root - $this->click_point['y_root'];		$win->move($x, $y);		$this->config->x = $x;		$this->config->y = $y;		$this->click_point = array(			'x_root' => $event->x_root,			'y_root' => $event->y_root		);	}	public function get_window(){		$parent = $this;		do{			$w = $parent;			$parent = $w->get_parent();		} while($parent != null);		return $w;	}}class ClockWidget extends GtkLabel{	protected $timeout_id;	protected $format;	public function __construct($format = 'd/m - H:i:s'){		parent::__construct();		$this->format=$format;		$this->timeout_id = Gtk::timeout_add(1000, array($this, 'on_timeout'));		$this->modify_font(new PangoFontDescription('Sans 7'));		$this->on_timeout();	}	public function on_timeout(){		$this->set_text(date($this->format));		return true;	}}class TitleBar extends MovableWidget{	protected $hbox;	public function __construct($config, $title){		parent::__construct($config);		$this->hbox = new GtkHbox();		$this->hbox->pack_start($this->label = new GtkLabel($title));		$this->label->modify_font(new PangoFontDescription('Sans Bold 7'));		$this->hbox->pack_end($this->button_close = new Button(' x '), false, false);		$this->hbox->pack_end($this->button_minimize = new Button(' ^ '), false, false);		$this->hbox->pack_end($this->button_reduce = new Button(' - '), false, false);		$this->button_close->connect('clicked', array($this, 'on_button_close'));		$this->button_minimize->connect('clicked', array($this, 'on_button_minimize'));		$this->button_reduce->connect('clicked', array($this, 'on_button_reduce'));		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#aaa'));		$this->add($this->hbox);		$this->show_all();	}	public function on_button_close(){		Gtk::main_quit();	}	public function on_button_minimize(){		$this->get_window()->hide_all();	}	public function on_button_reduce(){		static $visible = true;		$w = $this->allocation->width;		if($visible){			$this->managed_widget->hide_all();			$h = $this->allocation->height;		}		else{			$this->managed_widget->show_all();			$h = $this->allocation->height +$this->managed_widget->allocation->height;		}		$visible = !$visible;		$this->get_window()->resize($w, $h);	}	public function manage($widget){		$this->managed_widget = $widget;	}}class DesktopGadget{	protected $config;	protected $pannel;	protected $title_bar;	protected $window;	function __construct($title, $type=1){		$this->config = new Config();		switch($type){		case 1:			$this->window = new GtkWindow(Gtk::WINDOW_POPUP);  # display over any window			break;		case 2:			$this->window = new GtkWindow();			$this->window->set_type_hint(Gdk::WINDOW_TYPE_HINT_DOCK);  # display over any window, below gtk panel			break;		case 3:			$this->window = new GtkWindow();			$this->window->set_type_hint(Gdk::WINDOW_TYPE_HINT_DESKTOP);  # display on gtk desktop, under any window			break;		case 4:			# raw toplevel + some attributes  ; won't move over panel or outside screen			$this->window = new GtkWindow();			$this->window->set_skip_taskbar_hint(true);			$this->window->set_skip_pager_hint(true);			$this->window->set_keep_above(true);			# $this->window->set_keep_below(true);			$this->window->stick();			$this->window->set_decorated(false);			break;			case 'parameters-to-try':			# http://gtk.php.net/manual/en/gdk.enum.windowtypehint.php			$this->window->set_skip_taskbar_hint(true);			$this->window->set_skip_pager_hint(true);			$this->window->set_keep_above(true);			$this->window->set_keep_below(true);			$this->window->stick();			$this->window->unstick();			$this->window->set_decorated(false);			break;		default:			throw new Exception ("un supported DesktopGadget type '$type'"); 		}		$frame = new Frame('darkgreen');			$vbox = new GtkVbox();			$frame->add($vbox);				$this->title_bar = new TitleBar($this->config, $title);				$vbox->pack_start($this->title_bar, false, false);				$this->panel = new GtkVbox();				$vbox->pack_end($this->panel, true, true);				$this->title_bar->manage($this->panel);				# settings		# $this->window->set_size_request( 100, -1 );  # set window size		# place window to screen center ; will be overriden at realize with saved (x,y) from config		$this->window->set_position(Gtk::WIN_POS_CENTER); 		# connection tree		$this->window->add($frame);		# terminate		$this->window->show_all();	}	# override composite methods : add, pack_start, pack_end;	# now add child widget to $this->pannel (a GtkVbox widget)	public function add($w){		$this->pack_start($w);	}	public function pack_start($w, $expand = true, $fill = true, $padding=0){		$this->panel->pack_start($w, $expand, $fill, $padding);		$this->window->show_all();	}	public function pack_end($w, $expand = true, $fill = true, $padding=0){		$this->panel->pack_end($w, $expand, $fill, $padding);		$this->window->show_all();	}}$gadget = new DesktopGadget($title='Desktop Gadget');$gadget->pack_start($clock = new ClockWidget());Gtk::main();?>