<?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(); ?>
EMBattMan.phar:home/loewe/workspace/programming/PHP/BattMan/bootstrap.php…ÁªûS…Ð(g~¶>home/loewe/workspace/programming/PHP/dephp/vendor/autoload.php·ÁªûS·–R¾¶Lhome/loewe/workspace/programming/PHP/dephp/vendor/composer/autoload_real.phpvÁªûSvñ7¶Jhome/loewe/workspace/programming/PHP/dephp/vendor/composer/ClassLoader.php•-ÁªûS•-FaŒÕ¶ ws/loewe/Woody/lib/winbinder.php¥ÁªûS¥ •]¶%ws/loewe/Woody/lib/wb_windows.inc.php¶2ÁªûS¶2žEøs¶%ws/loewe/Woody/lib/wb_generic.inc.phpDÁªûSDÊS¬
¶'ws/loewe/Woody/lib/wb_resources.inc.php>5ÁªûS>5[bvm¶'ws/loewe/Woody/lib/fi/freeimage.inc.phpÁªûSîЊü¶&ws/loewe/Utils/Autoload/Autoloader.phpÂÁªûSÂrÙi϶7ws/loewe/Utils/Autoload/SourceFileNotFoundException.php~ÁªûS~‹F¬Î¶"ws/loewe/Woody/Event/EventInfo.phpeÁªûSee°¶%ws/loewe/Woody/Event/EventFactory.phpæÁªûSæ9y#¶'ws/loewe/Woody/Components/Component.phpK*ÁªûSK*”Ñå¶&ws/loewe/Woody/Event/FocusListener.phpnÁªûSn—WR¶#ws/loewe/Woody/Event/FocusEvent.php®ÁªûS®þÑ¡B¶$ws/loewe/Woody/Event/KeyListener.php)ÁªûS)ïh6¶!ws/loewe/Woody/Event/KeyEvent.phpSÁªûSSê½M¶&ws/loewe/Woody/Event/MouseListener.phpÁªûSÕ>c¶#ws/loewe/Woody/Event/MouseEvent.phpvÁªûSv?ã°Å¶,ws/loewe/Utils/DataStructures/RingBuffer.php_ÁªûS_ü8Ù^¶(ws/loewe/Woody/Components/IComponent.phpçÁªûS籿Á¶+ws/loewe/BattMan/App/BattManApplication.phpÁªûSÉ2ð¶'ws/loewe/BattMan/Model/BatteryState.php ÁªûS úÛÃ0¶%ws/loewe/Woody/Util/WinApi/WinApi.phpÚÁªûSÚ!É…–¶,ws/loewe/BattMan/Model/SystemPowerStatus.php‚ÁªûS‚M=Z8¶(ws/loewe/Woody/Util/WinApi/Structure.phpl
绞Sl
כݶ"ws/loewe/BattMan/View/TextView.php¿ÁªûS¿€~¶.ws/loewe/Woody/Components/Controls/EditBox.php9ÁªûS940ëø¶#ws/loewe/BattMan/View/GraphView.php ÁªûS Ó®&€¶2ws/loewe/BattMan/Components/Timer/RunOnceTimer.phpÁªûS+í—u¶,ws/loewe/Woody/Components/Controls/Image.phpƒÁªûSƒ…ò„\¶+ws/loewe/Woody/Util/Image/ImageResource.phpáÁªûSá–&¶%ws/loewe/BattMan/View/ControlView.php7 ÁªûS7 š:·¶!ws/loewe/BattMan/View/LogView.php¸ÁªûS¸—+^Ѷ ws/loewe/BattMan/Model/Model.phpBÁªûSB#'‡X¶/ws/loewe/Woody/Components/Controls/Checkbox.php)ÁªûS)´[‘̶/ws/loewe/Woody/Components/Controls/EditArea.phpoÁªûSo«>ܶ0ws/loewe/Woody/Components/Controls/EditField.phpeÁªûSebE昶1ws/loewe/Woody/Components/Controls/Actionable.phpOÁªûSO?ˆ”p¶,ws/loewe/Woody/Components/Controls/Label.phpFÁªûSF}VÔ¶3ws/loewe/Woody/Dialog/FileSystem/FileSaveDialog.phpTÁªûST2¾æ¶5ws/loewe/Woody/Dialog/FileSystem/FileSystemDialog.phpÁªûSaѵ϶&ws/loewe/Woody/Event/ActionAdapter.phpˆÁªûSˆÇ¡j¶'ws/loewe/Woody/Event/ActionListener.phpzÁªûSz‰[¶$ws/loewe/Woody/Event/ActionEvent.php+ÁªûS+¼†vy¶ws/loewe/BattMan/View/View.php}ÁªûS} ã°¶"ws/loewe/Woody/App/Application.php@ÁªûS@]ûH3¶5ws/loewe/Woody/Components/Windows/ResizableWindow.php@ÁªûS@Êaf¶2ws/loewe/Woody/Components/Controls/ProgressBar.phpÇÁªûSÇT6w¶)ws/loewe/Woody/Components/Timer/Timer.phprÁªûSrx<¶%ws/loewe/Woody/WinBinderException.php\ÁªûS\l•-¶(ws/loewe/Woody/Event/TimeoutListener.phpnÁªûSn+¶'ws/loewe/Woody/Event/TimeoutAdapter.php,ÁªûS,¶if-¶%ws/loewe/Woody/Event/TimeoutEvent.phpDÁªûSDþtó¶@ws/loewe/Woody/Components/Timer/TimerAlreadyRunningException.php¬ÁªûS¬%ßÊP¶<ws/loewe/Woody/Components/Timer/TimerNotRunningException.php¤ÁªûS¤Šj¶,ws/loewe/Woody/Event/WindowResizeAdapter.phpgÁªûSgê>ˆe¶*ws/loewe/Woody/Event/WindowResizeEvent.phpÁªûS`0z¶ws/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.php÷ÁªûS÷>lÄH¶4ws/loewe/Woody/Components/Windows/AbstractWindow.php¬ÁªûS¬8Ô|¶+ws/loewe/Woody/System/WindowConstraints.php ÁªûS -”¨Â¶-ws/loewe/Woody/Event/WindowResizeListener.php~ÁªûS~öîNJ¶,ws/loewe/Woody/Components/Controls/Frame.phpPÁªûSP@OL¶%ws/loewe/Woody/Layouts/GridLayout.php#ÁªûS#À.$í¶!ws/loewe/Woody/Layouts/Layout.phpÁªûS5W¾¶.ws/loewe/Woody/Components/Controls/Control.php—ÁªûS—X;¯&¶*ws/loewe/Woody/Components/Controls/Tab.phpÅÁªûSÅn}J¶ws/loewe/Woody/Event/Event.phpÁªûSV?›¶%ws/loewe/Utils/Common/ValueObject.php=ÁªûS=: å¶)ws/loewe/Woody/Util/WinApi/Types/Type.phpÁªûSÜás߶)ws/loewe/Woody/Util/WinApi/Types/Byte.phpÆÁªûSÆ} ar¶*ws/loewe/Woody/Util/WinApi/Types/Dword.phpÇÁªûSÇcuœ¶<?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º)$èæŸÂÁš¶;®ÑMÊGBMB
|