All pastes #395892 Raw Edit

Someone

public text v1 · immutable
·published 2007-03-15 11:16 UTC
rendered paste body
<?php
 
 error_reporting(E_ALL);
 
 $icon_handle_xpm = array(
 "16 8 3 1",
 "       c None",
 ".      c #606060",
 "+      c #FFFFFF",
 "                ",
 "                ",
 " .  .  .  .  .  ",
 "  +  +  +  +  + ",
 "                ",
 " .  .  .  .  .  ",
 "  +  +  +  +  + ",
 "                "
 );
 
 class HandleIcon extends GtkImage{
 	public function __construct($icon_data = null){
 		parent::__construct();
 		if($icon_data == null){
 			global $icon_handle_xpm;
 			$icon_data = $icon_handle_xpm;
 		}
 		
 		$this->set_from_pixbuf(GdkPixbuf::new_from_xpm_data($icon_data));
 	}
 }
 
 class Button extends GtkEventBox{
 	protected $label;
 	protected $callbacks;
 
 	public function __construct($label){
 		parent::__construct();
 		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#EEE'));
 		$this->label = new GtkLabel($label);
 		$this->add($this->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->callbacks = array();
 	}
 
 	public function connect($signal, $callback){
 		if($signal == 'clicked'){
 			$this->callbacks[] = $callback;
 		}
 		else
 			parent::connect($signal, $callback);
 	}
 
 	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;
 
 	public function __construct(){
 		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->click_point = null;
 	}
 
 	public function button_press_event($w, $event){
		$this->get_parent()->move_top($this);
 		$this->click_point = array( 'x'=> $event->x, 'y'=> $event->y);
 	}
 
 	public function motion_notify_event($w, $event){
 
 		# no button press
 		if($event->state == 0)
 			return;
 
 		# track new position and move object
 		$x = $this->allocation->x + $event->x - $this->click_point['x'];
 		$y = $this->allocation->y + $event->y - $this->click_point['y'];
 
 		$this->get_parent()->move($this, $x, $y);
 	}
 }
 
 class ArchitectClassWidget extends MovableWidget{
 
 	protected $_name;
 	protected $properties;
 
 	protected $vbox;
 	protected $frame;
 	protected $properties_box;
 
 	protected $expended = true;
 
 	protected $id;
 	static $id_counter = 0;
 
 	public function __construct($name, $properties){
 		parent::__construct();
 
 		$this->_name = $name;
 		$this->properties = $properties;
 
 		$this->frame = new GtkFrame();
 		$this->add($this->frame);
 
 			$this->vbox = new GtkVbox();
 			$this->frame->add($this->vbox);
 
 				$prop_event_box = new GtkEventbox();
 				$this->vbox->pack_end($prop_event_box);
 				$prop_event_box->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#DDD'));
 
 					$this->properties_box = new GtkVbox();
 					$prop_event_box->add($this->properties_box);
 
 
 		$this->buildTitle($this->vbox, $name);
 		$this->setProperties($this->properties_box, $properties);
 
 		$this->set_size_request(150, -1);
 		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#aaa'));
 		$this->id = ArchitectClassWidget::$id_counter++;
 	}
 
 	protected function buildTitle($parent, $title){
 
 		$hbox = new GtkHbox(); # title bar box
 		$parent->pack_start($hbox);
 
 
 		$hbox->pack_end($button = new Button('X'), false, false);
 		$button->connect('clicked', array($this, 'on_button_close'));
 
 		$hbox->pack_end($button = new Button('^'), false, false);
 		$button->connect('clicked', array($this, 'on_button_expand'));
 
 		global $icon_handle_xpm;
 		$handle = new HandleIcon();
 		$hbox->pack_start($handle, false, false);
 
 		$handle = new HandleIcon();
 		$hbox->pack_end($handle, false, false);
 
 		$hbox->pack_start($label = new GtkLabel($title), false, true);
 		$label->modify_font(new PangoFontDescription('Sans Bold 8'));
 
 	}
 
 	public function on_button_close(){
 		echo "ArchitectClassWidget::on_button_close()\n";
 		$this->get_parent()->link_remove($this);
 		$this->destroy();
 	}
 
 	public function on_button_expand(){
 		if($this->expended)
 			$this->properties_box->hide();
 		else
 			$this->show_all();
 		$this->expended = !$this->expended;
 	}
 
 	protected function setProperties($parent, $properties){
 
 		# remove existing labels.
 		foreach($parent->get_children() as $child)
 			$parent->remove($child);
 
 		foreach($properties as $key=>$prop){
 			$label = new GtkLabel();
 			$desc = sprintf('%s:%s', $key, $prop);
 			$label->set_markup($desc);
 			$label->set_justify(Gtk::JUSTIFY_LEFT);
 			$parent->pack_start($label, false, false);
 		}
 	}
 
 	public function center(){
 		$center = new stdClass();
 		$center->x = $this->allocation->x + intval($this->allocation->width/2);
 		$center->y = $this->allocation->y + intval($this->allocation->height/2);
 		return ($center);
 	}
 
 	function id(){
 		return $this->id;
 	}
 }
 
 
 class ArchitectWindow extends GtkFixed{
 
 	protected $links;
 	protected $widget;
 
 	public function __construct(){
 		parent::__construct();
 		$this->add_events(Gdk::EXPOSURE_MASK|Gdk::BUTTON_PRESS_MASK);
 		$this->connect('expose-event', array($this, 'expose_event'));
 		$this->connect('button-press-event', array($this, 'button_press_event'));
 		$this->links = array();
 		$this->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse("#000"));
 	}
 
	public function move_top($w){
		$pos = $w->allocation;
		$this->remove($w);
		$this->put($w,$pos->x,$pos->y);
	}

 	public function add_link($w1, $w2){
 		$this->links[] = array($w1, $w2);
 
 		if(!isset($this->widgets[$w1->id()])){
 			$this->widgets[$w1->id()] = $w1;
 		}
 		if(!isset($this->widgets[$w2->id()])){
 			$this->widgets[$w2->id()] = $w2;
 		}
 	}
 
 	public function link_remove($widget){
 		foreach($this->widgets as $w){
 			if($w->id() == $widget->id())
 				unset($this->widgets[$widget->id()]);
 		}
 
 		foreach($this->links as $key=>$link){
 			if($link[0]->id() == $widget->id() || $link[1]->id() == $widget->id())
 				unset($this->links[$key]);
 		}
 	}
 
 	public function expose_event($self, $event){
 		if($event->count != 0)
 			return;
 
 		foreach($this->links as $link){
 
 			$p1 = $link[0]->center();
 			$p2 = $link[1]->center();
 	
 			$this->window->draw_line($this->style->black_gc, $p1->x, $p1->y, $p2->x, $p2->y);
 		}
 	}
 	public function button_press_event($self, $event){
 		echo "ArchitectWindow::button_press_event()\n";
 		list($w1, $w2) = $this->links[0];
 		print_r($w1->window);
 	}
 }
 
 // Create a new window.
 $window = new GtkWindow();
 
 // Properly handle closing of the window.
 $window->connect_simple('destroy', array('Gtk', 'main_quit'));
 
 	$architect = new ArchitectWindow();
 	$window->add($architect);
 
 		$core = new ArchitectClassWidget('Core', $properties = array('id' => 'integer', 'name' => 'char'));
 		$architect->put($core, 150, 10);
 
 		$customer = new ArchitectClassWidget('Customer', $properties = array('name' => 'char'));
 		$architect->put($customer, 80, 70);
 
 		$article = new ArchitectClassWidget('Article', $properties = array('desc' => 'char'));
 		$architect->put($article, 235, 70);
 
 
 		$properties = array(
 			'x' => 'integer',
 			'y' => 'integer',
 			'w' => 'integer',
 			'h' => 'integer',
 			'background' => 'char',
 			'foreground' => 'char',
 			'font' => 'char',
 			'h' => 'integer',
 			'desc' => 'char'
 			);
 		$big = new ArchitectClassWidget('BigObject', $properties);
 		$architect->put($big, 10, 130);
 
 		$architect->add_link($core, $customer);
 		$architect->add_link($core, $article);
 		$architect->add_link($customer, $big);
 
 $window->set_size_request(400, 300);
 $window->set_position(Gtk::WIN_POS_CENTER);
 $window->show_all();
 
 Gtk::main();
 
 ?>