Source Code Cross Referenced for OptionListModel.java in  » 6.0-JDK-Core » swing » javax » swing » text » html » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.text.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1998-2000 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025        package javax.swing.text.html;
026
027        import javax.swing.*;
028        import javax.swing.event.*;
029        import java.util.EventListener;
030        import java.util.BitSet;
031        import java.io.Serializable;
032
033        /**
034         * This class extends DefaultListModel, and also implements
035         * the ListSelectionModel interface, allowing for it to store state
036         * relevant to a SELECT form element which is implemented as a List.
037         * If SELECT has a size attribute whose value is greater than 1,
038         * or if allows multiple selection then a JList is used to 
039         * represent it and the OptionListModel is used as its model.
040         * It also stores the initial state of the JList, to ensure an
041         * accurate reset, if the user requests a reset of the form.
042         *
043         @author Sunita Mani
044         @version 1.18 05/05/07
045         */
046
047        class OptionListModel extends DefaultListModel implements 
048                ListSelectionModel, Serializable {
049
050            private static final int MIN = -1;
051            private static final int MAX = Integer.MAX_VALUE;
052            private int selectionMode = SINGLE_SELECTION;
053            private int minIndex = MAX;
054            private int maxIndex = MIN;
055            private int anchorIndex = -1;
056            private int leadIndex = -1;
057            private int firstChangedIndex = MAX;
058            private int lastChangedIndex = MIN;
059            private boolean isAdjusting = false;
060            private BitSet value = new BitSet(32);
061            private BitSet initialValue = new BitSet(32);
062            protected EventListenerList listenerList = new EventListenerList();
063
064            protected boolean leadAnchorNotificationEnabled = true;
065
066            public int getMinSelectionIndex() {
067                return isSelectionEmpty() ? -1 : minIndex;
068            }
069
070            public int getMaxSelectionIndex() {
071                return maxIndex;
072            }
073
074            public boolean getValueIsAdjusting() {
075                return isAdjusting;
076            }
077
078            public int getSelectionMode() {
079                return selectionMode;
080            }
081
082            public void setSelectionMode(int selectionMode) {
083                switch (selectionMode) {
084                case SINGLE_SELECTION:
085                case SINGLE_INTERVAL_SELECTION:
086                case MULTIPLE_INTERVAL_SELECTION:
087                    this .selectionMode = selectionMode;
088                    break;
089                default:
090                    throw new IllegalArgumentException("invalid selectionMode");
091                }
092            }
093
094            public boolean isSelectedIndex(int index) {
095                return ((index < minIndex) || (index > maxIndex)) ? false
096                        : value.get(index);
097            }
098
099            public boolean isSelectionEmpty() {
100                return (minIndex > maxIndex);
101            }
102
103            public void addListSelectionListener(ListSelectionListener l) {
104                listenerList.add(ListSelectionListener.class, l);
105            }
106
107            public void removeListSelectionListener(ListSelectionListener l) {
108                listenerList.remove(ListSelectionListener.class, l);
109            }
110
111            /**
112             * Returns an array of all the <code>ListSelectionListener</code>s added
113             * to this OptionListModel with addListSelectionListener().
114             *
115             * @return all of the <code>ListSelectionListener</code>s added or an empty
116             *         array if no listeners have been added
117             * @since 1.4
118             */
119            public ListSelectionListener[] getListSelectionListeners() {
120                return (ListSelectionListener[]) listenerList
121                        .getListeners(ListSelectionListener.class);
122            }
123
124            /**
125             * Notify listeners that we are beginning or ending a
126             * series of value changes
127             */
128            protected void fireValueChanged(boolean isAdjusting) {
129                fireValueChanged(getMinSelectionIndex(),
130                        getMaxSelectionIndex(), isAdjusting);
131            }
132
133            /**
134             * Notify ListSelectionListeners that the value of the selection,
135             * in the closed interval firstIndex,lastIndex, has changed.
136             */
137            protected void fireValueChanged(int firstIndex, int lastIndex) {
138                fireValueChanged(firstIndex, lastIndex, getValueIsAdjusting());
139            }
140
141            /**
142             * @param firstIndex The first index in the interval.
143             * @param index1 The last index in the interval.
144             * @param isAdjusting True if this is the final change in a series of them.
145             * @see EventListenerList
146             */
147            protected void fireValueChanged(int firstIndex, int lastIndex,
148                    boolean isAdjusting) {
149                Object[] listeners = listenerList.getListenerList();
150                ListSelectionEvent e = null;
151
152                for (int i = listeners.length - 2; i >= 0; i -= 2) {
153                    if (listeners[i] == ListSelectionListener.class) {
154                        if (e == null) {
155                            e = new ListSelectionEvent(this , firstIndex,
156                                    lastIndex, isAdjusting);
157                        }
158                        ((ListSelectionListener) listeners[i + 1])
159                                .valueChanged(e);
160                    }
161                }
162            }
163
164            private void fireValueChanged() {
165                if (lastChangedIndex == MIN) {
166                    return;
167                }
168                /* Change the values before sending the event to the
169                 * listeners in case the event causes a listener to make
170                 * another change to the selection.
171                 */
172                int oldFirstChangedIndex = firstChangedIndex;
173                int oldLastChangedIndex = lastChangedIndex;
174                firstChangedIndex = MAX;
175                lastChangedIndex = MIN;
176                fireValueChanged(oldFirstChangedIndex, oldLastChangedIndex);
177            }
178
179            // Update first and last change indices
180            private void markAsDirty(int r) {
181                firstChangedIndex = Math.min(firstChangedIndex, r);
182                lastChangedIndex = Math.max(lastChangedIndex, r);
183            }
184
185            // Set the state at this index and update all relevant state.
186            private void set(int r) {
187                if (value.get(r)) {
188                    return;
189                }
190                value.set(r);
191                Option option = (Option) get(r);
192                option.setSelection(true);
193                markAsDirty(r);
194
195                // Update minimum and maximum indices
196                minIndex = Math.min(minIndex, r);
197                maxIndex = Math.max(maxIndex, r);
198            }
199
200            // Clear the state at this index and update all relevant state.
201            private void clear(int r) {
202                if (!value.get(r)) {
203                    return;
204                }
205                value.clear(r);
206                Option option = (Option) get(r);
207                option.setSelection(false);
208                markAsDirty(r);
209
210                // Update minimum and maximum indices
211                /*
212                   If (r > minIndex) the minimum has not changed.
213                   The case (r < minIndex) is not possible because r'th value was set.
214                   We only need to check for the case when lowest entry has been cleared,
215                   and in this case we need to search for the first value set above it.
216                 */
217                if (r == minIndex) {
218                    for (minIndex = minIndex + 1; minIndex <= maxIndex; minIndex++) {
219                        if (value.get(minIndex)) {
220                            break;
221                        }
222                    }
223                }
224                /*
225                   If (r < maxIndex) the maximum has not changed.
226                   The case (r > maxIndex) is not possible because r'th value was set.
227                   We only need to check for the case when highest entry has been cleared,
228                   and in this case we need to search for the first value set below it.
229                 */
230                if (r == maxIndex) {
231                    for (maxIndex = maxIndex - 1; minIndex <= maxIndex; maxIndex--) {
232                        if (value.get(maxIndex)) {
233                            break;
234                        }
235                    }
236                }
237                /* Performance note: This method is called from inside a loop in
238                   changeSelection() but we will only iterate in the loops
239                   above on the basis of one iteration per deselected cell - in total.
240                   Ie. the next time this method is called the work of the previous
241                   deselection will not be repeated.
242
243                   We also don't need to worry about the case when the min and max
244                   values are in their unassigned states. This cannot happen because
245                   this method's initial check ensures that the selection was not empty
246                   and therefore that the minIndex and maxIndex had 'real' values.
247
248                   If we have cleared the whole selection, set the minIndex and maxIndex
249                   to their cannonical values so that the next set command always works
250                   just by using Math.min and Math.max.
251                 */
252                if (isSelectionEmpty()) {
253                    minIndex = MAX;
254                    maxIndex = MIN;
255                }
256            }
257
258            /**
259             * Sets the value of the leadAnchorNotificationEnabled flag.
260             * @see		#isLeadAnchorNotificationEnabled()
261             */
262            public void setLeadAnchorNotificationEnabled(boolean flag) {
263                leadAnchorNotificationEnabled = flag;
264            }
265
266            /**
267             * Returns the value of the leadAnchorNotificationEnabled flag.
268             * When leadAnchorNotificationEnabled is true the model
269             * generates notification events with bounds that cover all the changes to
270             * the selection plus the changes to the lead and anchor indices.
271             * Setting the flag to false causes a norrowing of the event's bounds to
272             * include only the elements that have been selected or deselected since
273             * the last change. Either way, the model continues to maintain the lead
274             * and anchor variables internally. The default is true.
275             * @return 		the value of the leadAnchorNotificationEnabled flag
276             * @see		#setLeadAnchorNotificationEnabled(boolean)
277             */
278            public boolean isLeadAnchorNotificationEnabled() {
279                return leadAnchorNotificationEnabled;
280            }
281
282            private void updateLeadAnchorIndices(int anchorIndex, int leadIndex) {
283                if (leadAnchorNotificationEnabled) {
284                    if (this .anchorIndex != anchorIndex) {
285                        if (this .anchorIndex != -1) { // The unassigned state.
286                            markAsDirty(this .anchorIndex);
287                        }
288                        markAsDirty(anchorIndex);
289                    }
290
291                    if (this .leadIndex != leadIndex) {
292                        if (this .leadIndex != -1) { // The unassigned state.
293                            markAsDirty(this .leadIndex);
294                        }
295                        markAsDirty(leadIndex);
296                    }
297                }
298                this .anchorIndex = anchorIndex;
299                this .leadIndex = leadIndex;
300            }
301
302            private boolean contains(int a, int b, int i) {
303                return (i >= a) && (i <= b);
304            }
305
306            private void changeSelection(int clearMin, int clearMax,
307                    int setMin, int setMax, boolean clearFirst) {
308                for (int i = Math.min(setMin, clearMin); i <= Math.max(setMax,
309                        clearMax); i++) {
310
311                    boolean shouldClear = contains(clearMin, clearMax, i);
312                    boolean shouldSet = contains(setMin, setMax, i);
313
314                    if (shouldSet && shouldClear) {
315                        if (clearFirst) {
316                            shouldClear = false;
317                        } else {
318                            shouldSet = false;
319                        }
320                    }
321
322                    if (shouldSet) {
323                        set(i);
324                    }
325                    if (shouldClear) {
326                        clear(i);
327                    }
328                }
329                fireValueChanged();
330            }
331
332            /*   Change the selection with the effect of first clearing the values
333             *   in the inclusive range [clearMin, clearMax] then setting the values
334             *   in the inclusive range [setMin, setMax]. Do this in one pass so
335             *   that no values are cleared if they would later be set.
336             */
337            private void changeSelection(int clearMin, int clearMax,
338                    int setMin, int setMax) {
339                changeSelection(clearMin, clearMax, setMin, setMax, true);
340            }
341
342            public void clearSelection() {
343                removeSelectionInterval(minIndex, maxIndex);
344            }
345
346            public void setSelectionInterval(int index0, int index1) {
347                if (index0 == -1 || index1 == -1) {
348                    return;
349                }
350
351                if (getSelectionMode() == SINGLE_SELECTION) {
352                    index0 = index1;
353                }
354
355                updateLeadAnchorIndices(index0, index1);
356
357                int clearMin = minIndex;
358                int clearMax = maxIndex;
359                int setMin = Math.min(index0, index1);
360                int setMax = Math.max(index0, index1);
361                changeSelection(clearMin, clearMax, setMin, setMax);
362            }
363
364            public void addSelectionInterval(int index0, int index1) {
365                if (index0 == -1 || index1 == -1) {
366                    return;
367                }
368
369                if (getSelectionMode() != MULTIPLE_INTERVAL_SELECTION) {
370                    setSelectionInterval(index0, index1);
371                    return;
372                }
373
374                updateLeadAnchorIndices(index0, index1);
375
376                int clearMin = MAX;
377                int clearMax = MIN;
378                int setMin = Math.min(index0, index1);
379                int setMax = Math.max(index0, index1);
380                changeSelection(clearMin, clearMax, setMin, setMax);
381            }
382
383            public void removeSelectionInterval(int index0, int index1) {
384                if (index0 == -1 || index1 == -1) {
385                    return;
386                }
387
388                updateLeadAnchorIndices(index0, index1);
389
390                int clearMin = Math.min(index0, index1);
391                int clearMax = Math.max(index0, index1);
392                int setMin = MAX;
393                int setMax = MIN;
394                changeSelection(clearMin, clearMax, setMin, setMax);
395            }
396
397            private void setState(int index, boolean state) {
398                if (state) {
399                    set(index);
400                } else {
401                    clear(index);
402                }
403            }
404
405            /**
406             * Insert length indices beginning before/after index. If the value 
407             * at index is itself selected, set all of the newly inserted 
408             * items, otherwise leave them unselected. This method is typically
409             * called to sync the selection model with a corresponding change
410             * in the data model.
411             */
412            public void insertIndexInterval(int index, int length,
413                    boolean before) {
414                /* The first new index will appear at insMinIndex and the last
415                 * one will appear at insMaxIndex
416                 */
417                int insMinIndex = (before) ? index : index + 1;
418                int insMaxIndex = (insMinIndex + length) - 1;
419
420                /* Right shift the entire bitset by length, beginning with
421                 * index-1 if before is true, index+1 if it's false (i.e. with
422                 * insMinIndex).
423                 */
424                for (int i = maxIndex; i >= insMinIndex; i--) {
425                    setState(i + length, value.get(i));
426                }
427
428                /* Initialize the newly inserted indices.
429                 */
430                boolean setInsertedValues = value.get(index);
431                for (int i = insMinIndex; i <= insMaxIndex; i++) {
432                    setState(i, setInsertedValues);
433                }
434            }
435
436            /**
437             * Remove the indices in the interval index0,index1 (inclusive) from
438             * the selection model.  This is typically called to sync the selection
439             * model width a corresponding change in the data model.  Note
440             * that (as always) index0 can be greater than index1.
441             */
442            public void removeIndexInterval(int index0, int index1) {
443                int rmMinIndex = Math.min(index0, index1);
444                int rmMaxIndex = Math.max(index0, index1);
445                int gapLength = (rmMaxIndex - rmMinIndex) + 1;
446
447                /* Shift the entire bitset to the left to close the index0, index1
448                 * gap.
449                 */
450                for (int i = rmMinIndex; i <= maxIndex; i++) {
451                    setState(i, value.get(i + gapLength));
452                }
453            }
454
455            public void setValueIsAdjusting(boolean isAdjusting) {
456                if (isAdjusting != this .isAdjusting) {
457                    this .isAdjusting = isAdjusting;
458                    this .fireValueChanged(isAdjusting);
459                }
460            }
461
462            public String toString() {
463                String s = ((getValueIsAdjusting()) ? "~" : "=")
464                        + value.toString();
465                return getClass().getName() + " "
466                        + Integer.toString(hashCode()) + " " + s;
467            }
468
469            /**
470             * Returns a clone of the receiver with the same selection.
471             * <code>listenerLists</code> are not duplicated.
472             *
473             * @return a clone of the receiver
474             * @exception CloneNotSupportedException if the receiver does not
475             *    both (a) implement the <code>Cloneable</code> interface
476             *    and (b) define a <code>clone</code> method
477             */
478            public Object clone() throws CloneNotSupportedException {
479                OptionListModel clone = (OptionListModel) super .clone();
480                clone.value = (BitSet) value.clone();
481                clone.listenerList = new EventListenerList();
482                return clone;
483            }
484
485            public int getAnchorSelectionIndex() {
486                return anchorIndex;
487            }
488
489            public int getLeadSelectionIndex() {
490                return leadIndex;
491            }
492
493            /**
494             * Set the anchor selection index, leaving all selection values unchanged. 
495             *
496             * @see #getAnchorSelectionIndex     
497             * @see #setLeadSelectionIndex
498             */
499            public void setAnchorSelectionIndex(int anchorIndex) {
500                this .anchorIndex = anchorIndex;
501            }
502
503            /**
504             * Set the lead selection index, ensuring that values between the 
505             * anchor and the new lead are either all selected or all deselected. 
506             * If the value at the anchor index is selected, first clear all the 
507             * values in the range [anchor, oldLeadIndex], then select all the values 
508             * values in the range [anchor, newLeadIndex], where oldLeadIndex is the old 
509             * leadIndex and newLeadIndex is the new one. 
510             * <p> 
511             * If the value at the anchor index is not selected, do the same thing in reverse, 
512             * selecting values in the old range and deslecting values in the new one. 
513             * <p>
514             * Generate a single event for this change and notify all listeners. 
515             * For the purposes of generating minimal bounds in this event, do the 
516             * operation in a single pass; that way the first and last index inside the 
517             * ListSelectionEvent that is broadcast will refer to cells that actually 
518             * changed value because of this method. If, instead, this operation were 
519             * done in two steps the effect on the selection state would be the same 
520             * but two events would be generated and the bounds around the changed values 
521             * would be wider, including cells that had been first cleared and only 
522             * to later be set. 
523             * <p>
524             * This method can be used in the mouseDragged() method of a UI class 
525             * to extend a selection.  
526             *
527             * @see #getLeadSelectionIndex     
528             * @see #setAnchorSelectionIndex
529             */
530            public void setLeadSelectionIndex(int leadIndex) {
531                int anchorIndex = this .anchorIndex;
532                if (getSelectionMode() == SINGLE_SELECTION) {
533                    anchorIndex = leadIndex;
534                }
535
536                int oldMin = Math.min(this .anchorIndex, this .leadIndex);
537                ;
538                int oldMax = Math.max(this .anchorIndex, this .leadIndex);
539                ;
540                int newMin = Math.min(anchorIndex, leadIndex);
541                int newMax = Math.max(anchorIndex, leadIndex);
542                if (value.get(this .anchorIndex)) {
543                    changeSelection(oldMin, oldMax, newMin, newMax);
544                } else {
545                    changeSelection(newMin, newMax, oldMin, oldMax, false);
546                }
547                this .anchorIndex = anchorIndex;
548                this .leadIndex = leadIndex;
549            }
550
551            /**
552             * This method is responsible for storing the state
553             * of the initial selection.  If the selectionMode
554             * is the default, i.e allowing only for SINGLE_SELECTION,
555             * then the very last OPTION that has the selected
556             * attribute set wins.
557             */
558            public void setInitialSelection(int i) {
559                if (initialValue.get(i)) {
560                    return;
561                }
562                if (selectionMode == SINGLE_SELECTION) {
563                    // reset to empty
564                    initialValue.and(new BitSet());
565                }
566                initialValue.set(i);
567            }
568
569            /**
570             * Fetches the BitSet that represents the initial
571             * set of selected items in the list.
572             */
573            public BitSet getInitialSelection() {
574                return initialValue;
575            }
576        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.