KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > comp > BSelect


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: BSelect.java,v 1.23 2004/02/01 05:16:27 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.comp;
21
22 import java.util.*;
23
24 import org.apache.log4j.*;
25 import org.w3c.dom.*;
26 import org.w3c.dom.html.*;
27
28 import org.enhydra.barracuda.core.comp.model.*;
29 import org.enhydra.barracuda.core.comp.renderer.*;
30 import org.enhydra.barracuda.core.comp.renderer.html.*;
31 import org.enhydra.barracuda.core.comp.renderer.xml.*;
32 import org.enhydra.barracuda.core.event.*;
33 import org.enhydra.barracuda.core.view.*;
34 import org.enhydra.barracuda.core.util.dom.DOMUtil;
35 import org.enhydra.barracuda.plankton.*;
36
37 /**
38  * A BSelect element is used to render a list of items, and
39  * to indicate which element(s) are selected. It is typically
40  * used to manipulate <select> elements.
41  *
42  * <p>In most cases you will not actually need to bind the component
43  * to a view in order to use it--if you return it from a model, this
44  * will be done for you automatically. If however, you intend to use
45  * the component <em>standalone</em> (ie. manually attaching it to a
46  * specific node in the DOM) or <em>inline</em> (ie. in a toString()),
47  * then you MUST BIND IT TO A VIEW before rendering, or an error will
48  * be generated.
49  */

50 public class BSelect extends BList {
51
52     //public vars
53
protected static final Logger logger = Logger.getLogger(BSelect.class.getName());
54     
55     //private vars
56
protected ListSelectionModel selectionModel = null;
57     protected LocalModelListener scallback = null;
58     protected List listeners = null;
59     protected Integer JavaDoc viewSize = null;
60     protected boolean disableBackButton = false;
61     private ListenerFactory lnkListenerFactory;
62     protected BAction baction = null; //csc_041403.2
63

64     //--------------- Constructors -------------------------------
65
/**
66      * Public noargs constructor
67      */

68     public BSelect() {}
69     
70     /**
71      * Public constructor which creates the component and
72      * associates it with a ListModel
73      *
74      * @param imodel the specific model to back this component
75      */

76     public BSelect(ListModel imodel) {
77         this(imodel, null, null);
78     }
79     
80     /**
81      * Public constructor which creates the component and
82      * binds it to a specific model. The component is also
83      * bound to the specified view.
84      *
85      * <p>Null values may be passed in for any parameters,
86      * but if you do so you will need manually provide these
87      * values (via the accessor methods) prior to actually
88      * rendering the component
89      *
90      * @param model the specific model to back this component
91      * @param view the View the component should be bound to
92      * @param dvc the default ViewContext (opt--its presence allows the
93      * component to be rendered as markup in toString())
94      */

95     BSelect(ListModel imodel, View iview, ViewContext idvc) {
96         if (imodel!=null) setModel(imodel);
97         if (iview!=null) this.addView(iview);
98         if (idvc!=null) setDefaultViewContext(idvc);
99     }
100     
101
102
103
104     //--------------- Renderer -----------------------------------
105
/**
106      * Default component renderer factory registrations
107      */

108     static {
109         HTMLRendererFactory rfHTML = new HTMLRendererFactory();
110         installRendererFactory(rfHTML, BSelect.class, HTMLElement.class);
111         installRendererFactory(rfHTML, BSelect.class, HTMLDocument.class);
112
113     }
114
115     /**
116      * HTML RendererFactory
117      */

118     static class HTMLRendererFactory implements RendererFactory {
119         public Renderer getInstance() {return new HTMLSelectRenderer();}
120     }
121
122
123
124
125     //--------------- BSelect -----------------------------
126
/**
127      * Set the selection model that backs the list. This causes
128      * the list to register as a listener on the model, so any
129      * changes to it will be reflected in the list. If no
130      * SelectionModel is specified, a DefaultSelectionModel will
131      * be used.
132      *
133      * @param imodel the model that backs the list
134      */

135     public void setSelectionModel(ListSelectionModel imodel) {
136
137         //deregister if possible
138
if (selectionModel!=null && scallback!=null) {
139             selectionModel.removeModelListener(scallback);
140         }
141     
142         //set the model
143
selectionModel = imodel;
144         
145         //reregister if possible
146
if (selectionModel!=null) {
147             if (scallback==null) scallback = new LocalModelListener();
148             selectionModel.addModelListener(scallback);
149         }
150         invalidate();
151     }
152     
153     /**
154      * Get the selection model that backs the list
155      *
156      * @return the selection model that backs the list
157      */

158     public ListSelectionModel getSelectionModel() {
159         if (selectionModel==null) setSelectionModel(new DefaultListSelectionModel());
160         return selectionModel;
161     }
162
163     /**
164      * Convenience method to get the selected index (if the
165      * component allows multiple selections, this will return
166      * the index of the first selected item). Returns a -1 if
167      * there are no selected items
168      *
169      * @return the index of the first selected item
170      */

171     public int getSelectedIndex() {
172         if (model==null || model.getSize()<1) return -1;
173         if (selectionModel==null || selectionModel.isSelectionEmpty()) return -1;
174         for (int i=0,max=model.getSize(); i<max; i++) {
175             if (selectionModel.isSelectedIndex(i)) return i;
176         }
177         return -1;
178     }
179
180     /**
181      * Convenience method to set the selected index. Any other selected
182      * indexes will be cleared first. Setting this value to -1
183      * effectively clears all selections.
184      *
185      * @param i the index to be selected
186      */

187     public void setSelectedIndex(int i) {
188         if (selectionModel==null) getSelectionModel();
189         selectionModel.setSelectionInterval(i,i);
190         invalidate();
191     }
192
193     /**
194      * Convenience method to return an int array containing all
195      * selected indexes. Returns a null if there are no selected items
196      *
197      * @return an int array for selected indexes
198      */

199     public int[] getSelectedIndexes() {
200         if (model==null || model.getSize()<1) return null;
201         if (selectionModel==null || selectionModel.isSelectionEmpty()) return null;
202         int idx[] = new int[model.getSize()];
203         int cntr = -1;
204         for (int i=0,max=model.getSize(); i<max; i++) {
205             if (selectionModel.isSelectedIndex(i)) idx[++cntr] = i;
206         }
207         int idx2[] = new int[cntr];
208         System.arraycopy(idx, 0, idx2, 0, idx2.length);
209         return idx2;
210     }
211
212     /**
213      * Set the view size of the component (heighth in rows). If this value
214      * remains null, the height will default to whatever is specified in
215      * the underlying markup. If you set this value, then the size will
216      * be overridden in all the views associated with this component.
217      *
218      * Values less than 1 will be ignored.
219      *
220      * @param iviewSize an integer value representing the size.
221      */

222     public void setViewSize(Integer JavaDoc iviewSize) {
223         if (iviewSize==null || iviewSize.intValue()<1) return;
224         viewSize = iviewSize;
225         invalidate();
226     }
227     
228     /**
229      * Get the size of the component. May return a null if the size
230      * has not been manually specified. In this case, the renderer will
231      * simply not set the size attribute in the underlying markup, leaving
232      * it to default to whatever is already there.
233      *
234      * @return the view size
235      */

236     public Integer JavaDoc getViewSize() {
237         return viewSize;
238     }
239     
240     //csc_041403.2 - removed (was not being used anywhere)
241
/**
242      * Set disable back button (only works if your client supports
243      * Javascript)
244      *
245      * @param disable true if we want the back button disabled
246      */

247 /*
248     public void setDisableBackButton(boolean idisableBackButton) {
249         disableBackButton = idisableBackButton;
250     }
251 */

252     //csc_041403.2 - removed (was not being used anywhere)
253
/**
254      * Get disable back button
255      *
256      * @return true if we want the back button disabled
257      */

258 /*
259     public boolean getDisableBackButton() {
260         return disableBackButton;
261     }
262 */

263     
264     //csc_041403.2 - added
265
/**
266      * Specify an action for this component (rather than adding an even listener)
267      *
268      * @param ibaction the action to be fired when the BSelect is activated on the client
269      */

270     public void setAction(BAction ibaction) {
271         baction = ibaction;
272     }
273     
274     //csc_041403.2 - added
275
/**
276      * Returns the action associated with this component (if any)
277      *
278      * @return the action associated with this component (if any)
279      */

280     public BAction getAction() {
281         return baction;
282     }
283     
284     //csc_041403.2 - added
285
/**
286      * Add an event listener to this component.
287      *
288      * @param lf the event listener to be added
289      * @param idisableBackButton true if the back button should be
290      * disabled when the action occurs
291      */

292     public void addEventListener(ListenerFactory lf, boolean idisableBackButton) {
293         if (lf==null) return;
294         disableBackButton = idisableBackButton;
295         if (listeners==null) listeners = new ArrayList(5);
296         listeners.add(lf);
297         invalidate();
298     }
299     
300     /**
301      * Add an event listener to this component.
302      *
303      * @param lf the event listener to be added
304      */

305     public void addEventListener(ListenerFactory lf) {
306         if (lf==null) return;
307         if (listeners==null) listeners = new ArrayList(5);
308         listeners.add(lf);
309         invalidate();
310     }
311     
312     /**
313      * Remove an event listener from this component
314      *
315      * @param lf the event listener to be removed
316      */

317     public void removeEventListener(ListenerFactory lf) {
318         if (lf==null) return;
319         if (listeners==null) return;
320         listeners.remove(lf);
321         invalidate();
322     }
323
324     /**
325      * Here in the pre-render phase we actually add
326      * BAction step children for any of the listeners
327      * that might have been added to this component
328      */

329     protected void preRender(ViewContext vc, int depth) {
330
331         //add in our BAction as a step child
332
if (baction!=null) this.addStepChild(baction, true); //csc_041403.2
333

334         //we want to actually add proxy components as step children
335
//for any event listeners we might have to support
336
if (listeners!=null) {
337             //run through our list of listeners
338
Iterator it = listeners.iterator();
339             while (it.hasNext()) {
340                 ListenerFactory lf = (ListenerFactory) it.next();
341             
342                 //run through our list of views
343
//csc_041403.2_start
344
/*
345 The problem with this is that its creating a separate BAction for each view, and it really
346 doesn't need to do that...just create one and add in as many views as there are
347                 Iterator it2 = getViews().iterator();
348                 while (it2.hasNext()) {
349                     View v = (View) it2.next();
350                     BAction baComp = new BAction();
351                     baComp.addView(v);
352                     baComp.setDisableBackButton(disableBackButton); //csc_041403.2
353                     baComp.addEventListener(lf);
354                     this.addStepChild(baComp, true);
355                 }
356
357                 //csc_101001.1 - added
358                 //run through our list of temp views too (these
359                 //will be set if the component was returned from a
360                 //model without being pre-bound to a view)
361                 if (tempViews!=null) {
362                     it2 = tempViews.iterator();
363                     while (it2.hasNext()) {
364                         View v = (View) it2.next();
365                         BAction baComp = new BAction();
366                         baComp.addView(v);
367                         baComp.setDisableBackButton(disableBackButton); //csc_041403.2
368                         baComp.addEventListener(lf);
369                         this.addStepChild(baComp, true);
370                     }
371                 }
372 */

373                 BAction baComp = new BAction();
374                 baComp.setDisableBackButton(disableBackButton);
375                 baComp.addEventListener(lf);
376                 this.addStepChild(baComp, true);
377 //csc_041403.2_end
378
}
379         }
380     }
381
382     /**
383      * Render a specific view for the component.
384      *
385      * @param view View to be rendered
386      * @param vc ViewContext for the client view
387      * @throws RenderException if the particular View is not supported
388      * @param list a List of all the views for this component
389      */

390 /*
391 //021102.3_csc - removed, because now its in BComponent
392     protected void renderView (View view, ViewContext vc, int depth) throws RenderException {
393         if (logger.isInfoEnabled()) logger.info("rendering comp:"+this.toRef()+" view:"+view);
394
395         //actually render the view according to known interfaces
396         try {
397             Renderer r = getRenderer(view);
398             r.renderComponent(this, view, vc);
399             
400         } catch (DOMException e) {
401             logger.warn("DOM Error:", e);
402             throw new DOMAccessException("Error rendering component in view:"+e, e);
403         }
404     }
405 */

406
407
408
409
410     //--------------- Lifecycle ----------------------------------
411
/**
412      * Destroy cycle. The component should use this cycle to
413      * perform any special cleanup.
414      */

415     public void destroyCycle() {
416         //default destroy
417
super.destroyCycle();
418     
419         //we set the model to null so that the component can be
420
//garbage collected. If we don't do this, the model retains
421
//a reference back to the component and so the component
422
//will never be freed up...
423
setSelectionModel(null);
424     }
425
426
427
428
429     //--------------- Utility ------------------------------------
430
/*
431     class LocalListSelectionListener implements ListSelectionListener {
432         //if the selection model changes, invalidate the component
433         public void valueChanged(ListSelectionEvent e) {
434             invalidate();
435         }
436     }
437 */

438     class LocalModelListener implements ModelListener {
439         //get notified when one of the underlying models changes
440
public void modelChanged(Model m) {
441             invalidate();
442         }
443     }
444     
445 }
Popular Tags