PHP WinBinder 4: Coding
PHP WinBinder 4 : Introduction | Rollover | Icons | Size and position | Configuration file | Command Processing | Coding | Final Tray Menu
|
|
UniServer 5-Nano PHP WinBinder 4 - Tray Menu. |
WinBinder Part 4 - Coding
Introduction
Our tray-menu contains unresolved details such as what elements to include in the master array and configuration file.
In order to start coding now is a good time to be specific, like remove the ability to have a sub-men title a future feature that probably will never be used.
Retain configuration file and parameter items strictly not required a single line would suffice. However two lines makes it easier for a user to understand.
In a similar vein all those redundant lines for a spacer can be removed. Also delete the item number server's no real purpose.
This page provides final details required to implement our tray-menu.
Basic format
Main menu and sub-menus have this structure:
|
|
The configuration file consists of defined blocks each block has a unique name contained in square brackets. Main menus block must start with [main_menu] sub-menu blocks must have a unique name enclosed in square brackets. Note: Names must be alphanumeric lowercase and contain no spaces for example sub_menu_1 All menu entries with the exception of a spacer (single line) consist of five lines Line 1[]-Line 2[] these are arrays and must have a value or set to a empty string. A menu entry can be one of three types a click-able link, a separator or a sub-menu. |
Each menu entry block consists of five arrays (lines) with the following names and function:
item[] | Text displayed in menu (menu item) | |
action[] | Action functions are: Command (run or runh). Or a sub-menu (sub). Or a menu spacer (separator) | |
file[] | File name if above is a command. Sub-menu name if above is a sub | |
parameter[] | Optional parameters to pass if command is the action. | |
icon[] | Left icon to display index=0 no icon displayed |
Note 1 : Every menu item must have a complete block of five lines.
Note 2 : Exception to the above is a spacer which requires only a single line (action) .
Configuration file example
Master array elements
$main[$i][0] // Configuration section name $main[$i][1] // Configuration menu item text $main[$i][2] // Configuration menu item action $main[$i][3] // Configuration menu file path $main[$i][4] // Configuration menu parameter to pass $main[$i][5] // Configuration menu icon 0 = no icon $main[$i][6] // y-top where an item or rollover starts $main[$i][7] // y-rollover-end where a rollover ends $main[$i][8] // y-bottom where an item ends and the next one starts $main[$i][9] // x-icon1 where left icon starts $main[$i][10] // x-rollover-start where a rollover starts $main[$i][11] // x-rollover-end where rollover ends $main[$i][12] // x-rollover-width width of rollover $main[$i][13] // x-rollover-height height of a rollover $main[$i][14] // x-text where text starts $main[$i][15] // Maximum string for either main menu or sub-menu $main[$i][16] // x-icon2 where right icon starts $main[$i][17] // x-icon2 end where right icon ends |
Produces a relatively small array. |
Command core function
The following example code could be used to process our two commands run and runh
I say could because all paths must be specified as absolute paths.
//=== PROCESS COMMAND ========================================================= function process_command($command_array){ // There are only two types of command to process run and runh (run hidden) if($command_array[0] == "run"){ // Standard command to run $cmd1 = "start "; // Start of command $cmd2 = $command_array[1]; // Path string including file name $cmd3 = " "; // Assume user missed the space $cmd4 = $command_array[2]; // parameters to include $cmd5 = $cmd1.$cmd2.$cmd3.$cmd4; // build command string pclose(popen($cmd5,'r')); // Run a detached process } if($command_array[0] == "runh"){ // Standard command run hidden $cmd1 = "start uniserv.exe \""; // Start of command including utility $cmd2 = $command_array[1]; // Path string including file name $cmd3 = " "; // Assume user missed the space $cmd4 = $command_array[2]; // parameters to include $cmd5 = "\" "; // Add final quote $cmd6 = $cmd1.$cmd2.$cmd3.$cmd4.$cmd5; // build command string pclose(popen($cmd6,'r')); // Run a detached process } } //===================================================== END PROCESS COMMAND ===
Problem Paths
Absolute paths are incompatible with portability in particular USB drives. At best only the drive letter will change worst-case scenario a user moves the application (uniform server) to a different folder.
For Uniform Server this is not an issue because it dynamically rewrites all paths and if integrated into the architecture this tray-menu would be no exception.
However our tray-menu is intended to be general purpose. To address the above issue a user can specify relative paths however not all relative paths work the OS insists on absolute paths for some applications.
Solution; prior to command processing replace all relative paths with absolute ones.
(PHP CLI) relative to absolute path conversion function
The following function converts any relative paths in a string to absolute paths. It assumes relatives paths are relative to the script.
//=== CONVERT RELATIVE TO ABSOLUTE PATHS ====================================== // Convers any relative paths found in a string to absolute paths // Assumes paths are relative to this file function relative_to_absolute_paths($str){ $path_array = explode("\\",dirname(__FILE__)); // Blow path appart at "\" // Path is this file $str = trim($str); // Remove L&R spaces $str = preg_replace('/\s+/', ' ', $str); // Remove double spaces $str_array = explode(" ",$str); // Blow string apart at " " for($i = 0; $i < count($str_array); $i++) { // scan str array line by line if( strchr($str_array[$i],"../")){ // Does string contain ../ $str_count = substr_count($str_array[$i],"../"); // Yes: How many $str_array[$i] = substr_replace($str_array[$i],"",0,$str_count*3); // Remove $new_path =""; // reset new path for($i2 = 0; $i2 < count($path_array)-$str_count; $i2++) { // scan original path $new_path = $new_path.$path_array[$i2]."/"; // build new path } $str_array[$i] = $new_path.$str_array[$i]; // Replace relative path } // with absolute path } for($i = 0; $i < count($str_array); $i++) { // scan str array line by line $new_str = $new_str. $str_array[$i]." "; // Rebuild new string } return $new_str; // Return modified string } //================================== END CONVERT RELATIVE TO ABSOLUTE PATHS === |
To the process_command() function add the two lines as shown (Convert paths):
//=== PROCESS COMMAND ========================================================= function process_command($command_array){ // There are only two types of command to process run and runh (run hidden) //== Convert paths $command_array[1] = relative_to_absolute_paths($command_array[1]); $command_array[2] = relative_to_absolute_paths($command_array[2]);
Array imbalance problem
Having a single array for a spacer introduces an imbalance of arrays. However since the configuration array is processed sequentially we know where this imbalance occurs hence we can rebalance the arrays.
Although it adds additional code, when configuring a menu configuration file makes life easier for an end user.
These arrays are sequentially ordered hence this function fits the bill:
Array insert function
//=== Array Insert ============================================================= function array_insert(&$array, $insert, $position = -1) { $position = ($position == -1) ? count($array) : $position ; if($position != count($array)) { // Is it end of array $ta = $array; // New array for($i = $position; $i < (count($array)); $i++) { // Scan array if(!isset($array[$i])) { // Check there are no holes in array die(print_r($array, 1)."\r\nInvalid array: All keys must be numerical and in sequence."); } $tmp[$i+1] = $array[$i]; // Build part of array unset($ta[$i]); // Kill element } $ta[$position] = $insert; // Insert value $array = $ta + $tmp; // Build complete array //print_r($array); } else { // Yes: End of array $array[$position] = $insert; // just insert value } ksort($array); // Ensure keys are ordered return true; } //========================================================= END Array Insert === |
Summary
Well in all honesty this page said coding hence filled it with some luddite code. If you are into object orientated programming along with hacking down to “c” level make WinBinder forum your first port of call. They have excellent material.
Hey! They don’t like luddites! However they do respect that we exist. Yep! Supposed to be a joke, point is, WinBinder caters for both traditional and object oriented programming styles. Style is a personal choice there are no restriction imposed by WinBinder.
Tutorial:
That completes this tutorial.
Was the objective meet?
"Objective is to produce a tray menu with format and features similar to Unitray. This ideally would be a replacement for Unitray. Secondary objective is to explore the capabilities of WinBinder."
Secondary objective certainly was and best part of the prime objective. However the menu lacks a right button pop-up menu. Right menu runs the server as a service and is easily catered for by adding items to the left menu.
Currently the menu is generic (see next page for details) and is usable for other applications.
For it to be a UniTray replacement a few Uniform Server specific features require adding. That said if you do not require multi-server support you could use it as is.
Next page looks the tray-menu demo included with the download.