Source for file treemenu-defs.php

Documentation is available at treemenu-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: treemenu-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for a non-javascript multi-level (tree) */
  24. /* menu system, in vertical rendering. */
  25. /* */
  26. /* ******************************************************************** */
  27. /** @package menu */
  28. include_once("menu-defs.php");
  29.  
  30. // ----------------------------------------------------------------------
  31. /**
  32. * A hierarchical menu renderer which does not use Javascript to
  33. * implement the menuoption display.
  34. * @package menu
  35. */
  36. class treemenu extends RenderableObject {
  37. // Public
  38. /** Menu name eg: 'main' */
  39.  
  40. var $menu_name = "";
  41. /** Menu language, or default if zero */
  42.  
  43. var $language = 0;
  44. /** Path to the stylesheet for menu */
  45.  
  46. var $stylesheet = "";
  47. /** Overall class for the menu table */
  48.  
  49. var $Tablestyle = "none";
  50. /** Alignment of the menu table */
  51.  
  52. var $Align = "left";
  53. /** Colour of normal top menu item text */
  54.  
  55. var $LowColor = "black";
  56. /** Colour of normal top menu item background */
  57.  
  58. var $LowBgColor = "white";
  59. /** Colour of highlighted top menu item text */
  60.  
  61. var $HighColor = "white";
  62. /** Colour of highlighted top menu item background */
  63.  
  64. var $HighBgColor = "black";
  65. /** Colour of top menu item border */
  66.  
  67. var $BorderColor = "black";
  68. /** Width of top menu border in px */
  69.  
  70. var $BorderWidth = "";
  71. /** Colour of sub-menu item normal text */
  72.  
  73. var $SubLowColor = "#efefef";
  74. /** Colour of sub-menu item background */
  75.  
  76. var $SubLowBgColor = "#666666";
  77. /** Colour of sub-menu highlighted item text */
  78.  
  79. var $SubHighColor = "white";
  80. /** Colour of sub-menu highlighted item background */
  81.  
  82. var $SubHighBgColor = "#666666";
  83. /** Colour of sub-menu border */
  84.  
  85. var $SubBorderColor = "black";
  86. /** Width of sub-menu border in px */
  87.  
  88. var $SubBorderWidth = "";
  89. /** Fixed menu width, or zero if not fixed */
  90.  
  91. var $menu_width = 0;
  92. /** Size of level indent padding in px */
  93.  
  94. var $padsize = 10;
  95. /** Padding between menuoption image, and menu item text
  96. in pixels */
  97. var $label_padding_left = 0;
  98. /** Padding before (above) the top-level menu options */
  99.  
  100. var $top_item_spacing = 0;
  101. /** Padding before (above) menu options which are
  102. headings for sub-menus */
  103. var $heading_item_spacing = 0;
  104. /** Padding before (above) 'pseudo' menu options */
  105.  
  106. var $pseudo_item_spacing = 0;
  107. /** Padding before (above) 'normal' menu options */
  108.  
  109. var $item_spacing = 0;
  110.  
  111. // Private
  112. /** The menu instance
  113. @access private */
  114. var $menu;
  115. /** Unique database menu ID
  116. @access private */
  117. var $menu_id = 0;
  118. /** The current user session ID
  119. @access private */
  120. var $session_id;
  121. /** Whether this menu exists in the database
  122. @access private */
  123. var $exists = false;
  124. /** Initial menuoption ID
  125. @access private */
  126. var $menuoption_id;
  127. /** Image to use for collapsed sub-menu
  128. @access private */
  129. var $expandimage;
  130. /** Image to use for expanded sub-menu
  131. @access private */
  132. var $collapseimage;
  133. /** Image to use to indicate a menu option
  134. @access private */
  135. var $menuopimage;
  136. /** Image to use for padding/indenting menu options
  137. @access private */
  138. var $padimage;
  139. // ....................................................................
  140. /**
  141. * Constructor
  142. * Create a new menumaintainer.
  143. * @param string $menu_name Menu name
  144. * @param object $webpage Webpage object that this menu is being created for
  145. * @param string $stylsheet Name of stylesheet file to reference for menu styles
  146. * @param integer $lang Optional language variant of this menu (0 = default)
  147. */
  148. function treemenu($menu_name="main", $webpage=false, $stylesheet="", $lang=-1) {
  149. global $RESPONSE, $LIBDIR, $cachecontrol;
  150.  
  151. // Default these standard images..
  152. $this->expandimage = new img("$LIBDIR/img/_plus.gif", "Expand", "Expand", 9, 9);
  153. $this->collapseimage = new img("$LIBDIR/img/_minus.gif", "Collapse", "Collapse", 9, 9);
  154. $this->menuopimage = new img("$LIBDIR/img/_mop.gif", "", "", 9, 9);
  155. $this->padimage = new img("$LIBDIR/img/_pad.gif", "", "", 1, 1);
  156.  
  157. // Set menu name..
  158. $this->menu_name = $menu_name;
  159. // Set the menu language..
  160. if ($lang != -1) {
  161. $this->language = $lang;
  162. }
  163. elseif ($webpage !== false && $webpage->multilang && isset($webpage->languages[0])) {
  164. $this->language = $webpage->languages[0];
  165. }
  166. elseif (isset($RESPONSE) && $RESPONSE->multilang && isset($RESPONSE->languages[0])) {
  167. $this->language = $RESPONSE->languages[0];
  168. }
  169. // Check if we can use a menu stored in the session..
  170. // Manage selected menuoption..
  171. if (is_object($webpage) && $webpage->cachecontrol != "refresh") {
  172. $this->session_id = $webpage->session_id;
  173. if ($webpage->session_record["menu_status"] != "") {
  174. debugbr("unserializing menu..");
  175. $menu = unserialize($webpage->session_record["menu_status"]);
  176. if (is_object($menu) && $menu->valid
  177. && ($menu->menu_name == $this->menu_name && $menu->language == $this->language)) {
  178. debugbr("installing pre-existing menu..");
  179. $this->menu = $menu;
  180. if ($this->menu->get_if_modified()) {
  181. debugbr("rebuilt modified menu..");
  182. $this->save_to_session();
  183. }
  184. }
  185. }
  186. }
  187. // Create it if it doesn't exist, re-create if required..
  188. if (!isset($this->menu)) {
  189. $this->menu = new menu_instance($this->menu_name, $this->language);
  190. debugbr("treemenu: new menu generated", DBG_DEBUG);
  191. }
  192. // Find the stylesheet, check for changes..
  193. $this->webpage = ($webpage === false) ? $RESPONSE : $webpage;
  194. if ($this->webpage->head->stylesheet != "") {
  195. $this->get_styles();
  196. }
  197. // If valid, continue processing..
  198. if ($this->menu->valid) {
  199. $this->menu_id = $this->menu->menu_id;
  200. $this->exists = true;
  201. // This processes the menu option selected and makes any
  202. // necessary adjustments to menu structure, and saves it..
  203. $this->process_navigation();
  204. }
  205. } // treemenu
  206. // ....................................................................
  207. /**
  208. * Process any menu navigation.
  209. * This means we take note of any $_mid value which signifies a menu
  210. * option of that ID is currently being focussed on and alter the menu
  211. * configuration accordingly. We also look at the current page and
  212. * compare that to the menu id 'action' to determine where we are and
  213. * what we should be doing.
  214. * @access private
  215. */
  216. function process_navigation() {
  217. global $_mid, $RESPONSE;
  218. if ($this->exists) {
  219. if (isset($_mid) && $this->menu->menuop_exists($_mid)) {
  220. $this->menu->current_menu_option = $_mid;
  221. $selmop = $this->menu->menuop($_mid);
  222. if ($selmop !== false && $selmop->is_submenuheading()) {
  223. $selmop->expanded = !$selmop->expanded;
  224. $this->menu->menu_ops[$_mid] = $selmop;
  225. }
  226. // Save the updated menu instance object..
  227. $this->save_to_session();
  228. }
  229. }
  230. } // process_navigation
  231. // ....................................................................
  232. /**
  233. * This method saves the menu_instance to the user session for next
  234. * time. This gives the menu persistence.
  235. * @access private
  236. */
  237. function save_to_session() {
  238. $up = new dbupdate("ax_wwwsession");
  239. $up->set("menu_status", serialize($this->menu));
  240. $up->where("session_id='$this->session_id'");
  241. $up->execute();
  242. } // save_to_session
  243. // ....................................................................
  244. /**
  245. * Obtain the non-standard styles from the stylesheet
  246. */
  247. function get_styles() {
  248. // Get fonts and colours etc. If this stylesheet is undefined or
  249. // doesn't exist on disk, then we should still be able to generate
  250. // the vars below, but will get the defaults in each case..
  251. if (isset($this->webpage->head)) {
  252. $ss = new stylesheet($this->webpage->site_docroot . $this->webpage->head->stylesheet);
  253.  
  254. // Read in all the style settings..
  255. $this->Tablestyle = defaulted($ss->style("menu", "menu-tablestyle"), "none");
  256. $this->Align = defaulted($ss->style("menu", "menu-align"), "left");
  257. $this->VerticalAlign = defaulted($ss->style("menu", "menu-vertical-align"), "left");
  258. $this->LowColor = defaulted($ss->style("menu", "color"), "black");
  259. $this->LowBgColor = defaulted($ss->style("menu", "background-color"), "white");
  260. $this->HighColor = defaulted($ss->style("menu_highlight", "color"), "white");
  261. $this->HighBgColor = defaulted($ss->style("menu_highlight", "background-color"), "black");
  262. $this->BorderColor = defaulted($ss->style("menu", "border-color"), "black");
  263. $this->BorderWidth = defaulted($ss->style("menu", "border-width"), "");
  264. $this->SubLowColor = defaulted($ss->style("submenu", "color"), "#efefef");
  265. $this->SubLowBgColor = defaulted($ss->style("submenu", "background-color"), "#666666");
  266. $this->SubHighColor = defaulted($ss->style("submenu_highlight", "color"), "white");
  267. $this->SubHighBgColor = defaulted($ss->style("submenu_highlight", "background-color"), "#666666");
  268. $this->SubBorderColor = defaulted($ss->style("submenu", "border-color"), "black");
  269. $this->SubBorderWidth = defaulted($ss->style("submenu", "border-width"), "");
  270.  
  271. // Menu fixed width. Zero means not fixed..
  272. $val = defaulted($ss->style("menu", "menu-fixed-width"), "0px");
  273. $this->menu_width = str_replace("px", "", $val);
  274.  
  275. // Padding which is inserted just before the text menu option labels..
  276. $val = defaulted($ss->style("menu", "label-padding-left"), "0px");
  277. $this->label_padding_left = str_replace("px", "", $val);
  278.  
  279. // Vertical spacing above level0 top menu options..
  280. $val = defaulted($ss->style("menu", "top-item-spacing"), "0px");
  281. $this->top_item_spacing = str_replace("px", "", $val);
  282.  
  283. // Vertical spacing above heading submenu-options. These
  284. // are the parent options of non-top-level sub-menus..
  285. $val = defaulted($ss->style("menu", "heading-item-spacing"), "0px");
  286. $this->heading_item_spacing = str_replace("px", "", $val);
  287.  
  288. // Vertical spacing above 'pseudo' menu options..
  289. $val = defaulted($ss->style("menu", "pseudo-item-spacing"), "0px");
  290. $this->pseudo_item_spacing = str_replace("px", "", $val);
  291.  
  292. // Vertical spacing above 'normal' menu options..
  293. $val = defaulted($ss->style("menu", "item-spacing"), "0px");
  294. $this->item_spacing = str_replace("px", "", $val);
  295.  
  296. // Padding size of level indentation is determined by the overlap factor..
  297. $overlap = defaulted($ss->style("menu", "child-overlap"), "0.96");
  298. if ($overlap > 1) $overlap = 1;
  299. $width = ($this->menu_width > 0) ? $this->menu_width : 200;
  300. $this->padsize = floor((1 - $overlap) * $width);
  301. $val = defaulted($ss->style("menu", "show-arrows"), "no");
  302. $this->ShowArrow = ($val == "yes");
  303. }
  304. } // get_styles
  305. // ....................................................................
  306. /**
  307. * Over-rides the standard '+' and '-' icon images used to indicate a
  308. * sub-menu can be expanded or collapsed. The values passed should be
  309. * image image objects as instances of the 'img' class (@see img()).
  310. * @param object $expandimg New image for 'expand' graphic
  311. * @param object $collapseimg New image for 'collapse' graphic
  312. * @param object $mopimg New image for 'menu option' graphic
  313. * @param object $padimg New image for 'pad' graphic
  314. */
  315. function set_menu_images($expandimg=false, $collapseimg=false, $menuopimg=false, $padimg=false) {
  316. if ($expandimg !== false) {
  317. $this->expandimage = $expandimg;
  318. }
  319. if ($collapseimg !== false) {
  320. $this->collapseimage = $collapseimg;
  321. }
  322. if ($menuopimg !== false) {
  323. $this->menuopimage = $menuopimg;
  324. }
  325. if ($padimg !== false) {
  326. $this->padimage = $padimg;
  327. }
  328. } // set_menu_images
  329. // ....................................................................
  330. /**
  331. * Process a menu entry/option/item and return the HTML rendering
  332. * of it as it would sit in the menu. We also process child options
  333. * of the given option by iteration.
  334. * @param object $Tmenu The table object the menu is being built in
  335. * @param string $prefix The prefix string for the menu option
  336. * @param integer $mopid The menu option ID of this menu option
  337. * @return object The modified menu table object
  338. * @access private
  339. */
  340. function menu_entry($Tmenu, $prefix, $mopid) {
  341. global $LIBDIR, $RESPONSE;
  342. static $first = true;
  343.  
  344. $childcount = 0;
  345. $s = "";
  346.  
  347. // Store current menu option..
  348. $mop = $this->menu->menuop($mopid);
  349. if ($mop !== false) {
  350. $details = $mop->details();
  351. $menu_level = $mop->menu_level;
  352. $label = $mop->label;
  353. $action = $mop->action;
  354. $target = $mop->target;
  355. $expanded = $mop->expanded;
  356. $heading = $mop->is_submenuheading(); // Whether it is a heading for sub-menu
  357. $pseudo = $mop->is_pseudo(); // Whether it is a pseudo menu-item
  358. $menuoption = !$heading;
  359.  
  360. // Set up menu/submenu styling..
  361. if ($menu_level == 0) {
  362. $class = "menu";
  363. $hicolour = $this->HighColor;
  364. $hibg = $this->HighBgColor;
  365. $border = $this->BorderWidth;
  366. }
  367. else {
  368. $class = "submenu";
  369. $hicolour = $this->SubHighColor;
  370. $hibg = $this->SubHighBgColor;
  371. $border = $this->SubBorderWidth;
  372. }
  373.  
  374. // Non-pseudo menu-items first..
  375. if (!$pseudo) {
  376. if ($heading) {
  377. // Widgets for headings (non-menuoptions)..
  378. if ($expanded) {
  379. $widget = $this->collapseimage;
  380. }
  381. else {
  382. $widget = $this->expandimage;
  383. }
  384. // Link to current page for refresh..
  385. if ($action == "") {
  386. $action = $RESPONSE->requested;
  387. if ($RESPONSE->requested_query != "") {
  388. $action .= "?$RESPONSE->requested_query";
  389. }
  390. }
  391. }
  392. else {
  393. // padding for standard menuoption..
  394. if ($menu_level > 0) {
  395. if ($this->ShowArrow) {
  396. $widget = $this->menuopimage;
  397. }
  398. else {
  399. $widget = $this->padimage;
  400. $widget->setwidth($this->padsize);
  401. }
  402. }
  403. else {
  404. $widget = $this->padimage;
  405. $widget->setwidth($this->padsize);
  406. }
  407. }
  408. //$widget->sethspace(2);
  409. // Add selected menu option id to URL, but only if it is
  410. // not an off-site URL of some kind..
  411. if (!protocol_prefixed($action)) {
  412. $action = href_addparm($action, "_mid", $mopid);
  413.  
  414. // Make sure our menu gets refreshed and not stuck in a static
  415. // state in the web-browser's cache..
  416. $action = href_addparm($action, "cachecontrol", "dynamic");
  417. }
  418.  
  419. // Padding for this menu level..
  420. $padding = $this->padimage;
  421. $padding->setwidth($this->padsize * $menu_level);
  422.  
  423. // Highlight if the current script name occurs in the item action..
  424. $style = "";
  425. $requestedurl = basename($RESPONSE->requested) . ($RESPONSE->requested_query != "" ? "\?$RESPONSE->requested_query" : "");
  426.  
  427. $pad = new img("$LIBDIR/img/_pad.gif", "", "", $this->label_padding_left, 1);
  428. if (!$heading && preg_match(";$requestedurl;i", $action)) {
  429. $menuop = $padding->render() . $widget->render() . $pad->render() . $label;
  430. $style = "color:$hicolour;background-color:$hibg;";
  431. }
  432. // Create a clickable anchor link..
  433. else {
  434. $widget_link = new anchor($action, $widget->render());
  435. $menuop_link = new anchor($action, $label);
  436. if (preg_match(";$requestedurl;i", $action) && $mop->is_submenuheading() && trim($mop->action) != "") {
  437. $style = "color:$hicolour;background-color:$hibg;";
  438. $menuop_link->setcss($style);
  439. }
  440. if ($target != "") {
  441. $widget_link->settarget($target);
  442. $menuop_link->settarget($target);
  443. }
  444. $menuop = "";
  445. if ( $padding->width > 0 ) {
  446. $menuop .= $padding->render();
  447. }
  448. $menuop .= $widget_link->render() . $pad->render() . $menuop_link->render();
  449. }
  450. }
  451. // Deal with pseudo menu-items here..
  452. else {
  453. switch ($label) {
  454. case MENU_ITEM_SEPARATOR:
  455. // This results in a separator line 1px wide..
  456. $menuop = "<table border=0 cellspacing=0 cellpadding=0 width=\"100%\" ";
  457. $menuop .= "style=\"background-color:$this->LowColor\">";
  458. $menuop .= "<tr><td></td></tr>";
  459. $menuop .= "</table>";
  460. break;
  461. default:
  462. // 1-pixel placeholder, so we have some content..
  463. $pad = new img("$LIBDIR/img/_pad.gif", "", "", 1, 1);
  464. $menuop = $pad->render();
  465. } // switch
  466. }
  467.  
  468. // Borders, if any..
  469. if ($border != "" && substr($border,0,1) != "0") {
  470. if ($first) {
  471. $style .= "border-width:$border;";
  472. }
  473. else {
  474. $style .= "border-width:0px $border $border $border;";
  475. }
  476. }
  477. if ($first) $first = false;
  478.  
  479. // Render menu item/option..
  480. $Tmenu->tr();
  481. $Tmenu->td($menuop, $class);
  482. if ($style != "") {
  483. $Tmenu->td_css($style);
  484. }
  485.  
  486. // Spacing and padding styles..
  487. $top_spacing = 0;
  488. $bot_spacing = 0;
  489. if ($pseudo) {
  490. $spacing = ($this->pseudo_item_spacing > 0) ? $this->pseudo_item_spacing : $this->item_spacing;
  491. $top_spacing = ceil($spacing / 2);
  492. $bot_spacing = $spacing - $top_spacing;
  493. $Tmenu->td_alignment("","middle");
  494. }
  495. elseif ($menu_level == 0) {
  496. $top_spacing = $this->top_item_spacing;
  497. }
  498. elseif ($heading) {
  499. $top_spacing = $this->heading_item_spacing;
  500. }
  501. else {
  502. $top_spacing = $this->item_spacing;
  503. }
  504.  
  505. // Apply any spacing which eventuated..
  506. if ($top_spacing > 0) {
  507. $Tmenu->td_css("padding-top:" . $top_spacing . "px");
  508. }
  509. if ($bot_spacing > 0) {
  510. $Tmenu->td_css("padding-bottom:" . $bot_spacing . "px");
  511. }
  512.  
  513. // And now do the children of sub-menu heading..
  514. //if ($heading && $expanded) {
  515. if ($expanded) {
  516. if (isset($mop->children) && $mop->children != "") {
  517. $childoptions = explode("|", $mop->children);
  518. $childcount = count($childoptions);
  519. $pfxcount = 1;
  520. foreach ($childoptions as $childmopid) {
  521. $childprefix = $prefix . "|" . $pfxcount;
  522. $Tmenu = $this->menu_entry($Tmenu, $childprefix, $childmopid);
  523. $pfxcount += 1;
  524. }
  525. }
  526. }
  527. }
  528. // Return the menu table..
  529. return $Tmenu;
  530. } // menu_entry
  531. // ....................................................................
  532. /**
  533. * Render the menu as HTML. Please note that the TreeMenu is by design
  534. * a VERTICAL menu system, so don't expect the 'orientation' style in
  535. * the stylesheet to have any effect for this class.
  536. * @return string The HTML
  537. */
  538. function html() {
  539. debug_trace($this);
  540. global $LIBDIR, $RESPONSE;
  541. global $_mid;
  542.  
  543. // Menu layout table..
  544. $Tmenu = new table($this->menu_id . "_menu", "");
  545. $Tmenu->setalign($this->Align);
  546. $Tmenu->setvalign($this->VerticalAlign);
  547. if ($this->menu_width > 0) {
  548. $Tmenu->setwidth($this->menu_width);
  549. }
  550. else {
  551. $Tmenu->setwidth("100%");
  552. }
  553.  
  554. // Apply given tablestyle class..
  555. if ($this->Tablestyle != "none") {
  556. $Tmenu->setclass($this->Tablestyle);
  557. }
  558.  
  559. // MENU ITEM DETAIL..
  560. if ($this->menu->menuop_count() > 0) {
  561. // Store each row..
  562. foreach ($this->menu->menu_top as $item_no => $mopid) {
  563. $prefix = "$item_no";
  564. $Tmenu = $this->menu_entry($Tmenu, $prefix, $mopid);
  565. }
  566. }
  567. // Render the menu viewer table..
  568. return $Tmenu->render();
  569. } // html
  570.  
  571. } // treemenu class
  572. // ----------------------------------------------------------------------
  573.  
  574. ?>

Documentation generated by phpDocumentor 1.3.0RC3