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)) {
  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. || (isset($cachecontrol) && $cachecontrol == "refresh")) {
  190. $this->menu = new menu_instance($this->menu_name, $this->language);
  191. debugbr("treemenu: new menu generated", DBG_DEBUG);
  192. }
  193. // Find the stylesheet, check for changes..
  194. $this->webpage = ($webpage === false) ? $RESPONSE : $webpage;
  195. if ($this->webpage->head->stylesheet != "") {
  196. $this->get_styles();
  197. }
  198. // If valid, continue processing..
  199. if ($this->menu->valid) {
  200. $this->menu_id = $this->menu->menu_id;
  201. $this->exists = true;
  202. // This processes the menu option selected and makes any
  203. // necessary adjustments to menu structure, and saves it..
  204. $this->process_navigation();
  205. }
  206. } // treemenu
  207. // ....................................................................
  208. /**
  209. * Process any menu navigation.
  210. * This means we take note of any $_mid value which signifies a menu
  211. * option of that ID is currently being focussed on and alter the menu
  212. * configuration accordingly. We also look at the current page and
  213. * compare that to the menu id 'action' to determine where we are and
  214. * what we should be doing.
  215. * @access private
  216. */
  217. function process_navigation() {
  218. global $_mid, $RESPONSE;
  219. if ($this->exists) {
  220. if (isset($_mid) && $this->menu->menuop_exists($_mid)) {
  221. $this->menu->current_menu_option = $_mid;
  222. $selmop = $this->menu->menuop($_mid);
  223. if ($selmop !== false && $selmop->is_submenuheading()) {
  224. $selmop->expanded = !$selmop->expanded;
  225. $this->menu->menu_ops[$_mid] = $selmop;
  226. }
  227. // Save the updated menu instance object..
  228. $this->save_to_session();
  229. }
  230. }
  231. } // process_navigation
  232. // ....................................................................
  233. /**
  234. * This method saves the menu_instance to the user session for next
  235. * time. This gives the menu persistence.
  236. * @access private
  237. */
  238. function save_to_session() {
  239. $up = new dbupdate("ax_wwwsession");
  240. $up->set("menu_status", serialize($this->menu));
  241. $up->where("session_id='$this->session_id'");
  242. $up->execute();
  243. } // save_to_session
  244. // ....................................................................
  245. /**
  246. * Obtain the non-standard styles from the stylesheet
  247. */
  248. function get_styles() {
  249. // Get fonts and colours etc. If this stylesheet is undefined or
  250. // doesn't exist on disk, then we should still be able to generate
  251. // the vars below, but will get the defaults in each case..
  252. if (isset($this->webpage->head)) {
  253. $ss = new stylesheet($this->webpage->site_docroot . $this->webpage->head->stylesheet);
  254.  
  255. // Read in all the style settings..
  256. $this->Tablestyle = defaulted($ss->style("menu", "menu-tablestyle"), "none");
  257. $this->Align = defaulted($ss->style("menu", "menu-align"), "left");
  258. $this->VerticalAlign = defaulted($ss->style("menu", "menu-vertical-align"), "left");
  259. $this->LowColor = defaulted($ss->style("menu", "color"), "black");
  260. $this->LowBgColor = defaulted($ss->style("menu", "background-color"), "white");
  261. $this->HighColor = defaulted($ss->style("menu_highlight", "color"), "white");
  262. $this->HighBgColor = defaulted($ss->style("menu_highlight", "background-color"), "black");
  263. $this->BorderColor = defaulted($ss->style("menu", "border-color"), "black");
  264. $this->BorderWidth = defaulted($ss->style("menu", "border-width"), "");
  265. $this->SubLowColor = defaulted($ss->style("submenu", "color"), "#efefef");
  266. $this->SubLowBgColor = defaulted($ss->style("submenu", "background-color"), "#666666");
  267. $this->SubHighColor = defaulted($ss->style("submenu_highlight", "color"), "white");
  268. $this->SubHighBgColor = defaulted($ss->style("submenu_highlight", "background-color"), "#666666");
  269. $this->SubBorderColor = defaulted($ss->style("submenu", "border-color"), "black");
  270. $this->SubBorderWidth = defaulted($ss->style("submenu", "border-width"), "");
  271.  
  272. // Menu fixed width. Zero means not fixed..
  273. $val = defaulted($ss->style("menu", "menu-fixed-width"), "0px");
  274. $this->menu_width = str_replace("px", "", $val);
  275.  
  276. // Padding which is inserted just before the text menu option labels..
  277. $val = defaulted($ss->style("menu", "label-padding-left"), "0px");
  278. $this->label_padding_left = str_replace("px", "", $val);
  279.  
  280. // Vertical spacing above level0 top menu options..
  281. $val = defaulted($ss->style("menu", "top-item-spacing"), "0px");
  282. $this->top_item_spacing = str_replace("px", "", $val);
  283.  
  284. // Vertical spacing above heading submenu-options. These
  285. // are the parent options of non-top-level sub-menus..
  286. $val = defaulted($ss->style("menu", "heading-item-spacing"), "0px");
  287. $this->heading_item_spacing = str_replace("px", "", $val);
  288.  
  289. // Vertical spacing above 'pseudo' menu options..
  290. $val = defaulted($ss->style("menu", "pseudo-item-spacing"), "0px");
  291. $this->pseudo_item_spacing = str_replace("px", "", $val);
  292.  
  293. // Vertical spacing above 'normal' menu options..
  294. $val = defaulted($ss->style("menu", "item-spacing"), "0px");
  295. $this->item_spacing = str_replace("px", "", $val);
  296.  
  297. // Padding size of level indentation is determined by the overlap factor..
  298. $overlap = defaulted($ss->style("menu", "child-overlap"), "0.96");
  299. if ($overlap > 1) $overlap = 1;
  300. $width = ($this->menu_width > 0) ? $this->menu_width : 200;
  301. $this->padsize = floor((1 - $overlap) * $width);
  302. $val = defaulted($ss->style("menu", "show-arrows"), "no");
  303. $this->ShowArrow = ($val == "yes");
  304. }
  305. } // get_styles
  306. // ....................................................................
  307. /**
  308. * Over-rides the standard '+' and '-' icon images used to indicate a
  309. * sub-menu can be expanded or collapsed. The values passed should be
  310. * image image objects as instances of the 'img' class (@see img()).
  311. * @param object $expandimg New image for 'expand' graphic
  312. * @param object $collapseimg New image for 'collapse' graphic
  313. * @param object $mopimg New image for 'menu option' graphic
  314. * @param object $padimg New image for 'pad' graphic
  315. */
  316. function set_menu_images($expandimg=false, $collapseimg=false, $menuopimg=false, $padimg=false) {
  317. if ($expandimg !== false) {
  318. $this->expandimage = $expandimg;
  319. }
  320. if ($collapseimg !== false) {
  321. $this->collapseimage = $collapseimg;
  322. }
  323. if ($menuopimg !== false) {
  324. $this->menuopimage = $menuopimg;
  325. }
  326. if ($padimg !== false) {
  327. $this->padimage = $padimg;
  328. }
  329. } // set_menu_images
  330. // ....................................................................
  331. /**
  332. * Process a menu entry/option/item and return the HTML rendering
  333. * of it as it would sit in the menu. We also process child options
  334. * of the given option by iteration.
  335. * @param object $Tmenu The table object the menu is being built in
  336. * @param string $prefix The prefix string for the menu option
  337. * @param integer $mopid The menu option ID of this menu option
  338. * @return object The modified menu table object
  339. * @access private
  340. */
  341. function menu_entry($Tmenu, $prefix, $mopid) {
  342. global $LIBDIR, $RESPONSE;
  343. static $first = true;
  344.  
  345. $childcount = 0;
  346. $s = "";
  347.  
  348. // Store current menu option..
  349. $mop = $this->menu->menuop($mopid);
  350. if ($mop !== false) {
  351. $details = $mop->details();
  352. $menu_level = $mop->menu_level;
  353. $label = $mop->label;
  354. $action = $mop->action;
  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.  
  410. // Add selected menu option id to url..
  411. $action = href_addparm($action, "_mid", $mopid);
  412.  
  413. // Make sure our menu gets refreshed and not stuck in a static
  414. // state in the web-browser's cache..
  415. $action = href_addparm($action, "cachecontrol", "dynamic");
  416.  
  417. // Padding for this menu level..
  418. $padding = $this->padimage;
  419. $padding->setwidth($this->padsize * $menu_level);
  420.  
  421. // Highlight if the current script name occurs in the item action..
  422. $style = "";
  423. $requestedurl = basename($RESPONSE->requested) . ($RESPONSE->requested_query != "" ? "\?$RESPONSE->requested_query" : "");
  424.  
  425. $pad = new img("$LIBDIR/img/_pad.gif", "", "", $this->label_padding_left, 1);
  426. if (!$heading && preg_match("/$requestedurl/i", $action)) {
  427. $menuop = $padding->render() . $widget->render() . $pad->render() . $label;
  428. $style = "color:$hicolour;background-color:$hibg;";
  429. }
  430. // Create a clickable anchor link..
  431. else {
  432. $widget_link = new anchor($action, $widget->render());
  433. $menuop_link = new anchor($action, $label);
  434. $menuop = "";
  435. if ( $padding->width > 0 ) {
  436. $menuop .= $padding->render();
  437. }
  438. $menuop .= $widget_link->render() . $pad->render() . $menuop_link->render();
  439. }
  440. }
  441. // Deal with pseudo menu-items here..
  442. else {
  443. switch ($label) {
  444. case MENU_ITEM_SEPARATOR:
  445. // This results in a separator line 1px wide..
  446. $menuop = "<table border=0 cellspacing=0 cellpadding=0 width=\"100%\" ";
  447. $menuop .= "style=\"background-color:$this->LowColor\">";
  448. $menuop .= "<tr><td></td></tr>";
  449. $menuop .= "</table>";
  450. break;
  451. default:
  452. // 1-pixel placeholder, so we have some content..
  453. $pad = new img("$LIBDIR/img/_pad.gif", "", "", 1, 1);
  454. $menuop = $pad->render();
  455. } // switch
  456. }
  457.  
  458. // Borders, if any..
  459. if ($border != "" && substr($border,0,1) != "0") {
  460. if ($first) {
  461. $style .= "border-width:$border;";
  462. }
  463. else {
  464. $style .= "border-width:0px $border $border $border;";
  465. }
  466. }
  467. if ($first) $first = false;
  468.  
  469. // Render menu item/option..
  470. $Tmenu->tr();
  471. $Tmenu->td($menuop, $class);
  472. if ($style != "") {
  473. $Tmenu->td_css($style);
  474. }
  475.  
  476. // Spacing and padding styles..
  477. $top_spacing = 0;
  478. $bot_spacing = 0;
  479. if ($pseudo) {
  480. $spacing = ($this->pseudo_item_spacing > 0) ? $this->pseudo_item_spacing : $this->item_spacing;
  481. $top_spacing = ceil($spacing / 2);
  482. $bot_spacing = $spacing - $top_spacing;
  483. $Tmenu->td_alignment("","middle");
  484. }
  485. elseif ($menu_level == 0) {
  486. $top_spacing = $this->top_item_spacing;
  487. }
  488. elseif ($heading) {
  489. $top_spacing = $this->heading_item_spacing;
  490. }
  491. else {
  492. $top_spacing = $this->item_spacing;
  493. }
  494.  
  495. // Apply any spacing which eventuated..
  496. if ($top_spacing > 0) {
  497. $Tmenu->td_css("padding-top:" . $top_spacing . "px");
  498. }
  499. if ($bot_spacing > 0) {
  500. $Tmenu->td_css("padding-bottom:" . $bot_spacing . "px");
  501. }
  502.  
  503. // And now do the children of sub-menu heading..
  504. //if ($heading && $expanded) {
  505. if ($expanded) {
  506. if (isset($mop->children) && $mop->children != "") {
  507. $childoptions = explode("|", $mop->children);
  508. $childcount = count($childoptions);
  509. $pfxcount = 1;
  510. foreach ($childoptions as $childmopid) {
  511. $childprefix = $prefix . "|" . $pfxcount;
  512. $Tmenu = $this->menu_entry($Tmenu, $childprefix, $childmopid);
  513. $pfxcount += 1;
  514. }
  515. }
  516. }
  517. }
  518. // Return the menu table..
  519. return $Tmenu;
  520. } // menu_entry
  521. // ....................................................................
  522. /**
  523. * Render the menu as HTML. Please note that the TreeMenu is by design
  524. * a VERTICAL menu system, so don't expect the 'orientation' style in
  525. * the stylesheet to have any effect for this class.
  526. * @return string The HTML
  527. */
  528. function html() {
  529. debug_trace($this);
  530. global $LIBDIR, $RESPONSE;
  531. global $_mid;
  532.  
  533. // Menu layout table..
  534. $Tmenu = new table($this->menu_id . "_menu", "");
  535. $Tmenu->setalign($this->Align);
  536. $Tmenu->setvalign($this->VerticalAlign);
  537. if ($this->menu_width > 0) {
  538. $Tmenu->setwidth($this->menu_width);
  539. }
  540. else {
  541. $Tmenu->setwidth("100%");
  542. }
  543.  
  544. // Apply given tablestyle class..
  545. if ($this->Tablestyle != "none") {
  546. $Tmenu->setclass($this->Tablestyle);
  547. }
  548.  
  549. // MENU ITEM DETAIL..
  550. if ($this->menu->menuop_count() > 0) {
  551. // Store each row..
  552. foreach ($this->menu->menu_top as $item_no => $mopid) {
  553. $prefix = "$item_no";
  554. $Tmenu = $this->menu_entry($Tmenu, $prefix, $mopid);
  555. }
  556. }
  557. // Render the menu viewer table..
  558. return $Tmenu->render();
  559. } // html
  560.  
  561. } // treemenu class
  562. // ----------------------------------------------------------------------
  563.  
  564. ?>

Documentation generated by phpDocumentor 1.3.0RC3