xref: /trunk/main/odk/examples/DevelopersGuide/Forms/ControlLock.java (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  *  The Contents of this file are made available subject to the terms of
4  *  the BSD license.
5  *
6  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *************************************************************************/
34 
35 import com.sun.star.uno.*;
36 import com.sun.star.lang.*;
37 import com.sun.star.container.*;
38 import com.sun.star.beans.*;
39 import com.sun.star.form.*;
40 import com.sun.star.util.*;
41 import com.sun.star.sdbc.*;
42 
43 
44 /**************************************************************************/
45 /** A helper class for recursively locking control models which are bound
46     to a specific field
47 */
48 
49 class LockControlModels extends ComponentTreeTraversal
50 {
51     private String  m_sDataField;
52     private Boolean m_aLockIt;
53     private int     m_nLevel;   // nesting level relative to the form we started with
54 
55     /* ------------------------------------------------------------------ */
56     public LockControlModels( String sDataField, boolean bLockIt )
57     {
58         m_sDataField = sDataField;
59         m_aLockIt = new Boolean( bLockIt );
60         m_nLevel = 0;
61     }
62 
63     /* ------------------------------------------------------------------ */
64     protected boolean shouldStepInto( XIndexContainer xContainer ) throws com.sun.star.uno.Exception
65     {
66         if ( !super.shouldStepInto( xContainer ) )
67             return false;   // don't try to be more clever than our base class
68 
69         XForm xForm = (XForm)UnoRuntime.queryInterface( XForm.class, xContainer );
70         if ( ( null != xForm ) && ( m_nLevel > 1 ) )
71             // don't step into sub forms - we only handle the form we were originally
72             // applied to
73             return false;
74 
75         return true;
76     }
77 
78     /* ------------------------------------------------------------------ */
79     public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception
80     {
81         // entering this nesting level
82         ++m_nLevel;
83 
84         // check if the component has a DataField property
85         XPropertySet xCompProps = UNO.queryPropertySet( aFormComponent );
86         XPropertySetInfo xPSI = null;
87         if ( null != xCompProps )
88             xPSI = xCompProps.getPropertySetInfo();
89 
90         if ( ( null != xPSI ) && xPSI.hasPropertyByName( "DataField" ) )
91         {   // indeed it has ....
92             String sDataField = (String)xCompProps.getPropertyValue( "DataField" );
93             if ( sDataField.equals( m_sDataField ) )
94             {   // we found a control model which is bound to what we're looking for
95                 xCompProps.setPropertyValue( "ReadOnly", m_aLockIt );
96             }
97         }
98 
99         // allow the super class to step down, if possible
100         super.handle( aFormComponent );
101 
102         // leaving this nesting level
103         --m_nLevel;
104     }
105 };
106 
107 /**************************************************************************/
108 /** a class which automatically handles control locking.
109     <p>The class has to be bound to a form. Upon every movement of the form,
110     all controls which are bound to a (to be specified) field are locked
111     on existing and unlocked on new records.</p>
112 */
113 class ControlLock implements XRowSetListener
114 {
115     private XPropertySet    m_xForm;
116     private String          m_sDataField;
117     private boolean         m_bLockingEnabled;
118     private boolean         m_bPreviousRoundLock;
119 
120     /* ------------------------------------------------------------------ */
121     ControlLock( XPropertySet xForm, String sBoundDataField )
122     {
123         m_xForm = xForm;
124         m_sDataField = sBoundDataField;
125         m_bLockingEnabled = false;
126         m_bPreviousRoundLock = false;
127     }
128 
129     /* ------------------------------------------------------------------ */
130     /** updates the locks on the affected controls
131     */
132     protected void updateLocks( )
133     {
134         try
135         {
136             // first determine if we need to lock
137             Boolean aIsNewRecord = (Boolean)m_xForm.getPropertyValue( "IsNew" );
138 
139             boolean bNeedLock = m_bLockingEnabled && !aIsNewRecord.booleanValue();
140 
141             if ( m_bPreviousRoundLock != bNeedLock )
142             {
143                 LockControlModels aLocker = new LockControlModels( m_sDataField, bNeedLock );
144                 aLocker.handle( m_xForm );
145                 m_bPreviousRoundLock = bNeedLock;
146             }
147 
148             // please note that we choose the expensive way here: We always loop through
149             // _all_ control models belonging to the form. This clearly slows down the
150             // whole process.
151             // A better solution would be to cache the affected control models. Then we
152             // could either rely on the fact that the model hierarchy is static, or we
153             // could add ourself as container listener to the form.
154         }
155         catch(com.sun.star.uno.Exception e)
156         {
157             System.out.println(e);
158             e.printStackTrace();
159         }
160     }
161 
162     /* ------------------------------------------------------------------ */
163     /** enables the locking in general
164         <p>If the control models are really locked depends on the current
165         record of the form: on the insert row, controls are never locked.</p>
166     */
167     public void enableLock( boolean bLock )
168     {
169         // remember this new setting
170         m_bLockingEnabled = bLock;
171 
172         // add or remove ourself as listener to get notified of cursor moves
173         XRowSet xRowSet = (XRowSet)UnoRuntime.queryInterface(
174             XRowSet.class, m_xForm );
175         if ( m_bLockingEnabled )
176         {
177             xRowSet.addRowSetListener( this );
178         }
179         else
180         {
181             xRowSet.removeRowSetListener( this );
182         }
183 
184         // update the locks
185         updateLocks();
186     }
187 
188     /* ==================================================================
189        = UNO callbacks
190        ================================================================== */
191 
192     /* ------------------------------------------------------------------ */
193     // XResetListener overridables
194     /* ------------------------------------------------------------------ */
195     public void cursorMoved( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
196     {
197         updateLocks( );
198     }
199 
200     /* ------------------------------------------------------------------ */
201     public void rowChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
202     {
203         // not interested in
204     }
205 
206     /* ------------------------------------------------------------------ */
207     public void rowSetChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
208     {
209         // not interested in
210     }
211 
212     /* ------------------------------------------------------------------ */
213     // XEventListener overridables
214     /* ------------------------------------------------------------------ */
215     public void disposing( EventObject aEvent )
216     {
217         // not interested in
218     }
219 }
220