1 16 package org.apache.cocoon.forms.formmodel.tree; 17 18 import java.util.HashMap ; 19 import java.util.HashSet ; 20 import java.util.Iterator ; 21 import java.util.Locale ; 22 import java.util.Set ; 23 24 import org.apache.cocoon.environment.Request; 25 import org.apache.cocoon.forms.FormContext; 26 import org.apache.cocoon.forms.event.WidgetEventMulticaster; 27 import org.apache.cocoon.forms.formmodel.AbstractWidget; 28 import org.apache.cocoon.forms.formmodel.Widget; 29 import org.apache.cocoon.forms.formmodel.WidgetDefinition; 30 import org.xml.sax.ContentHandler ; 31 import org.xml.sax.SAXException ; 32 33 38 public class Tree extends AbstractWidget { 39 40 public static final int SINGLE_SELECTION = 0; 41 public static final int MULTIPLE_SELECTION = 1; 42 43 public interface ActionHandler { 44 public void act(Tree tree, FormContext context); 45 } 46 47 private TreeDefinition treeDef; 48 49 private TreeModel treeModel; 50 51 private Set expandedPaths = new HashSet (); 52 53 private Set selectedPaths = new HashSet (); 54 55 private Set changedPaths = new HashSet (); 56 57 private HashMap pathWidgets = new HashMap (); 58 59 private boolean rootVisible = true; 60 61 private boolean expandSelectedPath = false; 62 63 private TreeSelectionListener selectionListener; 64 65 private int selectionModel = MULTIPLE_SELECTION; 66 67 private TreeModelListener modelListener = new TreeModelListener() { 68 public void treeStructureChanged(TreeModelEvent event) { 69 markForRefresh(event.getPath()); 70 } 71 }; 72 73 protected Tree(TreeDefinition definition) { 74 super(definition); 75 this.treeDef = definition; 76 this.rootVisible = definition.isRootVisible(); 77 if (!this.rootVisible) { 78 this.expandedPaths.add(TreePath.ROOT_PATH); 80 } 81 this.treeModel = definition.createModel(); 82 this.treeModel.addTreeModelListener(modelListener); 83 this.selectionListener = definition.getSelectionListener(); 84 this.selectionModel = definition.getSelectionModel(); 85 } 86 87 public WidgetDefinition getDefinition() { 88 return this.treeDef; 89 } 90 91 protected String getXMLElementName() { 92 return "tree"; 93 } 94 95 protected void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException { 96 throw new UnsupportedOperationException (this + " cannot be rendered using <ft:widget>. Please use <ft:tree>."); 97 } 98 99 public void readFromRequest(FormContext formContext) { 100 102 Request req = formContext.getRequest(); 103 String paramName = getRequestParameterName(); 104 105 String [] selectValues = req.getParameterValues(paramName + ":select"); 109 if (selectValues != null) { 110 Set newSelection = new HashSet (); 112 for (int i = 0; i < selectValues.length; i++) { 113 newSelection.add(TreePath.valueOf(selectValues[i])); 114 } 115 116 TreePath[] currentSelection = (TreePath[])this.selectedPaths.toArray(new TreePath[this.selectedPaths.size()]); 118 for (int i = 0; i < currentSelection.length; i++) { 119 TreePath p = currentSelection[i]; 120 if (!newSelection.contains(p) && isVisible(p)) { 121 removeSelectionPath(p); 122 } 123 } 124 125 Iterator iter = newSelection.iterator(); 127 while(iter.hasNext()) { 128 addSelectionPath((TreePath)iter.next()); 129 } 130 } 131 132 String action = req.getParameter(paramName + ":action"); 138 139 if (action == null || action.length() == 0) { 140 return; 142 } 143 144 getForm().setSubmitWidget(this); 145 String pathValue = req.getParameter(paramName + ":path"); 146 147 if (pathValue == null || pathValue.length() == 0) { 148 return; 150 } 151 152 TreePath path = TreePath.valueOf(pathValue); 154 155 if ("expand".equals(action)) { 156 this.expandPath(path); 157 } else if ("collapse".equals(action)) { 158 this.collapsePath(path); 159 } else if ("toggle-collapse".equals(action)) { 160 if (this.isExpanded(path)) { 161 this.collapsePath(path); 162 } else { 163 this.expandPath(path); 164 } 165 } else if ("select".equals(action)) { 166 this.addSelectionPath(path); 167 } else if ("unselect".equals(action)) { 168 this.removeSelectionPath(path); 169 } else if ("toggle-select".equals(action)) { 170 if (this.isPathSelected(path)) { 171 this.removeSelectionPath(path); 172 } else { 173 this.addSelectionPath(path); 174 } 175 } else { 176 } 179 } 180 181 public TreeModel getModel() { 182 return this.treeModel; 183 } 184 185 public void setModel(TreeModel model) { 186 if (model == null) { 187 model = DefaultTreeModel.UNSPECIFIED_MODEL; 188 } 189 this.treeModel.removeTreeModelListener(this.modelListener); 190 this.treeModel = model; 191 model.addTreeModelListener(this.modelListener); 192 } 193 194 private void markForRefresh(TreePath path) { 195 this.changedPaths.add(path); 196 getForm().addWidgetUpdate(this); 197 } 198 199 203 public void setSelectionModel(int model) { 204 if (model < 0 || model > MULTIPLE_SELECTION) { 205 throw new IllegalArgumentException ("Illegal selection model " + model); 206 } 207 208 if (model == this.selectionModel) { 209 return; 210 } 211 212 this.selectionModel = model; 213 if (model == SINGLE_SELECTION && getSelectionCount() > 1) { 214 clearSelection(); 215 } 216 } 217 218 public int getSelectionCount() { 219 return this.selectedPaths.size(); 220 } 221 222 public TreePath getSelectionPath() { 223 if (this.selectedPaths.isEmpty()) { 224 return null; 225 } else { 226 return (TreePath)this.selectedPaths.iterator().next(); 227 } 228 } 229 230 public TreePath[] getSelectionPaths() { 231 return (TreePath[])this.selectedPaths.toArray(new TreePath[this.selectedPaths.size()]); 232 } 233 234 public boolean isPathSelected(TreePath path) { 235 return this.selectedPaths.contains(path); 236 } 237 238 public boolean isSelectionEmpty() { 239 return this.selectedPaths.isEmpty(); 240 } 241 242 public void setSelectionPath(TreePath path) { 243 clearSelection(); 244 addSelectionPath(path); 245 } 246 247 public void setSelectionPaths(TreePath paths[]) { 248 clearSelection(); 249 addSelectionPaths(paths); 250 } 251 252 public void addSelectionPath(TreePath path) { 253 if (this.selectionModel == SINGLE_SELECTION) { 254 clearSelection(); 255 } 256 257 if (this.selectedPaths.add(path)) { 258 markForRefresh(path); 259 if (this.expandSelectedPath) { 260 expandPath(path); 261 } 262 if (this.selectionListener != null) { 263 this.selectionListener.selectionChanged(new TreeSelectionEvent(this, path, true)); 264 } 265 } 266 } 267 268 public void addSelectionPaths(TreePath paths[]) { 269 if (this.selectionModel == SINGLE_SELECTION) { 270 setSelectionPath(paths[0]); 271 } else { 272 for (int i = 0; i < paths.length; i++) { 273 addSelectionPath(paths[i]); 274 } 276 } 277 } 278 279 public void removeSelectionPath(TreePath path) { 280 if (this.selectedPaths.remove(path)) { 281 markForRefresh(path.getParentPath()); 283 if (this.selectionListener != null) { 284 this.selectionListener.selectionChanged(new TreeSelectionEvent(this, path, false)); 285 } 286 } 287 } 288 289 public void removeSelectionPaths(TreePath paths[]) { 290 for (int i = 0; i < paths.length; i++) { 291 removeSelectionPath(paths[i]); 292 } 294 } 295 296 public void clearSelection() { 297 if (this.isSelectionEmpty()) { 298 return; 299 } 300 301 TreePath[] paths = (TreePath[])this.selectedPaths.toArray(new TreePath[this.selectedPaths.size()]); 302 for (int i = 0; i < paths.length; i++) { 303 markForRefresh(paths[i].getParentPath()); 305 } 306 this.selectedPaths.clear(); 307 if (this.selectionListener != null) { 308 this.selectionListener.selectionChanged(new TreeSelectionEvent(this, paths, false)); 309 } 310 } 311 312 public void addTreeSelectionListener(TreeSelectionListener listener) { 313 this.selectionListener = WidgetEventMulticaster.add(this.selectionListener, listener); 314 } 315 316 public void removeTreeSelectionListener(TreeSelectionListener listener) { 317 this.selectionListener = WidgetEventMulticaster.remove(this.selectionListener, listener); 318 } 319 320 324 public boolean isCollapsed(TreePath path) { 325 return !isExpanded(path); 326 } 327 328 public boolean isExpanded(TreePath path) { 329 if (this.expandedPaths.contains(path)) { 330 TreePath parent = path.getParentPath(); 332 return parent == null ? true : isExpanded(parent); 333 } else { 334 return false; 335 } 336 } 337 338 345 public boolean isVisible(TreePath path) { 346 if (path == TreePath.ROOT_PATH) { 347 return true; 348 } 349 if (path != null) { 350 TreePath parent = path.getParentPath(); 351 if (parent != null) { 352 return isExpanded(parent); 353 } else { 354 return true; 356 } 357 } else { 358 return false; 359 } 360 } 361 362 public void makeVisible(TreePath path) { 363 if (path != null) { 364 TreePath parent = path.getParentPath(); 365 if (parent != null) { 366 expandPath(parent); 367 } 368 } 369 } 370 371 public boolean isRootVisible() { 372 return this.rootVisible; 373 } 374 375 public void setRootVisible(boolean visible) { 376 if (this.rootVisible != visible) { 377 this.markForRefresh(TreePath.ROOT_PATH); 378 this.rootVisible = visible; 379 if (!visible) { 380 this.expandPath(TreePath.ROOT_PATH); 382 } 383 } 384 } 385 386 public void collapsePath(TreePath path) { 387 if (path != null) { 388 if (this.expandedPaths.remove(path)) { 389 markForRefresh(path); 390 } 391 } 392 } 393 394 public void expandPath(TreePath path) { 395 if (path != null) { 396 if (this.expandedPaths.add(path)) { 397 markForRefresh(path); 398 } 399 } 400 } 401 402 public void setExpandsSelectedPath(boolean value) { 403 this.expandSelectedPath = value; 404 } 405 406 410 public Widget getWidgetForPath(TreePath path) { 411 Widget result = (Widget)this.pathWidgets.get(path); 412 if (result == null && !this.pathWidgets.containsKey(path)) { 413 result = createWidgetForPath(path); 414 if (result != null) { 415 result.setAttribute("TreePath", path); 416 } 417 this.pathWidgets.put(path, result); 418 } 419 420 return result; 421 } 422 423 private Widget createWidgetForPath(TreePath path) { 424 return null; 426 } 427 428 } 433 | Popular Tags |