001: /*
002: * Copyright (C) 2006 Methodhead Software LLC. All rights reserved.
003: *
004: * This file is part of TransferCM.
005: *
006: * TransferCM is free software; you can redistribute it and/or modify it under the
007: * terms of the GNU General Public License as published by the Free Software
008: * Foundation; either version 2 of the License, or (at your option) any later
009: * version.
010: *
011: * TransferCM is distributed in the hope that it will be useful, but WITHOUT ANY
012: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
013: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
014: * details.
015: *
016: * You should have received a copy of the GNU General Public License along with
017: * TransferCM; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
018: * Fifth Floor, Boston, MA 02110-1301 USA
019: */
020:
021: package com.methodhead.menu;
022:
023: import com.methodhead.tree.FoldingTreeNode;
024:
025: /**
026: <p>
027: Renders a DHTML menu using the HVMenu 5.5
028: (http://www.dynamicdrive.com/dynamicindex1/hvmenu/). The
029: menu is logically defined using menu classes from the
030: <tt>java.awt</tt> package. Assemble <tt>Menu</tt>s and
031: <tt>MenuItem</tt>s almost as you would in a GUI application.
032: Only a few of the <tt>awt</tt> methods are important
033: however:
034: </p>
035: <ul>
036: <li><tt>MenuItem.setLabel()</tt>: Sets the menu item's label.</li>
037: <li>
038: <tt>MenuItem.setActionCommand()</tt>: Sets the menu
039: item's URL; set to an empty string if it should not link to
040: anything.
041: </li>
042: </ul>
043: <p>
044: Also, <tt>MenuBar</tt> is not used at all. Instead, the
045: menu bar is represented by the root <tt>Menu</tt>.
046: <tt>Menu</tt> offers more methods to manage it contents.
047: </p>
048: <p>
049: HVMenu offers many configuration options. This renderer
050: does not manage those options. Instead, this class renders
051: only the menu definitions. Therefore, other script must be
052: present for this to work right: the variables that define
053: the look and operation of the menus and the menu script
054: itself.
055: </p>
056: */
057: public class MenuRenderer {
058:
059: // constructors /////////////////////////////////////////////////////////////
060:
061: // constants ////////////////////////////////////////////////////////////////
062:
063: // classes //////////////////////////////////////////////////////////////////
064:
065: // methods //////////////////////////////////////////////////////////////////
066:
067: /**
068: * Returns the JavaScript variable name for a menu item at
069: * <tt>path</tt> (e.g., a path of <tt>{1, 2}</tt> results
070: * in <tt>Menu1_2</tt>).
071: */
072: protected static String getVarName(int[] path) {
073:
074: String html = "Menu";
075:
076: for (int i = 0; i < path.length; i++) {
077: if (i == 0)
078: html += path[i];
079: else
080: html += "_" + path[i];
081: }
082:
083: return html;
084: }
085:
086: /**
087: * For the menu items in <tt>menu</tt>, returns the length of the longest
088: * label.
089: */
090: protected static int getLongestLabelLength(FoldingTreeNode menu) {
091:
092: int len = 0;
093: int tmp = 0;
094:
095: for (int i = 0; i < menu.getChildCount(); i++) {
096:
097: String label = ((FoldingTreeNode) menu.getChildAt(i))
098: .getLabel();
099: if (label == null)
100: label = "";
101:
102: tmp = label.length();
103: if (tmp > len)
104: len = tmp;
105: }
106:
107: return len;
108: }
109:
110: protected void getMenuHtml(StringBuffer buf, FoldingTreeNode menu,
111: int[] path, int width, int height) {
112:
113: //
114: // prepend baseUrl if menu item has an action command
115: //
116: String url = menu.getUrl();
117: if (url.length() > 0)
118: url = baseUrl_ + url;
119:
120: //
121: // render the html
122: //
123: String label = menu.getLabel();
124: if (label == null)
125: label = "null label";
126:
127: buf.append(getVarName(path) + "=new Array(\"" + label + "\",\""
128: + url + "\",\"\"," + menu.getChildCount() + ","
129: + height + "," + width + ");\n");
130:
131: //
132: // recurse into menu items
133: //
134: if (menu.getChildCount() > 0) {
135:
136: //
137: // calculate the menu width
138: //
139: width = getLongestLabelLength(menu) * fontWidthHint_;
140:
141: //
142: // allocate a new path array
143: //
144: int[] menupath = new int[path.length + 1];
145: System.arraycopy(path, 0, menupath, 0, path.length);
146: int last = menupath.length - 1;
147:
148: //
149: // get menu html
150: //
151: for (int i = 0; i < menu.getChildCount(); i++) {
152: menupath[last]++;
153: getMenuHtml(buf, (FoldingTreeNode) menu.getChildAt(i),
154: menupath, width, height);
155: }
156: }
157: }
158:
159: /**
160: * Returns a string containing the render menu
161: * definitions.
162: */
163: public String renderMenu(FoldingTreeNode menu) {
164:
165: StringBuffer buf = new StringBuffer();
166:
167: buf.append("NoOffFirstLineMenus=" + menu.getChildCount()
168: + ";\n");
169:
170: int[] path = new int[1];
171: for (int i = 0; i < menu.getChildCount(); i++) {
172: path[0] = i + 1;
173: FoldingTreeNode submenu = (FoldingTreeNode) menu
174: .getChildAt(i);
175:
176: //
177: // check for a missing label
178: //
179: String label = submenu.getLabel();
180: if (label == null)
181: label = "null label";
182:
183: getMenuHtml(buf, submenu, path, fontWidthHint_
184: * label.length(), fontHeightHint_);
185: }
186:
187: return buf.toString();
188: }
189:
190: // properties ///////////////////////////////////////////////////////////////
191:
192: /**
193: * Sets the approximate width of characters in the font used in the menu
194: * (defaults to 10).
195: */
196: public void setFontWidthHint(int width) {
197:
198: fontWidthHint_ = width;
199: }
200:
201: /**
202: * Sets the approximate height of characters in the font used in the menu
203: * (defaults to 20).
204: */
205: public void setFontHeightHint(int height) {
206:
207: fontHeightHint_ = height;
208: }
209:
210: /**
211: * Sets the base url prepended to all action commands.
212: */
213: public void setBaseUrl(String baseUrl) {
214:
215: baseUrl_ = baseUrl;
216: }
217:
218: // attributes ///////////////////////////////////////////////////////////////
219:
220: protected int fontWidthHint_ = 10;
221: protected int fontHeightHint_ = 20;
222: protected String baseUrl_ = "";
223: }
|