PHP Classes

File: dist/BattMan/BattMan.phar

Recommend this page to a friend!
  Classes of Stefan Lwe   BattMan   dist/BattMan/BattMan.phar   Download  
File: dist/BattMan/BattMan.phar
Role: Example script
Content type: text/plain
Description: Example script
Class: BattMan
Monitor the battery charge level of computers
Author: By
Last change:
Date: 6 months ago
Size: 177,193 bytes
 

Contents

Class file image Download
<?php error_reporting(E_ALL | E_STRICT); // define name of pha Phar::mapPhar('BattMan.phar'); require_once 'phar://BattMan.phar/ws/loewe/Utils/Autoload/Autoloader.php'; require_once 'phar://BattMan.phar/ws/loewe/Woody/lib/winbinder.php'; require_once 'phar://BattMan.phar/ws/loewe/Woody/lib/fi/freeimage.inc.php'; use \ws\loewe\Utils\Autoload\Autoloader; use \ws\loewe\Woody\Event\EventInfo; use \ws\loewe\Woody\Event\EventFactory; use \ws\loewe\Woody\Components\Component; error_reporting(E_ALL | E_STRICT); $autoloader = new Autoloader('phar://BattMan.phar/', 'php'); spl_autoload_register(array($autoloader, 'autoload')); function globalWinBinderEventHandler($windowID, $id, $controlID = 0, $type = 0, $property = 0) { $eventInfo = new EventInfo($windowID, $id, Component::getComponentByID($controlID), $type, $property); foreach(EventFactory::createEvent($eventInfo) as $event) { if($event != null) { $event->dispatch(); } } } $app = new \ws\loewe\BattMan\App\BattManApplication(); $app->start(); __HALT_COMPILER(); ?> EM BattMan.phar:home/loewe/workspace/programming/PHP/BattMan/bootstrap.phpS(g~>home/loewe/workspace/programming/PHP/dephp/vendor/autoload.phpSRLhome/loewe/workspace/programming/PHP/dephp/vendor/composer/autoload_real.phpvSv7Jhome/loewe/workspace/programming/PHP/dephp/vendor/composer/ClassLoader.php-S-Faն ws/loewe/Woody/lib/winbinder.phpS ]%ws/loewe/Woody/lib/wb_windows.inc.php2S2Es%ws/loewe/Woody/lib/wb_generic.inc.phpDSDS 'ws/loewe/Woody/lib/wb_resources.inc.php>5S>5[bvm'ws/loewe/Woody/lib/fi/freeimage.inc.phpSЊ&ws/loewe/Utils/Autoload/Autoloader.phpSri϶7ws/loewe/Utils/Autoload/SourceFileNotFoundException.php~S~Fζ"ws/loewe/Woody/Event/EventInfo.phpeSee%ws/loewe/Woody/Event/EventFactory.phpS9y#'ws/loewe/Woody/Components/Component.phpK*SK*&ws/loewe/Woody/Event/FocusListener.phpnSnWR#ws/loewe/Woody/Event/FocusEvent.phpSѡB$ws/loewe/Woody/Event/KeyListener.php)S)h6!ws/loewe/Woody/Event/KeyEvent.phpSSSM&ws/loewe/Woody/Event/MouseListener.phpS>c#ws/loewe/Woody/Event/MouseEvent.phpvSv?Ŷ,ws/loewe/Utils/DataStructures/RingBuffer.php_S_8^(ws/loewe/Woody/Components/IComponent.phpS+ws/loewe/BattMan/App/BattManApplication.phpS 2'ws/loewe/BattMan/Model/BatteryState.php S 0%ws/loewe/Woody/Util/WinApi/WinApi.phpS!Ʌ,ws/loewe/BattMan/Model/SystemPowerStatus.phpSM=Z8(ws/loewe/Woody/Util/WinApi/Structure.phpl Sl כ"ws/loewe/BattMan/View/TextView.php S ~.ws/loewe/Woody/Components/Controls/EditBox.php9S940#ws/loewe/BattMan/View/GraphView.php S Ӯ&2ws/loewe/BattMan/Components/Timer/RunOnceTimer.phpS+u,ws/loewe/Woody/Components/Controls/Image.phpS\+ws/loewe/Woody/Util/Image/ImageResource.phpS&%ws/loewe/BattMan/View/ControlView.php7 S7 :!ws/loewe/BattMan/View/LogView.php S +^Ѷ ws/loewe/BattMan/Model/Model.phpBSB#'X/ws/loewe/Woody/Components/Controls/Checkbox.php)S)[̶/ws/loewe/Woody/Components/Controls/EditArea.phpoSo>0ws/loewe/Woody/Components/Controls/EditField.phpeSebE昶1ws/loewe/Woody/Components/Controls/Actionable.phpOSO?p,ws/loewe/Woody/Components/Controls/Label.phpFSF}V3ws/loewe/Woody/Dialog/FileSystem/FileSaveDialog.phpTST2歶5ws/loewe/Woody/Dialog/FileSystem/FileSystemDialog.phpSaѵ϶&ws/loewe/Woody/Event/ActionAdapter.phpSǡj'ws/loewe/Woody/Event/ActionListener.phpzSz[$ws/loewe/Woody/Event/ActionEvent.php+S+vyws/loewe/BattMan/View/View.php}S} 㰐"ws/loewe/Woody/App/Application.php@S@]H35ws/loewe/Woody/Components/Windows/ResizableWindow.php@S@af2ws/loewe/Woody/Components/Controls/ProgressBar.phpST6w)ws/loewe/Woody/Components/Timer/Timer.phprSrx<%ws/loewe/Woody/WinBinderException.php\S\l-(ws/loewe/Woody/Event/TimeoutListener.phpnSn+'ws/loewe/Woody/Event/TimeoutAdapter.php,S,if-%ws/loewe/Woody/Event/TimeoutEvent.phpDSDt@ws/loewe/Woody/Components/Timer/TimerAlreadyRunningException.phpS%P<ws/loewe/Woody/Components/Timer/TimerNotRunningException.phpSj,ws/loewe/Woody/Event/WindowResizeAdapter.phpgSg>e*ws/loewe/Woody/Event/WindowResizeEvent.phpS`0zws/loewe/Utils/Geom/Point.php} S} ޮd!ws/loewe/Utils/Geom/Dimension.phpF SF Ѷ+ws/loewe/Woody/Event/WindowCloseAdapter.php_S_L,ws/loewe/Woody/Event/WindowCloseListener.php{S{ :)ws/loewe/Woody/Event/WindowCloseEvent.phpS>lH4ws/loewe/Woody/Components/Windows/AbstractWindow.phpS8|+ws/loewe/Woody/System/WindowConstraints.php S -¶-ws/loewe/Woody/Event/WindowResizeListener.php~S~NJ,ws/loewe/Woody/Components/Controls/Frame.phpPSP@OL%ws/loewe/Woody/Layouts/GridLayout.php# S# .$!ws/loewe/Woody/Layouts/Layout.phpS5W.ws/loewe/Woody/Components/Controls/Control.phpSX;&*ws/loewe/Woody/Components/Controls/Tab.phpSn}Jws/loewe/Woody/Event/Event.php S V?%ws/loewe/Utils/Common/ValueObject.php=S=: )ws/loewe/Woody/Util/WinApi/Types/Type.phpSs߶)ws/loewe/Woody/Util/WinApi/Types/Byte.phpS} ar*ws/loewe/Woody/Util/WinApi/Types/Dword.phpScu<?php require_once './vendor/autoload.php'; require_once './vendor/ws/loewe/Woody/lib/winbinder.php'; require_once './vendor/ws/loewe/Woody/lib/fi/freeimage.inc.php'; use \ws\loewe\Utils\Autoload\Autoloader; use \ws\loewe\Woody\Event\EventInfo; use \ws\loewe\Woody\Event\EventFactory; use \ws\loewe\Woody\Components\Component; error_reporting(E_ALL | E_STRICT); $autoloader = new Autoloader('./source/', 'php'); spl_autoload_register(array($autoloader, 'autoload')); function globalWinBinderEventHandler($windowID, $id, $controlID = 0, $type = 0, $property = 0) { $eventInfo = new EventInfo($windowID, $id, Component::getComponentByID($controlID), $type, $property); foreach(EventFactory::createEvent($eventInfo) as $event) { if($event != null) { $event->dispatch(); } } } $app = new ws\loewe\BattMan\App\BattManApplication(); $app->start();<?php // autoload.php @generated by Composer require_once __DIR__ . '/composer' . '/autoload_real.php'; return ComposerAutoloaderInitc0d449c849372f8c576887ed2f551a3f::getLoader(); <?php // autoload_real.php @generated by Composer class ComposerAutoloaderInitc0d449c849372f8c576887ed2f551a3f { private static $loader; public static function loadClassLoader($class) { if ('Composer\Autoload\ClassLoader' === $class) { require __DIR__ . '/ClassLoader.php'; } } public static function getLoader() { if (null !== self::$loader) { return self::$loader; } spl_autoload_register(array('ComposerAutoloaderInitc0d449c849372f8c576887ed2f551a3f', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInitc0d449c849372f8c576887ed2f551a3f', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { $loader->set($namespace, $path); } $map = require __DIR__ . '/autoload_psr4.php'; foreach ($map as $namespace => $path) { $loader->setPsr4($namespace, $path); } $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } $loader->register(true); return $loader; } } function composerRequirec0d449c849372f8c576887ed2f551a3f($file) { require $file; } <?php /* * This file is part of Composer. * * (c) Nils Adermann <naderman@naderman.de> * Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; /** * ClassLoader implements a PSR-0 class loader * * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md * * $loader = new \Composer\Autoload\ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (eg. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * This class is loosely based on the Symfony UniversalClassLoader. * * @author Fabien Potencier <fabien@symfony.com> * @author Jordi Boggiano <j.boggiano@seld.be> */ class ClassLoader { // PSR-4 private $prefixLengthsPsr4 = array(); private $prefixDirsPsr4 = array(); private $fallbackDirsPsr4 = array(); // PSR-0 private $prefixesPsr0 = array(); private $fallbackDirsPsr0 = array(); private $useIncludePath = false; private $classMap = array(); public function getPrefixes() { return call_user_func_array('array_merge', $this->prefixesPsr0); } public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } public function getFallbackDirs() { return $this->fallbackDirsPsr0; } public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { if ($this->classMap) { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; } } /** * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( (array) $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, (array) $paths ); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( (array) $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], (array) $paths ); } } /** * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-0 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( (array) $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, (array) $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { // Register directories for a new namespace. $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( (array) $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], (array) $paths ); } } /** * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr0 = (array) $paths; } else { $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; } } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr4 = (array) $paths; } else { $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } } /** * Turns on searching the include path for class files. * * @param bool $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile($class) { // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 if ('\\' == $class[0]) { $class = substr($class, 1); } // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if ($file === null && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if ($file === null) { // Remember that this class does not exist. return $this->classMap[$class] = false; } return $file; } private function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach ($this->prefixDirsPsr4[$prefix] as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } // PSR-0 lookup if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } } } } // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } // PSR-0 include paths. if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } } } /** * Scope isolated include. * * Prevents access to $this/self from included files. */ function includeFile($file) { include $file; } <?php /******************************************************************************* WINBINDER - The native Windows binding for PHP for PHP Copyright Hypervisual - see LICENSE.TXT for details Author: Rubem Pechansky (http://winbinder.org/contact.php) Main inclusion file for WinBinder *******************************************************************************/ if(!extension_loaded('winbinder') && !dl('php_winbinder.dll')) { trigger_error("WinBinder extension could not be loaded.\n", E_USER_ERROR); } // WinBinder PHP functions require_once 'wb_windows.inc.php'; require_once 'wb_generic.inc.php'; require_once 'wb_resources.inc.php';<?php /******************************************************************************* WINBINDER - The native Windows binding for PHP for PHP Copyright � Hypervisual - see LICENSE.TXT for details Author: Rubem Pechansky (http://winbinder.org/contact.php) Windows functions *******************************************************************************/ // TODO: These functions must be ported ("rewritten" is a better term) to C // so this file will not be necessary in the future //-------------------------------------------------------------------- CONSTANTS // Windows constants define("BM_SETCHECK", 241); define("LVM_FIRST", 0x1000); define("LVM_DELETEALLITEMS", (LVM_FIRST+9)); define("LVM_GETITEMCOUNT", (LVM_FIRST+4)); define("LVM_GETITEMSTATE", (LVM_FIRST+44)); define("LVM_GETSELECTEDCOUNT", (LVM_FIRST+50)); define("LVIS_SELECTED", 2); define("TCM_GETCURSEL", 4875); define("CB_FINDSTRINGEXACT", 344); define("CB_SETCURSEL", 334); define("LB_FINDSTRINGEXACT", 418); define("LB_SETCURSEL", 390); define("TCM_SETCURSEL", 4876); define("WM_SETTEXT", 12); //------------------------------------------------------------- WINDOW FUNCTIONS /* Creates a window control, menu, toolbar, status bar or accelerator. */ function wb_create_control($parent, $class, $caption="", $xpos=0, $ypos=0, $width=0, $height=0, $id=null, $style=0, $lparam=null, $ntab=0) { switch($class) { case Accel: return wbtemp_set_accel_table($parent, $caption); case ToolBar: return wbtemp_create_toolbar($parent, $caption, $width, $height, $lparam); case Menu: return wbtemp_create_menu($parent, $caption); case HyperLink: return wbtemp_create_control($parent, $class, $caption, $xpos, $ypos, $width, $height, $id, $style, is_null($lparam) ? NOCOLOR : $lparam, $ntab); case ComboBox: case ListBox: case ListView: $ctrl = wbtemp_create_control($parent, $class, $caption, $xpos, $ypos, $width, $height, $id, $style, $lparam, $ntab); if(is_array($caption)) wb_set_text($ctrl, $caption[0]); return $ctrl; case TreeView: $ctrl = wbtemp_create_control($parent, $class, $caption, $xpos, $ypos, $width, $height, $id, $style, $lparam, $ntab); if(is_array($caption)) wb_set_text($ctrl, $caption[0]); return $ctrl; case Gauge: case Slider: case ScrollBar: $ctrl = wbtemp_create_control($parent, $class, $caption, $xpos, $ypos, $width, $height, $id, $style, $lparam, $ntab); if($lparam) wb_set_value($ctrl, $lparam); return $ctrl; default: return wbtemp_create_control($parent, $class, $caption, $xpos, $ypos, $width, $height, $id, $style, $lparam, $ntab); } } /* Sets the value of a control or control item */ function wb_set_value($ctrl, $value, $item = null) { if(!$ctrl) return null; $class = wb_get_class($ctrl); switch($class) { case ListView: // Array with items to be checked if($value === null) break; elseif(is_string($value) && strstr($value, ",")) $values = explode(",", $value); elseif(!is_array($value)) $values = array($value); else $values = $value; foreach($values as $index) wbtemp_set_listview_item_checked($ctrl, $index, 1); break; case TreeView: // Array with items to be checked if($item === null) $item = wb_get_selected($ctrl); return wbtemp_set_treeview_item_value($ctrl, $item, $value); default: if($value !== null) { return wbtemp_set_value($ctrl, $value, $item); } } } /* Gets the text from a control, a control item, or a control sub-item. */ function wb_get_text($ctrl, $item=null, $subitem=null) { if(!$ctrl) return null; if(wb_get_class($ctrl) == ListView) { if($item !== null) { // Valid item $line = wbtemp_get_listview_text($ctrl, $item); if($subitem === null) return $line; else return $line[$subitem]; } else { // NULL item $sel = wb_get_selected($ctrl); if($sel === null) { // Returns the entire table $items = array(); for($i = 0;;$i++) { $item = wbtemp_get_listview_text($ctrl, $i); $all = ''; foreach($item as $col) $all .= $col; if($all == '') break; $items[] = $item; } return $items ? $items : null; } else { $items = array(); foreach($sel as $row) $items[] = wbtemp_get_listview_text($ctrl, $row); return $items ? $items : null; } } } elseif(wb_get_class($ctrl) == TreeView) { if($item) { return wbtemp_get_treeview_item_text($ctrl, $item); } else { $sel = wb_get_selected($ctrl); if($sel === null) return null; else { return wbtemp_get_text($ctrl); } } } elseif(wb_get_class($ctrl) == ComboBox) { return wbtemp_get_text($ctrl, $item === null ? -1 : $item); } elseif(wb_get_class($ctrl) == ListBox) { return wbtemp_get_text($ctrl, $item === null ? -1 : $item); } else { return wbtemp_get_text($ctrl, $item); } } /* Sets the text of a control. In a ListView, it creates columns: each element of the array text is a column. In a tab control, it renames the tabs. Sets the text of a control item. */ function wb_set_text($ctrl, $text, $item=null, $subitem=null) { if(!$ctrl) return null; switch(wb_get_class($ctrl)) { case ListView: if($item !== null) { if(!is_array($text) && $subitem !== null) { // Set text of a ListView cell according to $item and $subitem wbtemp_set_listview_item_text($ctrl, $item, $subitem, $text); } else { // Set text of several ListView cells, ignoring $subitem for($sub = 0; $sub < count($text); $sub++) { if($text) { if(($text[$sub] !== null)) { wbtemp_set_listview_item_text($ctrl, $item, $sub, (string)$text[$sub]); } } else { wbtemp_set_listview_item_text($ctrl, $item, $sub, ""); } } } } else { if(!is_array($text)) $text = explode(",", $text); wb_delete_items($ctrl, null); if(!$item) { wbtemp_clear_listview_columns($ctrl); // Create column headers // In the loop below, passing -1 as the 'width' argument of wbtemp_create_listview_column() // makes it calculate the column width automatically for($i = 0; $i < count($text); $i++) { if(is_array($text[$i])) wbtemp_create_listview_column($ctrl, $i, (string)$text[$i][0], isset($text[$i][1]) ? (int)$text[$i][1] : -1, isset($text[$i][2]) ? (int)$text[$i][2] : WBC_LEFT ); else wbtemp_create_listview_column($ctrl, $i, (string)$text[$i], -1, 0); } } } break; case ListBox: if(!$text) { wb_delete_items($ctrl); } elseif(is_string($text)) { if(strchr($text, "\r") || strchr($text, "\n")) { $text = preg_split("/[\r\n,]/", $text); wb_delete_items($ctrl); foreach($text as $str) wbtemp_create_item($ctrl, (string)$str); } else { $index = wb_send_message($ctrl, LB_FINDSTRINGEXACT, -1, wb_get_address($text)); wb_send_message($ctrl, LB_SETCURSEL, $index, 0); } } elseif(is_array($text)) { wb_delete_items($ctrl); foreach($text as $str) wbtemp_create_item($ctrl, (string)$str); } return; case ComboBox: if(!$text) wb_delete_items($ctrl); elseif(is_string($text)) { if(strchr($text, "\r") || strchr($text, "\n")) { $text = preg_split("/[\r\n,]/", $text); wb_delete_items($ctrl); foreach($text as $str) wbtemp_create_item($ctrl, (string)$str); } else { $index = wb_send_message($ctrl, CB_FINDSTRINGEXACT, -1, wb_get_address($text)); wb_send_message($ctrl, CB_SETCURSEL, $index, 0); if($index == -1) wb_send_message($ctrl, WM_SETTEXT, 0, wb_get_address($text)); } } elseif(is_array($text)) { wb_delete_items($ctrl); foreach($text as $str) wbtemp_create_item($ctrl, (string)$str); } return; case TreeView: if($item) return wbtemp_set_treeview_item_text($ctrl, $item, $text); else return wb_create_items($ctrl, $text, true); default: // The (string) cast below works well but is a temporary fix, must be // removed when wbtemp_set_text() accepts numeric types correctly if(is_array($text)) return wbtemp_set_text($ctrl, $text, $item); else return wbtemp_set_text($ctrl, (string)$text, $item); } } /* Selects one or more items. Compare with wb_set_value() which checks items instead. */ function wb_set_selected($ctrl, $selitems, $selected=TRUE) { switch(wb_get_class($ctrl)) { case ComboBox: wb_send_message($ctrl, CB_SETCURSEL, (int)$selitems, 0); break; case ListBox: wb_send_message($ctrl, LB_SETCURSEL, (int)$selitems, 0); break; case ListView: if(is_null($selitems)) { return wbtemp_select_all_listview_items($ctrl, false); } elseif(is_array($selitems)) { foreach($selitems as $item) wbtemp_select_listview_item($ctrl, $item, $selected); return TRUE; } else return wbtemp_select_listview_item($ctrl, $selitems, $selected); break; case Menu: return wbtemp_set_menu_item_checked($ctrl, $selitems, $selected); case TabControl: wbtemp_select_tab($ctrl, (int)$selitems); break; case TreeView: wbtemp_set_treeview_item_selected($ctrl, $selitems); break; default: return false; } return true; } /* Creates one or more items in a control. */ function wb_create_items($ctrl, $items, $clear=false, $param=null) { switch(wb_get_class($ctrl)) { case ListView: if($clear) wb_send_message($ctrl, LVM_DELETEALLITEMS, 0, 0); $last = -1; // For each row for($i = 0; $i < count($items); $i++) { if(!is_scalar($items[$i])) $last = wbtemp_create_listview_item( $ctrl, -1, -1, (string)$items[$i][0]); else $last = wbtemp_create_listview_item( $ctrl, -1, -1, (string)$items[$i]); wbtemp_set_listview_item_text($ctrl, -1, 0, (string)$items[$i][0]); // For each column except the first for($sub = 0; $sub < count($items[$i]) - 1; $sub++) { if($param) { $result = call_user_func($param, // Callback function $items[$i][$sub + 1], // Item value $i, // Row $sub // Column ); wbtemp_set_listview_item_text($ctrl, $last, $sub + 1, $result); } else wbtemp_set_listview_item_text($ctrl, $last, $sub + 1, (string)$items[$i][$sub + 1]); } } return $last; break; case TreeView: if($clear) $handle = wb_delete_items($ctrl); // Empty the treeview if(!$items) break; $ret = array(); for($i = 0; $i < count($items); $i++) { $ret[] = wbtemp_create_treeview_item($ctrl, (string)$items[$i][0], // Name isset($items[$i][1]) ? $items[$i][1] : 0, // Value isset($items[$i][2]) ? $items[$i][2] : 0, // Where isset($items[$i][3]) ? $items[$i][3] : -1, // ImageIndex isset($items[$i][4]) ? $items[$i][4] : -1, // SelectedImageIndex isset($items[$i][5]) ? $items[$i][5] : 0 // InsertionType ); } return (count($ret) > 1 ? $ret : $ret[0]); break; case StatusBar: wbtemp_create_statusbar_items($ctrl, $items, $clear, $param); return true; default: if(is_array($items)) { foreach($items as $item) wbtemp_create_item($ctrl, $item); return true; } else return wbtemp_create_item($ctrl, $items); break; } } /* Opens the standard Open dialog box. */ function wb_sys_dlg_open($parent=null, $title=null, $filter=null, $path=null, $filename=null, $flags = null) { $filter = _make_file_filter($filter ? $filter : $filename); return wbtemp_sys_dlg_open($parent, $title, $filter, $path, $flags); } /* Opens the standard Save As dialog box. */ function wb_sys_dlg_save($parent=null, $title=null, $filter=null, $path=null, $filename=null, $defext=null) { $filter = _make_file_filter($filter ? $filter : $filename); return wbtemp_sys_dlg_save($parent, $title, $filter, $path, $filename, $defext); } //----------------------------------------- AUXILIARY FUNCTIONS FOR INTERNAL USE /* Creates a file filter for Open/Save dialog boxes based on an array. */ function _make_file_filter($filter) { if(!$filter) return "All Files (*.*)\0*.*\0\0"; if(is_array($filter)) { $result = ""; foreach($filter as $line) $result .= "$line[0] ($line[1])\0$line[1]\0"; $result .= "\0"; return $result; } else return $filter; } //-------------------------------------------------------------------------- END ?> <?php /******************************************************************************* WINBINDER - The native Windows binding for PHP for PHP Copyright Hypervisual - see LICENSE.TXT for details Author: Rubem Pechansky (http://winbinder.org/contact.php) General-purpose supporting functions *******************************************************************************/ //-------------------------------------------------------------------- FUNCTIONS /* Mimics function file_put_contents from PHP 5 int file_put_contents (string filename, string data [, int flags [, resource context]]) */ if(PHP_VERSION < "5.0.0") { function file_put_contents($filename, $data, $flags=0, $zcontext=null) { if($zcontext) $fp = @fopen($filename, "w+b", $flags, $zcontext); else $fp = @fopen($filename, "w+b", $flags); if(!$fp) return FALSE; fwrite($fp, $data); fclose($fp); return TRUE; } } // PHP_VERSION < "5.0.0" /* Returns an array with all files of subdirectory $path. If $subdirs is TRUE, includes subdirectories recursively. $mask is a PCRE regular expression. */ function get_folder_files($path, $subdirs=false, $fullname=true, $mask="", $forcelowercase=TRUE) { // Correct path name, if needed $path = str_replace('/', '\\', $path); if(substr($path, -1) != '\\') $path .= "\\"; if(!$path || !@is_dir($path)) return array(); // Browse the subdiretory list recursively $dir = array(); if($handle = opendir($path)) { while(($file = readdir($handle)) !== false) { if(!is_dir($path.$file)) { // No directories / subdirectories if($forcelowercase) $file = strtolower($file); if(!$mask) { $dir[] = $fullname ? $path.$file : $file; } else if($mask && preg_match($mask, $file)) { $dir[] = $fullname ? $path.$file : $file; } } else if($subdirs && $file[0] != ".") { // Exclude "." and ".." $dir = array_merge($dir, get_folder_files($path.$file, $subdirs, $fullname, $mask)); } } } closedir($handle); return $dir; } //-------------------------------------------------------------------- INI FILES /* Transforms the array $data in a text that can be saved as an INI file. Escapes double-quotes as (\") */ function generate_ini($data, $comments="") { if(!is_array($data)) { trigger_error(__FUNCTION__ . ": Cannot save INI file."); return null; } $text = $comments; foreach($data as $name=>$section) { $text .= "\r\n[$name]\r\n"; foreach($section as $key=>$value) { $value = trim($value); if((string)((int)$value) == (string)$value) // Integer: does nothing ; elseif((string)((float)$value) == (string)$value) // Floating point: does nothing ; elseif($value === "") // Empty string $value = '""'; elseif(strstr($value, '"')) // Escape double-quotes $value = '"' . str_replace('"', '\"', $value) . '"'; else $value = '"' . $value . '"'; $text .= "$key = " . $value . "\r\n"; } } return $text; } /* Replaces function parse_ini_file() so INI files may be processed more similarly to Windows. Replaces escaped double-quotes (\") with double-quotes ("). See manual for details. */ function parse_ini($initext, $changecase=TRUE, $convertwords=TRUE) { $ini = preg_split("/\r\n|\n/", $initext); $secpattern = "/^\[(.[^\]]*)\]/i"; // $entrypattern = "/^([a-z_0-9]*)\s*=\s*\"?([^\"]*)?\"?" . '$' . "/i"; // $strpattern = "/^\"?(.[^\"]*)\"?" . '$' . "/i"; $entrypattern = "/^([a-z_0-9]*)\s*=\s*\"?([^\"]*)?\"?\$/i"; $strpattern = "/^\"?(.[^\"]*)\"?\$/i"; $section = array(); $sec = ""; // Predefined words static $words = array("yes", "on", "true", "no", "off", "false", "null"); static $values = array( 1, 1, 1, 0, 0, 0, null); // Lines loop for($i = 0; $i < count($ini); $i++) { $line = trim($ini[$i]); // Replaces escaped double-quotes (\") with special signal /%quote%/ if(strstr($line, '\"')) $line = str_replace('\"', '/%quote%/', $line); // Skips blank lines and comments if($line == "" || preg_match("/^;/i", $line)) continue; if(preg_match($secpattern, $line, $matches)) { // It's a section $sec = $matches[1]; if($changecase) $sec = ucfirst(strtolower($sec)); $section[$sec] = array(); } elseif(preg_match($entrypattern, $line, $matches)) { // It's an entry $entry = $matches[1]; if($changecase) $entry = strtolower($entry); $value = preg_replace($entrypattern, "\\2", $line); // Restores double-quotes (") $value = str_replace('/%quote%/', '"', $value); // Convert some special words to their respective values if($convertwords) { $index = array_search(strtolower($value), $words); if($index !== false) $value = $values[$index]; } $section[$sec][$entry] = $value; } else { // It's a normal string $section[$sec][] = preg_replace($strpattern, "\\1", $line); } } return $section; } //------------------------------------------------------------------ END OF FILE ?><?php /******************************************************************************* WINBINDER - The native Windows binding for PHP for PHP Copyright Hypervisual - see LICENSE.TXT for details Author: Rubem Pechansky (http://winbinder.org/contact.php) RC file parser: convert Windows resource file to WinBinder commands *******************************************************************************/ // TODO: These functions will be replaced by the visual layout editor // so this file will not be necessary in the future //-------------------------------------------------------------------- CONSTANTS define("WB_KX_SCREEN", 1.498); // Determined through trial and error define("WB_KY_SCREEN", 1.625); // Determined through trial and error //------------------------------------------------- WINDOWS CONSTANTS FROM WIN.H define("WS_VISIBLE", 0x10000000); define("WS_DISABLED", 0x08000000); define("WS_GROUP", 0x00020000); define("WS_EX_STATICEDGE", 0x00020000); // Button styles define("BS_PUSHBUTTON", 0x00); define("BS_CHECKBOX", 0x02); define("BS_AUTOCHECKBOX", 0x03); define("BS_RADIOBUTTON", 0x04); define("BS_GROUPBOX", 0x07); define("BS_AUTORADIOBUTTON", 0x09); define("BS_ICON", 0x40); define("BS_BITMAP", 0x80); // Edit control styles define("ES_NUMBER", 0x2000); define("ES_PASSWORD", 0x20); define("ES_READONLY", 0x0800); define("ES_UPPERCASE", 0x08); define("ES_LEFT", 0x0); define("ES_CENTER", 0x01); define("ES_RIGHT", 0x02); define("ES_MULTILINE", 0x04); // Static styles define("SS_LEFT", 0x00); define("SS_CENTER", 0x01); define("SS_RIGHT", 0x02); define("SS_ETCHEDHORZ", 0x10); define("SS_ETCHEDVERT", 0x11); define("SS_ETCHEDFRAME", 0x12); define("SS_ICON", 0x03); define("SS_BITMAP", 0x0E); define("SS_LEFTNOWORDWRAP", 0x0C); define("SS_WORDELLIPSIS", 0xC000); // Other styles define("CBS_SORT", 0x100); define("CBS_DROPDOWNLIST", 3); define("LBS_SORT", 2); define("LVS_NOSORTHEADER", 0x00008000); define("LVS_GRIDLINES", 0x00800000); // Actually WS_BORDER define("LVS_CHECKBOXES", 0x00000800); // Actually LVS_ALIGNLEFT define("LVS_SINGLESEL", 0x00000004); define("TBS_AUTOTICKS", 1); //-------------------------------------------------------------------- FUNCTIONS /* Returns the WinBinder code that results from the resource text $rc, usually read from a RC (Windows resource) file. TODO: Extend support to several RC generators (currently supports WinAsm Studio only) NOTE: Caption is not used, it's taken from the resource instead. The parameter is kept here just to be compatible with wb_create_window() */ function parse_rc($rc, $winvar='$mainwin', $parent=null, $type="AppWindow", $caption=null, $x=WBC_CENTER, $y=WBC_CENTER, $width=WBC_CENTER, $height=WBC_CENTER, $style=0, $lparam=0, $respath=PATH_RES) { global $_winclass, $_usergeom, $path_res; // Read file $_usergeom = array($x, $y, $width, $height); $path_res = $respath; // Remove comments and useless spaces $rc = preg_replace("/^\s*;.*$/m", "", $rc); $rc = preg_replace("/^\s*(.*)$/m", "\\1", $rc); // Maintain #defines and discard the rest (fixed to work with newer versions of PHP -- thanks Hans) // $def = preg_replace("/(?!^\s*#define)(.*)$/m", "\\2", $rc); $def = preg_replace('/^((?!#define).)*$/m', "\\2", $rc); // Remove blank lines $def = preg_replace("/\n+/m", "\n", $def); // Change string C #defines to PHP format $def = preg_replace("/#define\s+(\w+)\s+\"(.*)\"/", "if(!defined(\"\\1\")) define(\"\\1\", \"\\2\");", $def); // Change character C #defines to PHP format $def = preg_replace("/#define\s+(\w+)\s+'(.+)'/", "if(!defined(\"\\1\")) define(\"\\1\", \"\\2\");", $def); // Change numeric C #defines to PHP format $def = preg_replace("/#define\s+(\w+)\s+(\S+)/", "if(!defined(\"\\1\")) define(\"\\1\", \\2);", $def); $def = "// Control identifiers\n\n" . preg_replace("/(\r\n|\r|\n)+/sm", "\n", $def); // Return to original string and eliminates the #defines $rc = preg_replace("/^\s*#define(.*)$/m", "", $rc); // Create the window $_winclass = $type; $tok = "\s*((?:[\"'][\S \t]*[\"'])|(?:[\S^,'\"]+))\s*"; // Normal or quoted token $rc = "// Create window\n\n" . preg_replace_callback("/^$tok\s+DIALOGEX$tok,$tok,$tok,$tok\s+CAPTION$tok\s+FONT$tok,$tok\s+STYLE$tok\s+EXSTYLE$tok/m", "_scale_dialog", $rc); // Create the controls $rc = preg_replace_callback("/^\s*CONTROL\s+$tok,$tok,$tok,$tok,$tok,$tok,$tok,$tok,$tok/m", "_scale_controls", $rc); // Create BEGIN / END comments $rc = preg_replace("/^\s*BEGIN/m", "\n// Insert controls\n", $rc); $rc = preg_replace("/^\s*END/m", "\n// End controls", $rc); // Replace variable names $rc = str_replace("%WINVAR%", $winvar, $rc); $rc = str_replace("%PARENT%", $parent? $parent : "NULL", $rc); $rc = str_replace("%STYLE%", $style, $rc); $rc = str_replace("%LPARAM%", $lparam, $rc); return "$def\n$rc"; } //----------------------------------------------------------- INTERNAL FUNCTIONS function _scale_dialog($c) { global $_winclass, $_usergeom, $_tabN; if($_winclass == "TabControl") { $_tabN++; $code = "wbtemp_create_item(%PARENT%, ". $c[6] . ");\n"; } else { $_addx = 8; //width + 2xborder $_addy = 4 + 42 + 17 + 4; //border + caption + border switch(is_string($_winclass) ? strtolower($_winclass) : $_winclass) { case "appwindow": $_winclass = AppWindow; $_addx = 8; //width + 2xborder $_addy = 3 + 18 + 22 + 18 + 3; //border + caption + menu + statusbar + border break; case "resizablewindow": $_winclass = ResizableWindow; $_addx = 8; //width + 2xborder $_addy = 4 + 42 + 17 + 4; //border + caption + menu + statusbar + border break; case "modaldialog": $_winclass = ModalDialog; $_addx = 8; //width + 2xborder $_addy = 4 + 42 + 17 + 4; //border + caption + border break; case "modelessdialog": $_winclass = ModelessDialog; break; case "tooldialog": $_winclass = ToolDialog; break; } if(!(($_usergeom[0] == WBC_CENTER && $_usergeom[1] == WBC_CENTER && $_usergeom[2] == WBC_CENTER && $_usergeom[3] == WBC_CENTER))) { $code = "%WINVAR% = wb_create_window(" . "%PARENT%, " . // parent "$_winclass, " . // class $c[6] . ", " . // caption $_usergeom[0] . ", " . // left $_usergeom[1] . ", " . // top $_usergeom[2] . ", " . // width $_usergeom[3] . ", " . // height "%STYLE%, " . // style "%LPARAM%);\n"; // lparam } else { if(is_array($_usergeom)) { if(count($_usergeom) == 2) { // Width, height only $_usergeom[2] = $_usergeom[0]; $_usergeom[3] = $_usergeom[1]; $_usergeom[0] = WBC_CENTER; $_usergeom[1] = WBC_CENTER; } } elseif(is_null($_usergeom)) { $_usergeom[0] = WBC_DEFAULTPOS; $_usergeom[1] = WBC_DEFAULTPOS; $_usergeom[2] = WBC_DEFAULTPOS; $_usergeom[3] = WBC_DEFAULTPOS; } $code = "%WINVAR% = wb_create_window(" . "%PARENT%, " . // parent "$_winclass, " . // class $c[6] . ", " . // caption "WBC_CENTER, " . // left "WBC_CENTER, " . // top // (int)($c[4] * WB_KX_SCREEN + $_addx) . ", " . // (int)($c[5] * WB_KY_SCREEN + $_addy) . ", " . (int)($c[4] * WB_KX_SCREEN) . ", " . (int)($c[5] * WB_KY_SCREEN) . ", " . "%STYLE%, " . // style "%LPARAM%);\n"; // lparam } $_tabN = 0; } return $code; } function _scale_controls($c) { global $_tabN, $path_res; $winclass = $c[3]; $winstyle = hexdec($c[4]); $winexstyle = hexdec($c[9]); if(_bit_test($winstyle, WS_VISIBLE)) $style = "WBC_VISIBLE"; else $style = "WBC_INVISIBLE"; if(_bit_test($winstyle, WS_DISABLED)) $style .= " | WBC_DISABLED"; else $style .= " | WBC_ENABLED"; if(_bit_test($winexstyle, WS_EX_STATICEDGE)) $style .= " | WBC_BORDER"; // Set attributes according to control class switch(strtolower($winclass)) { case '"button"': switch($winstyle & 0x0F) { case BS_AUTORADIOBUTTON: case BS_RADIOBUTTON: $class = "RadioButton"; if(_bit_test($winstyle, WS_GROUP)) $style .= " | WBC_GROUP"; break; case BS_AUTOCHECKBOX: case BS_CHECKBOX: $class = "CheckBox"; break; case BS_GROUPBOX: $class = "Frame"; break; case BS_PUSHBUTTON: default: $class = "PushButton"; break; } break; case '"static"': switch($winstyle & 0x1F) { case SS_ICON: case SS_BITMAP: $style .= " | WBC_IMAGE | WBC_CENTER"; $class = "Frame"; break; case SS_ETCHEDHORZ: case SS_ETCHEDVERT: case SS_ETCHEDFRAME: $class = "Frame"; break; case SS_CENTER: if(_bit_test($winstyle, SS_WORDELLIPSIS)) $style .= " | WBC_ELLIPSIS"; $style .= " | WBC_CENTER"; $class = "Label"; break; case SS_RIGHT: if(_bit_test($winstyle, SS_WORDELLIPSIS)) $style .= " | WBC_ELLIPSIS"; $style .= " | WBC_RIGHT"; $class = "Label"; break; case SS_LEFT: default: if(!_bit_test($winstyle, SS_LEFTNOWORDWRAP)) $style .= " | WBC_MULTILINE"; if(_bit_test($winstyle, SS_WORDELLIPSIS)) $style .= " | WBC_ELLIPSIS"; $class = "Label"; break; } break; case '"edit"': $class = "EditBox"; if(_bit_test($winstyle, ES_MULTILINE)) { $style .= " | WBC_MULTILINE"; } else { switch($winstyle & 0x03) { case ES_CENTER: $style .= " | WBC_CENTER"; break; case ES_RIGHT: $style .= " | WBC_RIGHT"; break; case ES_LEFT: default: break; } } if(_bit_test($winstyle, ES_READONLY)) $style .= " | WBC_READONLY"; if(_bit_test($winstyle, ES_PASSWORD)) $style .= " | WBC_MASKED"; if(_bit_test($winstyle, ES_NUMBER)) $style .= " | WBC_NUMBER"; break; case '"richedit20a"': if(_bit_test($winstyle, ES_READONLY)) $style .= " | WBC_READONLY"; $class = "RTFEditBox"; switch($winstyle & 0x03) { case ES_CENTER: $style .= " | WBC_CENTER"; break; case ES_RIGHT: $style .= " | WBC_RIGHT"; break; case ES_LEFT: default: break; } break; case '"combobox"': $class = "ComboBox"; if(_bit_test($winstyle, CBS_SORT)) $style .= " | WBC_SORT"; if(_bit_test($winstyle, CBS_DROPDOWNLIST)) $style .= " | WBC_READONLY"; break; case '"listbox"': $class = "ListBox"; if(_bit_test($winstyle, LBS_SORT)) $style .= " | WBC_SORT"; break; case '"scrollbar"': $class = "ScrollBar"; break; case '"syslistview32"': $class = "ListView"; if(!_bit_test($winstyle, LVS_NOSORTHEADER)) $style .= " | WBC_SORT"; if(_bit_test($winstyle, LVS_GRIDLINES)) $style .= " | WBC_LINES"; if(_bit_test($winstyle, LVS_CHECKBOXES)) $style .= " | WBC_CHECKBOXES"; if(!_bit_test($winstyle, LVS_SINGLESEL)) $style .= " | WBC_SINGLE"; break; case '"systabcontrol32"': $class = "TabControl"; break; case '"systreeview32"': $class = "TreeView"; break; case '"toolbarwindow32"': $class = "ToolBar"; break; case '"msctls_progress32"': $class = "Gauge"; break; case '"msctls_statusbar32"': $class = "StatusBar"; break; case '"sysmonthcal32"': $class = "Calendar"; break; case '"msctls_trackbar32"': $class = "Slider"; if(_bit_test($winstyle, TBS_AUTOTICKS)) $style .= " | WBC_LINES"; break; case '"msctls_updown32"': $class = "Spinner"; if(_bit_test($winstyle, WS_GROUP)) $style .= " | WBC_GROUP"; break; } // Convert Windows style to WinBinder style $str = "wb_create_control(" . "%WINVAR%, " . // Parent $class . ", " . // Class $c[1] . ", " . // Caption (int)($c[5] * WB_KX_SCREEN) . ", " . // Left (int)($c[6] * WB_KY_SCREEN) . ", " . // Top (int)($c[7] * WB_KX_SCREEN) . ", " . // Width (int)($c[8] * WB_KY_SCREEN) . ", " . // Height $c[2] . ", " . // ID $style . ", " . // Style "0" . // Param ($_tabN ? ", " . ($_tabN - 1) . ");\n" : ");\n"); // Tab # // Add some attributes to controls where needed switch($class) { case "Frame": if(strstr($style, "WBC_IMAGE")) { if(($winstyle & (SS_BITMAP | SS_ICON)) && ($c[1] !== '""')) { $image = $path_res . _trim_quotes($c[1]); if(preg_match("/\.(bmp|ico)$/", $image)) $str = "\$_tmp_ctrl_ = " . $str . "wb_set_image(\$_tmp_ctrl_, '$image', GREEN);" . " unset(\$_tmp_ctrl_);\n"; } } break; case "PushButton": if(($winstyle & (BS_BITMAP | BS_ICON)) && ($c[1] !== '""')) { $image = $path_res . _trim_quotes($c[1]); if($image) if(preg_match("/\.(bmp|ico)$/", $image)) $str = "\$_tmp_ctrl_ = " . $str . "wb_set_image(\$_tmp_ctrl_, '$image', GREEN);" . " unset(\$_tmp_ctrl_);\n"; } break; } return $str; } function _trim_quotes($str) { return str_replace('"', '', $str); } function _bit_test($v, $t) { return (($v & $t) == $t); } //-------------------------------------------------------------------------- EN ?> <?php /******************************************************************************* WINBINDER - The native Windows binding for PHP for PHP Copyright © Hypervisual - see LICENSE.TXT for details Author: Rubem Pechansky (http://winbinder.org/contact.php) Some functions to call the FreeImage library directly *******************************************************************************/ /* This software uses the FreeImage open source image library. See http://freeimage.sourceforge.net for details. FreeImage is used under the FIPL version 1.0. Go to the FreeImage web site (http://freeimage.sourceforge.net) to download the FreeImage DLL and documentation. These functions were successfully tested with the following FreeImage versions: 2.3.1 (600 kB, 260 kB zipped) 2.5.4 (670 kB, 290 kB zipped) 3.4.0 (744 kB, 350 kB zipped) 3.5.3 (888 kB, 413 kB zipped) */ //-------------------------------------------------------------------- CONSTANTS // These were taken from FreeImage.h (version 3.5.3) define("FIF_UNKNOWN", -1); define("FIF_BMP", 0); define("FIF_ICO", 1); define("FIF_JPEG", 2); define("FIF_JNG", 3); define("FIF_KOALA", 4); define("FIF_LBM", 5); define("FIF_IFF", FIF_LBM); define("FIF_MNG", 6); define("FIF_PBM", 7); define("FIF_PBMRAW", 8); define("FIF_PCD", 9); define("FIF_PCX", 10); define("FIF_PGM", 11); define("FIF_PGMRAW", 12); define("FIF_PNG", 13); define("FIF_PPM", 14); define("FIF_PPMRAW", 15); define("FIF_RAS", 16); define("FIF_TARGA", 17); define("FIF_TIFF", 18); define("FIF_WBMP", 19); define("FIF_PSD", 20); define("FIF_CUT", 21); define("FIF_XBM", 22); define("FIF_XPM", 23); define("FIF_DDS", 24); define("FIF_GIF", 25); //------------------------------------------------------------- GLOBAL VARIABLES if(!isset($FI)) { /* * check in application directory, the current directory, 32-bit System directory (e.g. C:\WINDOWS\SYSTEM32), * 16-bit System directory (e.g. C:\WINDOWS\SYSTEM), Windows directory (e.g. C:\WINDOWS) and the directories contained * in the PATH */ $currentLevel = error_reporting(0); $FI = wb_load_library('freeimage'); error_reporting($currentLevel); /* * if the above failed, check for ext-subfolder, hoping that PHP is in the PATH and the dll is in the ext-subfolder */ if(!$FI) { $FI = wb_load_library('ext\\freeimage'); } if(!$FI) { wb_message_box(null, 'FreeImage extension could not be loaded.', 'Error', WBC_STOP); die(); } } //-------------------------------------------------------------------- FUNCTIONS function FreeImage_GetVersion() { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_GetVersion", $FI); // Must use wb_peek because this function returns a string pointer $version = wb_peek(wb_call_function($pfn)); return $version; } function FreeImage_GetInfoHeader($dib) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_GetInfoHeader", $FI); return wb_call_function($pfn, array($dib)); } function FreeImage_GetBits($dib) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_GetBits", $FI); return wb_call_function($pfn, array($dib)); } function FreeImage_Allocate($width, $height, $bpp) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_Allocate@24", $FI); return wb_call_function($pfn, array($width, $height, $bpp, 0, 0, 0)); } function FreeImage_Unload($bmp) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_Unload", $FI); return wb_call_function($pfn, array($bmp)); } function FreeImage_GetWidth($bmp) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_GetWidth", $FI); return wb_call_function($pfn, array($bmp)); } function FreeImage_GetHeight($bmp) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_GetHeight", $FI); return wb_call_function($pfn, array($bmp)); } function FreeImage_Load($type, $filename, $flags=0) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_Load", $FI); return wb_call_function($pfn, array($type, $filename, $flags)); } function FreeImage_Save($type, $dib, $filename, $flags=0) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_Save", $FI); return wb_call_function($pfn, array($type, $dib, $filename, $flags)); } function FreeImage_Rescale($dib, $dst_width, $dst_height, $filter=0) { global $FI; static $pfn = null; if($pfn === null) $pfn = wb_get_function_address("FreeImage_Rescale", $FI); return wb_call_function($pfn, array($dib, $dst_width, $dst_height, $filter)); } //-------------------------------------------------------------------------- END ?><?php namespace ws\loewe\Utils\Autoload; /** * exceptions thrown during autoload need to be linked statically */ require_once 'SourceFileNotFoundException.php'; /** * This class acts as a just-in-time autoloader for class files. Given a base directory, class files are looked up by mapping the classes namespace to a folder, and the class name to a file name in that particular folder. */ class Autoloader { /** * the base directory from where to start looking for source files * * @var string */ private $baseDirectory = null; /** * the extension of the source files to include * * @var string */ private $extension = null; /** * This method acts as the constructor of the class. * * @param string $baseDirectory the base directory from where to start looking for source files */ public function __construct($baseDirectory, $extension = 'inc') { $this->baseDirectory = str_replace('\\', '/', $baseDirectory); $this->extension = $extension; } /** * This method tries to load the source file associated with the class denoted by the given class name. * * If no source file can be found, a SourceFileNotFoundException will be thrown. * * @param string the name of the class to load the source file for */ public function autoload($className) { try { if(file_exists($filename = $this->getFileName($className))) require_once $filename; else throw new SourceFileNotFoundException($className); } catch(SourceFileNotFoundException $sfnfe) { //var_dump($sfnfe->getMessage()); } } /** * This method determines the file name for a given class name, taking the base directory into account. * * @param string the name of the class to load the source file for * @return string the absolute path to the source file */ private function getFileName($className) { return $this->baseDirectory.str_replace('\\', '/', $className).'.'.$this->extension; } }<?php namespace ws\loewe\Utils\Autoload; /** * This class represents an exception, which is thrown when the autoloader is unable to locate a source file that holds the definition of a class or interface. */ class SourceFileNotFoundException extends \RuntimeException { /** * This method acts as the constructor for the class. * * @param string $name the name of the class/interface which could not be found. */ public function __construct($name) { $this->message = 'No source file holding the class/interface definition of the class/interface "'.$name.'" were found!'; } }<?php namespace ws\loewe\Woody\Event; use \ws\loewe\Woody\Components\Component; class EventInfo { use \ws\loewe\Utils\Common\ValueObject; private $windowID = null; private $id = null; private $controlID = null; private $type = null; private $property = null; private $source = null; public function __construct($windowID, $woodyID, Component $component, $typeID, $propertyID) { $this->windowID = $windowID; $this->id = $woodyID; $this->controlID = $component->getControlID(); $this->type = $typeID; $this->property = $propertyID; $this->source = $component; } public function isWindowEvent() { return $this->windowID == $this->controlID; } public function isWindowResizeEvent() { return (is_int($this->type) ? $this->type === WBC_RESIZE : FALSE); } public function isWindowCloseEvent() { return $this->id === IDCLOSE; } public function isOkEvent() { return $this->isWindowEvent() && $this->id == 1 && $this->id != IDCLOSE; } public function isCancelEvent() { return $this->isWindowEvent() && $this->id == 2 && $this->id != IDCLOSE; } public function isTimerEvent() { return $this->isWindowEvent() && $this->id != 0 && $this->id != IDCLOSE; } public function isControlEvent() { return $this->id !== 0; } public function isFocusEvent() { return (is_int($this->type) ? $this->type === WBC_GETFOCUS : FALSE); } public function isMouseEvent() { if(is_int($this->type)) { return ($this->type & WBC_MOUSEDOWN) || ($this->type & WBC_MOUSEUP) || ($this->type & WBC_DBLCLICK); } else { return FALSE; } } public function isKeyEvent() { if(is_int($this->type)) { return ($this->type === WBC_KEYDOWN) || ($this->type === WBC_KEYUP); } else { return FALSE; } } } <?php namespace ws\loewe\Woody\Event; use \ws\loewe\Utils\Http\HttpGetRequest; use \ws\loewe\Woody\Components\Controls\Actionable; use \ws\loewe\Woody\Components\Controls\Control; /** * This class is responsible for creating events from the raw winbinder event data. Furhtermore, it dispatched the * created events to listeneres registered at the respective source of the event. */ class EventFactory { /** * the control that just had the focus before * * @var Control */ private static $previousFocusedControl = null; /** * This method creates a collection of events based in the event info object that is given as input. * * @param EventInfo $eventInfo the event info object containing the raw event information * @return \Traversable */ public static function createEvent(EventInfo $eventInfo) { $events = new \ArrayObject(); // window close button is not a real control, so handle it here - close window if($eventInfo->isWindowCloseEvent()) { $events[] = self::createWindowClosedEvent($eventInfo); } // events being triggered when pressing ENTER or ESC in controls else if($eventInfo->isOkEvent() || $eventInfo->isCancelEvent()) { // ignore for now } // timeout of timers are handled here, too - the callback is executed by calling Timer::run else if($eventInfo->isTimerEvent()) { $events[] = self::createTimeoutEvent($eventInfo); } else if($eventInfo->isFocusEvent()) { $events[] = self::createFocusEvent($eventInfo); } else if($eventInfo->isMouseEvent()) { $events[] = self::createMouseEvent($eventInfo); } else if($eventInfo->isKeyEvent()) { $events[] = self::createKeyEvent($eventInfo); } // create and dispatch WindowEvents, e.g. when resizing a window else if($eventInfo->isWindowEvent()) { if($eventInfo->isWindowResizeEvent()) { $events[] = self::createWindowResizeEvent($eventInfo); } } if($eventInfo->isControlEvent()) { // only handle non-focus-events of controls (FocusEvent was handled above and does not trigger Actions) if(!$eventInfo->isFocusEvent()) { $events[] = self::createActionEvent($eventInfo); } } // app crashes when an ActionEvent was created and $event was returned here !?!?!?! return $events; } private static function createFocusEvent($eventInfo) { $event = new FocusEvent($eventInfo, self::$previousFocusedControl); self::$previousFocusedControl = $event->getSource(); return $event; } private static function createMouseEvent($eventInfo) { $event = new MouseEvent($eventInfo); return $event; } private static function createKeyEvent($eventInfo) { return new KeyEvent($eventInfo); } // no other events are raised when, e.g., clicking on a button, or selecting from a listbox, therefore, AcionEvents // are needed // TODO: for EditBox, an ActionEvent would be FocusLost + content changed = onChangeEvent private static function createActionEvent($eventInfo) { // trigger action events for all Actionables, as well as when the propertyID actually is a HttpGetRequest // the later are special events, namely those raised by HTMLControls when they receive new data // @see HtmlControlServer::processClient $event = new ActionEvent($eventInfo); if($event->getSource() instanceof Actionable || $event->property instanceof HttpGetRequest) { return $event; } return null; } private static function createWindowResizeEvent($eventInfo) { $event = new WindowResizeEvent($eventInfo); // update the dimension of the Woody object here (the actual component is already resized) if($event->getSource() !== null) $event->getSource()->resizeTo($event->getNewDimension()); return $event; } private static function createWindowClosedEvent($eventInfo) { return new WindowCloseEvent($eventInfo); } private static function createTimeoutEvent($eventInfo) { return new TimeoutEvent($eventInfo); } }<?php namespace ws\loewe\Woody\Components; use ws\loewe\Utils\Geom\Dimension; use ws\loewe\Utils\Geom\Point; use ws\loewe\Woody\Components\Controls\Frame; use ws\loewe\Woody\Event\ActionListener; use ws\loewe\Woody\Event\FocusListener; use ws\loewe\Woody\Event\KeyListener; use ws\loewe\Woody\Event\MouseListener; /** * This class defines the basic frame for any component of a graphical user interface. * * @author stefan.loewe.ws */ abstract class Component implements IComponent { /** * the internal winbinder control id of this component * * @var int */ protected $controlID = null; /** * the logical id of this component, i.e the woody id * * @var int */ protected $id = null; /** * the type of the component, i.e. the winbinder constant representing the control type * * @var int */ protected $type = null; /** * the top left corner of the component * * @var Point */ protected $topLeftCorner = null; /** * the dimension of the component * * @var Dimension */ protected $dimension = null; /** * the value (e.g. value of an EditBox, the label of a Frame, the selection of a ListBox) of the control * * @var string */ protected $value = null; /** * the parent container of this window * * @var Frame */ protected $parent = null; /** * the collection of action listeners registered for the component * * @var \SplObjectStorage */ private $actionListeners = null; /** * the collection of mouse listeners registered for the component * * @var \SplObjectStorage */ private $mouseListeners = null; /** * the collection of action listeners registered for the component * * @var \SplObjectStorage */ private $keyListeners = null; /** * the collection of focus listeners registered for the component * * @var \SplObjectStorage */ private $focusListeners = null; // @TODO handle param and style with constructor injection, subclassing or decorator pattern? protected $style = 0; protected $param = 0; protected static $components = array(); /** * static internal integer, that is used as id generator for creating components, starting at 1024 not to interfer * with special control ids (e.g. 8 is window close) * * @var int */ private static $IDENTIFIER = 1024; public function __construct($value, Point $topLeftCorner, Dimension $dimension) { $this->id = self::getUniqueID(); $this->value = $value; $this->topLeftCorner = Point::createInstance($topLeftCorner->x, $topLeftCorner->y); $this->dimension = Dimension::createInstance($dimension->width, $dimension->height); } /** * This method return an unique identifier for each control * * The fact that this method is public is an implementation detail - the Timer class needs this functionality, too. * Do not call this method yourself. * * @return int */ public static function getUniqueID() { return ++self::$IDENTIFIER; } /** * This method returns the component having the given winbinder id. * * Normally, it should not be neccassary to call this method, but rather manage references to the respective controls * within the dialog class. This is currently only needed internally for event handling. Note that a component has to * be created first (@see Component::create) to be returned by this method. * * @param int $id the winbinder id of the component * @return Component the component with the respective winbinder id */ public static function getComponentByID($id) { return self::$components[$id]; } /** * This method creates a component physically as a winbinder control. * * Do not call this method manually, it is called by ws\loewe\Woody\Components\Container::add only. It is an implementation * side-effect that it is public. * * @param Component $parent the parent component of this component * @return $this */ abstract protected function create(Component $parent); public function getControlID() { return $this->controlID; } public function getID() { return $this->id; } public function getParent() { return $this->parent; } public function getPosition() { return Point::createInstance($this->topLeftCorner->x, $this->topLeftCorner->y); } public function getDimension() { return Dimension::createInstance($this->dimension->width, $this->dimension->height); } public function moveBy(Dimension $dimension) { return $this->move($this->topLeftCorner->moveBy($dimension)); } public function moveTo(Point $topLeftCorner) { return $this->move($topLeftCorner); } /** * This method moves the top left corner of the component to the given point, respecting the bounds of the screen. * * @param Point $topLeftCorner * @return Component $this */ protected function move(Point $topLeftCorner) { wb_set_position($this->controlID, $topLeftCorner->x, $topLeftCorner->y); $this->topLeftCorner = Point::createInstance($topLeftCorner->x, $topLeftCorner->y); return $this; } public function resizeBy(Dimension $dimension) { return $this->resize($this->dimension->resizeBy($dimension)); } public function resizeTo(Dimension $dimension) { return $this->resize($dimension); } /** * This method resizes the component to the given dimension, respecting the minimal size of a window. * * @param Dimension $dimension the new dimension of the component. * @return Component $this */ protected function resize(Dimension $dimension) { $width = $dimension->width; $height = $dimension->height; wb_set_size($this->controlID, $width, $height); $this->dimension = Dimension::createInstance($width, $height); return $this; } /** * This method adds an action listener to the component. * * @param ActionListener $actionListener the action listener to add * @return Component $this */ public function addActionListener(ActionListener $actionListener) { if($this->actionListeners == null) { $this->actionListeners = new \SplObjectStorage(); } $this->actionListeners->attach($actionListener); return $this; } /** * This method returns the collection of action listeners registered for the component. * * @return \SplObjectStorage the collection of action listeners registered for the component */ public function getActionListeners() { return ($this->actionListeners == null) ? new \SplObjectStorage() : $this->actionListeners; } /** * This method removes an action listener from the component. * * @param ActionListener $actionListener the action listener to remove * @return Component $this */ public function removeActionListener(ActionListener $actionListener) { if($this->actionListeners != null) { $this->actionListeners->detach($actionListener); } return $this; } /** * This method adds a focus listener to the component. * * @param FocusListener $focusListener the focus listener to add * @return Component $this */ public function addFocusListener(FocusListener $focusListener) { if($this->focusListeners == null) { $this->focusListeners = new \SplObjectStorage(); } $this->focusListeners->attach($focusListener); return $this; } /** * This method returns the collection of focus listeners registered for the component. * * @return \SplObjectStorage the collection of focus listeners registered for the component */ public function getFocusListeners() { return ($this->focusListeners == null) ? new \SplObjectStorage() : $this->focusListeners; } /** * This method removes a focus listener from the component. * * @param FocusListener $focusListener the focus listener to remove * @return Component $this */ public function removeFocusListener(FocusListener $focusListener) { if($this->focusListeners != null) { $this->focusListeners->detach($focusListener); } return $this; } /** * This method adds a key listener to the component. * * @param KeyListener $keyListener the key listener to add * @return Component $this */ public function addKeyListener(KeyListener $keyListener) { if($this->keyListeners == null) { $this->keyListeners = new \SplObjectStorage(); } $this->keyListeners->attach($keyListener); return $this; } /** * This method returns the collection of key listeners registered for the component. * * @return \SplObjectStorage the collection of key listeners registered for the component */ public function getKeyListeners() { return ($this->keyListeners == null) ? new \SplObjectStorage() : $this->keyListeners; } /** * This method removes a key listener from the component. * * @param KeyListener $keyListener the key listener to remove * @return Component $this */ public function removeKeyListener(KeyListener $keyListener) { if($this->keyListeners != null) { $this->keyListeners->detach($keyListener); } return $this; } /** * This method adds a mouse listener to the component. * * @param MouseListener $mouseListener the mouse listener to add * @return Component $this */ public function addMouseListener(MouseListener $mouseListener) { if($this->mouseListeners == null) { $this->mouseListeners = new \SplObjectStorage(); } $this->mouseListeners->attach($mouseListener); return $this; } /** * This method returns the collection of mouse listeners registered for the component. * * @return \SplObjectStorage the collection of mouse listeners registered for the component */ public function getMouseListeners() { return ($this->mouseListeners == null) ? new \SplObjectStorage() : $this->mouseListeners; } /** * This method removes a mouse listener from the component. * * @param MouseListener $mouseListener the mouse listener to remove * @return Component $this */ public function removeMouseListener(MouseListener $mouseListener) { if($this->mouseListeners != null) { $this->mouseListeners->detach($mouseListener); } return $this; } public function refresh($now = TRUE) { wb_refresh($this->controlID, $now); return $this; } public function enable() { wb_set_enabled($this->controlID, TRUE); return $this; } public function disable() { wb_set_enabled($this->controlID, FALSE); return $this; } public function show() { wb_set_visible($this->controlID, TRUE); return $this; } public function hide() { wb_set_visible($this->controlID, FALSE); return $this; } } <?php namespace ws\loewe\Woody\Event; interface FocusListener { function focusGained(FocusEvent $event); }<?php namespace ws\loewe\Woody\Event; use \ws\loewe\Woody\Components\Component; class FocusEvent extends Event { /** * the component which lost the focus, maybe null if no component was focused before * * @var Component */ protected $lostFocusComponent = null; /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event * @param $lostFocusComponent Component the component which lost the focus, which maybe null if no component was */ public function __construct(EventInfo $eventInfo, Component $lostFocusComponent = null) { parent::__construct($eventInfo); $this->lostFocusComponent = $lostFocusComponent; } public function dispatch() { foreach($this->getSource()->getFocusListeners() as $focusListener) { $focusListener->focusGained($this); } } /** * This method returns which component gained focus. * * @return Component the component which gained focus */ public function getFocusGainedComponent() { return $this->getSource(); } /** * This method returns which component lost focus. * * @return Component the component which lost focus */ public function getFocusLostComponent() { return $this->lostFocusComponent; } /** * This method returns the string representation of the event. * * @return string the string representation of the event */ public function __toString() { return parent::__toString().PHP_EOL. 'gained = '.$this->getFocusGainedComponent()->getID().PHP_EOL. 'lost = '.($this->lostFocusComponent === null ? 'none' : $this->lostFocusComponent->getID()); } }<?php namespace ws\loewe\Woody\Event; interface KeyListener { /** * This method is called, when the key-pressed event occurs. */ function keyPressed(KeyEvent $event); /** * This method is called, when the key-pressed event occurs. */ function keyReleased(KeyEvent $event); }<?php namespace ws\loewe\Woody\Event; class KeyEvent extends Event { /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); } public function dispatch() { foreach($this->getSource()->getKeyListeners() as $keyListener) { if($this->isKeyDownEvent()) { $keyListener->keyPressed($this); } else if($this->isKeyUpEvent()) { $keyListener->keyReleased($this); } } } private function isKeyUpEvent() { return ($this->type & WBC_KEYUP) == WBC_KEYUP; } private function isKeyDownEvent() { return ($this->type & WBC_KEYDOWN) === WBC_KEYDOWN; } /** * This method returns which key was pressed. * * @return string the key which was pressed */ public function getPressedKey() { return chr($this->property); } /** * This method returns the string representation of the event. * * @return string the string representation of the event */ public function __toString() { return parent::__toString().PHP_EOL. 'key = '.$this->getPressedKey().PHP_EOL. 'A/C/S = '.$this->isAltKeyPressed() .'/'.$this->isCtrlKeyPressed() .'/'.$this->isShiftKeyPressed(); } }<?php namespace ws\loewe\Woody\Event; interface MouseListener { function mousePressed(MouseEvent $event); function mouseReleased(MouseEvent $event); }<?php namespace ws\loewe\Woody\Event; use \ws\loewe\Utils\DataStructures\RingBuffer; use \ws\loewe\Utils\Geom\Point; class MouseEvent extends Event { /** * constant for no mouse button being pressed */ const NO_BUTTON = 0; /** * constant for left/first mouse button being pressed */ const BUTTON1 = WBC_LBUTTON; /** * constant for right/second mouse button being pressed */ const BUTTON2 = WBC_RBUTTON; /** * constant for middle/third mouse button being pressed */ const BUTTON3 = WBC_MBUTTON; /** * the event ring buffer - needed for determining the click-counter of mouse events. * * @var RingBuffer */ private static $eventBuffer = null; /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); if(self::$eventBuffer === null) { self::$eventBuffer = new RingBuffer(10); } if($this->isMouseDownEvent()) { self::$eventBuffer->add($this); } } public function dispatch() { foreach($this->getSource()->getMouseListeners() as $mouseListener) { if($this->isMouseDownEvent()) { $mouseListener->mousePressed($this); } else if($this->isMouseUpEvent()) { $mouseListener->mouseReleased($this); } } } private function isMouseDownEvent() { return (($this->type & WBC_MOUSEDOWN) === WBC_MOUSEDOWN) || (($this->type & WBC_DBLCLICK) === WBC_DBLCLICK); } private function isMouseUpEvent() { return ($this->type & WBC_MOUSEUP) === WBC_MOUSEUP; } /** * This method returns the position of the mouse when the event occured. * * @var Point the position of the mouse when the event occured */ public function getPosition() { return Point::createInstance($this->property & 0xFFFF, ($this->property & 0xFFFF0000) >> 16); } /** * This method returns which mouse button was pressed. * * @return int the mouse button which was pressed, either one of MouseEvent:NO_BUTTON, MouseEvent::BUTTON1, * MouseEvent::BUTTON2 or MouseEvent::BUTTON3 */ public function getPressedButton() { $button = self::NO_BUTTON; if($this->type & self::BUTTON1) { $button = self::BUTTON1; } else if($this->type & self::BUTTON2) { $button = self::BUTTON2; } else if($this->type & self::BUTTON3) { $button = self::BUTTON3; } return $button; } public function getClickCount() { $libUser = wb_load_library('USER'); $function = wb_get_function_address('GetDoubleClickTime', $libUser); $interval = wb_call_function($function, array()) / 1000; $button = $this->getPressedButton(); $clickCount = 0; $eventFound = FALSE; foreach(self::$eventBuffer->getLiFoOrder() as $currentEvent) { $eventFound = $eventFound || $this == $currentEvent; if($eventFound) { if($currentEvent->getPressedButton() !== $button) { return $clickCount; } if(($this->time - $currentEvent->time) > $interval) { return $clickCount; } $clickCount++; } } return $clickCount; } /** * This method returns the string representation of the event. * * @return string the string representation of the event */ public function __toString() { return parent::__toString().PHP_EOL. 'button = '.$this->getPressedButton().PHP_EOL. 'position = '.$this->getPosition().PHP_EOL. 'A/C/S = '.$this->isAltKeyPressed() .'/'.$this->isCtrlKeyPressed() .'/'.$this->isShiftKeyPressed(); } }<?php namespace ws\loewe\Utils\DataStructures; class RingBuffer { /** * the size of the buffer * * @var int */ private $buffer = null; /** * the current index of the buffer * * @var int */ private $index = 0; /** * This method acts as the constructor of the class. * * @param int $size the size of the buffer */ public function __construct($size) { $this->buffer = new \SplFixedArray($size); } /** * This method adds the item to the buffer. * * @param mixed $item the item to add */ public function add($item) { $this->index = (++$this->index) % $this->buffer->getSize(); $this->buffer[$this->index] = $item; } /** * This method returns the items in reversed (i.e. last in, first out) order, starting with the item that was inserted * last. * * @return array[int]mixed the set of items, in reveresed order */ public function getLifoOrder() { $result = array(); for($i = 0; $i < $this->buffer->getSize(); $i++) { $currentIndex = $this->index - $i; if($currentIndex < 0) { $currentIndex = $currentIndex + $this->buffer->getSize(); } if($this->buffer[$currentIndex] !== null) { $result[] = $this->buffer[$currentIndex]; } } return $result; } }<?php namespace ws\loewe\Woody\Components; use ws\loewe\Woody\Components\Controls\Frame; use ws\loewe\Utils\Geom\Dimension; use ws\loewe\Utils\Geom\Point; interface IComponent { /** * This method returns the winbinder control id of the component. * * @return int */ public function getControlID(); /** * This method returns the id of the component. * * @return int */ public function getID(); /** * This method returns the container holding the component. * * @return Frame the container holding the component */ public function getParent(); /** * This method returns the top left corner of the component. * * @return Point the top left corner of the component. */ public function getPosition(); /** * This method returns the dimension of the top left corner of the component. * * @return Dimension the dimension of the control */ public function getDimension(); /** * This method moves the component by an offset, given as dimension. * * @param Dimension $dimension the dimension by which this point shall be moved by * @return Component $this */ public function moveBy(Dimension $dimension); /** * This method moves the top left corner of the component to the given point. * * @param Point $topLeftCorner the new point of the top left corner * @return Component $this */ public function moveTo(Point $topLeftCorner); /** * This method resizes the component by the offset given as a dimension. * * @param Dimension $dimension the offset by which the component has to be resized * @return Component $this */ public function resizeBy(Dimension $dimension); /** * This method resizes the component to the given dimension. * * @param Dimension $dimension the new dimension of the component. * @return Component $this */ public function resizeTo(Dimension $dimension); public function refresh(); public function enable(); public function disable(); }<?php namespace ws\loewe\BattMan\App; use \ws\loewe\BattMan\Model\BatteryState; use \ws\loewe\BattMan\View\TextView; use \ws\loewe\BattMan\View\GraphView; use \ws\loewe\BattMan\View\ControlView; use \ws\loewe\BattMan\View\LogView; use \ws\loewe\Woody\App\Application; use \ws\loewe\Woody\Components\Windows\ResizableWindow; use \ws\loewe\Woody\Components\Controls\ProgressBar; use \ws\loewe\Woody\Components\Timer\Timer; use \ws\loewe\Woody\Event\WindowResizeAdapter; use \ws\loewe\Woody\Event\WindowResizeEvent; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class BattManApplication extends Application { private $status = null; private $textView = null; private $graphView = null; private $controlView = null; private $logView = null; private $barPower = null; private $updateTimer = null; private $updateTimerInterval = 1000; private $isRunning = FALSE; private $shutdownTimer = null; /** * This method acts as the constructor of the class. */ public function __construct() { parent::__construct(); $this->window = new ResizableWindow('ws\loewe\BattMan', Point::createInstance(50, 50), Dimension::createInstance(825, 525)); $this->window->create(null); $this->window->addWindowResizeListener(new WindowResizeAdapter(function(WindowResizeEvent $event) { $delta = $event->getDeltaDimension(); $this->graphView->resizeBy(Dimension::createInstance($delta->width, $delta->height)); $this->logView->resizeBy(Dimension::createInstance($delta->width, $delta->height)); $this->barPower->moveBy(Dimension::createInstance(0, $delta->height))->resizeBy(Dimension::createInstance($delta->width, 0)); })); $this->window->setWindowCloseListener( new \ws\loewe\Woody\Event\WindowCloseAdapter( function($event) { $event->getSource()->close(); echo "\nGoodbye";} )); $this->shutdownTimer = new Timer($this->getShutdownCallback(), $this->window, 1000); $this->shutdownTimer->start(); } // the callback that actually closes the window private function getShutdownCallback() { return function() { if(!$this->isRunning) { $this->shutdownTimer->destroy(); $this->window->destroy(); } }; } /** * This method starts the application. * * @return \ws\loewe\BattMan\App\ws\loewe\BattManApplication $this */ public function start() { $this->isRunning = TRUE; $this->init(); $this->window->startEventHandler(); return $this; } private function initTextView() { $this->textView = new TextView(Point::createInstance(5, 5), Dimension::createInstance(300, 120)); $this->window->getRootPane()->add($this->textView->getFrame()); $this->textView->initialize(); } private function initGraphView() { $this->graphView = new GraphView(Point::createInstance(305, 5), Dimension::createInstance(500, 450)); $this->window->getRootPane()->add($this->graphView->getFrame()); $this->graphView->initialize(); } private function initControlView() { $this->controlView = new ControlView(Point::createInstance(5, 130), Dimension::createInstance(300, 50)); $this->window->getRootPane()->add($this->controlView->getFrame()); $this->controlView->initialize(); } private function initLogView() { $this->logView = new LogView(Point::createInstance(5, 185), Dimension::createInstance(300, 297)); $this->window->getRootPane()->add($this->logView->getFrame()); $this->logView->initialize(); } private function init() { $this->initTextView(); $this->initControlView(); $this->initGraphView(); $this->initLogView(); $this->barPower = new ProgressBar(Point::createInstance(305, 465), Dimension::createInstance(500, 25)); $this->window->getRootPane()->add($this->barPower); $this->barPower->setRange(0, 100); // make view updates periodically $updateCallback = function() { $this->updateViews(); }; $this->updateTimer = new Timer($updateCallback, $this->window, $this->updateTimerInterval); $this->updateTimer->start(); $this->updateViews(); } private function updateViews() { $this->status = new BatteryState($this->status); $this->textView->update($this->status); $this->barPower->setProgress($this->status->getPercentRemaining()); // update log and graph only every 10th time if($this->updateTimer->getExecutionCount() % 10 === 0) { $this->graphView->update($this->status); $this->logView->update($this->status); } } /** * This method stops the application. * * @return \ws\loewe\BattMan\App\ws\loewe\BattManApplication $this */ public function stop() { $this->isRunning = FALSE; } /** * This method is a utility method to format an amount of seconds in a human readable way. * * @param int $seconds the amount of seconds * @return string the amount of seconds formatted in a human readable way */ public static function formatSeconds($seconds) { $date = new \DateTime(); $date->add(new \DateInterval('PT'.$seconds.'S')); return $date->diff(new \DateTime())->format('%H:%I:%S'); } }<?php namespace ws\loewe\BattMan\Model; use \ws\loewe\Woody\Util\WinApi\WinApi; class BatteryState implements Model { private $state = null; private $creationTime = 0; private $timeOnBattery = 0; const AC_OFFLINE = 0; const AC_ONLINE = 1; const NO_BATTERY = 128; const BATTERY_STATE_UNKNOWN = 255; const BATTERY_CHARGING = 8; const PERCENTAGE_UNKNOWN = 255; const TIME_UNKNOWN = -1; public function __construct(self $previousStatus = null) { $this->initialize(); $this->creationTime = time(); if($previousStatus === null) { $this->timeOnBattery = 0; } else { $this->timeOnBattery = $previousStatus->timeOnBattery; if($this->state->ACLineStatus === self::AC_OFFLINE) { $this->timeOnBattery += $this->creationTime - $previousStatus->creationTime; } } } private function initialize() { $this->state = new SystemPowerStatus(); WinApi::call('Kernel32::GetSystemPowerStatus', array($this->state)); } public function getPowerStatus() { if($this->state->ACLineStatus === self::AC_OFFLINE) { return 'no'; } else if($this->state->ACLineStatus === self::AC_ONLINE) { return 'yes'; } return 'unknown'; } public function getBatteryStatus() { if($this->state->BatteryFlag === self::BATTERY_STATE_UNKNOWN) { return 'unknown'; } else if($this->state->BatteryFlag === self::NO_BATTERY) { return 'no battery available'; } else if(($this->state->BatteryFlag & self::BATTERY_CHARGING) === self::BATTERY_CHARGING) { return 'yes'; } return 'no'; } public function getPercentRemaining() { if($this->state->BatteryLifePercent === self::PERCENTAGE_UNKNOWN) { return 'unknown'; } return $this->state->BatteryLifePercent; } public function getTimeRemaining() { if($this->state->BatteryLifeTime === self::TIME_UNKNOWN) { return 0; } return $this->state->BatteryLifeTime; } public function getTimeOnBattery() { return $this->timeOnBattery; } public function getCreationTime() { return $this->creationTime; } } <?php namespace ws\loewe\Woody\Util\WinApi; class WinApi { /** * This method allows making calls to function of the Windows API. * * @param string $callTarget the functin to be called, given in the format <LibraryName>::<functionName>, * e.g. Kernel32::GetSystemPowerStatus * @param array $arguments the set of arguments to pass to the called Windows API function */ public static function call($callTarget, array $arguments) { $parts = explode('::', $callTarget); $libraryName = $parts[0]; $functionName = $parts[1]; $library = wb_load_library($libraryName); $function = wb_get_function_address($functionName, $library); // automatically pack objects of type Structure $originalArguments = array(); foreach($arguments as $index => $argument) { if($argument instanceof Structure) { $originalArguments[$index] = $argument; $arguments[$index] = $argument->pack(); } } wb_call_function($function, $arguments); // automatically unpack objects of type Structure foreach($originalArguments as $index => $argument) { if($argument instanceof Structure) { $argument->unpack($arguments[$index]); } } } }<?php namespace ws\loewe\BattMan\Model; use \ws\loewe\Woody\Util\WinApi\Structure; class SystemPowerStatus extends Structure { /** * @var Byte */ public $ACLineStatus = null; /** * @var Byte */ public $BatteryFlag = null; /** * @var Byte */ public $BatteryLifePercent = null; /** * @var Byte */ public $Reserved1 = null; /** * @var Dword */ public $BatteryLifeTime = null; /** * @var Dword */ public $BatteryFullLifeTime = null; /** * This method acts as the constructor of the class. */ public function __construct() {} }<?php namespace ws\loewe\Woody\Util\WinApi; abstract class Structure { /** * This method acts as the constructor of the class. */ public function __construct() { } /** * This method returns the packed binary representation of this object, so that it can be passed to the C backend. * * @return string packed binary representation of this object */ public function pack() { $packString = ''; foreach($this->getTypeMapping() as $type) { $typeClassName = "\\ws\loewe\Woody\\Util\\WinApi\\Types\\".$type; $typeClass = new $typeClassName(); $packString = $packString.pack($typeClass->getPackFormatCharacter(), $typeClass->getLength()); } return $packString; } /** * This method unpacks the given packed binary data, and maps it to this objects properties * * @param string $pack the binary data to unpack */ public function unpack($pack) { $asArray = unpack($this->getUnpackFormatString(), $pack); foreach($asArray as $propertyName => $propertyValue) { $this->$propertyName = $propertyValue; } } /** * This method computes the format string for unpacking the binary representation of this class. * * @return string the format string needed for unpacking */ private function getUnpackFormatString() { $unpackString = ''; foreach($this->getTypeMapping() as $propertyName => $type) { $typeClassName = "\\ws\loewe\Woody\\Util\\WinApi\\Types\\".$type; $typeClass = new $typeClassName(); $unpackString = $unpackString.$typeClass->getPackFormatCharacter().$propertyName.'/'; } return $unpackString; } /** * This method gets a mapping from class property name to the type of the class property. * * @return array[string]string */ private function getTypeMapping() { $reflectionClass = new \ReflectionClass($this); $properties = $reflectionClass->getProperties(); $mapping = array(); foreach($properties as $property) { $mapping[$property->getName()] = $this->extractType($property->getDocComment()); } return $mapping; } /** * This method extracts the type name from a class properties' doc-block comment. * * @param string $docBlockComment the doc-block comment from where to extract the type name. * @return string the type name of the class property */ private function extractType($docBlockComment) { $lines = explode("\n", $docBlockComment); foreach($lines as $line) { if(strpos(trim($line), '* @var') === 0) { return trim(str_replace('* @var', '', $line)); } } return 'void'; } }<?php namespace ws\loewe\BattMan\View; use ws\loewe\BattMan\App\BattManApplication; use ws\loewe\BattMan\Model\Model; use ws\loewe\Utils\Geom\Dimension; use ws\loewe\Utils\Geom\Point; use ws\loewe\Woody\Components\Controls\EditBox; use ws\loewe\Woody\Components\Controls\Label; use ws\loewe\Woody\Layouts\GridLayout; class TextView extends View { private $txtConnectedToAC = null; private $txtIsCharging = null; private $txtPercentLeft = null; private $txtTimeLeft = null; private $txtTimeOnBattery = null; public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct($topLeftCorner, $dimension); } public function initialize() { $this->frame->setLayout($layout = new GridLayout(5, 2, 0, 0)); $this->frame->add(new Label('connected to power:', Point::createInstance(5, 5), Dimension::createInstance(15, 15))); $this->frame->add($this->txtConnectedToAC = new EditBox('', Point::createInstance(25, 5), Dimension::createInstance(15, 15))); $this->frame->add(new Label('battery being charged:', Point::createInstance(5, 25), Dimension::createInstance(15, 15))); $this->frame->add($this->txtIsCharging = new EditBox('', Point::createInstance(25, 25), Dimension::createInstance(15, 15))); $this->frame->add(new Label('remaining battery life:', Point::createInstance(5, 45), Dimension::createInstance(15, 15))); $this->frame->add($this->txtPercentLeft = new EditBox('', Point::createInstance(25, 45), Dimension::createInstance(15, 15))); $this->frame->add(new Label('remaining battery time:', Point::createInstance(5, 65), Dimension::createInstance(15, 15))); $this->frame->add($this->txtTimeLeft = new EditBox('', Point::createInstance(25, 65), Dimension::createInstance(15, 15))); $this->frame->add(new Label('time running on battery:', Point::createInstance(5, 65), Dimension::createInstance(15, 15))); $this->frame->add($this->txtTimeOnBattery = new EditBox('', Point::createInstance(25, 65), Dimension::createInstance(15, 15))); $layout->layout($this->frame); $this->txtConnectedToAC->setReadOnly(TRUE); $this->txtIsCharging->setReadOnly(TRUE); $this->txtPercentLeft->setReadOnly(TRUE); $this->txtTimeLeft->setReadOnly(TRUE); $this->txtTimeOnBattery->setReadOnly(TRUE); } public function update(Model $currentState) { $this->txtConnectedToAC->setValue($currentState->getPowerStatus()); $this->txtIsCharging->setValue($currentState->getBatteryStatus()); $this->txtPercentLeft->setValue($currentState->getPercentRemaining()); $this->txtTimeLeft->setValue(BattManApplication::formatSeconds($currentState->getTimeRemaining())); $this->txtTimeOnBattery->setValue(BattManApplication::formatSeconds($currentState->getTimeOnBattery())); /* if($currentState->getPowerStatus() === 'offline') { $timeOnBattery = $this->txtTimeOnBattery->getValue(); if($timeOnBattery === null) { $timeOnBattery = -1; } $date = new \DateTime(); $date->add(new \DateInterval('PT'.($timeOnBattery + 1).'S')); $this->txtTimeOnBattery->setValue($date->diff(new \DateTime())->format('%H:%I:%S')); } */ } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class EditBox extends EditField { /** * This method acts as the constructor of the class. * * @param mixed $value the preset value of the edit box * @param Point $topLeftCorner the top left corner of the edit box * @param Dimension $dimension the dimension of the edit box */ public function __construct($value, Point $topLeftCorner, Dimension $dimension) { parent::__construct($value, $topLeftCorner, $dimension); } }<?php namespace ws\loewe\BattMan\View; use \ws\loewe\BattMan\App\BattManApplication; use \ws\loewe\BattMan\Components\Timer\RunOnceTimer; use \ws\loewe\BattMan\Model\Model; use \ws\loewe\Utils\Geom\Dimension; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Woody\Components\Controls\Image; use \ws\loewe\Woody\Util\Image\ImageResource; class GraphView extends View { /** * the dimension of the frame * * @var Dimension */ private $frmDimension = null; /** * the inset of the graph * * @var Dimension */ private $imgInset = null; /** * the image holding th egraph * * @var Image */ private $imgGraph = null; /** * the collection of states * * @var ArrayObject */ private $states = null; /** * the timer for repainting * * @var Timer */ private $repaintTimer = null; public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct($topLeftCorner, $dimension); $this->frmDimension = $dimension; $this->imgInset = Dimension::createInstance(-10, -20); } public function initialize() { $this->initializeGraphImage($this->initializeBitmap()); $this->states = new \ArrayObject(); } private function initializeGraphImage($bitmap) { $this->imgGraph = new Image($bitmap, Point::createInstance(5, 15), $this->frmDimension->resizeBy($this->imgInset)); $this->frame->add($this->imgGraph); } private function initializeBitmap() { return ImageResource::create($this->frmDimension->resizeBy($this->imgInset)); } public function update(Model $currentState) { $imageDimension = $this->frmDimension->resizeBy($this->imgInset); if($imageDimension->width === 0 || $imageDimension->height === 0) { return; } // only add the current state if collection is empty or last element is not same as current state // the latter might happen when adding it repeatedly during resizing if($this->states->count() == 0 || $this->states[$this->states->count() - 1] != $currentState) { $this->states[] = $currentState; } $bitmap = $this->initializeBitmap(); $this->drawBackground($bitmap) ->drawGrid($bitmap) ->drawTimeLines($bitmap, $imageDimension) ->drawChart($bitmap, $imageDimension); // force repaint of frame, image $this->frame->remove($this->imgGraph); $this->imgGraph = new Image($bitmap, Point::createInstance(5, 15), $imageDimension); $this->frame->add($this->imgGraph); } private function drawBackground($bitmap) { $bitmap->drawRectangle(Point::createInstance(0, 0), $this->frmDimension->resizeBy($this->imgInset), 0xFFFFFF); return $this; } private function drawGrid($bitmap) { for($x = 0; $x < $this->frame->getDimension()->width; $x += 10) { $source = Point::createInstance($x, 0); $target = Point::createInstance($x, $this->frmDimension->height - $this->imgInset->height); $bitmap->drawLine($source, $target, 0xFFC0A0); } return $this; } private function drawChart($bitmap, $imageDimension) { $stepWidth = 1;//$imageDimension->width / (count($this->states) + 1); $stepHeight = $imageDimension->height / 100; $increment = ceil(count($this->states) / $imageDimension->width); $index = 1; for($i = 0; $i < count($this->states) - $increment; $i = $i + $increment) { $sourceState = $this->states[$i]; $targetState = $this->states[$i + $increment]; $source = Point::createInstance(($index - 1) * $stepWidth, $stepHeight * (100 - $sourceState->getPercentRemaining())); $target = Point::createInstance($index * $stepWidth, $stepHeight * (100 - $targetState->getPercentRemaining())); $bitmap->drawLine($source, $target, 0x0000FF, 1); $index++; } return $this; } private function drawTimeLines($bitmap, $imageDimension) { $increment = (ceil(count($this->states) / $imageDimension->width)); for($i = 0; $i < 64; $i++) { $xOffset = (90 * $i) / $increment; $source = Point::createInstance($xOffset, 0); $target = Point::createInstance($xOffset, $this->frmDimension->height - $this->imgInset->height); $bitmap->drawLine($source, $target, 0xFFC0A0, 3); } return $this; } public function resizeBy(Dimension $delta) { $this->imgGraph->hide(); $this->frame->resizeBy(Dimension::createInstance($delta->width, $delta->height)); $this->frmDimension = $this->frmDimension->resizeBy(Dimension::createInstance($delta->width, $delta->height)); if($this->repaintTimer !== null && $this->repaintTimer->isRunning()) { $this->repaintTimer->destroy(); } $this->repaintTimer = new RunOnceTimer( function() { $this->update($this->states[$this->states->count() - 1]); }, BattManApplication::getInstance()->getWindow(), 500); $this->repaintTimer->start(); return $this; } }<?php namespace ws\loewe\BattMan\Components\Timer; use \ws\loewe\Woody\Components\Windows\AbstractWindow; use \ws\loewe\Woody\Components\Timer\Timer; use \ws\loewe\Woody\Event\TimeoutAdapter; class RunOnceTimer extends Timer { public function __construct(\Closure $callback, AbstractWindow $window, $interval) { parent::__construct($callback, $window, $interval); $this->addTimeoutListener(new TimeoutAdapter(function () { if($this->counter == 1) { $this->destroy(); } })); } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Woody\Components\Component; use \ws\loewe\Woody\Util\Image\ImageResource; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class Image extends Control implements Actionable { /** * the image resource the image control is associated with * * @var \ws\loewe\Woody\Utils\Image\ImageResource */ protected $imageResource = null; /** * This method acts as the constructor of the class. * * @param \ws\loewe\Woody\Utils\Image\ImageResource $imageResource the image resource the image control is associated with * @param Point $topLeftCorner the top left corner of the image * @param Dimension $dimension the dimension of the image */ public function __construct(ImageResource $imageResource, Point $topLeftCorner, Dimension $dimension) { parent::__construct(null, $topLeftCorner, $dimension); $this->type = Frame; $this->style = WBC_IMAGE; $this->imageResource = $imageResource; } protected function create(Component $parent) { parent::create($parent); $this->setImage(); } /** * This method sets the image of the image control. * * @return Image $this */ protected function setImage() { $bitmap = $this->imageResource->getResource(); wb_set_image($this->controlID, $bitmap); wb_destroy_image($bitmap); return $this; } }<?php namespace ws\loewe\Woody\Util\Image; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class ImageResource { /** * the dimension of the image resource * * @var Dimension */ private $dimension = null; /** * the handle to the raw resource * * @var int */ private $resource = null; /** * This method creates a blank image. * * @param Dimension $dimension the dimension of the image * @return ImageResource the blank image */ public static function create(Dimension $dimension) { return new ImageResource($dimension, null); } /** * This method creates an image from the given file with the dimensions of the image, or with the supplied dimension. * * @param string the file name of the image file * @param Dimension $dimension the dimension to which to crop the image * @return ImageResource the blank image */ public static function createFromFile($imageFileName, Dimension $dimension = null) { if($dimension == null) { $dimension = getimagesize($imageFileName); $dimension = Dimension::createInstance($dimension[0], $dimension[1]); } return new ImageResource($dimension, $imageFileName); } /** * This method acts as the constructor of the class. * * @param Dimension $dimension the dimension of the image * @param string $imageFileName the image file to create the image from */ private function __construct(Dimension $dimension, $imageFileName = null) { $this->dimension = Dimension::createInstance($dimension->width, $dimension->height); if($imageFileName !== null) { $this->createResourceFromFile($imageFileName); } else { $this->createResourceBlank(); } } /** * This method creates a blank image resource. */ private function createResourceBlank() { $this->resource = wb_create_image($this->dimension->width, $this->dimension->height); } /** * This method creates an image resource from a given image file. * * @param string $imageFileName the image file to create the image from */ private function createResourceFromFile($imageFileName) { $dib = FreeImage_Load(self::isJpeg($imageFileName) ? FIF_JPEG : FIF_BMP, $imageFileName, 0); $this->resource = wb_create_image( $this->dimension->width, $this->dimension->height, FreeImage_GetInfoHeader($dib), FreeImage_GetBits($dib) ); FreeImage_Unload($dib); } /** * This method determines if the given image is a jpeg or not. * * @param string $imageFileName the file name of the image file to determine its file type * * @return boolean true, if the image is a jpeg, else false */ private static function isJpeg($imageFileName) { return substr($imageFileName, -4) === '.jpg'; } /** * This method returns the dimension of the image resource. * * @return Dimension the image resource */ public function getDimension() { return Dimension::createInstance($this->dimension->width, $this->dimension->height); } /** * This method draws a line on the image. * * @param Point $source the source point of the line * @param Point $target the target point of the line * @param int $color the color of the line * @param boolean $width the width of the line in pixels * @param boolean $style the sytle of the line * @return ImageResource $this */ public function drawLine(Point $source, Point $target, $color, $width = null, $style = null) { wb_draw_line($this->resource, $source->x, $source->y, $target->x, $target->y, $color, $width, $style); return $this; } /** * This method draws a rectangle on the image. * * @param Point $tlc the top left corner of the rectangle * @param Dimension $dim the dimension of the rectangle * @param int $color the color of the rectangle * @param boolean $filled whether or not to draw the rectangle filled * @param boolean $width the width of the line in pixels * @param boolean $style the sytle of the line * @return ImageResource $this */ public function drawRectangle(Point $tlc, Dimension $dim, $color, $filled = TRUE, $width = null, $style = null) { wb_draw_rect( $this->resource, $tlc->x, $tlc->y, $dim->width, $dim->height, $color, $filled, $width, $style ); return $this; } /** * This method returns the handle to the raw resource. * * @return int */ public function getResource() { return $this->resource; } }<?php namespace ws\loewe\BattMan\View; use \ws\loewe\BattMan\Model\Model; use \ws\loewe\Woody\App\Application; use \ws\loewe\Woody\Components\Controls\Checkbox; use \ws\loewe\Woody\Components\Controls\Label; use \ws\loewe\Woody\Components\Timer\Timer; use \ws\loewe\Woody\Event\ActionAdapter; use \ws\loewe\Woody\Layouts\GridLayout; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class ControlView extends View { private $chkDimDisplay = null; private $chkStayAwake = null; public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct($topLeftCorner, $dimension); } public function initialize() { $this->frame->setLayout($layout = new GridLayout(2, 2, 0, 0)); $this->frame->add(new Label('dim display:', Point::createInstance(5, 5), Dimension::createInstance(15, 15))); $this->chkDimDisplay = new Checkbox(0, Point::createInstance(10, 110), Dimension::createInstance(25, 25)); $this->frame->add($this->chkDimDisplay); $this->frame->add(new Label('stay awake:', Point::createInstance(5, 5), Dimension::createInstance(15, 15))); $this->chkStayAwake = new Checkbox(0, Point::createInstance(10, 140), Dimension::createInstance(25, 25)); $this->frame->add($this->chkStayAwake); $timerDisplayRequired = new Timer(function() { if($this->chkStayAwake->isChecked()) { $libKernel32 = wb_load_library('Kernel32'); $function = wb_get_function_address('SetThreadExecutionState', $libKernel32); wb_call_function($function, array(//ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED:= 0x00000001 | 0x00000002)); } }, Application::getInstance()->getWindow(), 55555); $timerDisplayRequired->start(); $this->chkDimDisplay->addActionListener(new ActionAdapter(function($event) { $value = $event->getSource()->isChecked() ? 0 : 100; exec('powershell -executionPolicy Unrestricted -Command "function set-monitorBrightness { [CmdletBinding()] param ( [ValidateRange(0,100)] [int]$brightness ) $monitors = Get-WmiObject -Namespace root\wmi -Class WmiMonitorBrightnessMethods; foreach ($monitor in $monitors){ $monitor.WmiSetBrightness(5, $brightness) } }; set-monitorBrightness '.$value.';" < NUL'); })); $layout->layout($this->frame); } public function update(Model $currentState) { } }<?php namespace ws\loewe\BattMan\View; use ws\loewe\BattMan\App\BattManApplication; use ws\loewe\BattMan\Model\Model; use ws\loewe\Utils\Geom\Dimension; use ws\loewe\Utils\Geom\Point; use ws\loewe\Woody\Components\Controls\Checkbox; use ws\loewe\Woody\Components\Controls\EditArea; use ws\loewe\Woody\Components\Controls\Label; use ws\loewe\Woody\Dialog\FileSystem\FileSaveDialog; use ws\loewe\Woody\Event\ActionAdapter; class LogView extends View { /** * the label of the checkbox for file logging * * @var Label */ private $lblDoLogToFile = null; /** * the checkbox for file logging * * @var Checkbox */ private $chkDoLogToFile = null; /** * the text area where to log is shown * * @var EditArea */ private $txtLog = null; /** * path to the file where to log to * * @var string */ private $logFile = null; public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct($topLeftCorner, $dimension); } public function initialize() { $this->frame->add($this->lblDoLogToFile = new Label('log to file:', Point::createInstance(10, 15), Dimension::createInstance(100, 15))); $this->frame->add($this->chkDoLogToFile = new Checkbox(0, Point::createInstance(152, 10), Dimension::createInstance(25, 25))); $this->frame->add($this->txtLog = new EditArea('', Point::createInstance(10, 40), Dimension::createInstance(280, 240))); $this->txtLog->setReadOnly(TRUE); $this->chkDoLogToFile->addActionListener(new ActionAdapter(function($event) { if(!$this->chkDoLogToFile->isChecked()) { return; } $dialog = new FileSaveDialog('Please enter the file name where to store the log.'); $dialog->open(); if(($selection = $dialog->getSelection()) != null) { $this->logFile = $selection; } })); } public function update(Model $currentState) { $currentLog = $this->txtLog->getValue(); $entry = (($currentLog === null) ? '' : PHP_EOL).date('H:i:s'); $entry .= ', '.$currentState->getPowerStatus(); $entry .= ', '.$currentState->getBatteryStatus(); $entry .= ', '.$currentState->getPercentRemaining().'%'; $entry .= ', '.BattManApplication::formatSeconds($currentState->getTimeRemaining()); $entry .= ', '.BattManApplication::formatSeconds($currentState->getTimeOnBattery()); $this->txtLog->setValue(null); $this->txtLog->setValue($currentLog.$entry); if($this->chkDoLogToFile->isChecked() && $this->logFile != null) { file_put_contents($this->logFile, trim($entry).PHP_EOL, FILE_APPEND); } unset($currentLog); unset($entry); } public function resizeBy(Dimension $delta) { // no grid layout, so we manually resize the frame and the text area where to the log is shown $this->frame->resizeBy(Dimension::createInstance(0, $delta->height)); $this->txtLog->resizeBy(Dimension::createInstance(0, $delta->height)); return $this; } }<?php namespace ws\loewe\BattMan\Model; interface Model { }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class Checkbox extends Control implements Actionable { /** * the maximal width of a checkbox */ const MAX_WIDTH = 17; /** * the maximal height of a checkbox */ const MAX_HEIGHT = 17; /** * This method acts as the constructor of the class. * * @param boolean $value the preset value of the checkbox * @param Point $topLeftCorner the top left corner of the checkbox * @param Dimension $dimension the dimension of the checkbox */ public function __construct($value, Point $topLeftCorner, Dimension $dimension) { parent::__construct('', $topLeftCorner, $dimension); $this->type = CheckBox; $this->param = ($value === true) ? 1 : 0; } /** * @inheritDoc * * A checkbox cannot be resized any larger than defined by VISIBLE_WIDTH and VISIBLE_HEIGHT, respectively. * * @param Dimension $dimension the Dimension to resize the Checkbox to. */ public function resizeTo(Dimension $dimension) { if($dimension->width > Checkbox::MAX_WIDTH) { $dimension = $dimension->resizeTo(Dimension::createInstance(Checkbox::MAX_WIDTH, $dimension->height)); } if($dimension->height > Checkbox::MAX_HEIGHT) { $dimension = $dimension->resizeTo(Dimension::createInstance($dimension->width, Checkbox::MAX_HEIGHT)); } parent::resizeTo($dimension); } /** * This method returns whether the checkbox is checked or not. * * @return boolean true, if the checkbox is checked, else false */ public function isChecked() { // comparison with === 1 fails for checked checkbox return wb_get_value($this->controlID) == 1; } /** * This method sets the checkbox checked or unchecked, depending on the given value. * * @param boolean $isChecked a flag whether to check or uncheck the checkbox * @return Checkbox $this */ public function setChecked($value) { wb_set_value($this->controlID, ($value === true) ? 1 : 0); return $this; } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class EditArea extends EditField { /** * This method acts as the constructor of the class. * * @param mixed $value the preset value of the edit area * @param Point $topLeftCorner the top left corner of the edit area * @param Dimension $dimension the dimension of the edit area */ public function __construct($value, Point $topLeftCorner, Dimension $dimension) { parent::__construct($value, $topLeftCorner, $dimension); $this->style = $this->style | WBC_MULTILINE; } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; abstract class EditField extends Control implements Actionable { /** * This method acts as the constructor of the class. * * @param mixed $value the preset value of the edit field * @param Point $topLeftCorner the top left corner of the edit field * @param Dimension $dimension the dimension of the edit field */ public function __construct($value, Point $topLeftCorner, Dimension $dimension) { parent::__construct($value, $topLeftCorner, $dimension); $this->type = EditBox; } /** * This method returns the value of the edit field. * * @param boolean $trimmed determines whether or not to returned the trimmed value * @return string the value of the edit field */ public function getValue($trimmed = TRUE) { $value = wb_get_text($this->controlID); if($trimmed) { $value = trim($value); } if(strlen($value) === 0) { $value = null; } return $value; } /** * This method sets the value of the edit field. * * @param mixed $newValue the new value of the edit field. * @return \ws\loewe\Woody\Components\Controls\EditField $this */ public function setValue($newValue) { //$this->pauseEvents = TRUE; wb_set_text($this->controlID, $newValue); //$this->pauseEvents = FALSE; return $this; } /** * This method sets the edit field to be either read-only or not. * * @param boolean $isReadonly the read-only state of the edit field * @return \ws\loewe\Woody\Components\Controls\EditField $this */ public function setReadOnly($isReadonly) { // 0x00CF = EM_SETREADONLY wb_send_message($this->controlID, 0x00CF, $isReadonly, 1); return $this; } /** * This method sets the cursor of the edit field to the specified index. * * @param int $index the index to set the cursor to * @return EditField $this */ public function setCursor($index) { // 0x00B1 = EM_SETSEL wb_send_message($this->controlID, 0x00B1, $index, $index); return $this; } }<?php namespace ws\loewe\Woody\Components\Controls; interface Actionable { }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class Label extends Control { /** * This method acts as the constructor of the class. * * @param string $label the label of the label control * @param Point $topLeftCorner the top left corner of the label control * @param Dimension $dimension the dimension of the label control */ public function __construct($label, Point $topLeftCorner, Dimension $dimension) { parent::__construct($label, $topLeftCorner, $dimension); $this->type = Label; } /** * This method returns the label of the label control * * @return string the label of the label control */ public function getLabel() { return wb_get_text($this->controlID); } /** * This method sets the label of the label control * * @param string $label the label of the label control * @return \ws\loewe\Woody\Components\Controls\Label $this */ public function setLabel($label) { wb_set_text($this->controlID, $label); return $this; } }<?php namespace ws\loewe\Woody\Dialog\FileSystem; use \ws\loewe\Woody\Components\Windows\AbstractWindow; class FileSaveDialog extends FileSystemDialog { /** * the collection of file filters for this dialog * * @var \ws\loewe\Woody\Dialog\FileSystem\FileFilters */ private $filters = null; /** * This method acts as the constructor of the class. */ public function __construct($title, AbstractWindow $parentWindow = null, $path = null, $filters = null) { parent::__construct($title, $parentWindow, $path); $this->filters = $filters; } public function open() { $this->selection[0] = wb_sys_dlg_save( $this->window === null ? null : $this->window->getControlID(), $this->title, $this->filters === null ? '' : $this->filters->toArray(), $this->path, null, null ); } }<?php namespace ws\loewe\Woody\Dialog\FileSystem; use \ws\loewe\Woody\Components\Windows\AbstractWindow; abstract class FileSystemDialog { /** * the title of the dialog * * @var string */ protected $title = null; /** * the window the dialog belongs to, may be null * * @var \ws\loewe\Woody\Components\Windows\AbstractWindow */ protected $window = null; /** * the default path which to open, must be delimitet by slash, e.g. "C:\path\to\dir\" */ protected $path = null; /** * the collection of full paths to the file system objects the user selected * * @var array the collection of full paths to the file system objects the user selected */ protected $selection = array(); /** * This method acts as the constructor of the class. */ public function __construct($title, AbstractWindow $parentWindow = null, $path = null) { $this->title = $title; $this->window = $parentWindow; $this->path = $path; } /** * This method opens the respective dialog. */ abstract function open(); /** * This method returns the full path to the selected file system object, or null if nothing was selected. * * @return string the full path to the selected file system object, or null if nothing was selected */ public function getSelection() { return (count($this->selection) === 0) ? null : trim($this->selection[0]); } }<?php namespace ws\loewe\Woody\Event; class ActionAdapter implements ActionListener { /** * the callback to be executed for the action-performed event, if null, no callback for this event type will be * executed * * @var callable */ private $onActionPerformed = null; /** * This method acts as the constructor of the class. * * @param callable $onMousePressed the callback to be executed for the mouse-pressed event, if null, no callback for * this event type will be executed * @param callable $onMouseReleased the callback to be executed for the mouse-released event, if null, no callback for * this event type will be executed */ public function __construct(callable $onActionPerformed) { $this->onActionPerformed = $onActionPerformed; } public function actionPerformed(ActionEvent $event) { $this->onActionPerformed->__invoke($event); } }<?php namespace ws\loewe\Woody\Event; interface ActionListener { function actionPerformed(ActionEvent $actionEvent); }<?php namespace ws\loewe\Woody\Event; class ActionEvent extends Event { /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); } public function dispatch() { foreach($this->getSource()->getActionListeners() as $actionListener) { $actionListener->actionPerformed($this); } } /** * This method returns the string representation of the event. * * @return string the string representation of the event */ public function __toString() { return parent::__toString().PHP_EOL. 'A/C/S = '.$this->isAltKeyPressed().'/'.$this->isCtrlKeyPressed().'/'.$this->isShiftKeyPressed(); } }<?php namespace ws\loewe\BattMan\View; use \ws\loewe\BattMan\Model\Model; use \ws\loewe\Woody\Components\Controls\Frame; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; abstract class View { protected $frame = null; public function __construct(Point $topLeftCorner, Dimension $dimension) { $this->frame = new Frame('', $topLeftCorner, $dimension); } abstract public function initialize(); abstract public function update(Model $model); public function getFrame() { return $this->frame; } public function resizeBy(Dimension $delta) { return $this; } }<?php namespace ws\loewe\Woody\App; abstract class Application { /** * the main window of the application * * @var \ws\loewe\Woody\Components\Windows\AbstractWindow */ protected $window = null; /** * the current instance of the application * * @var Application */ protected static $instance = null; /** * This method acts as the constructor of the class. */ public function __construct() { static::$instance = $this; } /** * This method return the current instance of the application. * * Note that this is not a singleton class. * * @return Application */ public static function getInstance() { return static::$instance; } /** * This method returns the main window of the application. * * @return \ws\loewe\Woody\Components\Windows\AbstractWindow */ public function getWindow() { return $this->window; } /** * This method starts the application. */ abstract public function start(); /** * This method stops the application. */ abstract public function stop(); }<?php namespace ws\loewe\Woody\Components\Windows; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class ResizableWindow extends AbstractWindow { public function __construct($label, Point $point, Dimension $dimension) { parent::__construct(ResizableWindow, $label, $point, $dimension); } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class ProgressBar extends Control { /** * the identifier of the message for getting a value from a progress bar * * PBM_GETPOS = (WM_USER + 8) = 400 + 8 = 408 * * @var int */ private static $PBM_GETPOS = 0x408; /** * This method acts as the constructor of the class. * * @param Point $topLeftCorner the top left corner of the progress bar * @param Dimension $dimension the dimension of the progress bar */ public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct(null, $topLeftCorner, $dimension); $this->type = Gauge; } /** * This method gets the current value of the progress bar. * * @return int the current value of the progress bar */ public function getProgress() { // wb_get_value always returns 0 for a gauge, so get the value with a low-level call return wb_send_message($this->controlID, self::$PBM_GETPOS); } /** * This method sets the current value of the progress bar. * * @param $value the new value of the progress bar * @return \ws\loewe\Woody\Components\Controls\ProgressBar $this */ public function setProgress($value) { wb_set_value($this->controlID, $value); return $this; } /** * This method sets the range of the progress bar. * * @param int $min the minimal value of the progress bar * @param int $max the maximal value of the progress bar * @return \ws\loewe\Woody\Components\Controls\ProgressBar $this */ public function setRange($min, $max) { wb_set_range($this->controlID, $min, $max); return $this; } }<?php namespace ws\loewe\Woody\Components\Timer; use \ws\loewe\Woody\WinBinderException; use \ws\loewe\Woody\Components\Component; use \ws\loewe\Woody\Components\Windows\AbstractWindow; use \ws\loewe\Woody\Event\TimeoutListener; use \ws\loewe\Woody\Event\TimeoutAdapter; class Timer { /** * the id of the timer * * @var int */ protected $id = null; /** * the window to which the timer is bound to * * @var \ws\loewe\Woody\Components\Windows\AbstractWindow */ protected $window = null; /** * the number of milliseconds that pass between timeout * * @var int */ protected $interval = null; /** * boolean flag to determine, if timer is running * * @var boolean */ private $isRunning = false; /** * counter for counting how often the timer was already called * * @var int */ protected $counter = 0; /** * the collection of timeout listeners * * @var \SplObjectStorage */ private $timeoutListeners = null; /** * the collection of all timers * * @var array[int]Timer */ private static $timers = array(); /** * timeout used for scheduling unit tests */ const TEST_TIMEOUT = 100; /** * This method acts as the constructor of the timer. * * @param \Closure $callback the default callback that is executed on each timeout * @param \ws\loewe\Woody\Components\Windows\AbstractWindow $window the window to which the timer is bound to. * @param int $interval the number of milliseconds that pass between each timeout */ public function __construct(\Closure $callback, AbstractWindow $window, $interval) { $this->id = Component::getUniqueID(); $this->window = $window; $this->interval = $interval; // an auxilliary callback to track the number of executions $this->addTimeoutListener(new TimeoutAdapter(function () {$this->counter++;})); // the default callback provided by the user $this->addTimeoutListener(new TimeoutAdapter($callback)); self::$timers[$this->id] = $this; } /** * This method return the id of the timer. * * @return int */ public function getID() { return $this->id; } /** * This method returns the timer associated with the given woody id. * * @param int $timerID the woody id of the timer * @return Timer the timer with the given id, or null if no timer with this id exists */ public static function getTimerByID($timerID) { if(isset(self::$timers[$timerID])) { return self::$timers[$timerID]; } return null; } /** * This method starts the timer. If it was already started before without being destroyed since, an exception is * thrown. * * @return ws\loewe\Woody\Components\Timer\Timer $this */ public function start() { if($this->isRunning) { throw new TimerAlreadyRunningException($this); } if(!wb_create_timer($this->window->getControlID(), $this->id, $this->interval)) { throw new WinBinderException('Unable to create winbinder timer object for timer with id '.$this->id); } $this->isRunning = true; return $this; } /** * This method destroys the timer, i.e. associated callbacks will no longer be executed. * * @return ws\loewe\Woody\Components\Timer\Timer $this */ public function destroy() { if(!$this->isRunning) { throw new TimerNotRunningException($this); } $this->isRunning = false; if(!wb_destroy_timer($this->window->getControlID(), $this->id)) { throw new WinBinderException('Unable to destroy winbinder timer object for timer with id '.$this->id); } return $this; } /** * This method determines if the timer is running or not. * * @return true if the the timer is running, else false */ public function isRunning() { return $this->isRunning; } /** * This method determines how often the timer was called. * * @return int the number of times the counter was called */ public function getExecutionCount() { return $this->counter; } /** * This method adds a timeout listener to this timer. * * @param TimeoutListener $timeoutListener the timeout listener to add * @return Timer $this */ public function addTimeoutListener(TimeoutListener $timeoutListener) { if($this->timeoutListeners == null) { $this->timeoutListeners = new \SplObjectStorage(); } $this->timeoutListeners->attach($timeoutListener); return $this; } /** * This method returns the collection of timeout listeners registered for this timer. * * @return \SplObjectStorage the collection of timeout listeners registered for this timer */ public function getTimeoutListeners() { return ($this->timeoutListeners == null) ? new \SplObjectStorage() : $this->timeoutListeners; } /** * This method removes a timeout listener from this timer. * * @param TimeoutListener $timeoutListener the timeout listener to remove * @return Timer $this */ public function removeTimeoutListener(TimeoutListener $timeoutListener) { if($this->timeoutListeners != null) { $this->timeoutListeners->detach($timeoutListener); } return $this; } }<?php namespace ws\loewe\Woody; /** * This class represents an Exception that is thrown if a winbinder function signals an error by a return value. */ class WinBinderException extends \RuntimeException { public function __construct($message, $code = 0, \Exception $previous = NULL) { parent::__construct($message, $code, $previous); } }<?php namespace ws\loewe\Woody\Event; interface TimeoutListener { function timeout(TimeoutEvent $event); }<?php namespace ws\loewe\Woody\Event; class TimeoutAdapter implements TimeoutListener { /** * the callback to be executed when the timeout occurs * * @var \Closure */ private $onTimeout = null; /** * This method acts as the constructor of the class. * * @param \Closure $onTimeout the callback to be executed when the timeout occurs */ public function __construct(\Closure $onTimeout) { $this->onTimeout = $onTimeout; } public function timeout(TimeoutEvent $event) { $this->onTimeout->__invoke($event); } }<?php namespace ws\loewe\Woody\Event; use \ws\loewe\Woody\Components\Timer\Timer; class TimeoutEvent extends Event { /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); } public function dispatch() { $timeoutListeners = Timer::getTimerByID($this->id)->getTimeoutListeners(); foreach($timeoutListeners as $timeoutListener) { $timeoutListener->timeout($this); } } }<?php namespace ws\loewe\Woody\Components\Timer; class TimerAlreadyRunningException extends \BadMethodCallException { /** * This method acts as the constructor of the class. * * @param \ws\loewe\Woody\Components\Timer\Timer $timer the timer that is in an illegal state */ public function __construct(Timer $timer) { parent::__construct('The timer with the id '.$timer->getID().' is already running'); } }<?php namespace ws\loewe\Woody\Components\Timer; class TimerNotRunningException extends \BadMethodCallException { /** * This method acts as the constructor of the class. * * @param \ws\loewe\Woody\Components\Timer\Timer $timer the timer that is in an illegal state */ public function __construct(Timer $timer) { parent::__construct('The timer with the id '.$timer->getID().' is not running'); } }<?php namespace ws\loewe\Woody\Event; class WindowResizeAdapter implements WindowResizeListener { /** * the callback to be executed for the window resize event * * @var \Closure */ private $onWindowResize = null; /** * This method acts as the constructor of the class. * * @param \Closure $onWindowResize the callback to be executed for the window resize event */ public function __construct(\Closure $onWindowResize) { $this->onWindowResize = $onWindowResize; } public function windowResized(WindowResizeEvent $event) { $this->onWindowResize->__invoke($event); } }<?php namespace ws\loewe\Woody\Event; use ws\loewe\Utils\Geom\Dimension; use ws\loewe\Woody\Components\Windows\AbstractWindow; class WindowResizeEvent extends Event { /** * the old dimension of the component before resizing * * @var Dimension */ private $oldDimension = null; /** * the new dimension of the component after resizing * * @var Dimension */ private $newDimension = null; /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); // the previous dimension is still stored in the Woody object $this->oldDimension = $this->getSource()->getDimension(); // the winbinder resource already has the new dimension $newDim = wb_get_size($this->getSource()->getControlID()); $this->newDimension = Dimension::createInstance($newDim[0], $newDim[1]); } public function dispatch() { $source = $this->getSource(); if($source instanceof AbstractWindow) { foreach($source->getWindowResizeListeners() as $resizeListener) { $resizeListener->windowResized($this); } } else { throw new \RuntimeException('Dispatching WindowResizedEvent from a non-window control!'); } } /** * This method returns the old dimension of the component before resizing * * @return Dimension */ public function getOldDimension() { return $this->oldDimension; } /** * This method returns the new dimension of the component after resizing * * @return Dimension */ public function getNewDimension() { return $this->newDimension; } /** * This method returns the delta of the old and new dimension, i.e. Dimension::createInstance(newX - oldX, newY - oldY) * * @return Dimension */ public function getDeltaDimension() { return $this->newDimension->resizeBy(Dimension::createInstance(-$this->oldDimension->width, -$this->oldDimension->height)); } }<?php namespace ws\loewe\Utils\Geom; /** * This class represents a point in the two-dimensional space. */ class Point { /** * the x-coordinate of the point * * @var int */ private $x = null; /** * the y-coordinate of the point * * @var int */ private $y = null; /** * the cache used for this value object class * * @var array */ private static $cache = array(); /** * This method acts as the constructor of the class. * * @param int $x the x-coordinate of the point * @param int $y the y-coordinate of the point */ private function __construct($x, $y) { $this->x = $x; $this->y = $y; } /** * This method creates a new Point. * * @param int $x the x-coordinate of the point * @param int $y the y-coordinate of the point * @return Point the new Point */ public static function createInstance($x, $y) { $hash = $x.':'.$y; if(!isset(self::$cache[$hash])) { self::$cache[$hash] = new Point($x, $y); } return self::$cache[$hash]; } /** * This method is a magic getter method for the class. * * @todo replace this with Trait in PHP 5.4 * @param string $memberName the name of the member to get * @return mixed the value of the member */ public function __get($memberName) { return $this->$memberName; } /** * This method sets the x-coordinate of the point. * * @param int $x the new x-coordinate of the point * @return \ws\loewe\Utils\Geom\Point this point */ public function setX($x) { return Point::createInstance($x, $this->y); } /** * This method sets the y-coordinate of the point. * * @param int $y the new y-coordinate of the point * @return \ws\loewe\Utils\Geom\Point this point */ public function setY($y) { return Point::createInstance($this->x, $y); } /** * This method moves a point by an offset, given as dimension. * * @param \ws\loewe\Utils\Geom\Dimension $dimension the dimension by which this point shall be moved by * @return \ws\loewe\Utils\Geom\Point a new point moved by the offset encapsulated by the given point */ public function moveBy(Dimension $dimension) { return Point::createInstance($this->x + $dimension->width, $this->y + $dimension->height); } /** * This method moves a point to another point, given as another point. * * @param \ws\loewe\Utils\Geom\Point $point the point by which this point shall be moved by * @return \ws\loewe\Utils\Geom\Point a new point moved by the offset encapsulated by the given point */ public function moveTo(Point $point) { return Point::createInstance($this->x + $point->x, $this->y + $point->y); } /** * This method returns a string representation of the point. * * @return string the string representation of the point */ public function __toString() { return 'x: '.$this->x.', y: '.$this->y; } }<?php namespace ws\loewe\Utils\Geom; /** * This class encapsulates the width and height of an object in the two-dimensional space, e.g. a rectangle or an ellipse. */ class Dimension { /** * the width of the dimension * * @var int */ private $width = null; /** * the height of the dimension * * @var int */ private $height = null; /** * the cache used for this value object class * * @var array */ private static $cache = array(); /** * This method acts as the constructor of the class. * * @param int $width the width of the dimension * @param int $height the height of the dimension */ private function __construct($width, $height) { $this->width = $width; $this->height = $height; } /** * This method creates a new Dimension. * * @param int $width the width of the dimension * @param int $height the height of the dimension * @return Dimension the new Dimension */ public static function createInstance($width, $height) { $hash = $width.':'.$height; if(!isset(self::$cache[$hash])) { self::$cache[$hash] = new Dimension($width, $height); } return self::$cache[$hash]; } /** * This method is a magic getter method for the class. * * @todo replace this with Trait in PHP 5.4 * @param string $memberName the name of the member to get * @return mixed the value of the member */ public function __get($memberName) { return $this->$memberName; } /** * This method resizes a dimension by the offset encoded by a dimension. * * @param Dimension $dimension the offset by which the dimension has to be resized * @return Dimension a new Dimension resized by the offset encoded in the given dimension */ public function resizeBy(Dimension $dimension) { return Dimension::createInstance($this->width + $dimension->width, $this->height + $dimension->height); } /** * This method resizes a dimension to the size of another dimension. * * This is only useful for chaining, as it merely is an alias for a copy-constructor. * * @param Dimension $dimension the offset by which the Dimension has to be resized * @return Dimension a new Dimension resized by the offset encoded in the given dimension */ public function resizeTo(Dimension $dimension) { return Dimension::createInstance($dimension->width, $dimension->height); } /** * This method returns a string representation of the dimension. * * @return string the string representation of the dimension */ public function __toString() { return 'width: '.$this->width.' / height: '.$this->height; } } ?> <?php namespace ws\loewe\Woody\Event; class WindowCloseAdapter implements WindowCloseListener { /** * the callback to be executed when the window is closed * * @var \Closure */ private $onWindowClosed = null; /** * This method acts as the constructor of the class. * * @param \Closure $onWindowClosed the callback to be executed when the window is closed */ public function __construct(\Closure $onWindowClosed) { $this->onWindowClosed = $onWindowClosed; } public function windowClosed(WindowCloseEvent $event) { $this->onWindowClosed->__invoke($event); } }<?php namespace ws\loewe\Woody\Event; interface WindowCloseListener { function windowClosed(WindowCloseEvent $event); }<?php namespace ws\loewe\Woody\Event; use ws\loewe\Woody\Components\Windows\AbstractWindow; class WindowCloseEvent extends Event { /** * This method acts as the constructor of the class. * * @param EventInfo the event info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { parent::__construct($eventInfo); } public function dispatch() { $source = $this->getSource(); if($source instanceof AbstractWindow) { $closeListener = $source->getWindowCloseListener(); if($closeListener !== null) { $closeListener->windowClosed($this); } } else { throw new \RuntimeException('Dispatching WindowCloseEvent from a non-window control!'); } } }<?php namespace ws\loewe\Woody\Components\Windows; use \ws\loewe\Woody\Components\Component; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; use \ws\loewe\Woody\System\WindowConstraints; use \ws\loewe\Woody\Event\WindowResizeListener; use \ws\loewe\Woody\Components\Controls\Frame; use \ws\loewe\Woody\Event\WindowCloseListener; abstract class AbstractWindow extends Component { /** * the close listener registered for this window * * @var \ws\loewe\Woody\Event\WindowCloseListener */ protected $closeListener = null; /** * the collection of resize listeners registered for this window * * @var \SplObjectStorage */ protected $resizeListeners = null; /** * the root pane of the window * * @var ws\loewe\Woody\Components\Controls\Frame */ protected $rootPane = null; public function __construct($type, $label, Point $topLeftCorner, Dimension $dimension) { parent::__construct($label, $topLeftCorner, $dimension); $this->type = $type; $this->parent = null; } public function create(Component $parent = null) { $this->controlID = wb_create_window( $parent === null ? null : $parent->getControlID(), $this->type, $this->value, $this->topLeftCorner->x, $this->topLeftCorner->y, $this->dimension->width, $this->dimension->height, $this->style | WBC_TASKBAR | WBC_NOTIFY, $this->getParameters() ); static::$components[$this->controlID] = $this; $this->createRootPane(); return $this; } /** * This method creates the root pane for this window. All other controls have to be added to this frame. */ private function createRootPane() { $rootPaneTopLeftCorner = Point::createInstance(-1, -8); $rootPaneDimension = Dimension::createInstance($this->dimension->width, $this->dimension->height); $this->rootPane = new Frame('', $rootPaneTopLeftCorner, $rootPaneDimension); $this->rootPane->create($this); } /** * This method closes the window. * * @return AbstractWindow $this */ public function close() { $this->destroy(); return $this; } /** * This method destroys the window. * * @return AbstractWindow $this */ private function destroy() { wb_destroy_window($this->controlID); return $this; } /** * This method starts the main loop of the window. * * @return AbstractWindow $this */ public function startEventHandler() { wb_set_handler($this->controlID, 'globalWinBinderEventHandler'); wb_main_loop(); return $this; } /** * @inheritDoc * * The resizing will adhere to some form of sanatizing, as windows widths/heights of e.g. "0" are not possible. */ protected function resize(Dimension $dimension) { parent::resize(WindowConstraints::getInstance()->enforceConstraints($dimension)); $this->rootPane->resizeTo($dimension); return $this; } /** * This method returns the root pane of this window. * * @return Frame the root pane of this window */ public function getRootPane() { return $this->rootPane; } /** * This method is a helper for getting the event parameters * * @return int */ private function getParameters() { return $this->param | WBC_MOUSEDOWN | WBC_MOUSEUP | WBC_DBLCLICK /* | WBC_MOUSEMOVE */ | WBC_KEYDOWN | WBC_KEYUP | WBC_GETFOCUS | WBC_CUSTOMDRAW | WBC_REDRAW | WBC_RESIZE | WBC_HEADERSEL; } /** * This method gets the title of the window. * * @return string the title of the window */ public function getTitle() { return wb_get_text($this->controlID); } /** * This method sets the title of the window. * * @param string $title the title of the window * @return \ws\loewe\Woody\Components\Windows\AbstractWindow $this */ public function setTitle($title) { wb_set_text($this->controlID, $title); return $this; } /** * This method sets the close listener for this window, which can be used to do some clean-up duties before destroying * the window. * * @param WindowCloseListener $closeListener the resize listener to add * @return AbstractWindow $this */ public function setWindowCloseListener(WindowCloseListener $closeListener) { $this->closeListener = $closeListener; return $this; } /** * This method returns the current close listener for this window. * * @return WindowCloseListener */ public function getWindowCloseListener() { return $this->closeListener; } /** * This method removes the close listener for this window. * * @return AbstractWindow $this */ public function removeWindowCloseListener() { $this->closeListener = null; return $this; } /** * This method adds a resize listener to this window. * * @param WindowResizeListener $resizeListener the resize listener to add * @return AbstractWindow $this */ public function addWindowResizeListener(WindowResizeListener $resizeListener) { if($this->resizeListeners == null) { $this->resizeListeners = new \SplObjectStorage(); } $this->resizeListeners->attach($resizeListener); return $this; } /** * This method returns the collection of resize listeners registered for this window. * * @return \SplObjectStorage the collection of resize listeners registered for this window */ public function getWindowResizeListeners() { return ($this->resizeListeners == null) ? new \SplObjectStorage() : $this->resizeListeners; } /** * This method removes a resize listener from this window. * * @param ResizeListener $resizeListener the resize listener to remove * @return AbstractWindow $this */ public function removeWindowResizeListener(WindowResizeListener $resizeListener) { if($this->resizeListeners != null) { $this->resizeListeners->detach($resizeListener); } return $this; } }<?php namespace ws\loewe\Woody\System; use \ws\loewe\Utils\Geom\Dimension; class WindowConstraints { /** * the lowest width that is possible for a window on the current machine, with the current display settings * * @var int */ private $minWidth = null; /** * the lowest height that is possible for a window on the current machine, with the current display settings * * @var int */ private $minHeight = null; /** * the instance that this singleton encapsulates * * @var ws\loewe\Woody\System\WindowConstraints */ private static $instance = null; /** * a winbinder window handle to derive the constraints * * @var int */ private $window = null; /** * This method acts as the constructor of the class. */ private function __construct() { $this->window = wb_create_window( NULL, AppWindow, 'initializing ...', WBC_CENTER, WBC_CENTER, 0, 0, WBC_INVISIBLE ); $this->determineMinima(); wb_destroy_window($this->window); } /** * This method returns the sole instance of this class. * * @return ws\loewe\Woody\System\WindowConstraints the sole instance of this class */ public static function getInstance() { if(self::$instance === null) { self::$instance = new WindowConstraints(); } return self::$instance; } /** * This method calculates and sets the minimal width and height a window may have with the current display settings. * * @return ws\loewe\Woody\System\WindowConstraints $this */ private function determineMinima() { wb_set_size($this->window, 0, 0); $dimension = wb_get_size($this->window); $this->minWidth = $dimension[0]; $this->minHeight = $dimension[1]; return $this; } /** * This method enforces the contraints on the given dimension, and mutates it accordingly. * * @param Dimension $dimension the dimension to enforce the contraints on * @return ws\loewe\Utils\Geom\Dimension the dimension with the contraints enforced */ public function enforceConstraints(Dimension $dimension) { $width = max($this->minWidth, $dimension->width); $height = max($this->minHeight, $dimension->height); return Dimension::createInstance($width, $height); } }<?php namespace ws\loewe\Woody\Event; interface WindowResizeListener { function windowResized(WindowResizeEvent $event); }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Woody\Components\Component; use \ws\loewe\Woody\Layouts\GridLayout; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class Frame extends Control { /** * the child controls of this frame * * @var \SplObjectStorage */ protected $children = null; /** * the layout of frame * * @var \ws\loewe\Woody\Layouts\GridLayout */ protected $layout = null; /** * This method acts as the constructor of the class. * * @param string $label the label of the frame * @param Point $topLeftCorner the top left corner of the frame * @param Dimension $dimension the dimension of the frame, denoting the height of the bounding box - including the * border but without the excess vertical space used by the (optional) label of the frame * @param int $tabIndex the index of the tab page where to add the frame, only needed when adding frames to tabs * */ public function __construct($label, Point $topLeftCorner, Dimension $dimension, $tabIndex = null) { // the frame has to be increased by 8 pixels in height, to get the user specified height // these 8 pixels are subtracted by the Windows API when creating frames, as they are // reserved for the (optional) label parent::__construct($label, $topLeftCorner, $dimension->resizeBy(Dimension::createInstance(0, 8))); $this->type = Frame; $this->style = $this->style | WBC_NOTIFY; $this->param = $this->param | WBC_HEADERSEL; $this->tabIndex = $tabIndex; $this->children = new \SplObjectStorage(); } protected function create(Component $parent) { parent::create($parent); wb_set_handler($this->controlID, 'globalWinBinderEventHandler'); } /** * This method adds a control to the frame. Calling this method twice with the same object behaves like moving the * control from one parent to the other. * * The controls are only added logically to the frame, physically, they are added to the window to which the frame * belongs. * Furthermore, creating of the control (in respect to winbinder) is done only here, and not in the constructor, as * the parent element has to be known. * * @param Component $control * @return Frame */ public function add(Component $control) { if($control->parent !== null) { $this->remove($control); } $control->create($this); $this->children[$control] = $control->controlID; return $this; } /** * This method returns all controls contained in the frame. * * @return Control[] */ public function getComponents() { $components = new \SplFixedArray($this->children->count()); foreach($this->children as $index => $child) { $components[$index] = $child; } return $components; } /** * This method removes a control from the parent. * * @param Component $control */ public function remove(Component $control) { if($this->children->offsetExists($control)) { $this->children->offsetUnset($control); wb_destroy_control($control->controlID); $control->controlID = null; $control->parent = null; } return $this; } /** * This method returns the layout of the frame. * * @return \ws\loewe\Woody\Layouts\GridLayout the layout of the frame */ public function getLayout() { return $this->layout; } /** * This method sets the layout of the frame. * * @param \ws\loewe\Woody\Layouts\GridLayout $layout the layout to set */ public function setLayout(GridLayout $layout) { $this->layout = $layout; } }<?php namespace ws\loewe\Woody\Layouts; use \ws\loewe\Woody\Components\Controls\Frame; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class GridLayout implements Layout { /** * the number of rows in the grid * * @var int */ private $rows = 0; /** * the number of columns in the grid * * @var int */ private $columns = 0; /** * the width of the horizontal gap in the grid * * @var int */ private $horizontalGap = 0; /** * the height of the vertical gap in the grid * * @var int */ private $verticalGap = 0; /** * This method acts as the constructor of the class. * * @param int $rows the number of rows in the grid * @param int $columns the number of columns in the grid * @param int $horizontalGap width of the horizontal gap in the grid * @param int $verticalGap the height of the vertical gap in the grid */ public function __construct($rows, $columns, $horizontalGap = 0, $verticalGap = 0) { $this->rows = $rows; $this->columns = $columns; $this->horizontalGap = $horizontalGap; $this->verticalGap = $verticalGap; } public function layout(Frame $container) { $initialOffsetX = 7; $initialOffsetY = 13; $containerDimension = $container->getDimension(); $componentDimension = $this->getComponentDimension($containerDimension); foreach($container->getComponents() as $index => $component) { $component->resizeTo($componentDimension); $xOffset = ($this->horizontalGap + $componentDimension->width) * ($index % $this->columns); $yOffset = ($this->verticalGap + $componentDimension->height) * floor(($index / $this->columns)); $component->moveTo(Point::createInstance($initialOffsetX + $xOffset, $initialOffsetY + $yOffset)); } } /** * This method computes the dimension to be used for each component in the container to be layouted. * * @param Dimension $containerDimension the dimension of the container * @return ws\loewe\Utils\Geom\Dimension the dimension to be used for each component in the container to be layouted. */ private function getComponentDimension(Dimension $containerDimension) { $frameInsetX = 10; $frameInsetY = 18; $containerInnerWidth = $containerDimension->width - $frameInsetX; $containerInnerWidth = $containerInnerWidth - (($this->columns - 1) * $this->horizontalGap); $widthPerComponent = $containerInnerWidth / $this->columns; $containerInnerHeight = $containerDimension->height - $frameInsetY; $containerInnerHeight = $containerInnerHeight - (($this->rows - 1) * $this->verticalGap); $heightPerComponent = $containerInnerHeight / $this->rows; return Dimension::createInstance(intval($widthPerComponent), intval($heightPerComponent)); } }<?php namespace ws\loewe\Woody\Layouts; use ws\loewe\Woody\Components\Controls\Frame; interface Layout { /** * This method layouts the given container using this layout. * * @param Frame $container */ function layout(Frame $container); }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Woody\Components\Component; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; abstract class Control extends Component { /** * the tab index of the control * * @var int */ protected $tabIndex = null; /** * This method acts as the constructor of the class. * * @param mixed $value the value associated with the control * @param Point $topLeftCorner the top left corner of the control * @param Dimension $dimension the dimension of the control */ public function __construct($value, Point $topLeftCorner, Dimension $dimension) { parent::__construct($value, $topLeftCorner, $dimension); } /** * This method creates the actual control as winbinder resource, and binds it to its parent control. * * @param Component $parent the parent component of the control */ protected function create(Component $parent) { $this->parent = $parent; $this->controlID = wb_create_control( $parent->getControlID(), $this->type, $this->value, $this->topLeftCorner->x, $this->topLeftCorner->y, $this->dimension->width, $this->dimension->height, $this->id, $this->style, $this->param, ($this instanceof Frame && $parent instanceof Tab) ? ($this->tabIndex) : null ); static::$components[$this->controlID] = $this; } }<?php namespace ws\loewe\Woody\Components\Controls; use \ws\loewe\Utils\Geom\Point; use \ws\loewe\Utils\Geom\Dimension; class Tab extends Control { /** * the collection of pages associated with each winbinder tab page * * @var \ArrayObject */ private $pages = null; /** * This method acts as the constructor of the class. * * @param Point $topLeftCorner the top left corner of the edit box * @param Dimension $dimension the dimension of the edit box */ public function __construct(Point $topLeftCorner, Dimension $dimension) { parent::__construct(null, $topLeftCorner, $dimension); $this->type = TabControl; $this->pages = new \ArrayObject(); } /** * This method adds a new tab page to the tab control. * * @param string $header the name of the tab page */ public function addTabPage($header) { // create a winbinder tab page item wb_create_items($this->controlID, $header); $this->pages[$header] = new Frame( null, Point::createInstance(-2, -9), Dimension::createInstance($this->dimension->width, $this->dimension->height), $this->pages->count() ); $this->pages[$header]->create($this); } /** * This method returns a handle to the tab page with the given header. * * @param string $header the name of the tab page to be returned. * @return Frame */ public function getTabPage($header) { return $this->pages[$header]; } /** * This method returns a new collection of the tab pages of the control. * * @return Frame[] */ public function getTabPages() { $pages = new \SplFixedArray($this->pages->count()); $index = 0; foreach($this->pages as $page) { $pages[$index++] = $page; } return $pages; } /** * This method sets the focus on the page with the given header. * * @param string $header the name of the tab page to be focused. */ public function setFocus($header) { if(!$this->pages->offsetExists($header)) { return; } $index = 0; foreach($this->pages as $title => $frame) { if($title == $header) { wb_set_selected($this->getControlID(), $index); return; } $index++; } } }<?php namespace ws\loewe\Woody\Event; use \ws\loewe\Woody\Components\Component; abstract class Event { use \ws\loewe\Utils\Common\ValueObject; /** * the winbinder identifier for the window or origin * * @var int */ protected $windowID = null; /** * the identifier for the control or origin * * @var int */ protected $id = null; /** * the winbinder identifier for the control or origin * * @var int */ protected $controlID = null; /** * the winbinder identifier for the type of event * * @var int */ protected $type = null; /** * the winbinder identifier for properties of the event * * @var int */ protected $property = null; /** * the timestamp of the event * * @var int */ protected $time = null; /** * the source of the event * * @var Component */ protected $source = null; /** * This method acts as the constructor of the class. * * @param EventInfo the even info containing the raw data of this event */ public function __construct(EventInfo $eventInfo) { $this->windowID = $eventInfo->windowID; $this->id = $eventInfo->id; $this->controlID = $eventInfo->controlID; $this->type = $eventInfo->type; $this->property = $eventInfo->property; $this->source = $eventInfo->source; $this->time = microtime(TRUE); } /** * This method dispatches the event to the listeners registered at the source of the event. */ abstract public function dispatch(); /** * This method returns the source of the event. * * @return Component the source of the event */ public function getSource() { return $this->source; } /** * This method determines if the Alt key was pressed when the event occurred. * * @return boolean true if the Alt key was pressed when the event occurred, else false */ public function isAltKeyPressed() { return ($this->type & WBC_ALT) !== 0; } /** * This method determines if the Ctrl key was pressed when the event occurred. * * @return boolean true if the Ctrl key was pressed when the event occurred, else false */ public function isCtrlKeyPressed() { return ($this->type & WBC_CONTROL) !== 0; } /** * This method determines if the Shift key was pressed when the event occurred. * * @return boolean true if the Shift key was pressed when the event occurred, else false */ public function isShiftKeyPressed() { return ($this->type & WBC_SHIFT) !== 0; } /** * This method returns the string representation of the event. * * @return string the string representation of the event */ public function __toString() { return PHP_EOL.'------- '.str_replace(' ws\loewe\Woody\\Event\\', '', get_class($this)).' -------------'.PHP_EOL. 'windowID = '.$this->windowID.PHP_EOL. 'id = '.$this->id.PHP_EOL. 'controlID = '.$this->controlID.PHP_EOL. 'param1 = '.$this->type.PHP_EOL. 'param2 = '.$this->property; } } <?php namespace ws\loewe\Utils\Common; trait ValueObject { public function __get($memberName) { if(!property_exists($this, $memberName)) { throw new \BadMethodCallException('Tried to __get inexisting property "'.get_class($this).'->'.$memberName.'"!'); } return $this->$memberName; } public function __set($memberName, $value) { if(!property_exists($this, $memberName)) { throw new \BadMethodCallException('Tried to __set inexisting property "'.get_class($this).'->'.$memberName.'" to "'.$value.'"!'); } } }<?php namespace ws\loewe\Woody\Util\WinApi\Types; interface Type { /** * This method returns the pack-format charachter of this type. */ function getPackFormatCharacter(); /** * This method returns the byte lenfth of this type. */ function getLength(); }<?php namespace ws\loewe\Woody\Util\WinApi\Types; class Byte implements Type { public function getPackFormatCharacter() { return 'C'; } public function getLength() { return 1; } }<?php namespace ws\loewe\Woody\Util\WinApi\Types; class Dword implements Type { public function getPackFormatCharacter() { return 'L'; } public function getLength() { return 4; } }d&nw)$;MGBMB